billr@saab.CNA.TEK.COM (Bill Randle) (04/07/91)
Submitted-by: Bill Randle <billr@saab.CNA.TEK.COM> Posting-number: Volume 17, Issue 98 Archive-name: calentool/part17 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 17 (of 23)." # Contents: calentool.c common.c # Wrapped by billr@saab on Thu Mar 28 08:38:28 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'calentool.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'calentool.c'\" else echo shar: Extracting \"'calentool.c'\" \(22129 characters\) sed "s/^X//" >'calentool.c' <<'END_OF_FILE' X/* X * $Header: calentool.c,v 2.5 91/03/27 16:44:59 billr Exp $ X */ X/* X * calentool.c X * X * calentool - a year/month/week/day-at-a-glance calendar for Sun workstations. 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, 1991 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#include <stdio.h> X#include <suntool/sunview.h> X#include <suntool/panel.h> X#include <suntool/seln.h> X#include <sys/time.h> X#include <sys/file.h> X#include <signal.h> X#include "ct.h" X Xextern Pixfont *font, *sfont; Xextern char apts_pathname[], tmpapts_pathname[]; Xextern char clockstr[]; Xextern char *smonthnames[]; Xextern Panel_item clock_pi; Xextern Frame fframe; Xextern Panel panel; Xextern int day_is_open; X#ifndef NO_SUN_MOON Xextern Frame sframe; X#endif X XFrame frame = 0; XPixwin *main_pixwin; Xstruct tm today, current; Xstruct tm First, Last; Xstruct tm olddate, closedate; Xint mainsw_state, selected_type; Xint x_coord, y_coord, startx, starty; Xint read_only; Xint nr_weekdays, dayslot_width, day_message_size, n_tslots, n_slots; Xint week_message_size, weekslot_width, weekslot_height, dayslot_height; Xint ybox_height, ybox_width; Xstruct dayslot *slots; Xstruct rect_limits boxlims[31]; Xstruct rect_limits mboxlims[12]; Xstruct week_arrow week_arrows[6]; Xstruct weekrect week_boxes[7]; XPixrect *ic_pr, *rev_ic_pr, *na_ic_pr; XRect *closed_rect; XRect ilabel_rect = {1, 67, 62, 9}; /* location of timestring under icon */ Xchar *mailto = NULL; Xint one_based = 0, new_entry = 0, version2 = 0; Xint otherfile = 0; Xchar *othername; Xint beep = 0, show_time = 0, beep_open = 0; Xint include_old = 0, save_old = 0; X#ifndef NO_HOLIDAYS Xint holiday_a = 0, holiday_c = 0, holiday_i = 0; Xint holiday_j = 0, holiday_s = 0; X#endif Xchar *progname; Xstruct itimerval cal_timer; Xint update_interval = 0; Xint show_future = 1; XIcon icon, rev_icon, na_icon; XCursor year_cursor, month_cursor, week_cursor, day_cursor; XCursor wait_cursor; Xchar orig_apts_pathname[160]; Xint orig_ro; Xchar timestr[16], datestr_day[3]; Xstruct pr_prpos where; Xint working_msg; Xint hour24, monday_first, day_first; Xint expire_days = 0; Xint start_hour, end_hour, num_notes; Xint print_dev = PR_DEFAULT; Xint user_font = 0; Xint appt_check_limit, week_ofs = 0; Xint locked = 0; XSeln_client s_client; X Xstatic short icon_data[] = { X#include "std.icon" X}; Xstatic short rev_icon_data[] = { X#include "rev.icon" X}; Xstatic short na_icon_data[] = { X#include "nap.icon" X}; Xmpr_static(ic_mpr, 64, 64, 1, icon_data); Xmpr_static(rev_ic_mpr, 64, 64, 1, rev_icon_data); Xmpr_static(na_ic_mpr, 64, 64, 1, na_icon_data); X Xstatic short year_cursor_data[] = { X#include "year.cursor" X}; Xstatic short month_cursor_data[] = { X#include "month.cursor" X}; Xstatic short week_cursor_data[] = { X#include "week.cursor" X}; Xstatic short day_cursor_data[] = { X#include "day.cursor" X}; Xstatic short wait_cursor_data[] = { X#include <images/hglass.cursor> X}; Xmpr_static(year_cursor_pr, 16, 16, 1, year_cursor_data); Xmpr_static(month_cursor_pr, 16, 16, 1, month_cursor_data); Xmpr_static(week_cursor_pr, 16, 16, 1, week_cursor_data); Xmpr_static(day_cursor_pr, 16, 16, 1, day_cursor_data); Xmpr_static(wait_cursor_pr, 16, 16, 1, wait_cursor_data); X X#ifndef NO_SUN_MOON Xstatic short moon_icon_data[] = { X#include "moony.icon" X}; Xstatic short sun_icon_data[] = { X#include "sunny.icon" X}; Xmpr_static(moon_icon_pr, 64, 64, 1, moon_icon_data); Xmpr_static(sun_icon_pr, 64, 64, 1, sun_icon_data); X#endif X Xstatic short tri_up_data[] = { X#include <images/tri_up.pr> X}; Xmpr_static(tri_up_pr, 16, 16, 1, tri_up_data); X Xstatic short tri_right_data[] = { X#include <images/tri_right.pr> X}; Xmpr_static(tri_right_pr, 16, 16, 1, tri_right_data); X Xchar *strcpy(), *strcat(), *rindex(); Xstatic Notify_value itimer_handler(); XNotify_value leave(); XNotify_value myframe_interposer(); Xvoid sel_func_key_proc(); XSeln_result sel_reply_proc(); X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X int flag, i; X int printit = 0, toolrunning = 1, user_pos = 0; X int printit_dst = 0, limitcheck = -1; X extern char *optarg; X X if (progname = rindex(*argv, '/')) X progname++; X else X progname = *argv; X X /* X * setup defaults which might be changed by command X * line options X */ X nr_weekdays = NR_WEEKDAYS; X monday_first = MON_FIRST; X day_first = DAY_FIRST; X hour24 = HOUR_24; X start_hour = START_HOUR; X end_hour = END_HOUR; X num_notes = N_NOTESLOTS; X X get_today(); /* initial day is today */ X current = today; X read_only = 0; X working_msg = 0; X X /* X * Check for -p, -P, -m or -M option, which means we don't want X * to create the tool. Also check for -Wp and -Wi so we can supply X * a resonable default if the user doesn't supply one. X */ X i = argc; X while (--i > 0) { X if (!strncmp(argv[i], "-p", 2) || !strncmp(argv[i], "-m", 2) X || !strncmp(argv[i], "-P", 2) || !strncmp(argv[i], "-M", 2)) { X /* standard getopt doesn't allow optional X * arguments, so we do a check here for X * obsolete usage of the -p option X */ X if ((argv[i][1] == 'p' || argv[i][1] == 'P') && X argv[i][2] == '\0') { X fprintf(stderr, "calentool: -p/-P requires a 'd', 'w' or 'm' argument\n"); X exit(1); X } X toolrunning = 0; X } else if (!strcmp(argv[i], "-Wp")) X user_pos = 1; X else if (!strcmp(argv[i], "-Wt")) X user_font = 1; X } X if (toolrunning) { X /* X ** Parse args: window_create must be called before getopt, so X ** it can interpret and extract -W flags for SunView. X */ X frame = window_create(NULL, FRAME, X FRAME_ARGC_PTR_ARGV, &argc, argv, X WIN_ERROR_MSG, X "Can't create base frame. Are you in Suntools?", X 0); X if ((s_client = seln_create(sel_func_key_proc, sel_reply_proc, NULL)) == NULL) X err_rpt("Can't create selection svc client", NON_FATAL); X } X X while ((flag = getopt(argc, argv, "1:2:567bBd:eEf:il:m:M:op:P:rtu:zH:h:wx:T:s:S:N:")) != EOF) X switch (flag) { X case 'f': /* use this file */ X otherfile = 1; X othername = optarg; X break; X X case 'd': /* starting date */ X (void)parse_date(optarg, TRUE); X break; X X case 'r': /* read only file */ X read_only = 1; X break; X X case '1': /* -12 -- 12 hour time */ X if (*optarg == '2') X hour24 = FALSE; X break; X X case '2': /* -24 -- 24 hour time */ X if (*optarg == '4') X hour24 = TRUE; X break; X X case 'e': /* European calendar Mon-Sun */ X monday_first = TRUE; X break; X X case 'E': /* European style */ X monday_first = TRUE; X hour24 = TRUE; X day_first = TRUE; X break; X X case 'p': /* print and exit */ X read_only = 1; X switch (*optarg) { X case 'd': X case 'D': X printit = PRI_DAY; X break; X case 'w': X printit = PRI_WEEK; X week_ofs = 0; X break; X case 'W': X printit = PRI_WEEK; X week_ofs = 1; X break; X case 'm': X case 'M': X printit = PRI_MONTH; X break; X default: X fprintf(stderr, "calentool: unknown print option.", NON_FATAL); X break; X } X if (!printit_dst) X printit_dst = DST_STDOUT; X break; X X case 'P': /* print and exit (ignore some notes) */ X read_only = 1; X switch (*optarg) { X case 'd': X case 'D': X printit = PRI_DAY_XNOTES; X break; X case 'w': X printit = PRI_WEEK_XNOTES; X week_ofs = 0; X break; X case 'W': X printit = PRI_WEEK_XNOTES; X week_ofs = 1; X break; X case 'm': X case 'M': X printit = PRI_MONTH_XNOTES; X break; X default: X fprintf(stderr, "calentool: unknown print option.", NON_FATAL); X break; X } X if (!printit_dst) X printit_dst = DST_STDOUT; X break; X X case 'l': /* appt check limit */ X if (optarg) X limitcheck = atoi(optarg); X else X limitcheck = 0; X break; X X case 'm': /* mail today's appts and exit */ X read_only = 1; X if (!printit) X printit = PRI_DAY; X printit_dst = DST_MAIL; X mailto = optarg; X break; X X case 'M': /* mail today's appts and exit (ignore X some notes) */ X read_only = 1; X if (!printit) X printit = PRI_DAY_XNOTES; X printit_dst = DST_MAIL; X mailto = optarg; X break; X X case 'b': /* beep to console for pending appt */ X beep = 1; X break; X X case 'B': /* beep then open wondow */ X beep_open = 1; X break; X X case 'i': /* include old appt files */ X include_old = 1; X break; X X case 'o': /* save outdated appts to another file */ X save_old = 1; X break; X X case 't': /* display current time under icon */ X show_time = 1; X break; X X case '5': /* Mon - Fri week display */ X nr_weekdays = 5; X break; X X case '6': /* Mon - Sat week display */ X nr_weekdays = 6; X break; X X case '7': /* Sun - Sat (or Mon-Sun) week display */ X nr_weekdays = 7; X break; X X case 'u': /* update interval (in seconds) */ X update_interval = atoi(optarg); X break; X X case 'w': /* display Working! message */ X working_msg = 1; X break; X X case 'x': /* eXpire appts after so many days */ X expire_days = atoi(optarg); X break; X X case 'z': /* zero offset -- new style appts file */ X one_based = 1; X break; X X#ifndef NO_HOLIDAYS X case 'h': X /* show certain holidays */ X switch (*optarg) { X case 'A': X /* all holidays */ X holiday_a = holiday_c = holiday_i = 1; X holiday_j = holiday_s = 1; X break; X case 'a': X /* astronomical events */ X holiday_a = 1; X break; X case 'c': X /* Christian holidays */ X holiday_c = 1; X break; X case 'i': X /* Islamic holidays */ X holiday_i = 1; X break; X case 'j': X /* Jewish holidays */ X holiday_j = 1; X break; X case 's': X /* secular holidays */ X holiday_s = 1; X break; X default: X fprintf(stderr, "calentool: unknown holiday option (must be one of \"Aacijs\")"); X break; X } X break; X X case 'H': X /* show certain holidays day/week display only */ X switch (*optarg) { X case 'A': X /* all holidays */ X holiday_a = holiday_c = holiday_i = 2; X holiday_j = holiday_s = 2; X break; X case 'a': X /* astronomical events */ X holiday_a = 2; X break; X case 'c': X /* Christian holidays */ X holiday_c = 2; X break; X case 'i': X /* Islamic holidays */ X holiday_i = 2; X break; X case 'j': X /* Jewish holidays */ X holiday_j = 2; X break; X case 's': X /* secular holidays */ X holiday_s = 2; X break; X default: X fprintf(stderr, "calentool: unknown holiday option (must be one of \"Aacijs\")"); X break; X } X break; X#else X case 'h': X case 'H': X fprintf(stderr, "calentool: -h and -H options not available\n"); X break; X#endif X case 'T': X if (!strncmp(optarg, "ps", 2)) X print_dev = PR_POSTSCRIPT; X else X print_dev = PR_ASCII; X break; X X case 's': /* start hour */ X start_hour = atoi(optarg); X if (start_hour < 0 || start_hour > 23) X fprintf(stderr, "calentool: start hour must be in the range 0 - 23\n"); X break; X X case 'S': /* Stop (end) hour */ X end_hour = atoi(optarg); X if (end_hour < 1 || end_hour > 24) X fprintf(stderr, "calentool: end hour must be in the range 1 - 24\n"); X break; X X case 'N': /* number of note slots */ X num_notes = atoi(optarg); X break; X X case '?': X default: X fprintf(stderr, "usage: %s [options...]\nwhere <options> are:\n", progname); X fprintf(stderr, " -f <appointment_file>\n"); X fprintf(stderr, " -r // readonly\n"); X fprintf(stderr, " -p <dwWm> // print selected day [d], week [w] or month [m] appts and exit\n"); X fprintf(stderr, " -P <dwWm> // like -p, only don't print marked notes\n"); X fprintf(stderr, " -m <user> // mail selected days appts to <user>\n"); X fprintf(stderr, " -M <user> // like -m, only don't mail marked notes\n"); X fprintf(stderr, " [-5|-6|-7] // 5, 6 or 7-day week display\n"); X fprintf(stderr, " [-12|-24] // 12 or 24 hour time format\n"); X fprintf(stderr, " -d <date> // display appts for <date>\n"); X fprintf(stderr, " -b // beep and display message when appt is pending\n"); X fprintf(stderr, " -B // beep and open window when appt is pending\n"); X fprintf(stderr, " -i // auto-include outdated appts files\n"); X fprintf(stderr, " -l [0|1] // set limit check for appts to include notes\n"); X fprintf(stderr, " -o // create outdated include files\n"); X fprintf(stderr, " -t // display time below icon\n"); X fprintf(stderr, " -u <interval> // time update interval (seconds)\n"); X fprintf(stderr, " -w // display 'Working!' message\n"); X fprintf(stderr, " -e // Mon-Sun week display\n"); X fprintf(stderr, " -E // European options (-e, -24)\n"); X#ifndef NO_HOLIDAYS X fprintf(stderr, " -h <Aacijs> // display selected computed holidays\n"); X fprintf(stderr, " // A=All, a=astronomical, c=Christian,\n"); X fprintf(stderr, " // i=Islamic, j=Jewish, s=secular\n"); X fprintf(stderr, " -H <Aacijs> // like -h, only flag them as marked\n"); X#endif X fprintf(stderr, " -T <printdev> // printer output type for -p and -m options\n"); X fprintf(stderr, " -s <hour> // start hour\n"); X fprintf(stderr, " -S <hour> // stop hour\n"); X fprintf(stderr, " -N <num> // number of note slots\n"); X fprintf(stderr, " -x <days> // expire appts after <days> days\n"); X fprintf(stderr, " -z // conversion flag (see INSTALL)\n"); X fprintf(stderr, " <window_opts> // Suntools -W options\n"); X exit(1); X break; X } X X if (toolrunning) { X (void) notify_set_signal_func(frame, leave, SIGHUP, NOTIFY_ASYNC); X (void) notify_set_signal_func(frame, leave, SIGINT, NOTIFY_ASYNC); X (void) notify_set_signal_func(frame, leave, SIGTERM, NOTIFY_ASYNC); X } X X /* set default printer to something useful */ X if (print_dev == PR_DEFAULT) { X if (printit == PRI_MONTH || printit == PRI_MONTH_XNOTES) X print_dev = PR_POSTSCRIPT; X else X print_dev = PR_ASCII; X } X /* X ** setup number of slots and allocate memory for them X */ X if ( start_hour >= end_hour ) X err_rpt("Start Hour must be less than Stop Hour", FATAL); X n_tslots = (end_hour - start_hour) * 2; X n_slots = n_tslots + num_notes; X appt_check_limit = APPT_CHECK_LIMIT; /* set default */ X if (limitcheck == 0) X appt_check_limit = n_tslots; X else if (limitcheck == 1) X appt_check_limit = n_slots; X /* make room for n_slots dayslot entries and week entries */ X if ((slots = (struct dayslot *)malloc(n_slots* sizeof(struct dayslot))) == NULL) X err_rpt("Can't get enough storage for day slots", FATAL); X for (i=0; i<nr_weekdays; i++) X if ((week_boxes[i].weekslots = X (struct dayslot *)malloc(n_slots*sizeof(struct dayslot))) == NULL) X err_rpt("Can't get enough storage for week slots", FATAL); X X /* X ** Find the calendar file, etc. X */ X if (do_files(FALSE)) X /* can't open (or create) appts file */ X exit(1); X strcpy(orig_apts_pathname, apts_pathname); X orig_ro = read_only; X get_printer(); X X if (printit) { X print_apts(printit, printit_dst); X if (save_old || expire_days) { X read_only = 0; /* allow updates */ X expire(expire_days); X } X exit(0); X } X X get_fonts(); X X if (!update_interval) { X if (!strcmp(UPDATE_RATE, "minute")) X update_interval = 60; X else if (!strcmp(UPDATE_RATE, "second")) X update_interval = 1; /* check in 1 sec */ X else { X err_rpt("unknown update interval, defaulting to seconds", NON_FATAL); X update_interval = 1; /* check in 1 sec */ X } X } X X /* create the cursors */ X year_cursor = cursor_create(CURSOR_IMAGE, &year_cursor_pr, X CURSOR_XHOT, 7, CURSOR_YHOT, 7, X CURSOR_OP, PIX_SRC^PIX_DST, X 0); X month_cursor = cursor_create(CURSOR_IMAGE, &month_cursor_pr, X CURSOR_XHOT, 7, CURSOR_YHOT, 7, X CURSOR_OP, PIX_SRC^PIX_DST, X 0); X week_cursor = cursor_create(CURSOR_IMAGE, &week_cursor_pr, X CURSOR_XHOT, 7, CURSOR_YHOT, 7, X CURSOR_OP, PIX_SRC^PIX_DST, X 0); X day_cursor = cursor_create(CURSOR_IMAGE, &day_cursor_pr, X CURSOR_XHOT, 7, CURSOR_YHOT, 7, X CURSOR_OP, PIX_SRC^PIX_DST, X 0); X wait_cursor = cursor_create(CURSOR_IMAGE, &wait_cursor_pr, X CURSOR_XHOT, 7, CURSOR_YHOT, 7, X CURSOR_OP, PIX_SRC^PIX_DST, X 0); X X /* create the icons */ X icon = icon_create(0); X rev_icon = icon_create(0); X na_icon = icon_create(0); X /* X * make the icon big enough to display the time X * underneath the base icon image if -t option X */ X ic_pr = mem_create(64, (show_time ? 77 : 64), 1); X rev_ic_pr = mem_create(64, (show_time ? 77 : 64), 1); X na_ic_pr = mem_create(64, (show_time ? 77 : 64), 1); X sprintf(datestr_day, "%2d", today.tm_mday); X /* the basic standard icon */ X pr_rop(ic_pr, 0, 0, 64, 64, PIX_SRC, &ic_mpr, 0, 0); X if (show_time) { X /* time string displayed below icon */ X format_icon_time(); X if (update_interval >= 60) { X /* no seconds displayed, adjust label position */ X ilabel_rect.r_left += 2*sfont->pf_defaultsize.x - 2; X ilabel_rect.r_width -= 2*sfont->pf_defaultsize.x; X } X if (!hour24) { X /* am/pm, increase size of label rect */ X ilabel_rect.r_left -= sfont->pf_defaultsize.x; X ilabel_rect.r_width += sfont->pf_defaultsize.x; X } X /* draw a box around the time appendage */ X pr_vector(ic_pr, 0, 64, 63, 64, PIX_SET, 1); X pr_vector(ic_pr, 63, 64, 63, 76, PIX_SET, 1); X pr_vector(ic_pr, 63, 76, 0, 76, PIX_SET, 1); X pr_vector(ic_pr, 0, 76, 0, 64, PIX_SET, 1); X X pr_rop(rev_ic_pr, 0, 0, 64, 77, PIX_SRC, ic_pr, 0, 0); X pr_rop(rev_ic_pr, 0, 0, 64, 64, PIX_SRC, &rev_ic_mpr, 0, 0); X pr_rop(na_ic_pr, 0, 0, 64, 77, PIX_SRC, ic_pr, 0, 0); X pr_rop(na_ic_pr, 0, 0, 64, 64, PIX_SRC, &na_ic_mpr, 0, 0); X } else { X pr_rop(rev_ic_pr, 0, 0, 64, 64, PIX_SRC, &rev_ic_mpr, 0, 0); X pr_rop(na_ic_pr, 0, 0, 64, 64, PIX_SRC, &na_ic_mpr, 0, 0); X } X /* add in the date */ X where.pr = ic_pr; X where.pos.x = 13; X where.pos.y = 49 + 5; X pf_ttext(where, PIX_NOT(PIX_SRC), sfont, datestr_day); X where.pr = na_ic_pr; X pf_ttext(where, PIX_NOT(PIX_SRC), sfont, datestr_day); X where.pr = rev_ic_pr; X pf_ttext(where, PIX_SRC, sfont, datestr_day); X where.pos.x = 39; X where.pr = ic_pr; X pf_ttext(where, PIX_NOT(PIX_SRC), sfont, smonthnames[today.tm_mon]); X where.pr = na_ic_pr; X pf_ttext(where, PIX_NOT(PIX_SRC), sfont, smonthnames[today.tm_mon]); X where.pr = rev_ic_pr; X pf_ttext(where, PIX_SRC, sfont, smonthnames[today.tm_mon]); X (void)icon_init_from_pr(icon, ic_pr); X (void)icon_init_from_pr(rev_icon, rev_ic_pr); X (void)icon_init_from_pr(na_icon, na_ic_pr); X if (show_time) { X /* add label field */ X icon_set(icon, ICON_LABEL_RECT, &ilabel_rect, X ICON_LABEL, timestr, X ICON_FONT, sfont, X 0); X icon_set(rev_icon, ICON_LABEL_RECT, &ilabel_rect, X ICON_LABEL, timestr, X ICON_FONT, sfont, X 0); X icon_set(na_icon, ICON_LABEL_RECT, &ilabel_rect, X ICON_LABEL, timestr, X ICON_FONT, sfont, X 0); X } X X week_message_size = WEEK_MESSAGE_SIZE; X weekslot_width = (font->pf_defaultsize.x * week_message_size) + 6; X dayslot_width = (nr_weekdays - 1) * weekslot_width; X day_message_size = dayslot_width / font->pf_defaultsize.x; X ybox_height = dayslot_height = weekslot_height = font->pf_defaultsize.y + 6; X ybox_width = 3 * font->pf_defaultsize.x; X X init_pixrects(); /* Initialize pictures. */ X X /* Create the rest of the tool */ X if (user_pos) X window_set(frame, X WIN_WIDTH, (nr_weekdays+1)*weekslot_width+40, X WIN_HEIGHT, (n_slots+5)*weekslot_height+72, X FRAME_ICON, icon, X 0); X else X /* supply default position */ X window_set(frame, X WIN_WIDTH, (nr_weekdays+1)*weekslot_width+40, X WIN_HEIGHT, (n_slots+5)*weekslot_height+72, X WIN_X, 100, WIN_Y, 56, X FRAME_ICON, icon, X 0); X X closed_rect = (Rect *)window_get(frame, FRAME_CLOSED_RECT); X create_panel(); X create_main_window(); X create_attr_frame(); /* normally hidden */ X create_del_frame(); /* normally hidden */ X create_file_frame(); /* normally hidden */ X create_date_frame(); /* normally hidden */ X#ifndef NO_PRINTER X create_print_frame(); /* normally hidden */ X#endif X check_calendar(); /* set proper icon */ X X /* interpose on frame events (specifically open/close) */ X (void) notify_interpose_event_func(frame, myframe_interposer, NOTIFY_SAFE); X X timerclear(&(cal_timer.it_interval)); X timerclear(&(cal_timer.it_value)); X cal_timer.it_value.tv_sec = (long)update_interval; X cal_timer.it_value.tv_usec = 0L; X (void) notify_set_itimer_func(frame, itimer_handler, ITIMER_REAL, &cal_timer, NULL); X X window_main_loop(frame); X X (void)leave(); X} X X Xstatic Notify_value Xitimer_handler(me, which) XNotify_client me; Xint which; X{ X static int timeout_cntr = 0; X Icon cur_icon; X X timerclear(&(cal_timer.it_interval)); X timerclear(&(cal_timer.it_value)); X cal_timer.it_value.tv_sec = (long)update_interval; X cal_timer.it_value.tv_usec = 0L; X (void) notify_set_itimer_func(frame, itimer_handler, ITIMER_REAL, &cal_timer, NULL); X get_today(); X /* update date/time displayed in the panel */ X panel_set(clock_pi, PANEL_LABEL_STRING, clockstr, 0); X if (show_time && (int)window_get(frame, FRAME_CLOSED)) X update_icon_time(); X#ifndef NO_SUN_MOON X /* update data in Sun Data frame (if it's open) */ X if (sframe) X write_times(); X#endif X /* only check appointments every TIME_OUT minutes */ X timeout_cntr += update_interval; X#undef TIME_OUT X#define TIME_OUT 1 X if (timeout_cntr/60 < TIME_OUT) X return(NOTIFY_DONE); X timeout_cntr = 0; X /* check todays appointments */ X check_calendar(); X return(NOTIFY_DONE); X} X XNotify_value Xleave(me, signal, when) XNotify_client me; Xint signal; XNotify_signal_mode when; X{ X if (day_is_open) X close_day(); X X /* create outdated include files (if necessary) */ X if (save_old || expire_days) X expire(expire_days); X X /* delete tmp file */ X if (access(tmpapts_pathname, R_OK) == 0 && unlink(tmpapts_pathname) < 0) X perror(tmpapts_pathname); X X seln_destroy(s_client); X exit(0); X /* NOTREACHED */ X return(NOTIFY_DONE); X} END_OF_FILE if test 22129 -ne `wc -c <'calentool.c'`; then echo shar: \"'calentool.c'\" unpacked with wrong size! fi # end of 'calentool.c' fi if test -f 'common.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'common.c'\" else echo shar: Extracting \"'common.c'\" \(29124 characters\) sed "s/^X//" >'common.c' <<'END_OF_FILE' X/* X * $Header: common.c,v 1.2 91/03/27 16:45:05 billr Exp $ X */ X/* X * common.c X * X * Author: by: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM> X * X * Copyright (C) 1988, 1989, 1991 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#include <stdio.h> X#include <ctype.h> X#include <sys/time.h> X#include <sys/types.h> X#include <sys/stat.h> X#include <sys/file.h> X#ifndef CALENCHECK X# include <suntool/sunview.h> X# include <pwd.h> X#endif X#ifndef NO_DEFAULTS X# include <sunwindow/defaults.h> X#endif X#include "ct.h" X Xstruct tm save_day; Xstruct appt_entry future[MAX_FUTURE_ENTRIES]; Xint findex = 0; /* index into struct future array */; Xint day_is_open = 0; /* indicates when slot info is current */ Xchar apts_pathname[160], tmpapts_pathname[160]; Xchar apts_dir[128], lib_dir[128]; Xchar t_title[160]; X Xextern struct tm current, today, First; Xextern struct dayslot *slots; Xextern char apts_pathname[], tmpapts_pathname[]; Xextern char *progname; Xextern char *othername; Xextern int n_slots, n_tslots, read_only, new_entry; Xextern int otherfile, one_based, version2; Xextern int show_future, start_hour; Xextern int mainsw_state; X X#ifndef CALENCHECK Xextern struct tm olddate, closedate; Xextern Frame frame, prompt_frame; Xextern Icon icon, rev_icon, na_icon; Xextern char datestr_day[]; Xextern struct pr_prpos where; Xextern Pixrect *ic_pr, *rev_ic_pr, *na_ic_pr; Xextern int beep, beep_open; Xextern int appt_check_limit; Xextern Pixfont *sfont; Xextern char *smonthnames[]; Xextern char *mailto; Xextern int locked; Xextern char *version(); X#endif X X#ifndef NO_HOLIDAYS Xextern int holiday_a, holiday_c, holiday_i, holiday_j, holiday_s; X Xextern int a_dates(), c_dates(), i_dates(), j_dates(), s_dates(); Xextern struct appt_entry a_appts[], c_appts[]; Xextern struct appt_entry i_appts[], j_appts[]; Xextern struct appt_entry s_appts[]; X#endif Xextern char *strcpy(), *strncpy(), *index(); 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 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 && !found;optr=optr->next) X if (!strcmp(nappt->str, optr->str) X && !(optr->flags & DELETED) X && Repeating(optr->flags)) { 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) { X if (slots[slotno].active > 1) X /* there's another one here */ X next_appt(slotno, dpyflag); X else X deactivate_slot(slotno, dpyflag); X /* adjust reference counts */ X slots[slotno].count--; X slots[slotno].active--; X i = 0; X while (++i <= n_arrows) X --slots[slotno+i].count; 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 /* adjust the counts */ X slots[slotno].active--; X while (n_arrows >= 0) X slots[slotno+(n_arrows--)].count--; X } X } else { X /* just adjust the counts */ X slots[slotno].active--; X while (n_arrows >= 0) X slots[slotno+(n_arrows--)].count--; X } X } else { X /* look for matching deleted appt in list */ X if (Repeating(nappt->flags)) { X for (optr=slots[slotno].first;optr && !found;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 slots[slotno].active++; X while (n_arrows >= 0) X slots[slotno+(n_arrows--)].count++; X return; X } 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 if (slots[slotno].active) X deactivate_slot(slotno, dpyflag); 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].count++; X slots[slotno].active++; X if (n_arrows > 0) { X slots[slotno+n_arrows].count++; X while (--n_arrows > 0) X slots[slotno+n_arrows].count++; X } X } X if (dpyflag) X draw_day_appts(); /* redraw display */ X} X X/* add a note to the current day */ Xadd_note(appt) Xstruct appt_entry *appt; X{ X int slotno, found = 0; X struct appt_entry *optr; X X /* This used to just find a free slot and add the note X * to it. However, with deleted notes we need to find X * the matching slotno (if it exists) to make sure that X * the deleted and non-deleted notes end up in the same X * slot number (so they won't be displayed). X */ X if (appt->flags & DELETED) { X /* look for matching non-deleted note */ X for (slotno=n_tslots; slotno<n_slots && !found; slotno++) { X if (!slots[slotno].active) X break; /* no more notes */ X for (optr=slots[slotno].first;optr;optr=optr->next) { X if (!strcmp(appt->str, optr->str) X && !(optr->flags & DELETED) X && Repeating(optr->flags)) { X found = 1; X break; X } X } X } X } else { X /* look for free slot and/or matching deleted note */ X for (slotno=n_tslots; slotno<n_slots && !found; slotno++) { X if (!slots[slotno].active) X break; /* no more notes */ X for (optr=slots[slotno].first;optr;optr=optr->next) X if (!strcmp(appt->str, optr->str) X && (optr->flags & DELETED) X && Repeating(appt->flags)) { X found = 1; X break; X } X } X } X if (found) X --slotno; /* for loop incremented slotno */ 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/* 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 */ Xint Xget_day_appts() X{ X FILE *apts, *temp_apts; X int slotno, n_arrows, i, j, k; X int read_stat, some_appt = 0; X int runl; 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].count = 0; X slots[i].cur_appt = NULL; X slots[i].first = NULL; X slots[i].active = 0; 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 working(TRUE); X if (holiday_a) { X j = a_dates(holiday_a); X for (k=0; k<j; k++) X if (ymd2_compare(¤t, &a_appts[k]) == 0) { X some_appt |= (holiday_a == 1 ? SOME_MKNOTES : SOME_NOTES); X add_note(&a_appts[k]); X } X } X working(FALSE); X if (holiday_c) { X j = c_dates(holiday_c); X for (k=0; k<j; k++) X if (ymd2_compare(¤t, &c_appts[k]) == 0) { X some_appt |= (holiday_c == 1 ? SOME_MKNOTES : SOME_NOTES); X add_note(&c_appts[k]); X } X } X working(TRUE); X if (holiday_i) { X j = i_dates(holiday_i); X for (k=0; k<j; k++) X if (ymd2_compare(¤t, &i_appts[k]) == 0) { X some_appt |= (holiday_i == 1 ? SOME_MKNOTES : SOME_NOTES); X /* look for \n */ X if ((sptr = index(i_appts[k].str, '\n')) != NULL) { X appt = i_appts[k]; X /* two notes in one */ X strcpy(buf, appt.str); 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(&i_appts[k]); X } X } X working(FALSE); X if (holiday_j) { X j = j_dates(holiday_j); X for (k=0; k<j; k++) X if (ymd2_compare(¤t, &j_appts[k]) == 0) { X some_appt |= (holiday_j == 1 ? SOME_MKNOTES : SOME_NOTES); X add_note(&j_appts[k]); X } X } X working(TRUE); X if (holiday_s) { X j = s_dates(holiday_s); X for (k=0; k<j; k++) X if (ymd2_compare(¤t, &s_appts[k]) == 0) { X some_appt |= (holiday_s == 1 ? SOME_MKNOTES : SOME_NOTES); X add_note(&s_appts[k]); X } X } X working(FALSE); X#endif X X /* X * now go thru the appointments file X */ X while ((read_stat=get_aentry(apts, &appt, FALSE, FALSE, First.tm_mon+1)) != 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_MON_FRI) { X if (First.tm_wday >= MON && First.tm_wday <= FRI) X current.tm_mday = First.tm_mday; X else X current.tm_mday = 0; X } else if (appt.flags & EVERY_SOMEDAY) { X if ((Pickday(appt.flags) == First.tm_wday) X && (chk_week(appt.repeat, First.tm_mday))) { X if (appt.flags & RUN) { X runl = appt.runlength; X find_date(&appt); X while (ymd_compare(current, First) < 0 && --runl) { X current.tm_mday += 7; X find_date(&appt); X } X } else X current.tm_mday = First.tm_mday; X } else X current.tm_mday = 0; X } else if (appt.flags & REPEAT) { X if (appt.flags & RUN) X runl = appt.runlength; X else X runl = 1; X while (ymd_compare(current, First) < 0 && runl) { X if (appt.flags & RUN) X --runl; X if (runl) { X current.tm_mday += appt.repeat; X fix_current_day(); X } 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 if (appt.flags & MARKED) X /* marked note */ X some_appt |= SOME_MKNOTES; X else X /* regular note */ X some_appt |= SOME_NOTES; 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 some_appt |= SOME_APPTS; 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 some_appt |= SOME_FUTURES; 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 orphan_check(); X X return(some_appt); 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 int runl; X X save = current; X fix_current_day(); X /* set current to match dow of repeated appt */ X if (appt->flags & EVERY_MON_FRI) { X if (current.tm_wday == SUN) X current.tm_mday++; X else if (current.tm_wday == SAT) X current.tm_mday += 2; X } else 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 & RUN) && ((!(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 * orphan_check() - check each slot for orphan appointments. Orphans X * are a deleted recurring appointment where it is deleted on a X * specific date and the original appointment no longer exists. X */ Xorphan_check() X{ X int i, n_arrows; X struct appt_entry *aptr, *optr; X X for (i=0; i<n_slots; i++) { X while (slots[i].first != NULL) { X optr = slots[i].first; X if (chk_deleted(&slots[i], optr) == -1) { X /* just adjust the counts */ X n_arrows = optr->arrows; X while (n_arrows >= 0) X slots[i+(n_arrows--)].count++; X slots[i].active++; X if (optr->next) { X if (slots[i].cur_appt == slots[i].first) X slots[i].cur_appt = slots[i].first->next; X slots[i].first = slots[i].first->next; X } else { X /* last one */ X if (slots[i].cur_appt == slots[i].first) X slots[i].cur_appt = NULL; X slots[i].first = NULL; X slots[i].active = 0; X } X free(optr); X new_entry = 1; X } else { X while (aptr = optr->next) { X if (chk_deleted(&slots[i], aptr) == -1) { X /* just adjust the counts */ X n_arrows = aptr->arrows; X while (n_arrows >= 0) X slots[i+(n_arrows--)].count++; X slots[i].active++; X optr->next = aptr->next; X if (slots[i].cur_appt == aptr) X slots[i].cur_appt = aptr->next; X free(aptr); X new_entry = 1; X } else { X optr = aptr; X } X } X break; X } X } X if (chk_deleted(&slots[i], slots[i].cur_appt)) { X next_appt(i, FALSE); X if (slots[i].cur_appt == NULL) X /* only deleted appts, so reset to first */ X slots[i].cur_appt = slots[i].first; X } X } X} X X/* check to see if appt is deleted */ Xint Xchk_deleted(slptr, aptr) Xstruct dayslot *slptr; Xstruct appt_entry *aptr; X{ X int found = 0; X struct appt_entry *optr; X X if (slptr->first == NULL || aptr == NULL) X return(0); X if (aptr->flags & DELETED) { X /* run through the list and look for a matching X * repeating non-deleted entry. If we don't find one, X * this appt is a deleted orphan. X */ X for (optr=slptr->first; optr; optr=optr->next) X if (!(optr->flags & DELETED) && Repeating(optr->flags)) X /* now see if the current one matches */ X if (!strcmp(optr->str, aptr->str)) X return(1); X return(-1); /* orphan */ X } X if (Repeating(aptr->flags)) { X /* run through the list to see if there are any deleted */ X for (optr=slptr->first; optr; optr=optr->next) X if (optr->flags & DELETED) { X /* now see if the current one matches */ X if (!strcmp(optr->str, aptr->str)) X return(1); X } X } X X return(0); X} X X/* X * When timer has expired check to see if we are close to an X * appointment. If so, switch to the other icon so we have a X * visual indication and beep the console (if enabled). X */ Xcheck_calendar() X{ X int appt_pending = 0; /* no appointments pending */ X int slotno = 0; /* start with first timeslot */ X int smin, tmin; X int sno, save_ro; X static int echoed_sno = -1; X static int new_day = 0; X FILE *console; X struct appt_entry *aptr; X struct tm Saveday; X char *getenv(); X static time_t lastmod = (time_t)0; X struct stat stbuf; X#ifndef CALENCHECK X char msgfile[128]; X int some_appts = 0; /* no appointments today */ X static int icon_in_use = STD_ICON; X Icon cur_icon; X FILE *msgf; X#endif X X#ifndef CALENCHECK X if (locked) /* can't change yet */ X return; X lock_cursors(); X locked++; /* make it unique to us */ X strcpy(msgfile, getenv("HOME")); X strcat(msgfile, "/.msgfile"); X#endif X X sno = echoed_sno; /* assume no console echo */ X get_today(); X stat(apts_pathname, &stbuf); X Saveday = current; X /* X * Check to see if we're not displaying today. X * (Or in the case of "calencheck" if the appointments X * file has been modified.) If so, we need to update our X * slot information. X */ X#ifndef CALENCHECK X if ((int)window_get(frame, FRAME_CLOSED) && ymd_compare(closedate, today) != 0) X new_day++; X#endif X if (ymd_compare(current, today) != 0 || new_day) { X if (day_is_open) X close_day(); X current = today; X#ifdef CALENCHECK X new_day++; X#endif X } X if (stbuf.st_mtime > lastmod) { X lastmod = stbuf.st_mtime; X day_is_open = FALSE; /* force reading appts file */ X sno = echoed_sno = -1; X } X if (day_is_open) { X /* slot info is current */ X#ifndef CALENCHECK X unlock_cursors(); X#endif X } else { X#ifdef CALENCHECK X (void)get_day_appts(); X#else X save_ro = read_only; X read_only = 1; /* force read only mode */ X err2console(TRUE); X (void)get_day_appts(); X err2console(FALSE); X#endif X day_is_open = TRUE; X read_only = save_ro; X if (new_day) X sno = echoed_sno = -1; X } X X slotno = (today.tm_hour - start_hour)*2 + today.tm_min/30; X if (slotno < 0) X slotno = 0; X /* our current time (minutes past midnight) */ X tmin = today.tm_hour * 60 + today.tm_min; X if (slots[slotno].count > 0 && slotno < n_tslots) X /* something going on now */ X appt_pending++; X while (slotno < n_tslots) { X if (slots[slotno].count > 0) { X /* convert slotno back to time difference */ X smin = start_hour * 60 + slotno * 30 - tmin; X if (smin < 0) X smin = 0; X if (slots[slotno].active) { X /* get all valid appts at this time */ X for (aptr=slots[slotno].first; aptr; X aptr=aptr->next) X if (!chk_deleted(&slots[slotno], aptr) X && aptr->warn X && (smin <= aptr->warn)) { X sno = slotno; X appt_pending++; X break; X } X if (sno > echoed_sno) X break; X } X } X slotno++; X } X if (!appt_pending) { X#ifndef CALENCHECK X /* X * Is there anything happening today (optionally X * including memos)? X * Don't care about things that happened before now X * so start looking at <slotno>, which is set to X * reflect the current hour (or 0 if before start_hour). X */ X slotno = (today.tm_hour - start_hour)*2 + today.tm_min/30; X if (slotno < 0) X slotno = 0; X /* X * appt_check_limit is typically either "n_tslots" X * or "n_slots" depending on whether we include the X * notes section when indicating that we still have X * appts today. X */ X while (slotno < appt_check_limit) X if (slots[slotno++].count) { X some_appts++; X break; X } X /* maybe change the icon */ X if ((some_appts && (icon_in_use != STD_ICON)) || X (!some_appts && (icon_in_use != NA_ICON))) { X window_set(frame, X FRAME_ICON, (some_appts? X icon : na_icon), X 0); X icon_in_use = some_appts ? STD_ICON : NA_ICON; X } X /* clean out the ~/.msgfile file */ X if (beep && ((msgf = fopen(msgfile, "w")) != NULL)) { X fprintf(msgf, "I'm out running around."); X fclose(msgf); X } X#endif X } else { X /* notify the user via the console (once) ... */ X#ifdef CALENCHECK X if (sno > echoed_sno) { X echoed_sno = sno; X /* get all valid appts at this time */ X for (aptr=slots[sno].first; aptr; aptr=aptr->next) X if (!chk_deleted(&slots[sno], aptr)) { X if (getenv("WINDOW_PARENT") != NULL X && (console = fopen("/dev/console", "w")) != NULL) { X fprintf(console, "<< %s >> %s\n", X progname, aptr->str); X fclose(console); X } else { X fprintf(stderr, "\007\007<< %s >> %s\n", X progname, aptr->str); X } X } X } X#else X if ((beep || beep_open) && sno > echoed_sno) { X echoed_sno = sno; X window_bell(frame); X if (beep_open) { X olddate = Saveday = today; X mainsw_state = DISPLAYING_DAY; X window_set(frame, FRAME_CLOSED, FALSE, 0); X } X if (beep) X if ((console = fopen("/dev/console", "w")) != NULL) { X /* get all valid appts at this time */ X for (aptr=slots[sno].first; aptr; X aptr=aptr->next) X if (!chk_deleted(&slots[sno], aptr)) X fprintf(console, "<< %s >> %s\n", progname, aptr->str); X fclose(console); X } X /* X * also put a copy in ~/.msgfile, in case X * nlock(1) is running X */ X if ((msgf = fopen(msgfile, "w")) != NULL) { X fprintf(msgf, "%s", slots[sno].cur_appt->str); X fclose(msgf); X } X } X /* ... and change the icon */ X if (icon_in_use != REV_ICON) { X window_set(frame, X FRAME_ICON, rev_icon, X 0); X icon_in_use = REV_ICON; X } X#endif X } X#ifdef CALENCHECK X if (new_day) X Saveday = today; X#else X if (new_day && (int)window_get(frame, FRAME_CLOSED)) { X /* update times so that it opens on today */ X closedate = olddate = Saveday = today; X /* update date field of the icons */ X sprintf(datestr_day, "%d", today.tm_mday); X /* replace the date */ X where.pr = ic_pr; X where.pos.x = 13; X where.pos.y = 49 + 5; X pr_rop(where.pr, 14, 47, 10, 8, PIX_CLR, NULL, 0, 0); X pr_rop(where.pr, 40, 47, 16, 8, PIX_CLR, NULL, 0, 0); X pf_ttext(where, PIX_NOT(PIX_SRC), sfont, datestr_day); X where.pr = na_ic_pr; X pr_rop(where.pr, 14, 47, 10, 8, PIX_CLR, NULL, 0, 0); X pr_rop(where.pr, 40, 47, 16, 8, PIX_CLR, NULL, 0, 0); X pf_ttext(where, PIX_NOT(PIX_SRC), sfont, datestr_day); X where.pr = rev_ic_pr; X pr_rop(where.pr, 14, 47, 10, 8, PIX_SET, NULL, 0, 0); X pr_rop(where.pr, 40, 47, 16, 8, PIX_SET, NULL, 0, 0); X pf_ttext(where, PIX_SRC, sfont, datestr_day); X where.pos.x = 39; X where.pr = ic_pr; X pf_ttext(where, PIX_NOT(PIX_SRC), sfont, smonthnames[today.tm_mon]); X where.pr = na_ic_pr; X pf_ttext(where, PIX_NOT(PIX_SRC), sfont, smonthnames[today.tm_mon]); X where.pr = rev_ic_pr; X pf_ttext(where, PIX_SRC, sfont, smonthnames[today.tm_mon]); X icon_set(icon, ICON_IMAGE, ic_pr, 0); X icon_set(rev_icon, ICON_IMAGE, rev_ic_pr, 0); X icon_set(na_icon, ICON_IMAGE, na_ic_pr, 0); X switch (icon_in_use) { X case STD_ICON: X window_set(frame, FRAME_ICON, icon, 0); X break; X case REV_ICON: X window_set(frame, FRAME_ICON, rev_icon, 0); X break; X case NA_ICON: X window_set(frame, FRAME_ICON, na_icon, 0); X break; X } X new_day = 0; X show_future = 1; /* show future appts again */ X } X#endif X#ifndef CALENCHECK X current = Saveday; X err2console(TRUE); X (void)get_day_appts(); X err2console(FALSE); X if (locked == 2) X unlock_cursors(); X#endif X} X Xdo_files(window_prompt) Xint window_prompt; X{ X char *slash, *default_ptr, *envptr; X char buff[80]; X int to_slash, getpid(), fd, errflag, numask; X struct passwd *pw; X struct stat statbuf; X FILE *appts; X char *strcpy(), *rindex(), *getenv(); X X /* the tmp file */ X sprintf(tmpapts_pathname, "/tmp/appts%d", getpid()); X if (otherfile) { X strcpy(apts_pathname, othername); X if ((slash = rindex(apts_pathname, '/')) != NULL) { X to_slash = slash - apts_pathname; X strncpy(apts_dir, apts_pathname, to_slash); X apts_dir[to_slash] = '\0'; X } else { X strcpy(apts_dir, "."); X } X } else { X#ifndef NO_DEFAULTS X if ((default_ptr = defaults_get_string("/CalenTool/Appts", NULL, 0)) != NULL) { X if ((slash = rindex(default_ptr, '/')) != NULL) { X to_slash = slash - default_ptr; X strncpy(apts_dir, default_ptr, to_slash); X apts_dir[to_slash] = '\0'; X } else { X strcpy(apts_dir, "."); X } X } else X#endif X if ((envptr = getenv("CALENTOOL_DIR")) != NULL) { X strcpy(apts_dir, envptr); X#ifndef CALENCHECK X } else if (mailto) { X if ((pw = getpwnam(mailto)) == NULL) X /* no entry */ X exit(1); X envptr = pw->pw_dir; /* home directory */ X strcpy(apts_dir, envptr); X#endif X } else if ((envptr = getenv("HOME")) != NULL) { X strcpy(apts_dir, envptr); X } else { X apts_dir[0] = '\0'; X } X if (*apts_dir) { X /* prepend directory on pathnames */ X sprintf(apts_pathname, "%s/.appointments", apts_dir); X } else { X /* use current directory */ X strcpy(apts_pathname, ".appointments"); X } X } X X /* directory for date/event data files */ X#ifndef NO_DEFAULTS X if ((default_ptr = defaults_get_string("/CalenTool/LibDir", NULL, 0)) != NULL) X strcpy(lib_dir, default_ptr); X else X#endif X strcpy(lib_dir, DATELIB_DIR); X X errflag = 0; X if (access(apts_pathname, R_OK) == -1) { X#ifndef CALENCHECK X if (window_prompt) { X fprintf(stderr, "nonexistant file\n"); X sprintf(buff, "Cannot access calendar file %s - create?", apts_pathname); X create_prompt_frame(buff, TRUE); X if ((int)window_loop(prompt_frame) == 0) { X /* try to create the file */ X fprintf(stderr, "creating file\n"); X if ((fd=open(apts_pathname, O_CREAT|O_RDWR, 0644)) <= 0) { X perror(apts_pathname); X errflag = 1; X fprintf(stderr, "..error\n"); X } else { X if (write(fd, HEADER, sizeof(HEADER)) != sizeof(HEADER)) { X perror("writing header"); X errflag = 1; X } X close(fd); X fprintf(stderr, "..wrote header\n"); X one_based = 1; X } X } else { X fprintf(stderr, "window_ret != 0\n"); X errflag = 1; X } X window_set(prompt_frame, WIN_SHOW, FALSE, 0); X if (errflag) X return(1); X } else { X#endif X fprintf(stderr, "Cannot access calendar file %s - create? ", apts_pathname); X fgets(buff, 80, stdin); X if (buff[0] == 'y' || buff[0] == 'Y') { X if ((fd=open(apts_pathname, O_CREAT|O_RDWR, 0644)) <= 0) { X perror(apts_pathname); X return(1); X } else { X if (write(fd, HEADER, sizeof(HEADER)) != sizeof(HEADER)) { X perror("writing header"); X close(fd); X return(1); X } X close(fd); X one_based = 1; X } X } else X return(1); X } X#ifndef CALENCHECK X } X if (!read_only) X if (access(apts_pathname, W_OK) == -1) X read_only = 1; X /* X * set permissions on tmp file based on .appointments file X * with the expception that we need at least write permission X * for the owner. X */ X (void)stat(apts_pathname, &statbuf); X numask = ~statbuf.st_mode & 0077; /* yes, this is octal 77 */ X (void)umask(numask); X X /* update base frame label, if the tool is running */ X if (frame) { X strcpy(t_title, version()); X if (read_only) X strcat(t_title, " [Read Only]"); X strcat(t_title, " - "); X strcat(t_title, apts_pathname); X window_set(frame, FRAME_LABEL, t_title, 0); X } X#endif X X /* check first line of appts file to see if it is the new style */ X if ((appts = fopen(apts_pathname, "r")) != NULL) { X fgets(buff, 80, appts); X fclose(appts); X if (!strcmp(buff, OHEADER) || !strncmp(buff, HEADER, 18)) { X version2 = 1; X one_based = 1; X } X#ifdef CALENCHECK X else X err_rpt("wrong version appointments file format", FATAL); X#endif X } X X#ifndef CALENCHECK X /* Convert from old format to new. There may some appts files X * that are one-based, but are still old style. These are X * also handled. (Note: for old-style one-based appts files X * the user MUST start calentool with the -z flag.) X */ X if (!version2) X ver1to2(); X#endif X X return(0); X} X END_OF_FILE if test 29124 -ne `wc -c <'common.c'`; then echo shar: \"'common.c'\" unpacked with wrong size! fi # end of 'common.c' fi echo shar: End of archive 17 \(of 23\). cp /dev/null ark17isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 23 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.