mcgrew@dartagnan.rutgers.edu (Charles Mcgrew) (05/28/89)
Submitted-by: Bill Randle <billr@saab.cna.tek.com> Posting-number: Volume 1, Issue 13 Archive-name: calentool/part04 #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # devent.c # dpaint.c # holidays.c # This archive created: Sat May 27 13:12:02 1989 export PATH; PATH=/bin:$PATH echo shar: extracting "'devent.c'" '(27402 characters)' if test -f 'devent.c' then echo shar: will not over-write existing file "'devent.c'" else sed 's/^ X//' << \SHAR_EOF > 'devent.c' X/* X * $Header: devent.c,v 2.1 89/05/09 14:18:59 billr Exp $ X */ X/* X * devent.c X * X * Author: Philip Heller, Sun Microsystems. Inc. <terrapin!heller@sun.com> X * X * Original source Copyright (C) 1987, Sun Microsystems, Inc. X * All Rights Reserved X * Permission is hereby granted to use and modify this program in source X * or binary form as long as it is not sold for profit and this copyright X * notice remains intact. X * X * X * Changes/additions by: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM> X * X * Changes and additions Copyright (C) 1988, 1989 Tektronix, Inc. X * All Rights Reserved X * Permission is hereby granted to use and modify the modifications in source X * or binary form as long as they are not sold for profit and this copyright X * notice remains intact. X */ X/******************************************************** X * * X * Day event routines for main subwindow. * X * * X ********************************************************/ X X X#include <stdio.h> X#include <suntool/sunview.h> X#include <suntool/canvas.h> X#include <suntool/panel.h> X#include <suntool/menu.h> X#include <sys/time.h> X#include <fcntl.h> X#include "ct.h" X#include "event.h" X Xextern Menu day_sel_menu; Xextern Frame attr_frame; Xextern Panel_item everyx_pi, repeat_pi, remind_pi; Xextern Panel_item whichwk_pi, marked_pi; Xextern Panel_item del_choice_pi; Xextern Frame del_frame; Xextern Panel del_panel; Xextern Pixrect tri_right_pr, tri_up_pr; Xextern Pixrect *leftarrow, *rightarrow, *morebutton; Xextern int n_tslots; Xint attr_bi; Xstruct appt_entry shelf_appt = {0}; Xint old_slot = -1; /* for text cursor location */ X Xday_inputevent(canvas, event) XCanvas canvas; XEvent *event; X{ X Menu_item an_item; X int box_index, x, y, found_flag; X int i, j, active_above, strl; X struct appt_entry *aptr; X static int start_arrow_box = -1, prev_box = 0; X static int expecting = 0; X X found_flag = 0; /* See if cursor is in a box. */ X /* translate coordinates back to pixwin space */ X event = canvas_window_event(canvas, event); X x = event_x(event); X y = event_y(event); X /*fix_event(canvas, event); /* check for LOC_RGNENTER */ X if (event_id(event) == LOC_RGNEXIT && old_slot >= 0) { X /* erase text cursor */ X text_cursor(old_slot); X old_slot = -1; X } X X for (box_index=0; box_index<N_SLOTS; box_index++) { X /* is cursor inside a slot ? */ X if (x>=slots[box_index].slot_pos.left && x<=slots[box_index].slot_pos.right && X y>=slots[box_index].slot_pos.top && y<=slots[box_index].slot_pos.bottom) { X found_flag = FOUND_SLOT; X break; X } X /* is cursor inside a "more" button ? */ X if (x>=slots[box_index].moreb_pos.left && x<=slots[box_index].moreb_pos.right && X y>=slots[box_index].moreb_pos.top && y<=slots[box_index].moreb_pos.bottom) { X if (slots[box_index].count > 1) { X /* "more" button is active */ X found_flag = FOUND_MORE; X break; X } X } X /* is cursor inside a "leftarrow" button ? */ X if (x>=slots[box_index].larrow_pos.left && x<=slots[box_index].larrow_pos.right && X y>=slots[box_index].larrow_pos.top && y<=slots[box_index].larrow_pos.bottom) { X found_flag = FOUND_LARROW; X break; X } X /* is cursor inside a "rightarrow" button ? */ X if (x>=slots[box_index].rarrow_pos.left && x<=slots[box_index].rarrow_pos.right && X y>=slots[box_index].rarrow_pos.top && y<=slots[box_index].rarrow_pos.bottom) { X found_flag = FOUND_RARROW; X break; X } X } X if (old_slot >= 0) { X /* erase text cursor at old location */ X text_cursor(old_slot); X old_slot = -1; X } X X if (!found_flag && !expecting) X return(0); /* Not in a box => ignore. */ X X if (event_id(event) == LOC_STILL || (event_is_button(event) && event_is_up(event))) { X if (found_flag == FOUND_SLOT && box_index != old_slot) X /* in a different slot than we were before */ X if (slots[box_index].active == ACTIVE) X /* display cursor at new location */ X text_cursor(box_index); X } X if (found_flag == FOUND_SLOT && event_id(event) <= ASCII_LAST) { X /* Process a kbd event. */ X if (slots[box_index].active != ACTIVE) X return(0); X if (event_id(event) == CTRL_R) { X rewrite_string(box_index, JUSTIFY_LEFT); X return(0); X } X new_entry = 1; /* flag for file updating */ X strl = strlen(slots[box_index].cur_appt->str); X if (event_id(event) == CTRL_U) { X slots[box_index].cur_appt->str[0] = '\0'; X rewrite_string(box_index, JUSTIFY_LEFT); X } else if (event_id(event) == CTRL_W) { X while (strl > 0 && slots[box_index].cur_appt->str[strl-1] != ' ') { X slots[box_index].cur_appt->str[strl-1] = '\0'; X strl--; X } X rewrite_string(box_index, JUSTIFY_RIGHT); X } else if (event_id(event) == DEL || event_id(event) == BACKSPACE) { X if (strl > 0) { X slots[box_index].cur_appt->str[strl-1] = '\0'; X rewrite_string(box_index, JUSTIFY_RIGHT); X } X } else if (event_id(event) >= (int)' ' && strl < MAX_STRLEN-2) { X slots[box_index].cur_appt->str[strl] = (char)event_id(event); X slots[box_index].cur_appt->str[strl+1] = '\0'; X rewrite_string(box_index, JUSTIFY_RIGHT); X } X /* display cursor at new location */ X text_cursor(box_index); X } else if (event_id(event) == MS_LEFT && event_is_down(event)) { X /* LB down event */ X switch (found_flag) { X case FOUND_SLOT: X break; X case FOUND_MORE: X /* reverse video "more" button */ X pw_rop(main_pixwin, slots[box_index].moreb_pos.left, slots[box_index].moreb_pos.top, X morebutton->pr_width, morebutton->pr_height, PIX_NOT(PIX_DST), X morebutton, 0, 0); X expecting = box_index + (FOUND_MORE<<8); X break; X case FOUND_LARROW: X do_left_arrow(canvas, box_index); X break; X case FOUND_RARROW: X do_right_arrow(canvas, box_index); X break; X } X } else if (event_id(event) == MS_LEFT && event_is_up(event)) { X /* Process an LB up click. */ X i = expecting>>8; X if (expecting && found_flag != i) { X /* return button to normal video */ X if (i == FOUND_MORE) { X /* "more" button */ X i = expecting & 0xff; X pw_rop(main_pixwin, slots[i].moreb_pos.left, slots[i].moreb_pos.top, X morebutton->pr_width, morebutton->pr_height, PIX_SRC, X morebutton, 0, 0); X } X } else { X switch (found_flag) { X case FOUND_SLOT: X make_box_active(box_index); X new_entry = 1; X break; X case FOUND_MORE: X next_appt(box_index, TRUE); X /* normal video "more" button */ X pw_rop(main_pixwin, slots[box_index].moreb_pos.left, slots[box_index].moreb_pos.top, X morebutton->pr_width, morebutton->pr_height, PIX_SRC, X morebutton, 0, 0); X break; X case FOUND_LARROW: X break; X case FOUND_RARROW: X break; X } X } X expecting = 0; X } else if (found_flag == FOUND_SLOT && event_id(event) == MS_MIDDLE) { X /* Process a MB click. */ X if (box_index >= n_tslots) X /* don't flow into notes section */ X box_index = n_tslots - 1; X if (event_is_down(event)) { X /* try to start dragging from here */ X if (slots[box_index].active != ACTIVE) { X start_arrow_box = -1; X return(0); X } X if (slots[box_index].cur_appt->arrows > 0) { X /* remove old arrows and adjust counts */ X (void)deactivate_lower_arrows(box_index); X j = slots[box_index].cur_appt->arrows; X while (j > 0) X slots[box_index+(j--)].count--; X slots[box_index].cur_appt->arrows = 0; X } X prev_box = start_arrow_box = box_index; X } else { X /* end of dragging => end of arrow */ X if (box_index < start_arrow_box || start_arrow_box == -1) { X start_arrow_box = -1; X return(0); X } X if (box_index > start_arrow_box) { X i = start_arrow_box; X slots[i].cur_appt->arrows = box_index - start_arrow_box; X while (++i < box_index) { X slots[i].count++; X if (slots[i].active == INACTIVE) X slots[i].active = ARROW_SHAFT; X /* X * erase arrow shaft on boxes - it will be X * replaced by a real arrowshaft during redraw X */ X pw_rop(main_pixwin, slots[i].slot_pos.left+1, X slots[i].slot_pos.top+1, X dayslot_width-2, dayslot_height-2, X PIX_SRC^PIX_DST, arrowshaft_pr, X 0, 0); X } X slots[i].count++; X if (slots[i].active == INACTIVE) X slots[i].active = ARROW_HEAD; X /* X * erase arrow shaft on last box - it will be X * replaced by an arrowhead during redraw X */ X pw_rop(main_pixwin, slots[i].slot_pos.left+1, X slots[i].slot_pos.top+1, X dayslot_width-2, dayslot_height-2, X PIX_SRC^PIX_DST, arrowshaft_pr, X 0, 0); X } X start_arrow_box = -1; X new_entry = 1; X draw_day_appts(); X } X } else if (found_flag == FOUND_SLOT && event_id(event) == LOC_DRAG) { X /* mouse dragging - is it the middle button ? */ X if ((int)window_get(canvas, WIN_EVENT_STATE, MS_MIDDLE) && start_arrow_box >= 0) { X if (box_index >= n_tslots) X /* don't flow into notes section */ X box_index = n_tslots - 1; X /* X * xor arrow shaft thru current slot so X * we can see where we're dragging X */ X if (box_index > prev_box) { X while (++prev_box <= box_index) { X pw_rop(main_pixwin, slots[prev_box].slot_pos.left+1, X slots[prev_box].slot_pos.top+1, X dayslot_width-2, dayslot_height-2, X PIX_SRC^PIX_DST, arrowshaft_pr, X 0, 0); X } X prev_box = box_index; X } else if (box_index < prev_box && box_index >= start_arrow_box) { X /* going backwards - cleanup as we go */ X while (prev_box > box_index) { X pw_rop(main_pixwin, slots[prev_box].slot_pos.left+1, X slots[prev_box].slot_pos.top+1, X dayslot_width-2, dayslot_height-2, X PIX_SRC^PIX_DST, arrowshaft_pr, X 0, 0); X --prev_box; X } X } X } X } else if (found_flag == FOUND_SLOT && event_id(event) == MS_RIGHT && event_is_down(event)) { X /* Process a RB click. */ X /* X * display popup menu of choices, but first disable X * certain entries if this is a readonly appointment X * or an empty slot. X */ X /* undelete - almost always inactive */ X an_item = menu_get(day_sel_menu, MENU_NTH_ITEM, MUNDELETE); X menu_set(an_item, MENU_INACTIVE, TRUE, 0); X if (!slots[box_index].first) { X /* empty slot. only paste active */ X paste_only(); X } else if (slots[box_index].cur_appt->flags & READONLY) { X /* readonly => paste and copy only */ X paste_only(); X /* copy */ X an_item = menu_get(day_sel_menu, MENU_NTH_ITEM, MCOPY); X menu_set(an_item, MENU_INACTIVE, FALSE, 0); X } else { X /* delete */ X an_item = menu_get(day_sel_menu, MENU_NTH_ITEM, MDELETE); X menu_set(an_item, MENU_INACTIVE, FALSE, 0); X /* cut */ X an_item = menu_get(day_sel_menu, MENU_NTH_ITEM, MCUT); X menu_set(an_item, MENU_INACTIVE, FALSE, 0); X /* copy */ X an_item = menu_get(day_sel_menu, MENU_NTH_ITEM, MCOPY); X menu_set(an_item, MENU_INACTIVE, FALSE, 0); X /* modify */ X an_item = menu_get(day_sel_menu, MENU_NTH_ITEM, MMODIFY); X menu_set(an_item, MENU_INACTIVE, FALSE, 0); X for (aptr=slots[box_index].first; aptr; aptr=aptr->next) X if (aptr->flags & DELETED) { X if (slots[box_index].active != ACTIVE) X /* only paste and undelete */ X paste_only(); X /* undelete */ X an_item = menu_get(day_sel_menu, MENU_NTH_ITEM, MUNDELETE); X menu_set(an_item, MENU_INACTIVE, FALSE, 0); X break; X } X } X i = (int) menu_show(day_sel_menu, canvas, event, 0); X if (i > 0) X switch (i) { X case MDELETE: X delete_appt(box_index, canvas); X break; X case MCUT: X cut_appt(box_index, canvas); X break; X case MCOPY: X copy_appt(box_index); X break; X case MPASTE: X paste_appt(box_index); X break; X case MMODIFY: X modify_appt(box_index, canvas); X break; X case MUNDELETE: X undelete_appt(box_index); X break; X } X if (new_entry) { X close_day(); X draw_day(); /* redraw display */ X } X } else X window_default_event_proc(canvas, event, 0); X X} X X/* make "paste" the only active menu entry */ Xpaste_only() X{ X Menu_item an_item; X X /* delete */ X an_item = menu_get(day_sel_menu, MENU_NTH_ITEM, MDELETE); X menu_set(an_item, MENU_INACTIVE, TRUE, 0); X /* cut */ X an_item = menu_get(day_sel_menu, MENU_NTH_ITEM, MCUT); X menu_set(an_item, MENU_INACTIVE, TRUE, 0); X /* copy */ X an_item = menu_get(day_sel_menu, MENU_NTH_ITEM, MCOPY); X menu_set(an_item, MENU_INACTIVE, TRUE, 0); X /* modify */ X an_item = menu_get(day_sel_menu, MENU_NTH_ITEM, MMODIFY); X menu_set(an_item, MENU_INACTIVE, TRUE, 0); X} X X/* draw (or erase) text cursor in a day slot */ Xtext_cursor(slotno) Xint slotno; X{ X int strl, x; X X strl = strlen(&slots[slotno].cur_appt->str[slots[slotno].cur_appt->sindex]); X if (strl > (day_message_size-1)) { X pw_write(main_pixwin, slots[slotno].slot_pos.right, slots[slotno].slot_pos.bottom-4, X 8, 8, PIX_SRC^PIX_DST, &tri_right_pr, 0, 0); X } else { X x = slots[slotno].slot_pos.left + strl * font->pf_defaultsize.x; X pw_write(main_pixwin, x, slots[slotno].slot_pos.bottom-4, X 16, 16, PIX_SRC^PIX_DST, &tri_up_pr, 0, 0); X } X old_slot = slotno; X} X X/* make slot active */ Xmake_box_active(bi) Xint bi; X{ X add_to_slot(bi, NULL, TRUE); X fill_appt(bi); X rewrite_string(bi, JUSTIFY_LEFT); X text_cursor(bi); X} X X/* activate a hidden appt and make it visible */ Xint Xactivate_slot(bi, dpyflag) Xint bi; Xint dpyflag; X{ X int n, e_slot; X X if (slots[bi].count <= 0) X /* nothing to activate */ X return(0); X if (slots[bi].cur_appt == NULL) { X /* may be hidden arrows */ X /* find appt that they came from so we can see if X * it should be arrow shaft or arrow head X */ X n = bi; X while (--n >= 0 && slots[n].active != ACTIVE) X ; X if (n >= 0) { X e_slot = n + slots[n].cur_appt->arrows; X if (e_slot < bi) X /* no arrows here to show */ X return(0); X while (++n < e_slot && slots[n].active != ACTIVE) X slots[n].active = ARROW_SHAFT; X if (slots[n].active != ACTIVE) X slots[n].active = ARROW_HEAD; X } else X /* no active appt above */ X return(0); X } else { X /* there's a real appt hidden */ X slots[bi].active = ACTIVE; X if (slots[bi].cur_appt->arrows > 0) { X e_slot = bi + slots[bi].cur_appt->arrows; X while (++bi < e_slot && slots[bi].active != ACTIVE) X slots[bi].active = ARROW_SHAFT; X if (slots[bi].active != ACTIVE) X slots[bi].active = ARROW_HEAD; X } X } X if (dpyflag) X draw_day_appts(); /* redraw display */ X return(1); X} X X/* clears a day slot */ Xdeactivate_slot(bi, dpyflag) Xint bi; X{ X slots[bi].active = INACTIVE; X if (!dpyflag) X return; X /* erase text cursor at old location */ X if (old_slot >= 0) { X text_cursor(old_slot); X old_slot = -1; X } X /* erase displayed slot */ X if (!ymd_compare(current, today)) X pw_write(main_pixwin, slots[bi].slot_pos.left, slots[bi].slot_pos.top, X dayslot_width, dayslot_height, PIX_SRC, timeslot_td_pr, 0, 0); X else X pw_write(main_pixwin, slots[bi].slot_pos.left+1, slots[bi].slot_pos.top+1, X dayslot_width-2, dayslot_height-2, PIX_CLR, NULL, 0, 0); X} X X/* returns pointer to slot containing arrow head */ Xint Xdeactivate_lower_arrows(bi, dpyflag) Xint bi; X{ X while (bi < N_SLOTS-1) { X bi++; X if (slots[bi].active != ARROW_SHAFT && X slots[bi].active != ARROW_HEAD) X return(bi-1); X slots[bi].active = INACTIVE; X if (!dpyflag) X continue; X /* erase displayed slot */ X if (!ymd_compare(current, today)) X pw_write(main_pixwin, slots[bi].slot_pos.left, slots[bi].slot_pos.top, X dayslot_width, dayslot_height, PIX_SRC, timeslot_td_pr, 0, 0); X else X pw_write(main_pixwin, slots[bi].slot_pos.left+1, slots[bi].slot_pos.top+1, X dayslot_width-2, dayslot_height-2, PIX_CLR, NULL, 0, 0); X } X} X X/* fill in appt struct with current info */ Xfill_appt(bi) Xint bi; X{ X int s_hour, s_minute, n_arrows; X X slots[bi].cur_appt->year = current.tm_year; X slots[bi].cur_appt->month = current.tm_mon; X slots[bi].cur_appt->day = current.tm_mday; X slots[bi].cur_appt->arrows = 0; X slots[bi].cur_appt->flags = slots[bi].cur_appt->repeat = 0; X slots[bi].cur_appt->lookahead = slots[bi].cur_appt->sindex = 0; X if (bi >= n_tslots) { X /* notes section */ X slots[bi].cur_appt->hour = 99; X slots[bi].cur_appt->minute = 0; X slots[bi].cur_appt->flags = A_NOTE; X } else { X /* regular appt */ X slots[bi].cur_appt->hour = bi/2 + START_HOUR; X slots[bi].cur_appt->minute = (bi % 2) * 30; X } X slots[bi].cur_appt->str[0] = '\0'; X} X X/* X * Display delete popup window to let user choose delete mode for X * recurring appts (delete this one only or delete all), otherwise, X * just wipe it out with no options. X */ Xdelete_appt(bi, canvas) Xint bi; XCanvas canvas; X{ X Rect *canvas_r; X int top, left, width, height; X X if (slots[bi].cur_appt->flags & READONLY) { X err_rpt("Can't delete a read-only appt", NON_FATAL); X return; X } X if (slots[bi].cur_appt->flags & (REPEAT|ALL_YEARS|ALL_MONTHS|ALL_DAYS)) { X attr_bi = bi; /* set global index for notify func */ X X /* get x,y position of canvas window on the screen so we X * can center popup window in it. X */ X canvas_r = (Rect *) window_get(canvas, WIN_RECT); X panel_set(del_choice_pi, PANEL_CHOICE_STRINGS, X "Delete this occurrance only", X "Delete all occurrances", 0, X PANEL_CLIENT_DATA, 0, X 0); X window_fit(del_panel); X window_fit(del_frame); X width = (int) window_get(del_frame, WIN_WIDTH); X height = (int) window_get(del_frame, WIN_HEIGHT); X left = canvas_r->r_left + (canvas_r->r_width - width) / 2; X top = canvas_r->r_top + (canvas_r->r_height - height) / 2; X window_set(del_frame, WIN_X, left, WIN_Y, top, 0); X panel_set_value(del_choice_pi, 0); X X window_loop(del_frame); /* let user select things */ X } else { X cut_delete(bi); X new_entry = 1; X } X} X Xcut_appt(bi, canvas) Xint bi; XCanvas canvas; X{ X Rect *canvas_r; X int top, left, width, height; X int i; X X /* cut (delete) current entry, saving the info on the "shelf" */ X if (slots[bi].cur_appt->flags & READONLY) { X err_rpt("Can't cut a read-only appt", NON_FATAL); X return; X } X shelf_appt = *slots[bi].cur_appt; X if (slots[bi].cur_appt->flags & (REPEAT|ALL_YEARS|ALL_MONTHS|ALL_DAYS)) { X attr_bi = bi; /* set global index for notify func */ X X /* get x,y position of canvas window on the screen so we X * can center popup window in it. X */ X canvas_r = (Rect *) window_get(canvas, WIN_RECT); X panel_set(del_choice_pi, PANEL_CHOICE_STRINGS, X "Move this occurrance only", X "Move all occurrances", 0, X PANEL_CLIENT_DATA, 1, X 0); X window_fit(del_panel); X window_fit(del_frame); X width = (int) window_get(del_frame, WIN_WIDTH); X height = (int) window_get(del_frame, WIN_HEIGHT); X left = canvas_r->r_left + (canvas_r->r_width - width) / 2; X top = canvas_r->r_top + (canvas_r->r_height - height) / 2; X window_set(del_frame, WIN_X, left, WIN_Y, top, 0); X panel_set_value(del_choice_pi, 0); X X window_loop(del_frame); /* let user select things */ X } else { X cut_delete(bi); X new_entry = 1; X } X} X Xcut_delete(bi) Xint bi; X{ X int j; X struct appt_entry *aptr, *cptr, *optr; X X cptr = slots[bi].cur_appt; X slots[bi].count--; X deactivate_slot(bi, TRUE); X if ( (j = cptr->arrows) > 0) { X /* remove old arrows and adjust counts */ X (void) deactivate_lower_arrows(bi, TRUE); X while (j > 0) X slots[bi+(j--)].count--; X } X if (slots[bi].cur_appt == slots[bi].first) { X /* displaying first entry in list */ X /* see if there's any more */ X if (slots[bi].first->next) X slots[bi].first = slots[bi].first->next; X else { X /* last one */ X slots[bi].first = NULL; X slots[bi].active = INACTIVE; X } X slots[bi].cur_appt = slots[bi].first; X } else { X /* not first, so find previous one to this */ X for (aptr=slots[bi].first; slots[bi].cur_appt!=aptr; optr=aptr,aptr=aptr->next) X ; X slots[bi].cur_appt = optr->next = aptr->next; X if (!optr->next) X slots[bi].cur_appt = slots[bi].first; X } X free(cptr); X (void)activate_slot(bi, TRUE); /* show any hidden appts */ X} X Xcopy_appt(bi) Xint bi; X{ X /* copy current entry, saving the info on the "shelf" */ X shelf_appt = *slots[bi].cur_appt; X} X Xpaste_appt(bi) Xint bi; X{ X int j; X X /* insert the saved entry (if any) */ X if (shelf_appt.str[0] == '\0') { X err_rpt("nothing to paste", NON_FATAL); X return; X } X shelf_appt.year = current.tm_year; X shelf_appt.month = current.tm_mon; X shelf_appt.day = current.tm_mday; X if (bi >= N_TSLOTS) { X /* notes section */ X shelf_appt.hour = 99; X shelf_appt.minute = 0; X /* just in case converting from time to note */ X shelf_appt.flags |= A_NOTE; X } else { X /* regular appt */ X shelf_appt.hour = bi/2 + START_HOUR; X shelf_appt.minute = (bi % 2) * 30; X /* just in case converting from note to time */ X shelf_appt.flags &= ~MARKED_NOTE; X } X add_to_slot(bi, &shelf_appt, TRUE); X new_entry = 1; X} X X/* X * Display attributes popup window to let user modify X * various appointment options (such as repeat interval, X * etc.) X */ Xmodify_appt(bi, canvas) Xint bi; XCanvas canvas; X{ X Rect *canvas_r; X int top, left, width, height; X X if (slots[bi].cur_appt->flags & READONLY) { X err_rpt("Can't modify a read-only appt", NON_FATAL); X return; X } X attr_bi = bi; /* set global index for notify func */ X set_attr(); /* set panel item current values */ X X /* get x,y position of canvas window on the screen so we X * can center this one in it. X */ X canvas_r = (Rect *) window_get(canvas, WIN_RECT); X width = (int) window_get(attr_frame, WIN_WIDTH); X height = (int) window_get(attr_frame, WIN_HEIGHT); X left = canvas_r->r_left + (canvas_r->r_width - width) / 2; X top = canvas_r->r_top + (canvas_r->r_height - height) / 2; X window_set(attr_frame, WIN_X, left, WIN_Y, top, 0); X X window_loop(attr_frame); /* let user select things */ X window_set(attr_frame, WIN_SHOW, FALSE, 0); X} X X/* undelete a recurring appointment for this day */ X/* we only get here if a deleted appt exits */ Xundelete_appt(bi) Xint bi; X{ X struct appt_entry *aptr, *optr; X X /* search list to find deleted entry */ X for (optr=aptr=slots[bi].first; aptr; optr=aptr,aptr=aptr->next) X if (aptr->flags & DELETED) X break; X if (aptr == slots[bi].first) X slots[bi].first = aptr->next; X else X optr->next = aptr->next; X slots[bi].count++; X if (slots[bi].active == INACTIVE) { X slots[bi].cur_appt = slots[bi].first; X (void)activate_slot(bi, TRUE); X } X free(aptr); X new_entry = 1; X} X Xset_attr() X{ X int everyx_val = 0, whichwk_val = 0; X char str[5]; X struct appt_entry *apt = slots[attr_bi].cur_appt; X X panel_set_value(repeat_pi, ""); /* set default */ X panel_set_value(remind_pi, ""); /* set default */ X if (apt->flags & ALL_DAYS) X everyx_val |= 0x1; X if (apt->flags & ALL_MONTHS) X everyx_val |= 0x4; X if (apt->flags & ALL_YEARS) X everyx_val |= 0x8; X if (apt->flags & EVERY_SOMEDAY) { X everyx_val |= 0x2; X whichwk_val = apt->repeat; X panel_set(repeat_pi, PANEL_SHOW_ITEM, FALSE, 0); X panel_set(whichwk_pi, PANEL_SHOW_ITEM, TRUE, 0); X } else { X if (apt->repeat) { X sprintf(str, "%d", apt->repeat); X panel_set_value(repeat_pi, str); X } X panel_set(whichwk_pi, PANEL_SHOW_ITEM, FALSE, 0); X panel_set(repeat_pi, PANEL_SHOW_ITEM, TRUE, 0); X } X panel_set_value(everyx_pi, everyx_val); X panel_set_value(whichwk_pi, whichwk_val); X if (apt->flags & LOOKAHEAD) { X sprintf(str, "%d", apt->lookahead); X panel_set_value(remind_pi, str); X } X panel_set_value(marked_pi, (apt->flags & MARKED ? 1 : 0)); X if (apt->flags & A_NOTE) X panel_set(marked_pi, PANEL_SHOW_ITEM, TRUE, 0); X else X panel_set(marked_pi, PANEL_SHOW_ITEM, FALSE, 0); X} X X/* "more" button selected. Display next appt in rotation. */ Xnext_appt(bi, dpyflag) Xint bi; Xint dpyflag; X{ X if (slots[bi].active == ACTIVE) { X deactivate_slot(bi, dpyflag); X if (slots[bi].cur_appt->arrows > 0) X (void)deactivate_lower_arrows(bi, dpyflag); X } else X /* must have arrows displayed */ X (void)deactivate_lower_arrows(bi, dpyflag); X X if (slots[bi].cur_appt == NULL) X /* end of the chain */ X slots[bi].cur_appt = slots[bi].first; X else X /* activate next in chain */ X slots[bi].cur_appt = slots[bi].cur_appt->next; X /* make sure it is not a deleted one */ X if (chk_deleted(bi)) X next_appt(bi, dpyflag); /* try next in chain */ X else if (!activate_slot(bi, dpyflag)) X next_appt(bi, dpyflag); /* try next in chain */ X} X X/* check to see if current is deleted */ Xint Xchk_deleted(bi) Xint bi; X{ X int found = 0; X struct appt_entry *aptr; X X if (slots[bi].cur_appt == NULL) X return(0); X if (slots[bi].cur_appt->flags & DELETED) X return(1); X /* run through the list to see if there are any deleted */ X for (aptr=slots[bi].first; aptr; aptr=aptr->next) X if (aptr->flags & DELETED) { X found = 1; X break; X } X /* now see if the current one matches */ X if (found && !strcmp(aptr->str, slots[bi].cur_appt->str)) X return(1); X X return(0); X} X X/* left scroll arrow selected */ Xdo_left_arrow(canvas, bi) XCanvas canvas; Xint bi; X{ X struct timeval timeout; X Event event; X int fd, ertn, flags; X X if (slots[bi].active != ACTIVE || strlen(slots[bi].cur_appt->str) < day_message_size) X return; X timeout.tv_sec = 0L; X timeout.tv_usec = 100000L; /* 1/10 sec */ X fd = (int)window_get(canvas, WIN_FD); X flags = fcntl(fd, F_GETFL, 0); X (void)fcntl(fd, F_SETFL, flags|FNDELAY); X /* reverse video the arrow */ X pw_rop(main_pixwin, slots[bi].larrow_pos.left, slots[bi].larrow_pos.top, X 19, 14, PIX_NOT(PIX_DST), leftarrow, 0, 0); X while (TRUE) { X if (slots[bi].cur_appt->sindex < strlen(slots[bi].cur_appt->str)) { X ++slots[bi].cur_appt->sindex; X rewrite_string(bi, JUSTIFY_INDEX); X /* reverse video the arrow (rewrite changed it) */ X pw_rop(main_pixwin, slots[bi].larrow_pos.left, slots[bi].larrow_pos.top, X 19, 14, PIX_NOT(PIX_DST), leftarrow, 0, 0); X } X /* do this garbage to handle a repeat function */ X (void)select(0, NULL, NULL, NULL, &timeout); X ertn = window_read_event(canvas, &event); X if (ertn != -1 && event_is_up(&event)) X break; X } X /* put arrow back to normal */ X pw_rop(main_pixwin, slots[bi].larrow_pos.left, slots[bi].larrow_pos.top, X 19, 14, PIX_SRC, leftarrow, 0, 0); X (void)fcntl(fd, F_SETFL, flags & ~FNDELAY); X} X X/* right scroll arrow selected */ Xdo_right_arrow(canvas, bi) XCanvas canvas; Xint bi; X{ X struct timeval timeout; X Event event; X int fd, ertn, flags; X X if (slots[bi].active != ACTIVE || strlen(slots[bi].cur_appt->str) < day_message_size) X return; X timeout.tv_sec = 0L; X timeout.tv_usec = 100000L; /* 1/10 sec */ X fd = (int)window_get(canvas, WIN_FD); X flags = fcntl(fd, F_GETFL, 0); X (void)fcntl(fd, F_SETFL, flags|FNDELAY); X /* reverse video the arrow */ X pw_rop(main_pixwin, slots[bi].rarrow_pos.left, slots[bi].rarrow_pos.top, X 19, 14, PIX_NOT(PIX_DST), rightarrow, 0, 0); X while (TRUE) { X if (slots[bi].cur_appt->sindex > 0) { X --slots[bi].cur_appt->sindex; X rewrite_string(bi, JUSTIFY_INDEX); X /* reverse video the arrow (rewrite changed it) */ X pw_rop(main_pixwin, slots[bi].rarrow_pos.left, slots[bi].rarrow_pos.top, X 19, 14, PIX_NOT(PIX_DST), rightarrow, 0, 0); X } X /* do this garbage to handle a repeat function */ X (void)select(0, NULL, NULL, NULL, &timeout); X ertn = window_read_event(canvas, &event); X if (ertn != -1 && event_is_up(&event)) X break; X } X pw_rop(main_pixwin, slots[bi].rarrow_pos.left, slots[bi].rarrow_pos.top, X 19, 14, PIX_SRC, rightarrow, 0, 0); X (void)fcntl(fd, F_SETFL, flags & ~FNDELAY); X} SHAR_EOF if test 27402 -ne "`wc -c < 'devent.c'`" then echo shar: error transmitting "'devent.c'" '(should have been 27402 characters)' fi fi # end of overwriting check echo shar: extracting "'dpaint.c'" '(24098 characters)' if test -f 'dpaint.c' then echo shar: will not over-write existing file "'dpaint.c'" else sed 's/^ X//' << \SHAR_EOF > 'dpaint.c' X/* X * $Header: dpaint.c,v 2.2 89/05/10 10:06:20 billr Exp $ X */ X/* X * dpaint.c X * X * Author: Philip Heller, Sun Microsystems. Inc. <terrapin!heller@sun.com> X * X * Original source Copyright (C) 1987, Sun Microsystems, Inc. X * All Rights Reserved X * Permission is hereby granted to use and modify this program in source X * or binary form as long as it is not sold for profit and this copyright X * notice remains intact. X * X * X * Changes/additions by: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM> X * X * Changes and additions Copyright (C) 1988, 1989 Tektronix, Inc. X * All Rights Reserved X * Permission is hereby granted to use and modify the modifications in source X * or binary form as long as they are not sold for profit and this copyright X * notice remains intact. X */ X/*************************************************** X * * X * Artistic routines that draw in the main * X * subwindow for the day display. * X * * X ***************************************************/ X X#include <suntool/sunview.h> X#include <suntool/canvas.h> X#include <ctype.h> X#include <sys/time.h> X#include <stdio.h> X#include "ct.h" X#include "paint.h" X#include "riseset.h" X#define J1970 2440587.5 /* VAX clock Epoch 1970 Jan 1 (0h UT) */ X X#ifndef NO_SUN_MOON Xextern Frame mframe, sframe; Xextern Canvas mcanvas, scanvas; Xextern Panel_item mdate_pi, sdate_pi; X#endif Xextern Pixrect *leftarrow, *rightarrow; Xextern Pixrect *arrowshaft_pr, *arrowhead_pr; Xextern int day_message_size; Xextern char riseset_buf[][64]; Xextern int old_slot; Xextern int show_future; Xextern char *index(); X Xstruct tm save_day; Xstruct appt_entry future[MAX_FUTURE_ENTRIES]; Xint findex = 0; /* index into struct future array */ X X/* X * This one draws the current selected day in the X * main subwindow. X */ X Xdraw_day() X{ X draw_day1(); X draw_future_appts(); X#ifndef NO_SUN_MOON X if (sframe) X write_sun_data(); X if (mframe) X write_moon_data(); X#endif X} X X/* X * Draw main day page without future appts or Sun/Moon data X */ Xdraw_day1() X{ X lock_cursors(); X fix_current_day(); X working(TRUE); X pw_batch_on(main_pixwin); X draw_day_outline(); X pw_batch_off(main_pixwin); X get_day_appts(); X working(FALSE); X pw_batch_on(main_pixwin); X draw_day_appts(); X pw_batch_off(main_pixwin); X day_is_open = TRUE; X unlock_cursors(); X} X X/* X * Utility for draw_day ... draws the outline of a day. X */ Xdraw_day_outline() X{ X char timestring[6], daystring[31], buf[64], *src; X int x, y, starty, i, d; X Rect *rect; X X /* First erase the window. */ X rect = (Rect *) window_get(canvas, WIN_RECT); X pw_writebackground(main_pixwin, 0, 0, X rect->r_width, rect->r_height, PIX_CLR); X old_slot = -1; /* text cursor no longer displayed */ X X /* Calculate coords of top-left corner of big box. */ X x = (rect->r_width - dayslot_width) / 2; X starty = y = (rect->r_height - (N_SLOTS * dayslot_height)) / 2; X X /* Format daystring to say, for example, */ X /* Tuesday, March 12, 1985 */ X sprintf(daystring, "%s %s %d, %d", X daynames[current.tm_wday], monthnames[current.tm_mon], X current.tm_mday, 1900 + current.tm_year); X pw_text(main_pixwin, (rect->r_width - bigfont->pf_defaultsize.x*strlen(daystring))/2, starty/2 + 7, X PIX_SRC, bigfont, daystring); X X for (i=0; i<N_SLOTS; i++) { /* Init and draw each 30 minute slot. */ X slots[i].slot_pos.top = y; X slots[i].slot_pos.left = x; X slots[i].slot_pos.bottom = y + dayslot_height + 1; X slots[i].slot_pos.right = x + dayslot_width + 1; X slots[i].moreb_pos.top = y; X slots[i].moreb_pos.left = rect->r_width - 8 - morebutton->pr_size.x; X slots[i].moreb_pos.bottom = y + morebutton->pr_size.y; X slots[i].moreb_pos.right = rect->r_width - 8; X slots[i].larrow_pos.top = slots[i].slot_pos.top+(dayslot_height-leftarrow->pr_size.y)/2; X slots[i].larrow_pos.left = slots[i].slot_pos.right + 8; X slots[i].larrow_pos.bottom = slots[i].larrow_pos.top + leftarrow->pr_size.y; X slots[i].larrow_pos.right = slots[i].larrow_pos.left + leftarrow->pr_size.x; X slots[i].rarrow_pos.top = slots[i].larrow_pos.top; X slots[i].rarrow_pos.left = slots[i].larrow_pos.right + 8; X slots[i].rarrow_pos.bottom = slots[i].larrow_pos.bottom; X slots[i].rarrow_pos.right = slots[i].rarrow_pos.left + rightarrow->pr_size.x; X if (!ymd_compare(current, today)) X pw_write(main_pixwin,x,y,dayslot_width,dayslot_height,PIX_SRC,timeslot_td_pr,0,0); X else X pw_write(main_pixwin,x,y,dayslot_width,dayslot_height,PIX_SRC,timeslot_pr,0,0); X if (i < n_tslots) { X /* display time */ X sprintf(timestring, "%2d:%s", X (START_HOUR+(i/2))%12 == 0 ? 12 : (START_HOUR+(i/2))%12, X i%2 == 0 ? "00" : "30"); X } else if (i == n_tslots) { X sprintf(timestring, "Notes"); X } else { X sprintf(timestring, " "); X } X pw_text(main_pixwin,x-8*font->pf_defaultsize.x,y+font->pf_defaultsize.y,PIX_SRC,font,timestring); X y += dayslot_height - 1; X } X X pw_vector(main_pixwin,x,starty,x+dayslot_width-1,starty,PIX_SET,1); X pw_vector(main_pixwin,x,y,x+dayslot_width-1,y,PIX_SET,1); X y += (dayslot_height - 1) * 2; X sprintf(buf, "Day of year: %d -- %d days remaining", X day_of_year((double)current.tm_mday, current.tm_mon+1, current.tm_year), X days_remaining_in_year((double)current.tm_mday, current.tm_mon+1, current.tm_year)); X pw_text(main_pixwin, x, y, PIX_SRC, font, buf); X sun_moon_buttons(TRUE); X print_button(TRUE); X} X X X/* X * Fills in appointments for the day. X * The ".tmp.aptsXXXXX" file is filled out X * with all the lines from the ".appointments" file X * which do not pertain to the current day. X */ Xget_day_appts() X{ X FILE *apts, *temp_apts; X int slotno, n_arrows, i; X int read_stat; X struct appt_entry appt; X struct appt_entry *nappt, *aptr; X char buf[MAX_STRLEN], *sptr; X X if ((apts = fopen(apts_pathname, "r")) == NULL) X err_rpt("can't open appointments file", FATAL); X X if (!read_only) X if ((temp_apts = fopen(tmpapts_pathname, "w")) == NULL) X err_rpt("can't open temp file for writing", FATAL); X X for (i=0; i<N_SLOTS; i++) { /* init each slot */ X slots[i].active = INACTIVE; X slots[i].count = 0; X slots[i].cur_appt = NULL; X slots[i].first = NULL; X } X First = current; X findex = 0; X X#ifndef NO_HOLIDAYS X /* X * First check to see if the user has selected any holiday X * options and add them in. X */ X if (a_dates(&appt, holiday_a)) X add_note(&appt); X if (c_dates(&appt, holiday_c)) X add_note(&appt); X working(FALSE); X if (i = i_dates(&appt, holiday_i)) X if (i == 2) { X /* two notes in one */ X strcpy(buf, appt.str); X /* look for \n */ X sptr = index(appt.str, '\n'); X *sptr = '\0'; X add_note(&appt); X /* now second half of string in the next note */ X strcpy(appt.str, &buf[(int)(sptr-appt.str)+1]); X add_note(&appt); X } else X add_note(&appt); X working(TRUE); X if (j_dates(&appt, holiday_j)) X add_note(&appt); X if (s_dates(&appt, holiday_s)) X add_note(&appt); X#endif X X /* X * now go thru the appointments file X */ X while ((read_stat=get_aentry(apts, &appt)) != EOF) { X if (read_stat) X continue; /* read error (ignore) */ X if (appt.flags & A_COMMENT) { X if (put_aentry(temp_apts, &appt)) { X /* write error */ X break; X } X continue; X } X current.tm_year = appt.year; X current.tm_mon = appt.month; X current.tm_mday = appt.day; X if (appt.flags & ALL_YEARS) X current.tm_year = First.tm_year; X if (appt.flags & ALL_MONTHS) X current.tm_mon = First.tm_mon; X if (appt.flags & ALL_DAYS) X current.tm_mday = First.tm_mday; X else if (appt.flags & EVERY_SOMEDAY) { X if (Pickday(appt.flags) == First.tm_wday) { X if (chk_week(appt.repeat, First.tm_mday)) X current.tm_mday = First.tm_mday; X } X } else if (appt.flags & REPEAT) { X while (ymd_compare(current, First) < 0) { X current.tm_mday += appt.repeat; X fix_current_day(); X } X } X if (ymd_compare(current, First) == 0) { X /* if it's for this day, fill in slot info */ X if (appt.flags & A_NOTE) X /* notes section */ X add_note(&appt); X else { X /* regular appointment */ X slotno = (appt.hour-START_HOUR) * 2 + appt.minute / 30; X if (slotno < 0) X slotno = 0; X if (slotno >= n_tslots) X slotno = n_tslots - 1; X /* add this appt to the list of appts for the slot */ X /* and update all the reference counts */ X add_to_slot(slotno, &appt, FALSE); X } X } else if (appt.flags & LOOKAHEAD) { X /* This lookahead appt was not for today, so X * put it in the temp file. X */ X if (put_aentry(temp_apts, &appt)) { X /* write error */ X break; X } X if (appt.flags & EVERY_SOMEDAY) { X /* find next occurance of this appt */ X /* starting from the current day */ X current.tm_mday = First.tm_mday; X fix_current_day(); X find_date(&appt); /* may modify current */ X } X if (ymd_compare(current, First) > 0) { X /* this appt is happening in X * the future, so remind us of it if X * it is within the lookahead window. X */ X save_day = current; X current.tm_mday -= appt.lookahead; X fix_current_day(); X if (ymd_compare(current, First) <=0) { X /* save this one for the future popup window */ X if (findex > MAX_FUTURE_ENTRIES-1) { X err_rpt("Too many future reminders", NON_FATAL); X continue; X } X future[findex] = appt; X /* fix up ymd */ X future[findex].year = save_day.tm_year; X future[findex].month = save_day.tm_mon; X future[findex].day = save_day.tm_mday; X ++findex; X } X } X } else { /* line is not for today */ X /* copy it to temp file */ X if (put_aentry(temp_apts, &appt)) { X /* write error */ X break; X } X } X } X if (!read_only) { X if (ferror(temp_apts)) X err_rpt("write on temp file failed", FATAL); X fclose(temp_apts); X } X fclose(apts); X current = First; X fix_current_day(); X} X X X/* check for match on weekly re-ocurring appts */ Xchk_week(repeat, curday) Xint repeat, curday; X{ X int weeknr = 0; X X if ((repeat & ALL_WEEKS) == ALL_WEEKS) X return(1); /* every week */ X if ((repeat & LAST_WEEK) && ((curday+7) > monthlength(current.tm_mon))) X return(1); /* last week in month */ X X while (curday > 7) { X /* find which week this day is in */ X curday -= 7; X weeknr++; X } X if (repeat & (0x1<<weeknr)) X return(1); X X return(0); /* no match */ X} X X X/* X * get date of next occurrance of a weekly repeated appt X * (it may bridge into next week, month or year) X */ Xfind_date(appt) Xstruct appt_entry *appt; X{ X struct tm save; X X save = current; X /* set current to match dow of repeated appt */ X current.tm_mday += Pickday(appt->flags) - current.tm_wday; X fix_current_day(); X if (ymd_compare(current, save) < 0) { X /* already happened, so start looking next week */ X current.tm_mday += 7; X fix_current_day(); X } X /* search for first matching week */ X while (!chk_week(appt->repeat, current.tm_mday)) { X current.tm_mday += 7; X fix_current_day(); X } X /* now check to make sure this is legal, i.e. there X * were no month or year restrictions X */ X if ((!(appt->flags & ALL_YEARS) && current.tm_year != save.tm_year) X || (!(appt->flags & ALL_MONTHS) && current.tm_mon != save.tm_mon)) X /* invalid date, due to month or year wrap */ X current = save; X} X X X/* add a note to the current day */ Xadd_note(appt) Xstruct appt_entry *appt; X{ X int slotno; X X /* auto-hunt for free note slot */ X for (slotno=n_tslots; slotno<N_SLOTS; slotno++) X if (slots[slotno].active == INACTIVE) X break; X if (slotno == N_SLOTS) { X /* overflow of notes field, so X * add to last note field list X */ X slotno = N_SLOTS - 1; X } X add_to_slot(slotno, appt, FALSE); X} X X/* draw in todays appointments */ Xdraw_day_appts() X{ X int slotno = 0; X X while (slotno < N_SLOTS) { X if (slots[slotno].count > 0) { X switch (slots[slotno].active) { X case ACTIVE: X rewrite_string(slotno, JUSTIFY_LEFT); X break; X case ARROW_SHAFT: X draw_arrowshaft(slotno); X break; X case ARROW_HEAD: X draw_arrowhead(slotno); X break; X case INACTIVE: X break; X } X more_check(slotno); X } X ++slotno; X } X} X X/* Blacks out day-slot and then re-writes string. */ Xrewrite_string(bi, justify) Xint bi, justify; X{ X char slot_str[MAX_STRLEN]; X char *ptr; X int strl, *iptr; X X strl = strlen(slots[bi].cur_appt->str); X iptr = &slots[bi].cur_appt->sindex; X if (strl < day_message_size) { X *iptr = 0; /* just in case */ X strcpy(slot_str, slots[bi].cur_appt->str); X /* erase any previously existing scroll arrows */ X pw_writebackground(main_pixwin, slots[bi].larrow_pos.left, X slots[bi].larrow_pos.top, slots[bi].rarrow_pos.right-slots[bi].larrow_pos.left, X slots[bi].larrow_pos.bottom-slots[bi].larrow_pos.top, X PIX_CLR); X } else { X if (justify == JUSTIFY_RIGHT) { X /* show trailing part */ X ptr = &slots[bi].cur_appt->str[strl - day_message_size + 1]; X *iptr = strl - day_message_size + 1; X strcpy(slot_str, ptr); X } else { X /* show leading or indexed part */ X if (justify == JUSTIFY_LEFT) X *iptr = 0; X if (*iptr > (strl - day_message_size + 1)) X *iptr = strl - day_message_size + 1; X if (strlen(&slots[bi].cur_appt->str[*iptr]) >= day_message_size-1) { X strncpy(slot_str, &slots[bi].cur_appt->str[*iptr], day_message_size-1); X slot_str[day_message_size-1] = '\0'; X } else X strcpy(slot_str, &slots[bi].cur_appt->str[*iptr]); X } X /* display scroll arrows */ X pw_write(main_pixwin, slots[bi].larrow_pos.left, X slots[bi].larrow_pos.top, leftarrow->pr_size.x, X leftarrow->pr_size.y, PIX_SRC, leftarrow, 0, 0); X pw_write(main_pixwin, slots[bi].rarrow_pos.left, X slots[bi].rarrow_pos.top, rightarrow->pr_size.x, X rightarrow->pr_size.y, PIX_SRC, rightarrow, 0, 0); X } X pw_write(main_pixwin, slots[bi].slot_pos.left+1, slots[bi].slot_pos.top+1, X dayslot_width-2, dayslot_height-2, PIX_SET, NULL, 0, 0); X pw_text(main_pixwin, slots[bi].slot_pos.left+5, slots[bi].slot_pos.top+font->pf_defaultsize.y, X PIX_NOT(PIX_SRC), font, slot_str); X} X X/* display "more" button if necessary */ Xmore_check(slotno) Xint slotno; X{ X int x, y, w; X X x = morebutton->pr_size.x; X y = morebutton->pr_size.y; X X /* clear any previous button that may be there */ X pw_write(main_pixwin, slots[slotno].moreb_pos.left, slots[slotno].moreb_pos.top, X x, y, PIX_CLR, NULL, 0, 0); X /* button displayed when more than 1 reference X * and at least one real appt for this slot. X */ X if (slots[slotno].count > 1 && slots[slotno].first) X /* display more button to right of slot */ X pw_write(main_pixwin, slots[slotno].moreb_pos.left, slots[slotno].moreb_pos.top, X x, y, PIX_SRC, morebutton, 0, 0); X} X Xdraw_arrowshaft(i) Xint i; X{ X pw_rop(main_pixwin, slots[i].slot_pos.left+1, slots[i].slot_pos.top+1, X dayslot_width-2, dayslot_height-2, PIX_SRC|PIX_DST, arrowshaft_pr, 0, 0); X slots[i].active = ARROW_SHAFT; X} X X X Xdraw_arrowhead(i) Xint i; X{ X pw_rop(main_pixwin, slots[i].slot_pos.left+1, slots[i].slot_pos.top+1, X dayslot_width-2, dayslot_height-2, PIX_SRC|PIX_DST, arrowhead_pr, 0, 0); X slots[i].active = ARROW_HEAD; X} X X/* X * Routine to create popup window with future appts shown in it X */ Xdraw_future_appts() X{ X if (show_future && findex && (ymd_compare(current, today) == 0)) { X create_future_popup(); X } else { X /* nothing to show */ X /* destroy future appts popup, if it exists */ X if (fframe) { X window_destroy(fframe); X fframe = 0; X } X } X} X X/* X * Add an appointment entry pointed to by aptr to the day slot X * specified by slotno. This routine is also used by paste() X * when copying an entry off the save shelf. If dpyflag is true, X * then any deactivated slots are cleared on the display (used by X * paste). Also used to add a deleted entry for a specific day. X */ Xadd_to_slot(slotno, aptr, dpyflag) Xint slotno; Xstruct appt_entry *aptr; Xint dpyflag; X{ X struct appt_entry *nappt, *optr; X int n_arrows, n, nbi, found = 0, i; X int deactivate_lower_arrows(); X X if ((nappt = (struct appt_entry *)malloc(sizeof(struct appt_entry))) == NULL) X err_rpt("out of memory", FATAL); X if (aptr == NULL) { X /* fill in some needed fields */ X nappt->arrows = nappt->flags = 0; X nappt->sindex = 0; X nappt->str[0] = '\0'; X } else X *nappt = *aptr; X nappt->next = NULL; X /* add appt to list of appts for this slot */ X if (slots[slotno].first == NULL) { X slots[slotno].first = nappt; X slots[slotno].cur_appt = nappt; X } else { X /* search for end of list */ X for (optr=slots[slotno].first;optr->next;optr=optr->next) X ; X optr->next = nappt; X } X /* make sure it doesn't extend too far and truncate if neccessary */ X if (slotno >= n_tslots) X nappt->arrows = 0; /* force notes to have no arrows */ X else if ((slotno + nappt->arrows) >= n_tslots) X nappt->arrows = n_tslots - slotno - 1; /* truncate */ X n_arrows = nappt->arrows; X if (nappt->flags & DELETED) { X /* look for matching non-deleted appt in list */ X for (optr=slots[slotno].first;optr;optr=optr->next) X if (!strcmp(nappt->str, optr->str) && !(optr->flags & DELETED)) { X found = 1; X break; X } X if (found && slots[slotno].cur_appt == optr) { X /* the deleted appt is the current one */ X /* if it's active, undisplay it and display X * next one in list (if any) X */ X if (slots[slotno].active == ACTIVE) { X if (slots[slotno].count > 1) X /* there's another one here */ X next_appt(slotno, dpyflag); X else { X deactivate_slot(slotno, dpyflag); X if (slots[slotno].cur_appt->arrows > 0) X (void)deactivate_lower_arrows(slotno, dpyflag); X } X /* adjust reference counts */ X slots[slotno].count--; X i = 1; X while (i <= n_arrows) { X if (--(slots[slotno+i].count) > 0) X /* try to activate any hidden ones */ X (void)activate_slot(slotno+i, dpyflag); X ++i; X } X } else { X /* currently inactive */ X /* set current to next one in the list */ X if (optr->next) X slots[slotno].cur_appt = optr->next; X else X slots[slotno].cur_appt = slots[slotno].first; X while (n_arrows >= 0) X slots[slotno+(n_arrows--)].count--; X } X } else { X /* just adjust the counts */ X while (n_arrows >= 0) X slots[slotno+(n_arrows--)].count--; X } X } else { X /* look for matching deleted appt in list */ X for (optr=slots[slotno].first;optr;optr=optr->next) X if (!strcmp(nappt->str, optr->str) && optr->flags & DELETED) { X found = 1; X break; X } X if (found) { X /* just adjust reference counts and return */ X while (n_arrows >= 0) X slots[slotno+(n_arrows--)].count++; X return; X } X /* X * Make sure there are no overlaps with the appt we X * are adding. If there are, hide the overlapping appt. X */ X nbi = slotno; X do { X if (slots[nbi].active == ACTIVE) { X deactivate_slot(nbi, dpyflag); X if (slots[nbi].cur_appt->arrows > 0) X nbi = deactivate_lower_arrows(nbi, dpyflag); X } else if (slots[nbi].active != INACTIVE) X nbi = deactivate_lower_arrows(nbi, dpyflag); X while (++nbi <= slotno+n_arrows) X if (slots[nbi].active == ACTIVE) X break; X } while (nbi <= slotno + n_arrows); X /* set current one to the new one */ X slots[slotno].cur_appt = nappt; X /* now go back and put in the info for the appt we're inserting */ X slots[slotno].active = ACTIVE; X slots[slotno].count++; X if (n_arrows > 0) { X slots[slotno+n_arrows].count++; X slots[slotno+n_arrows].active = ARROW_HEAD; X while (--n_arrows > 0) { X slots[slotno+n_arrows].count++; X slots[slotno+n_arrows].active = ARROW_SHAFT; X } X } X } X if (dpyflag) X draw_day_appts(); /* redraw display */ X} X X X#ifndef NO_SUN_MOON X/* X * write sun data to the popup canvas X */ Xwrite_sun_data() X{ X int x, y, height; X char buf[64]; X Pixwin *spixwin; X Rect *rect; X struct timeval tp; X double jdays, secs, offset; X double julian_day(); X X /* first erase the window. */ X spixwin = (Pixwin *)canvas_pixwin(scanvas); X rect = (Rect *) window_get(scanvas, WIN_RECT); X pw_writebackground(spixwin, 0, 0, X rect->r_width, rect->r_height, PIX_CLR); X X x = font->pf_defaultsize.x; X height = y = font->pf_defaultsize.y; X X gettimeofday(&tp, 0); X if (ymd_compare(current, today) == 0) { X /* use current time */ X write_times(); X panel_set(sdate_pi, PANEL_LABEL_STRING, riseset_buf[B_DMY], 0); X y += 11 * height; X } else { X /* convert today's date to approx. seconds from 1-1-1970 */ X jdays = julian_day((double)today.tm_mday, today.tm_mon+1, today.tm_year+1900) - J1970; X /* seconds from 00:00 GMT to now */ X offset = tp.tv_sec - (jdays * 24. * 3600.); X /* convert this date to approx. seconds from 1-1-1970 */ X jdays = julian_day((double)current.tm_mday, current.tm_mon+1, current.tm_year+1900) - J1970; X /* seconds to the same time on selected day */ X secs = (jdays * 24.0 * 3600.) + offset; X riseset((long)secs); X panel_set(sdate_pi, PANEL_LABEL_STRING, riseset_buf[B_DMY], 0); X pw_text(spixwin, x, y, PIX_SRC, font, riseset_buf[B_JLD]); X y += height; X } X sprintf(buf, "Sun Rise (today): %s", riseset_buf[B_SRD]); X pw_text(spixwin, x, y, PIX_SRC, font, buf); X y += height; X sprintf(buf, "Sun Set (today): %s", riseset_buf[B_SSD]); X pw_text(spixwin, x, y, PIX_SRC, font, buf); X y += height; X sprintf(buf, "Sun Rise (tomorrow): %s", riseset_buf[B_SRT]); X pw_text(spixwin, x, y, PIX_SRC, font, buf); X y += height; X sprintf(buf, "Sun Set (tomorrow): %s", riseset_buf[B_SST]); X pw_text(spixwin, x, y, PIX_SRC, font, buf); X} X X/* X * write sun time data to the popup canvas X */ Xwrite_times() X{ X int x, y, height; X Pixwin *spixwin; X struct timeval tp; X X /* only update these if displaying today's page */ X if (ymd_compare(current, today) != 0) X return; X X spixwin = (Pixwin *)canvas_pixwin(scanvas); X X x = font->pf_defaultsize.x; X y = height = font->pf_defaultsize.y; X X gettimeofday(&tp, 0); X riseset(tp.tv_sec); X pw_text(spixwin, x, y, PIX_SRC, font, riseset_buf[B_GMT]); X y += height; X pw_text(spixwin, x, y, PIX_SRC, font, riseset_buf[B_TDT]); X y += height; X pw_text(spixwin, x, y, PIX_SRC, font, riseset_buf[B_LCT]); X y += height; X pw_text(spixwin, x, y, PIX_SRC, font, riseset_buf[B_LMT]); X y += height; X pw_text(spixwin, x, y, PIX_SRC, font, riseset_buf[B_GST]); X y += height; X pw_text(spixwin, x, y, PIX_SRC, font, riseset_buf[B_LST]); X y += height; X pw_text(spixwin, x, y, PIX_SRC, font, riseset_buf[B_JLD]); X y += height; X pw_text(spixwin, x, y, PIX_SRC, font, riseset_buf[B_LHA]); X y += height; X pw_text(spixwin, x, y, PIX_SRC, font, riseset_buf[B_SDE]); X y += height; X pw_text(spixwin, x, y, PIX_SRC, font, riseset_buf[B_SAZ]); X y += height; X pw_text(spixwin, x, y, PIX_SRC, font, riseset_buf[B_SEL]); X} X X/* X * write moon data to the popup canvas X */ Xwrite_moon_data() X{ X int x, y, height; X char buf[64]; X Pixwin *mpixwin; X Rect *rect; X struct timeval tp; X double jdays, secs, offset; X double julian_day(); X X /* first erase the window. */ X mpixwin = (Pixwin *)canvas_pixwin(mcanvas); X rect = (Rect *) window_get(mcanvas, WIN_RECT); X pw_writebackground(mpixwin, 0, 0, X rect->r_width, rect->r_height, PIX_CLR); X X x = font->pf_defaultsize.x; X y = height = font->pf_defaultsize.y; X X gettimeofday(&tp, 0); X if (ymd_compare(current, today) == 0) { X /* use current time */ X riseset(tp.tv_sec); X moon_data(tp.tv_sec); X } else { X /* convert today's date to approx. seconds from 1-1-1970 */ X jdays = julian_day((double)today.tm_mday, today.tm_mon+1, today.tm_year+1900) - J1970; X /* seconds from 00:00 GMT to now */ X offset = tp.tv_sec - (jdays * 24. * 3600.); X /* convert this date to seconds from 1-1-1970 */ X jdays = julian_day((double)current.tm_mday, current.tm_mon+1, current.tm_year+1900) - J1970; X /* seconds to the same time on selected day */ X secs = (jdays * 24.0 * 3600.) + offset; X riseset((long)secs); X moon_data((long)secs); X } X panel_set(mdate_pi, PANEL_LABEL_STRING, riseset_buf[B_DMY], 0); X y = 6 * height; X sprintf(buf, "Moon Rise (today): %s", riseset_buf[B_MRD]); X pw_text(mpixwin, x, y, PIX_SRC, font, buf); X y += height; X sprintf(buf, "Moon Set (today): %s", riseset_buf[B_MSD]); X pw_text(mpixwin, x, y, PIX_SRC, font, buf); X y += height; X sprintf(buf, "Moon Rise (tomorrow): %s", riseset_buf[B_MRT]); X pw_text(mpixwin, x, y, PIX_SRC, font, buf); X y += height; X sprintf(buf, "Moon Set (tomorrow): %s", riseset_buf[B_MST]); X pw_text(mpixwin, x, y, PIX_SRC, font, buf); X} X#endif /* NO_SUN_MOON */ SHAR_EOF if test 24098 -ne "`wc -c < 'dpaint.c'`" then echo shar: error transmitting "'dpaint.c'" '(should have been 24098 characters)' fi fi # end of overwriting check echo shar: extracting "'holidays.c'" '(9579 characters)' if test -f 'holidays.c' then echo shar: will not over-write existing file "'holidays.c'" else sed 's/^ X//' << \SHAR_EOF > 'holidays.c' X/* X * $Header: holidays.c,v 2.1 89/05/09 14:19:10 billr Exp $ X */ X/* X * holidays.c X * X * Author: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM> X * (based on a test driver by R.P.C. Rodgers) X * X * Copyright (C) 1989, Tektronix, Inc. All Rights Reserved X * X * Permission is hereby granted to use and modify this code in source X * or binary form as long as it is not sold for profit and this copyright X * notice remains intact. X */ X/* X * functions from datelib (by R.P.C. Rodgers) X */ X#include "ct.h" /* for the NO_HOLIDAYS #define */ X#ifndef NO_HOLIDAYS X X#include <sys/time.h> X Xdouble election_day(); /* Secular US holidays */ X Xdouble autumn_equinox(), /* Astronomical events */ X summer_solstice(), X vernal_equinox(), X winter_solstice(); X Xdouble ascension_day(), /* Christian holidays */ X ash_wednesday(), X corpus_christi(), X easter(), X easter_monday(), X easter_offset(), X first_sunday_advent(), X first_sunday_lent(), X fourth_sunday_lent(), X good_friday(), X maundy_thursday(), X palm_sunday(), X passion_sunday(), X rogation_sunday(), X septuagesima(), X sexagesima(), X quinquagesima(), X second_sunday_lent(), X shrove_monday(), X shrove_tuesday(), X third_sunday_lent(), X trinity_sunday(), X whitsunday(); X Xdouble islamic_new_year(), /* Islamic holidays */ X muharram_9(), X muharram_10(), X muharram_16(), X eid_i_milad_un_nabi(), X jumada_al_akhir_23(), X shab_e_miraj(), X shab_e_barat(), X shab_e_qadr(), X ramadan(), X eid_al_fitr(), X dhul_hijja_9(), X eid_al_adha(), X ghadir(); X Xdouble chanukah(), /* Jewish holidays */ X passover(), X passover_offset(), X purim(), X rosh_hashanah(), X shavuot(), X simchat_torah(), X sukkot(), X yom_kippur(); X Xint check_date(); X Xextern struct tm current; /* current day displayed from calentool */ Xint marked_note; X Xint Xa_dates(appt, flag) Xstruct appt_entry *appt; Xint flag; X{ X /* X * Astromonical Events X */ X if (!flag) X return(0); X marked_note = flag - 1; X if (check_date(appt, "Vernal Equinox", vernal_equinox, TRUE)) X return(1); X if (check_date(appt, "Summer Solstice", summer_solstice, TRUE)) X return(1); X if (check_date(appt, "Autumn Equinox", autumn_equinox, TRUE)) X return(1); X if (check_date(appt, "Winter Solstice", winter_solstice, TRUE)) X return(1); X return(0); X} X Xint Xc_dates(appt, flag) Xstruct appt_entry *appt; Xint flag; X{ X /* X * Christian holidays X */ X if (!flag) X return(0); X marked_note = flag - 1; X if (check_date(appt, "Septuagesima Sunday", septuagesima, FALSE)) X return(1); X if (check_date(appt, "Sexagesima Sunday", sexagesima, FALSE)) X return(1); X if (check_date(appt, "Quinquagesima Sunday", quinquagesima, FALSE)) X return(1); X if (check_date(appt, "Shrove Monday", shrove_monday, FALSE)) X return(1); X if (check_date(appt, "Shrove Tuesday (Mardi Gras)", shrove_tuesday, FALSE)) X return(1); X if (check_date(appt, "Ash Wednesday", ash_wednesday, FALSE)) X return(1); X if (check_date(appt, "First Sunday in Lent", first_sunday_lent, FALSE)) X return(1); X if (check_date(appt, "Second Sunday in Lent", second_sunday_lent, FALSE)) X return(1); X if (check_date(appt, "Third Sunday in Lent", third_sunday_lent, FALSE)) X return(1); X if (check_date(appt, "Fourth Sunday in Lent", fourth_sunday_lent, FALSE)) X return(1); X if (check_date(appt, "Passion Sunday", passion_sunday, FALSE)) X return(1); X if (check_date(appt, "Palm Sunday", palm_sunday, FALSE)) X return(1); X if (check_date(appt, "Maundy Thursday", maundy_thursday, FALSE)) X return(1); X if (check_date(appt, "Good Friday", good_friday, FALSE)) X return(1); X if (check_date(appt, "Easter", easter, FALSE)) X return(1); X if (check_date(appt, "Easter Monday (Canada)", easter_monday, FALSE)) X return(1); X if (check_date(appt, "Rogation Sunday", rogation_sunday, FALSE)) X return(1); X if (check_date(appt, "Ascension Day", ascension_day, FALSE)) X return(1); X if (check_date(appt, "Whitsunday", whitsunday, FALSE)) X return(1); X if (check_date(appt, "Trinity Sunday", trinity_sunday, FALSE)) X return(1); X if (check_date(appt, "Corpus Christi", corpus_christi, FALSE)) X return(1); X if (check_date(appt, "First Sunday in Advent", first_sunday_advent, FALSE)) X return(1); X return(0); X} X Xint Xi_dates(appt, flag) Xstruct appt_entry *appt; Xint flag; X{ X double day, date1, date2; X int ndates, myear1, myear2=0; X int month, year; X char buf[16]; X X /* X * Islamic holidays X */ X if (!flag) X return(0); X marked_note = flag - 1; X if (check_idate(appt, "Muharram 1, %d A.H.: Islamic New Year", islamic_new_year)) X return(1); X if (check_idate(appt, "Muharram 9, %d A.H.: Day of fasting", muharram_9)) X return(1); X if (check_idate(appt, X "Muharram 10, %d A.H.: Deliverance of Moses from the Pharoah (for Shia Islam, martyrdom of Husain)", muharram_10)) X return(1); X if (check_idate(appt, "Muharram 16, %d A.H. (Imamat Day; Ismaili Khoja)", muharram_16)) X return(1); X if (check_idate(appt, "Rabi I 12, %d A.H. (Eid-i-Milad-un-Nabi: The Prophet's Birthday)", eid_i_milad_un_nabi)) X return(1); X if (check_idate(appt, "Jumada al-Akhir 23, %d A.H. (Birth of Agha Khan IV, Ismaili)", jumada_al_akhir_23)) X return(1); X if (check_idate(appt, "Rajab 27, %d A.H. (Shab-e-Mi'raj: The Prophet's Ascension)", shab_e_miraj)) X return(1); X if (check_idate(appt, "Shaban 15, %d A.H. (Shab-e-Bara't: Night, followed by day of fasting)", shab_e_barat)) X return(1); X if (check_idate(appt, "Ramadan 1, %d A.H. (Fasting month begins)", ramadan)) X return(1); X if (check_idate(appt, "Ramadan 27, %d A.H. (Shab-e-Qadr: Night vigil))", shab_e_qadr)) X return(1); X if (check_idate(appt, "Shawwal 1, %d A.H. (Eid-al-Fitr: Day of Feast)", eid_al_fitr)) X return(1); X if (check_idate(appt, "Dhul-Hijj 9, %d A.H. (Day of Pilgrimage at Arafat, Mecca)", dhul_hijja_9)) X return(1); X if (check_idate(appt, "Dhul-Hijj 10, %d A.H. (Eid-al-Azha: Day of Abraham's Sacrifice)", eid_al_adha)) X return(1); X if (check_idate(appt, "Dhul-Hijj 18, %d A.H. (Ghadir: Ali's Nomination)", ghadir)) X return(1); X return(0); X} X Xint Xj_dates(appt, flag) Xstruct appt_entry *appt; Xint flag; X{ X char buf[24]; X int jyear; X X /* X * Jewish holidays X */ X if (!flag) X return(0); X marked_note = flag - 1; X if (check_jdate(appt, "Purim", purim)) X return(1); X if (check_jdate(appt, "First day of Passover", passover)) X return(1); X if (check_jdate(appt, "Shavuot", shavuot)) X return(1); X if (check_jdate(appt, "Rosh Hashanah (Jewish New Year)", rosh_hashanah)) X return(1); X if (check_jdate(appt, "Yom Kippur", yom_kippur)) X return(1); X if (check_jdate(appt, "First day of Sukkot (9 days)", sukkot)) X return(1); X if (check_jdate(appt, "Simchat Torah", simchat_torah)) X return(1); X if (check_jdate(appt, "First day of Chanukah (8 days)", chanukah)) X return(1); X return(0); X} X Xint Xs_dates(appt, flag) Xstruct appt_entry *appt; Xint flag; X{ X /* X * SECULAR US HOLIDAYS X * [Holidays specified as a given date (e.g. July 4) or as X * a known nth mday of a month (e.g. 2nd Monday) are not X * calculated here. They are available from one of the X * auxillary date files.] X */ X if (!flag) X return(0); X marked_note = flag - 1; X if (check_date(appt, "Election Day", election_day, FALSE)) X return(1); X return(0); X} X X/* X * check for gregorian (i.e. US secular & Christian) holidays X */ Xint Xcheck_date(aptr, str, func, timeflag) Xstruct appt_entry *aptr; Xchar *str; Xdouble (*func)(); Xint timeflag; X{ X int month, year; X double day, hday; X char *julian_time(); X X hday = (*func)(current.tm_year+1900); X gregorian_date(&day, &month, &year, hday); X if (current.tm_mon == --month && current.tm_mday == (int)day) { X aptr->year = current.tm_year; X aptr->month = current.tm_mon; X aptr->day = current.tm_mday; X aptr->arrows = aptr->repeat = aptr->lookahead = 0; X aptr->flags = (A_NOTE | READONLY); X if (marked_note) X aptr->flags |= MARKED; X strcpy(aptr->str, str); X if (timeflag) { X strcat(aptr->str, julian_time(hday)); X strcat(aptr->str, " GMT"); X } X return(1); X } X return(0); X} X X/* X * check for Islamic holidays X */ Xint Xcheck_idate(aptr, str, func) Xstruct appt_entry *aptr; Xchar *str; Xint (*func)(); X{ X double day, date1, date2; X int nr_dates, year1, year2; X int month, year; X int match = 0; X X (void)(*func)(current.tm_year+1900, &nr_dates, &date1, &date2, &year1, &year2); X gregorian_date(&day, &month, &year, date1); X if (current.tm_mon == --month && current.tm_mday == (int)day) X match = 1; X else if (nr_dates == 2) { X gregorian_date(&day, &month, &year, date2); X if (current.tm_mon == --month && current.tm_mday == (int)day) X match = 2; X } X if (match) { X aptr->year = current.tm_year; X aptr->month = current.tm_mon; X aptr->day = current.tm_mday; X aptr->arrows = aptr->repeat = aptr->lookahead = 0; X aptr->flags = (A_NOTE | READONLY); X if (marked_note) X aptr->flags |= MARKED; X if (match == 1) X /* match was on first year */ X sprintf(aptr->str, str, year1); X else X /* must have been second year */ X sprintf(aptr->str, str, year2); X return(1); X } X return(0); X} X X/* X * check for Jewish holidays X */ Xint Xcheck_jdate(aptr, str, func) Xstruct appt_entry *aptr; Xchar *str; Xdouble (*func)(); X{ X int month, year, jyear; X double hday, day; X char buf[32]; X X hday = (*func)(current.tm_year+1900, &jyear); X gregorian_date(&day, &month, &year, hday); X if (current.tm_mon == --month && current.tm_mday == (int)day) { X X aptr->year = current.tm_year; X aptr->month = current.tm_mon; X aptr->day = current.tm_mday; X aptr->arrows = aptr->repeat = aptr->lookahead = 0; X aptr->flags = (A_NOTE | READONLY); X if (marked_note) X aptr->flags |= MARKED; X strcpy(aptr->str, str); X sprintf(buf, " [Jewish year %d]", jyear); X strcat(aptr->str, buf); X return(1); X } X return(0); X} X#endif /* NO_HOLIDAYS */ SHAR_EOF if test 9579 -ne "`wc -c < 'holidays.c'`" then echo shar: error transmitting "'holidays.c'" '(should have been 9579 characters)' fi fi # end of overwriting check # End of shell archive exit 0