v17i098: calentool - day/week/month/year-at-a-glance SunView tool, Part17/23
Bill Randle
billr at saab.CNA.TEK.COM
Sun Apr 7 10:54:00 AEST 1991
Submitted-by: Bill Randle <billr at 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 at 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 at 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 at 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 at 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 at 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 at uunet.uu.net.
More information about the Comp.sources.misc
mailing list