mcgrew@dartagnan.rutgers.edu (Charles Mcgrew) (05/28/89)
Submitted-by: Bill Randle <billr@saab.cna.tek.com> Posting-number: Volume 1, Issue 11 Archive-name: calentool/part02 #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # cal2ct.c # calentool.1 # calentool.c # ct.h # This archive created: Sat May 27 13:10:56 1989 export PATH; PATH=/bin:$PATH echo shar: extracting "'cal2ct.c'" '(6731 characters)' if test -f 'cal2ct.c' then echo shar: will not over-write existing file "'cal2ct.c'" else sed 's/^ X//' << \SHAR_EOF > 'cal2ct.c' X/* X * $Header: cal2ct.c,v 2.1 89/05/09 14:18:41 billr Exp $ X */ X/* X * cal2ct - convert calendar reminder files to calentool style files X * X * Author: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM> X * X * Copyright (C) 1989 Tektronix, Inc. All Rights Reserved X * X * Permission is hereby granted to use and modify this code in source X * or binary form as long as it is not sold for profit and this copyright X * notice remains intact. X */ X X#include "ct.h" X#include <stdio.h> X#include <ctype.h> X#include <sys/time.h> X Xstruct appt_entry appts, *aptr; Xchar filename[128], *file; XFILE *fp; Xstruct tm current, today, *localtime(); Xstruct timeval tp; X Xextern char *getenv(); X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X if (argc > 1) X file = argv[1]; X else { X strcpy(filename, getenv("HOME")); X strcat(filename, "/calendar"); X file = filename; X } X X if ((fp = fopen(file, "r")) == NULL) { X fprintf(stderr, "can't open calendar file for reading\n"); X exit(1); X } X gettimeofday(&tp, NULL); X today = *localtime(&tp.tv_sec); X if (!read_cal_file()) { X fprintf(stderr, "no reminders read from %s\n", file); X exit(1); X } X fclose(fp); X strcpy(filename, getenv("HOME")); X strcat(filename, "/.appointments"); X if ((fp = fopen(filename, "w")) == NULL) { X fprintf(stderr, "can't open .appointments file for writing\n"); X exit(1); X } X write_ct_file(); X} X X/* X * read dates from calendar file and stuff into appts struct X */ Xread_cal_file() X{ X char *fgets(); X char buf[512]; X struct appt_entry *optr; X X aptr = &appts; X while (fgets(buf, 512, fp) != NULL) { X aptr->repeat = aptr->lookahead = 0; X aptr->flags = A_NOTE; X aptr->next = NULL; X if (!parse_date(buf)) X return(1); X aptr->next = (struct appt_entry *)malloc(sizeof(struct appt_entry)); X if (aptr->next == NULL) { X fprintf(stderr, "out of memory\n"); X return; X } X optr = aptr; X aptr = aptr->next; X } X if (aptr == &appts) X return(0); /* nothing read */ X /* don't need the last one */ X free(aptr); X optr->next = NULL; X return(1); X} X X/* X * write out the new .appointments file X */ Xwrite_ct_file() X{ X aptr = &appts; X fputs(HEADER, fp); X while (aptr) { X if (put_aentry(fp, aptr)) { X fprintf(stderr, "error writing .appointments file\n"); X return; X } X aptr = aptr->next; X } X} X Xchar *dayname[7] = {"SU", "MO", "TU", "WE", "TH", "FR", "SA"}; Xchar *monthname[12] = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN", X "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"}; X X/* X * parse the date on the command line and reset the "current" X * date to reflect that date. The date may take the form of a X * day name (e.g. Tu, Tue, Tuesday) or a date in m/d/y format X * where the month and/or year may be missing (e.g. 27 = 27th X * of this month, 8/27 = August 27 of this year, 8/27/89 = X * August 27 of 1989. month may also be a string (e.g. "Dec" X * or "december") or a '*' (all months). X */ Xparse_date(str) Xchar *str; X{ X char c[4]; X int i, dow = -1, mon = -1, m = -1, d = -1; X X current = today; /* start with this month, day, year */ X while (isspace(*str)) X ++str; X X if (isdigit(*str)) { X /* must be a m/d date */ X /* assume it's a month first */ X m = *str++ - '0'; X if (isdigit(*str)) X m = m*10 + *str++ - '0'; X if (*str != '/') { X /* no more chars => day only */ X d = m; X m = -1; X } else { X ++str; X while (isspace(*str)) X ++str; X if (isdigit(*str)) { X d = *str++ - '0'; X if (isdigit(*str)) X d = d*10 + *str++ - '0'; X } else { X fprintf(stderr, "badly formed date: %s\n", str-2); X return(0); X } X } X if (m > 0) X current.tm_mon = m - 1; X if (d > 0) X current.tm_mday = d; X } else if (*str == '*') { X aptr->flags |= ALL_MONTHS; X ++str; X while (isspace(*str) || *str == '/') X ++str; X d = *str++ - '0'; X if (isdigit(*str)) X d = d*10 + *str++ - '0'; X current.tm_mday = d; X } else { X /* day of week or month name */ X /* check for day names */ X c[0] = islower(*str) ? toupper(*str) : *str; X ++str; X c[1] = islower(*str) ? toupper(*str) : *str; X if (*++str) { X c[2] = islower(*str) ? toupper(*str) : *str; X c[3] = '\0'; X } else X c[2] = '\0'; X while (!isspace(*str)) X ++str; X /* check month names */ X for (i=0; i<12; i++) { X if (!strcmp(c, monthname[i])) { X mon = i; X break;; X } X } X if (mon >= 0) { X /* match found */ X current.tm_mon = mon; X while (!isspace(*str)) X ++str; X d = *++str - '0'; X ++str; X if (isdigit(*str)) X d = d*10 + *str++ - '0'; X current.tm_mday = d; X } else { X /* check day names */ X c[2] = '\0'; X for (i=0; i<7; i++) { X if (!strcmp(c, dayname[i])) { X dow = i; X break; X } X } X if (dow >= 0) { X /* match found */ X current.tm_mday += dow - current.tm_wday; X fix_current_day(); X } else X fprintf(stderr, "badly formed date: %s\n", str-2); X } X } X while (isspace(*str)) X ++str; X strcpy(aptr->str, str); X aptr->year = current.tm_year; X aptr->month = current.tm_mon; X aptr->day = current.tm_mday; X return(1); X} X X/* X * Reset some values in current tm structure. Year, month and X * day-of-month are valid but day and/or month may be < 0 or X * greater than the maximum value, in which case they are adjusted X * accordingly. Day-of-year and day-of-week are then recalculated. X */ Xfix_current_day() X{ X int month, totdays = 0; X struct tm from, to; X X if (current.tm_mon < JAN) { X current.tm_mon = DEC; X current.tm_year--; X } else if (current.tm_mon > DEC) { X current.tm_mon = JAN; X current.tm_year++; X } X if (current.tm_mday < 1) { X current.tm_mon--; X if (current.tm_mon < JAN) { X current.tm_mon = DEC; X current.tm_year--; X } X current.tm_mday += monthlength(current.tm_mon); X } else if (current.tm_mday > monthlength(current.tm_mon)) { X current.tm_mday -= monthlength(current.tm_mon); X current.tm_mon++; X if (current.tm_mon > DEC) { X current.tm_mon = JAN; X current.tm_year++; X } X } X current.tm_yday = current.tm_mday - 1; X for (month = 0; month < current.tm_mon; month++) { X current.tm_yday += monthlength(month); X } X if ((current.tm_year < today.tm_year) X || ((current.tm_year == today.tm_year) X && (current.tm_yday < today.tm_yday))) { X from = current; X to = today; X } else { X from = today; X to = current; X } X if (from.tm_year != to.tm_year) { X for (totdays = 0; from.tm_year < to.tm_year; from.tm_year++) X totdays += dysize(from.tm_year + 1900); X } X totdays += to.tm_yday - from.tm_yday; X if ((current.tm_year < today.tm_year) X || ((current.tm_year == today.tm_year) X && (current.tm_yday < today.tm_yday))) X totdays = -totdays; X current.tm_wday = X ((totdays % 7) + 7 + today.tm_wday) % 7; X} X Xint Xmonthlength(month) Xint month; X{ X static int monthlengths[] = {31,28,31,30,31,30,31,31,30,31,30,31}; X X if (month == FEB && (dysize(current.tm_year + 1900) == 366)) X return(29); X else X return(monthlengths[month]); X} SHAR_EOF if test 6731 -ne "`wc -c < 'cal2ct.c'`" then echo shar: error transmitting "'cal2ct.c'" '(should have been 6731 characters)' fi fi # end of overwriting check echo shar: extracting "'calentool.1'" '(29228 characters)' if test -f 'calentool.1' then echo shar: will not over-write existing file "'calentool.1'" else sed 's/^ X//' << \SHAR_EOF > 'calentool.1' X.\" $Header: calentool.1,v 2.2 89/05/16 16:38:22 billr Exp $ X.\" X.TH CALENTOOL 1 "15 May 1989" X.ds Ps P\s-2OST\s+2S\s-2CRIPT\s+2 X.SH NAME Xcalentool - day/week/month/year-at-a-glance SunView tool (the Hacker's Almanac) X.SH SYNOPSIS X.B calentool X[ X.B -b X] X[ X.B -d X.I date X] X[ X.B -f X.I apptsfile X] X[ X.B -h X[ X.I A a c i l j s X]] X[ X.B -H X[ X.I A a c i l j s X]] X[ X.B -i X] X[ X.B -m X.I userid X] X[ X.B -o X] X[ X.B -p X] X[ X.B -P X] X[ X.B -r X] X[ X.B -t X] X[ X.B -u X.I int X] X[ X.B -w X] X[ X.B -z X] X[ X.B -5 X] X[ X.B -7 X] X[ X.I window options X] X.SH DESCRIPTION X.I Calentool Xis a day/week/month/year-at-a-glance tool. It is a Xwindow-based calendar; the only time you should have to type is Xwhen entering the text for an appointment. X.I Calentool Xprovides for both one-time and recurring appointments, as well as notes X(appointments or reminders with no associated time). A period of advance Xwarning can be specified. A visual warning (and optional auditory bell) Xare produced at the approach of a scheduled appointment. X.LP XBy employing appropriate options, this tool can be used to send reminders Xof appointments by X.IR mail (1), Xand to examine colleagues appointment schedules. Daily and weekly schedules Xcan be sent to a \*(Ps printer. Outdated appointments can be sent Xautomatically to an archival file. An extensive set of files containing Xcommemorative dates is included, as well as a library of routines which Xcomputes the dates of various holidays which do not fall on fixed days Xof the Gregorian calendar (including religious holidays and astronomical Xevents). Lunar and solar almanacs are also included. X.LP XAlthough to take full advantage of X.I calentool Xyou should be operating within the SunView environment, the X.BR \-m , X.B \-p Xand X.B \-P Xoptions allow the Hacker's Almanac to be employed even from ordinary terminals. XThe accompanying utilities X.IR cal2ct (1L), X.IR month2ct (1L), Xand X.IR mt2ct (1L), Xtransform appointment files in X.IR calendar (1), X.IR month (1L), Xand X.IR monthtool (1L) Xformats to X.I calentool Xformat. X.LP XInstructions appear in the section DETAILED INSTRUCTIONS, which follows the XOPTIONS section. X.SH OPTIONS X.I Calentool Xaccepts standard X.I suntools Xcommand line options at the end of the command line. X.TP 15 X.B -b XWhen an appointment is pending, a bell character (along with the appointment Xmessage) is sent to the console; only one reminder is sent for each Xappointment. Also, place a copy of the appointment text in the file X.IR $HOME/.msgfile . XThe text in this file is displayed by the screen lock program X.IR nlock (1L); Xnotifying passers-by of the user's current activity. X.TP X.BI \-d \ date XOpen the calendar at the day X.IR date , Xwhich may take on several formats: X.RS X.TP Xday of current week: XTue, Th, fr, MONDAY X.TP Xnumeric dates: XDD (day DD of current month, for example 27 for the 27th of this month) X.br XMO/DD (day DD of month MO, for example 11/12 for November 12) X.br XMO/DD/YY (day DD of month MO, year YY, for example 9/1/88 for 1 September 1988) X.RE X.TP X.BI \-f \ apptsfile XUse X.I apptsfile Xas the appointments file. This is useful for seeing if Xother people on the net are free to attend a meeting. XIf everyone exports his appointments file (in a NFS environment) then Xpeople can plan appointments more effectively. X.IP XFile integrity can NOT be assured when this option is in use; Xif two people try to write to the same appointments file at the same time, the Xresult could be tragic. Only the person whose schedule is Xdescribed by a particular appointments file should have write permission for Xthat file. X.TP X.BI \-h char XCompute and display holidays which do not fall on set dates of the Gregorian Xcalendar. Notes appear in the day and week displays, and marks appear in Xthe month and year displays. This option is followed by a single character Xwhich indicates which set of holidays is to be computed (the option can be Xinvoked multiple times on the command line). The character codes for Xsupported date sets are: X.RS X.TP X.B A XUse all available date sets. When this option is chosen, the time required Xto produce a new display increases. It becomes long for the month display Xand extremely long for the year display. X.TP X.B a XAstronomical events (solstices and equinoxes). X.TP X.B c XChristian religious holidays. These dates may be inaccurate for years Xprior to the advent of the Gregorian calendar in 1582. X.TP X.B i XIslamic religious holidays. There are different conventions used by Muslim Xcountries to determine the dates in the Islamic calendar; the dates computed Xhere may differ by 1-2 days from the locally determined date. X.TP X.B l XLunar calendar (Chinese/Oriental) holidays (not yet implemented). X.TP X.B j XJewish religious holidays. These may not be accurate for years after 2000. XAlso note that until recent centuries, the Jewish calendar was regulated (like Xthe modern Islamic calendar) by sightings of the crescent Moon, so that Xdates for previous years must be interpreted with caution. X.TP X.B s XUS Secular holidays. X.RE X.TP X.BI \-H char XIdentical to the X.B \-h Xoption, except that computed dates are displayed only in the day and week Xdisplays; the month and year displays are not marked for these dates. X.TP X.B \-i XInclude all outdated appointments files (files named X.IR .appointments.yy , Xwhere X.I yy Xrepresents the last two digits of a past year). X.TP X.BI \-m \ userid XSend mail listing todays appointments to the user specified by X.I userid Xand exit. XThis feature is useful when calentool is run from X.IR cron (1), Xto send yourself mail about today's appointments. X(Note: this option eliminates the need for the separate program, X.IR calenmail (1L), Xwhich was distributed with earlier releases of X.IR calentool ). X.TP X.B \-o XAt the change of a year, send all outdated appointments to an outdated Xappointments file (a file named X.IR .appointments.yy , Xwhere X.I yy Xrepresents the last two digits of the past year). X.TP X.B -p XPrint today's appointments and exit. This is useful for reviewing Xappointments from an ordinary terminal or X.IR shelltool (1). X.TP X.B -P XPrint today's appointments and exit, ignoring notes which are not to mark Xthe month or year displays. This is useful for suppressing trivia when Xreviewing appointments from an ordinary terminal or X.IR shelltool (1). X.TP X.B -r XOpen the calendar tool in read-only mode. XAppointments can be edited, but no changes will be saved. XThe tool's banner strip will contain the string "[Read Only]". XThis is particularly useful for inspecting other users' appointment files Xwith the X.B -f Xoption. X.TP X.B -t XDisplay the current time below the X.I calentool Xicon (no further need for X.IR clocktool (1)). X.TP X.BI -u int XUpdate the time at the interval of X.I int Xseconds. X.TP X.B -w XDon't display the "Working!" message in the control panel during Xlengthy operations. The cursor still changes to an hourglass. X.TP X.B -z XConvert appointments file used by earlier versions of X.I calentool Xto the format used by the current version. This option should be invoked only Xonce, the first time an old format file is read by X.IR calentool . X.TP X.B -5 XDisplay only five days (Monday through Friday) in the week display. This is Xuseful if the installer has set the default display format to 7 days. X.TP X.B -7 XDisplay all seven days in the week display. This is useful if the installer Xhas set the default value to 5 days. The 7-day display is wider than the 5-day Xdisplay, allowing longer messages to be displayed. X.SH "DETAILED INSTRUCTIONS" X.SS "Examining the calendar" XWhen first opened, the tool displays the appointments for a single day (today Xif the X.B \-d Xoption has not been employed). The day page for today is demarcated in gray. XIf advance warning of future appointments has been requested, a popup Xdisplay appears. The day display containing a future appointment may be Xdisplayed if the future appointment is selected with the X.IR mouse-LB . XThe reminder popup may be removed permanently (during this X.I calentool Xsession) by selecting the X.B Done Xoption; if the X.B Keep Xoption is selected, the reminder window will reappear each time the current Xday page is displayed. X.LP XIf there are multiple appointments sharing a time slot, a X.B More Xbutton appears to the right of the time slot. This may be toggled repeatedly Xto view each appointment in turn. If appointment text is too wide for the Xday page, scroll buttons appear to the right of the text and may be used to Xview the text in its entirety. When first displayed, all text is left Xjustified. X.LP XThe control subwindow contains various control buttons and todays date and Xtime. View the current week, month, or year by employing Xthe X.I mouse-LB Xto select the X.BR Week , X.BR Month , Xor X.B Year Xpanel buttons. Pushing the X.I mouse-RB Xin the X.BR Day , X.BR Week , X.BR Month , Xor X.BR Year Xpanel buttons activates pull-down menus with appropriate selections (certain Xof the selections may be inactivated due to the current display mode). The X.B Today Xpanel button redisplays today's day page. In each of the four display modes, Xthe X.B Previous Xand X.B Next Xpanel buttons move backward or forward one day, week, month or year, as Xappropriate (maintaining the current display mode). There are also pull-down Xmenus associated with these buttons, produced by selecting the X.I mouse-RB X(again, certain options may be inactivated according to the current display Xmode). The X.B Current Xbutton displays the current day, week, month or year, depending upon the current Xdisplay mode. A pull-down menu associated with the X.B Current Xbutton allows selection of the current day, week, month, or year displays, or Xdirect entry of a specific date for which a day page is to be displayed. X.LP XIn the week display, the initial part of each appointment message is visible. XIf there are overlapping appointments/notes, a X.B More Xbutton appears at the bottom of the day column, which prints a message Xreminding the user to select the day display to be able to view all of the Xappointments/notes. XThe day strip for today, if present, is demarcated in gray. XMove the cursor over any day of the week and select the X.I mouse-LB Xto view the indicated day display. X.LP XIn the month display, a triangular hatch-mark in the Xupper right-hand corner of a day indicates an appointment. XThe day box for today, if present, is demarcated in gray. XMove the cursor over any day of the month and select the X.I mouse-LB Xto view the indicated day display. Position the cursor Xover the arrow to the left of a week and select the X.I mouse-LB Xto view the indicated week. X.LP XIn the year display, a reverse-video date indicates an appointment. XToday's date, if present, is marked in gray. XMove the cursor over a particular month and select the X.I mouse-LB Xto select the indicated month display. X.LP XThe pulldown menu actuated within the top control bar of the window Xby selecting the X.I mouse-RB Xallows the tool to be closed, moved, terminated, etc. X.SS "Lunar and Solar data" XSelection of the Sun or Moon icons in the day display reveals Xinformation about rising and setting times, lunar phases, local Xtime, sidereal time, etc. An abbreviated solar data display is shown Xif the day currently being displayed is not today. X.SS "Iconic warning of an appointment" XWhen X.I calentool Xis in iconic form, the icon is inverted to a reverse video representation Xapproximately ten minutes prior to a scheduled appointment and remains inverted Xfor the duration of the appointment. X.LP XWhen there are no appointments or notes remaining for the current day, Xan alternate icon with an empty page is displayed instead of the Xstandard or reverse video icons. XFor all icons, today's month and day of month are displayed at the Xbutton of the icon's calendar page. X.SS "Entering appointments" XAppointments can only be entered in the day display. The day display presents Xa number of labelled time slots (generally 30 minute intervals) as well as a X.I notes Xsection at the end of the day page, to enter reminders not associated with a Xspecific time. To enter an appointment, position the cursor over the required Xtime slot and press the X.IR mouse-LB . XThe slot is toggled from white to black; leaving the cursor positioned in the Xslot, type appropriate descriptive text. If the text exceeds the size of the Xwindow, scroll buttons will appear to the right. Typing new text into the Xtime slot automatically right-justifies the text already present, so that the Xnew text is appended. To indicate the duration of any appointment, click the X.I mouse-MB Xin the initial time slot (any existing duration arrow will be deleted); Xa vertical indicator arrow appears and follows the cursor. Drag the cursor Xto the location of the final time slot and release the button. XSelecting the X.I mouse-RB Xin the highlighted time slot produces a popup menu with the options X.BR modify , X.BR cut , X.BR paste , X.BR copy , X.BR delete , Xand X.BR undelete . XTo delete the current appointment, storing it in a temporary buffer, Xselect the X.B cut Xoption. To copy the text of an appointment into the buffer without deleting Xit, select X.BR copy , XTo place the text of a buffer-stored appointment into a time slot, click the X.I mouse-RB Xin the new time slot, and then select the X.B paste Xoption. X.LP XAn appointment may be further modified be selecting the X.B modify Xoption. This causes an options subwindow to appear, in which the user Xmay specify that the appointment is to be repeated every day, for selected Xweeks of the month (first through fifth, or last), every month, and/or every Xyear. Alternatively, Xthe appointment may be repeated at a specified interval of days. The user can Xalso specify a period of days prior to the appointment for which a reminder Xwill be printed. For example, one could specify that a meeting is to occur Xon the first and third Tuesday of the month, in perpetuity, by selecting Xthe repeat options X.BR "Selected Week" , X.BR "Every Month" , Xand X.BR "Every Year" , Xas well as the selected week indicators X.B 1st Xand X.BR 3rd . XAfter selecting the appointment options, the user can select either X.B Accept Xor X.B Abort Xto close the options subwindow. X.LP XTo delete the current appointment, select the X.B delete Xoption. If the appointment in question is recurring, a special subwindow Xappears which allows the user to delete every occurrence or just today's Xoccurrence. If the latter is selected, the X.B undelete Xoption is activated, which allows today's occurrence to be reinstated. X.SS "Entering notes" XEntering notes is similar to entering appointments, except that no duration Xarrows can be appended, and the modify panel allows the user to indicate Xwhether or not the note is to be used to mark the month and year displays, Xor to be printed when the X.B \-P Xoption is invoked. X.SS "Printing appointments" XThe X.B Print Xbutton prints a copy of the day, week, or month display. Pressing the X.I mouse-RB Xover this button produces a popup menu which allows either a raster image or Xa \*(Ps version of the current display to be printed. A third option allows Xmodification of the print command. The default print command is taken from Xthe first provided by the following sources: the X.I $HOME/.defaults Xfile, the X.I PRINTER Xenvironment variable, and the X.I PRINT_CMD Xvalue provided by the system manager at the time of installation. X.SS "Saving outdated appointments" XAppointments are recorded in a file named X.IR .appointments . XIf the X.B \-o Xoption is in effect, at the end of a year all appointments for the Xpast year are copied into a special file with a named X.I .appointments.yy X(where X.I yy Xcontains the final two digits of the past year). These appointments are then Xdeleted from the current X.I .appointments Xfile. X.SS "Examining other appointment files" XThe X.B File Xbutton displays a window in which an alternate X.I .appointments Xfile can be specified. This is useful for maintaining multiple appointment Xbooks or for examining colleagues' calendars. The file can be made Xread-only or read-write according to the toggle option, and a file name can Xbe typed into the window. The X.B Accept Xbutton Xinitiates reading of the currently displayed file, while X.B Done Xcloses the window without further action. XThe X.B Original Xbutton restores the original file name that calentool was invoke with. XThe X.B Reset Xbutton undoes any filename changes that have been made prior to Xselecting X.BR Accept . XThe X.B Save Xbutton updates the current appointments file with any changes made that Xhave not yet been logged. This is typically not an often used option. X.SH "FILE FORMAT" XUsing an included file (see below) is the one instance where manual editing Xof the X.I .appointments Xfile is still required (although one could use the window-based aids of X.I calentool Xto build such a file, by means of the X.B \-f Xoption, the include command must still be edited into the primary Xappointment file). The appointments file contains four types of lines: X.br X.nf X \fC# CalenTool V2 - DO NOT REMOVE THIS LINE X #include "file" X # <comment string> X YY MO DD HH MI AA [II] <WW> # \fImessage\fP X.fi X.SS Header line XThe first line in an X.I appointments Xfile identifies the version of X.I calentool Xin use. This line should never be removed. X.SS Included appointment files XA X.B non-editable Xappointments file (for example, one containing site specific holidays) can Xbe included. Three formats are possbile for specifying such a file: X.br X #include "/pathname/file" X.br Xor X.br X #include "file" X.br Xor X.br X #include <file> X.br XIn the second case, the file will be prepended with the pathname used for the Xappointments file. In the last case, the included file is assumed to reside Xin a system-wide library directory specified at the time of installation X(see your system administrator). The # X.B must Xstart in column 1 of the appointments file. The first line of an included file Xmust also have a header line. Included files may not include other files. X.SS Comment line XA X.I # Xin column one (not followed by the string "include") indicates a comment; Xthe rest of the line is ignored. X.SS Appointment/Note entries XAll fields are separated by at least one space character. X.RS X.SS Mandatory entries XThe X.I YY Xfield is the year (00-99), the X.I MO Xfield is the month (1-12) and X.I DD Xis the day (1-31). The X.I DD Xfield can also contain a two-character alphabetic string describing Xa day of the week: Su, Mo, Tu, We, Th, Fr, Sa. This feature is used Xin conjunction with wildcards (see below), and the X.I [II] Xfield, which must appear within square brackets, and which can contain the Xdigits 1-5 and the letter L, separated by commas, to indicate the first Xthrough fifth (or last) monthly occurrence of the specified day of the week. X.I HH Xand X.I MI Xare the starting hour (00-23) and Xminutes (00 or 30). XThe X.I AA Xfield is the number of arrow bars (additional 30 minute Xtime slots) required. X.SS Notes XA X.I HH Xvalue of 99 indicates a note, rather than an appointment, Xwith X.I MI Xdesignating whether presence of the note is to be noted in the month and year Xpanels (00 indicates that it is to be noted, 99 indicates that it should not Xbe noted). X.SS Wildcards for recurring appointments/notes XA double asterisk (**) can be used in place of the year, month and/or day Xfields. X.SS Optional entries XThe X.I [II] Xfield appears within square brackets, and (if the DD field contains a Xnumerical value) is taken to be an interval in days between recurring Xappointments. The X.I <WW> Xfield appears within broken brackets, and indicates the number of Xdays of advance warning required. X.SS Appointment text XIf a # character appears in front of the text, it indicates that a recurring Xappointment has been suppressed for that day. X.SS Example entries XA meeting that occurs weekly at 0900, starting on April 1st, would Xbe represented as: X.br X.nf X \fC88 04 01 09 00 00 [7] Weekly status meeting\fP X.fi XSeveral other examples: X.nf X \fC** 04 01 00 01 00 April Fool's Day X ** ** Tu 10 30 00 [1,3] Meeting on 1st and 3rd Tues. of Month X ** ** 01 00 01 00 <1> First day of every month, one day warning X 88 05 ** 00 01 00 On vacation for entire month of May 1988\fP X.fi X.RE X.SH "SUPPLIED SPECIAL DATES FILES" X.I Calentool Xis supplied with a number of system-wide special dates files which may be Xincluded in a user's X.I .appointments Xfile: X.RS X.TP Xceltic XHolidays/events of interest to Celts X.TP Xcomputing XEvents in the history of computing X.TP Xevents XHistorical events (major and minor) X.TP Xlives XBiographical dates of note X.TP Xlotr XSpecial dates for fans of Tolkien's X.I Lord of the Rings X.TP Xnature XNatural events X.TP Xpopcult XSpecial dates in Western popular culture X.TP Xusa_holiday XMajor US/Canadian holidays (holidays from work) X.TP Xusa_other XMinor US/Canadian holidays X.TP Xusa_states XUS holidays specific to selected states X.TP Xworld XHolidays from countries other than the US/Canada X.RE X.SH "ENVIRONMENT VARIABLES, INITIALIZATION FILES, AND COMPILATION OPTIONS" X.LP XBy default, the X.I .appointments Xfile employed by X.I calentool Xresides Xin the users' home directory. Alternatively, the environment variable XCALENTOOL_DIR can be set to the full pathname of a directory where the X.I .appointments Xfile resides. X.I Calentool Xmust have write permission in the directory to be used. X.LP X.I Calentool Xalso recognizes "/CalenTool/Appts", "/CalenTool/Font", "/CalenTool/BigFont", X"/CalenTool/LibDir" and "/CalenTool/Printer" Xentries in the X.IR suntools (1) Xinitialization file, X.IR .defaults . XThe "/CalenTool/Appts" entry, if it exists, is used instead of the CALENTOOL_DIR Xor HOME environment variables when searching for the X.I .appointments Xfile. "/CalenTool/Appts" should be the full pathname of the appointments Xfile (e.g. /usr/local/lib/calentool/billr.appts). [Useful if everyone's Xappointment files are NFS'd from a common directory.] XThe normal font (by default, the default system font, changeable Xby the X.IR suntools (1) X.B \-Wt Xoption) may be changed by use of the "/CalenTool/Font" entry. The default Xlarge font (gallant.r.10) may be changed by use of the "/CalenTool/BigFont" Xentry. XThe "/CalenTool/LibDir" entry overrides the compile time default directory Xfor files specified with the X.I #include <file> Xappointment file entry (such as the special date files mentioned Xabove). The "/CalenTool/Printer" entry overrides the compile time Xdefault and PRINTER environment variable for the printer name. X.LP XCompile time options allow modification of the start and ending year for the Xyear pull-down menu, and various parameters defining the display. X.SH FILES X.TP X$HOME/.appointments Xdefault appointments file X.TP X$HOME/.defaults X.IR suntools (1) Xdefaults initialization file X.TP X/tmp/appts* Xdefault temporary appointments file, while active X.TP X$HOME/.msgfile Xmessage file (containing current appointment) for X.IR nlock (1L) Xprogram X.TP X/usr/local/lib/calentool Xdirectory containing special date inclusion files X.TP X/usr/lib/defaults/CalenTool.d Xfile specifying system-wide alternate fonts and directories; such information may also be appended to a user's X.I $HOME/.defaults Xfile X.SH "SEE ALSO" Xcal(1), cal2ct(1L), calendar(1), clocktool(1), cron(8), Xmail(1), month(1L), monthtool(1L), month2ct(1L), mt2ct(1L), Xnlock(1L), suntools(1), vi(1) X.SH REFERENCES XAn excellent compendium which describes basic terminology of time measurement, Xmethods of astronomical computation, and the convoluted history of calendars: X.LP XThe Nautical Almanac Offices of the United Kingdom and the United States of XAmerica, \fIExplanatory Supplement to the Astronomical Ephemeris and the XAmerican Ephemeris and Nautical Almanac\fP, Her Majesty's Stationery Office, XLondon, 1961 (reprinted with amendments, 1977). X.LP XThe best single source for practical computations of solar and lunar data: X.LP XJean Meeus, \fIAstronomical Formulae for Calculators\fP, \fIMonografieen Xover Astronomie en Astrofysica\fP, Volkssterrenwacht Urania V.Z.W., XMattheessensstraat 62, B 2540 Hove, Belgium, Vereniging voor Sterrenkunde XV.Z.W., Ringlaan 3, B 1180 Brussel, Belgium, Vol. 4, Derde Druk, October 1980. X.LP XOther helpful references for astronomical computations: X.LP XEric Burgess, \fICelestial BASIC\fP, Revised Edition, Sybex, 1985 (cookbook Xoriented, many algorithms hard to dig out of turgid BASIC). X.LP XPierre Bretagnon and Jean-Louis Simon, \fIPlanetary Programs and Tables Xfrom -4000 to +2800\fP, Willmann-Bell, 1986 (for utmost accuracy in Xplanetary computations). X.LP XA non-scholarly work with easily implemented algorithms for computation of XChristian and Jewish holidays and (an approximation to) the Islamic New Year: X.LP XWolfgang Alexander Schocken, \fIThe calculated confusion of calendars; Xpuzzles in Christian, Jewish and Moslem calendars\fP, 1st Ed., Vantage Press, XNew York, 1976. X.LP XUseful tables and additional information about the Islamic calendar: X.LP XG. S. P. Freeman-Grenville, \fIThe Muslim and Christian Calendars\fP, XOxford University Press, London, 1963. X.LP XF. R. Unat, \fIHicri Tarihleri\fP, Turktarih Kurumu Basimevi, Ankara, 1959 (Turkish). X.LP XU. V. Tsybulsky, \fICalendar of Middle Eastern Countries\fP, Nauka XPublishing House, Moscow, 1979 (English). X.LP XInformation (regrettably, not at all current) about Japanese holidays: X.LP XW. H. Erskine, \fIJapanese Festival and Calendar Lore\fP, XKyo Bun Kwan, Tokyo, 1933. X.SH "CALLING ALL HACKERS" XPlease help us extend the special dates files and date computation library X(only carefully verified dates and algorithms, please!). In particular, it Xwould be splendid if someone would expand the range of astronomical Xcomputations, which currently include only the equinoxes and solstices; Xone could add dates/times of the major meteor showers, planetary risings and Xsettings, etc. Perhaps a sailing buff could build in high/low tide estimations. XThe lunar calendar date computation library remains to be completed. XThere are many other historical and contemporary calendrical systems we have Xoverlooked (Egyptian, Armenian, Babylonian, Greek, Julian, Indian, and Russian, Xas well as ecclesiatical calendars such as the Alexandrian). The present dates Xlibrary provides useful calendrical computations not currently exploited by X.IR calentool , Xsuch as determining the number of days, or weekdays, or Mondays Xbetween two dates. Perhaps a third icon could be placed next to those for Xthe solar and lunar almanacs, which would open a calendrical computation window. XIt would be very useful if someone would write a X.IR curses (3X) Xbased front-end for X.I calentool Xformat date files for those not using X.IR suntools (1). XAn efficient way of doing this might be to merge X.I calentool Xwith the excellent X.IR Dates (1L) Xprogram of Dain Samples (samples@dougfir.berkeley.edu). X.LP XFinally, it would appear that SunView is to be supplanted by the new XView Xtoolkit which Sun is making part of the next (public domain) MIT X Windows Xtape. An XView or NeWS version of X.I calentool Xwould be a useful contribution. X.LP XMail suggestions, corrections, and additions for the Hacker's Almanac to XBill Randle or Rick Rodgers (addresses below). X.SH BUGS XWithout a doubt. X.SH CAUTIONS XNote that the dates computed here are for the Gregorian calendar, which Xwas a modification of the Julian calendar first introduced in 1582. XCountries have adapted this system as recently as 1927 (Turkey), and in Xsome countries it is used as a civil calendar in co-existence with a separate Xindigenous calendar system. Apply caution in using computed dates for Xnon-recent years and non-European countries. X.SH AUTHORS XThe original version of X.I calentool Xwas contributed to the Sun User Group tape (17 April 1987) by XPhilip Heller (Sun Microsystems, heller%terrapin@sun.COM). Sun Microsystems Xowns this program, but has no interest in maintaining it. X.LP XExtensive corrections and additions have been executed by XBill Randle (Tektronix, Inc., billr@saab.CNA.TEK.COM); it is likely that XPhil Heller would recognize little of the current program! XR. P. C. Rodgers (School of Pharmacy, University of California, XSan Francisco, rodgers@maxwell.mmwb.ucsf.edu), performed extensive beta Xtesting, made numerous design suggestions, and contributed the holiday Xcomputation library, icons, manual pages, and special dates files (which were Xmodified from earlier net postings contributed by unknown authors). XWe thank Dr. Omar Afzal of Cornell University (Chairman of the Committee Xfor Crescent Observation) for his help in implementing the Islamic date Xcomputations. XThe lunar computations were adapted from a network posting of John Walker Xof Autodeck, Inc. (Sausalito, CA, sun!acad!kelvin), the solar computations Xwere adapted from a network posting of Marc T. Kaufman (Los Altos, CA), Xthe raster to \*(Ps conversion was adapted from a network posting Xby Glenn Boysko of Case Western Reserve University and the pcal code Xfor printing the pretty month calendar was adapted from a network Xposting by Ken Keirnan of Pacific Bell. X.LP XMatt Landau X(BBN Laboratories, mlandau@bbn.COM), David St. Pierre X(Pacific Bell, david@pbsaint.PacBell.COM), Casey Leedom X(Lawrence Livermore Laboratories, casey@lll-crg.llnl.GOV), Xand Alfred Correira (Lockheed Corp., correira@austin.lockheed.COM) Xalso provided useful suggestions and feedback on the earlier 2.0beta release. X.\" end of man page SHAR_EOF if test 29228 -ne "`wc -c < 'calentool.1'`" then echo shar: error transmitting "'calentool.1'" '(should have been 29228 characters)' fi fi # end of overwriting check echo shar: extracting "'calentool.c'" '(22137 characters)' if test -f 'calentool.c' then echo shar: will not over-write existing file "'calentool.c'" else sed 's/^ X//' << \SHAR_EOF > 'calentool.c' X/* X * $Header: calentool.c,v 2.1 89/05/09 15:28:43 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 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 <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 todays_date[]; Xextern char version[]; Xextern Panel_item clock_pi; Xextern Frame fframe; Xextern Panel panel; X#ifndef NO_SUN_MOON Xextern Frame sframe; X#endif X XFrame frame = 0; XPixwin *main_pixwin; Xint day_is_open; Xstruct tm today, current; Xstruct tm First, Last; Xstruct tm olddate; 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; Xint week_message_size, weekslot_width, weekslot_height, dayslot_height; Xint ybox_height, ybox_width; Xstruct dayslot slots[N_SLOTS]; Xstruct rect_limits boxlims[31]; Xstruct rect_limits mboxlims[12]; Xstruct week_arrow week_arrows[6]; Xstruct weekrect week_boxes[7]; XPixrect *daybox_pr, *timeslot_pr, *gray_pr; XPixrect *weekslot_pr, *weekarrow_pr, *smallarrow_pr; XPixrect *arrowhead_pr, *arrowshaft_pr; XPixrect *weekarrowhead_pr, *weekarrowshaft_pr; XPixrect *triangle_pr; XPixrect *ydaybox_pr, *ymonthbox_pr; XPixrect *ic_pr, *rev_ic_pr, *na_ic_pr; 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; 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], datestr_mon[4]; Xstruct pr_prpos where; Xint working_msg; 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 cleanup(), itimer_handler(); XNotify_value myframe_interposer(); X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X int flag, i; X int printit = 0, toolrunning = 1, user_pos = 0; X extern char *optarg; X X if (progname = rindex(*argv, '/')) X progname++; X else X progname = *argv; X X nr_weekdays = NR_WEEKDAYS; X n_tslots = (N_TSLOTS > N_SLOTS ? N_SLOTS : N_TSLOTS); X X get_today(); /* initial day is today */ X current = today; X read_only = 0; X working_msg = 1; X X /* X * Check for -p or -m option, which means we don't want X * to create the tool. Also check for -Wp 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 (!strcmp(argv[i], "-p") || !strcmp(argv[i], "-m") X || !strcmp(argv[i], "-P")) X toolrunning = 0; X if (!strcmp(argv[i], "-Wp")) X user_pos = 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 } X X while ((flag = getopt(argc, argv, "57bd:f:im:opPrtu:zH:h:w")) != 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 'p': /* print and exit */ X read_only = 1; X printit = 1; X break; X X case 'P': /* print and exit (ignore some notes) */ X read_only = 1; X printit = 3; X break; X X case 'm': /* mail today's appts and exit */ X read_only = 1; X printit = 2; X mailto = optarg; X break; X X case 'b': /* beep to console for pending appt */ X beep = 1; X break; X X case 'i': /* include old appt files */ X include_old = 1; X break; X X case 'o': /* save outdate 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 '7': /* Sun - Sat 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': /* don't display Working! message */ X working_msg = 0; 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, "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, "unknown holiday option (must be one of \"Aacijs\")"); X break; X } X break; X#else X case 'h': X case 'H': X fprintf(stderr, "-h and -H options not available\n"); X break; X#endif 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 // print selected days appts and exit\n"); X fprintf(stderr, " -P // like -p, only don't print marked notes\n"); X fprintf(stderr, " -m <user> // mail selected days appts to <user>\n"); X fprintf(stderr, " [-5|-7] // 5-day or 7-day week display\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, " -i // auto-include outdated appts files\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 // don't display 'Working!' message\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, " -z // conversion flag (see INSTALL)\n"); X fprintf(stderr, " <window_opts> // Suntools -W options\n"); X exit(1); X break; X } X X X if (toolrunning) { X (void) notify_set_signal_func(frame, cleanup, SIGHUP, NOTIFY_ASYNC); X (void) notify_set_signal_func(frame, cleanup, SIGINT, NOTIFY_ASYNC); X (void) notify_set_signal_func(frame, cleanup, SIGTERM, NOTIFY_ASYNC); X } 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); 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 /* 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 icon = icon_create(0); X rev_icon = icon_create(0); X na_icon = icon_create(0); X strncpy(datestr_mon, todays_date+4, 3); X datestr_mon[3] = '\0'; X strncpy(datestr_day, todays_date+8, 2); X datestr_day[2] = '\0'; 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 strcpy(timestr, todays_date+10); X if (update_interval == 60) { X /* display hh:mm */ X timestr[6] = '\0'; X ilabel_rect.r_left += 2*sfont->pf_defaultsize.x - 2; X ilabel_rect.r_width -= 2*sfont->pf_defaultsize.x; X } else X /* display hh:mm:ss */ X timestr[9] = '\0'; 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, datestr_mon); X where.pr = na_ic_pr; X pf_ttext(where, PIX_NOT(PIX_SRC), sfont, datestr_mon); X where.pr = rev_ic_pr; X pf_ttext(where, PIX_SRC, sfont, datestr_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 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 (void) notify_interpose_event_func(panel, myframe_interposer, NOTIFY_SAFE); X **/ 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 cleanup(); 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, todays_date, 0); X if (show_time && (int)window_get(frame, FRAME_CLOSED)) { X strcpy(timestr, todays_date+10); X if (update_interval == 60) X /* display hh:mm */ X timestr[6] = '\0'; X else X /* display hh:mm:ss */ X timestr[9] = '\0'; X cur_icon = (Icon) window_get(frame, FRAME_ICON); X icon_set(cur_icon, ICON_LABEL, timestr, 0); X window_set(frame, FRAME_ICON, cur_icon, 0); X } 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 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 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 some_appts = 0; /* no appointments today */ X int slotno = 0; /* start with first timeslot */ X static int icon_in_use = STD_ICON; X static int echoed_sno = -1; X static int new_day = 0; X int sno; X Icon cur_icon; X struct timeval gtime; X struct timezone tz; X struct tm Save; X FILE *console, *msgf; X char msgfile[128]; X char *getenv(); X X sno = echoed_sno; /* assume no console echo */ X Save = current; X strcpy(msgfile, getenv("HOME")); X strcat(msgfile, "/.msgfile"); X /* X * Check to see if we've run over into the next day. If so, X * we need to update our slot information. X */ X if (ymd_compare(current, today) != 0) { X if (day_is_open) X close_day(); X current = today; X err2console(TRUE); X get_day_appts(); X err2console(FALSE); X day_is_open = TRUE; X if (!new_day) { X new_day++; X sno = echoed_sno = -1; X } X } else X new_day = 0; X if (today.tm_hour >= START_HOUR) { X slotno = (today.tm_hour - START_HOUR)*2 + today.tm_min/30; X if (slotno < n_tslots) { X if (slots[slotno].active != INACTIVE) { X /* appointment is happening now */ X appt_pending++; X if (slots[slotno].active == ACTIVE) X sno = slotno; X } else if (slotno+1 < n_tslots) { X if (slots[slotno+1].active != INACTIVE) X /* are we within 10 mins of an appointment? */ X if ((today.tm_min % 30) >= 20) { X appt_pending++; X if (slots[slotno+1].active == ACTIVE) X sno = slotno+1; X } X } X } X } X if (!appt_pending) { 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 was set above to X * reflect the current hour (or 0 if before START_HOUR). X */ 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++].active != INACTIVE) { 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 } else { X /* notify the user via the console (once) ... */ X if (beep && sno != echoed_sno) { X echoed_sno = sno; X window_bell(frame); X if ((console = fopen("/dev/console", "w")) != NULL) { X fprintf(console, "%s\n", slots[sno].cur_appt->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 } X if (new_day) { X /* if we're iconic, then go ahead and update the current X * day, otherwise restore it to what it was before. X */ X if ((int)window_get(frame, FRAME_CLOSED)) { X /* so that it opens on today */ X olddate = current = today; X /* update date field of the icons */ X strncpy(datestr_mon, todays_date+4, 3); X strncpy(datestr_day, todays_date+8, 2); 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, datestr_mon); X where.pr = na_ic_pr; X pf_ttext(where, PIX_NOT(PIX_SRC), sfont, datestr_mon); X where.pr = rev_ic_pr; X pf_ttext(where, PIX_SRC, sfont, datestr_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 } else { X if (day_is_open) X close_day(); X current = Save; X err2console(TRUE); X get_day_appts(); X err2console(FALSE); X day_is_open = TRUE; X } X show_future = 1; /* show future appts again */ X } X} X Xstatic Notify_value Xcleanup(me, signal, when) XNotify_client me; Xint signal; XNotify_signal_mode when; X{ X if (day_is_open) X close_day(); X if (access(tmpapts_pathname, R_OK) == 0 && unlink(tmpapts_pathname) < 0) X perror(tmpapts_pathname); X exit(0); X /* NOTREACHED */ X return(NOTIFY_DONE); X} SHAR_EOF if test 22137 -ne "`wc -c < 'calentool.c'`" then echo shar: error transmitting "'calentool.c'" '(should have been 22137 characters)' fi fi # end of overwriting check echo shar: extracting "'ct.h'" '(7009 characters)' if test -f 'ct.h' then echo shar: will not over-write existing file "'ct.h'" else sed 's/^ X//' << \SHAR_EOF > 'ct.h' X/* X * $Header: ct.h,v 2.1 89/05/09 14:25:13 billr Exp $ X */ X/* X * ct.h - header file for calentool X * X * Author: Philip Heller, Sun Microsystems. Inc. <terrapin!heller@sun.com> X * X * Original source Copyright (C) 1987, Sun Microsystems, Inc. X * All Rights Reserved X * Permission is hereby granted to use and modify this program in source X * or binary form as long as it is not sold for profit and this copyright X * notice remains intact. X * X * X * Changes/additions by: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM> X * X * Changes and additions Copyright (C) 1988, 1989 Tektronix, Inc. X * All Rights Reserved X * Permission is hereby granted to use and modify the modifications in source X * or binary form as long as they are not sold for profit and this copyright X * notice remains intact. X */ X X/* directory for date/event files */ X#ifndef DATELIB_DIR X# define DATELIB_DIR "/usr/local/lib/calentool" X#endif X X#ifndef NOPRINTER X/* command string for sending a file to the Postscript printer */ X# ifndef PRINT_CMD X# define PRINT_CMD "lpr -Plw" X# endif X X/*# define RASTER_ONLY /* define this if no Postscript printer available */ X#endif X X/* define NR_WEEKDAYS for desired week display */ X/* NR_WEEKDAYS display */ X/* 5 Mon-Fri */ X/* 6 Mon-Sat */ X/* 7 Sun-Sat */ X/**/ X#ifndef NR_WEEKDAYS X# define NR_WEEKDAYS 5 X#endif X X#ifndef START_HOUR X# define START_HOUR 8 /* 8am */ X#endif /* to */ X#ifndef END_HOUR X# define END_HOUR 18 /* 6pm */ X#endif X X#ifndef START_YEAR X# define START_YEAR 89 X#endif X#ifndef NR_YEARS X# define NR_YEARS 5 /* number of years in menu */ X#endif X X#ifndef UPDATE_RATE X# define UPDATE_RATE "second" /* update time */ X#endif /* options are "second" & "minute" */ X#define TIME_OUT 5 /* check appts every 5 minutes */ X X/* X * If calentool is too big and you want a stripped-down version X * define some or all of these here or in the Makefile. Combined, X * they save ~100K bytes. X */ X/*#define NO_PRINTER /* exclude printer support code */ X/*#define NO_HOLIDAYS /* exclude holiday checking code */ X/*#define NO_SUN_MOON /* exclude Sun/Moon data frames */ X X/*********************************************************************/ X/* Nothing below here should need to be changed (typically) */ X/*********************************************************************/ X X#ifndef TRUE X# define TRUE 1 X#endif X#ifndef FALSE X# define FALSE 0 X#endif X X#ifndef N_TSLOTS X# define N_TSLOTS ((END_HOUR-START_HOUR)*2) /* Number of 30-minute slots in a day. */ X#endif X#define N_SLOTS (N_TSLOTS+10) /* Total number of slots on a day page. */ X#define MAX_FUTURE_ENTRIES 32 /* number of appts displayed in popup window */ X 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#ifndef APPT_CHECK_LIMIT X# define APPT_CHECK_LIMIT n_tslots X#endif X X/* Dimensions of 30-minute week slot. X * Message size determines width - everything else keyed X * off font size and message size X */ X#define WEEK_MESSAGE_SIZE 12 X X#define DISPLAYING_DAY 1 /* Defs for state of main */ X#define DISPLAYING_WEEK 2 /* subwindow (mainsw_state) */ X#define DISPLAYING_MONTH 3 X#define DISPLAYING_YEAR 4 X X#define BACKSPACE 8 /* editing chars */ X#define CTRL_R 18 X#define CTRL_U 21 X#define CTRL_W 23 X#define DEL 127 X X#define NONE 0 X#define DAY 1 /* Defs for "selected_type" (type of */ X#define WEEK 2 /* object selected by month click). */ X#define MONTH 3 X X#define INACTIVE 0 /* Defs for "active" field of timeslot. */ X#define ARROW_SHAFT 1 X#define ARROW_HEAD 2 X#define ACTIVE 4 X X#define JUSTIFY_LEFT 0 /* text justification in day slot */ X#define JUSTIFY_RIGHT 1 X#define JUSTIFY_INDEX 2 X X#define FOUND_SLOT 1 /* event tags for day display */ X#define FOUND_MORE 2 X#define FOUND_LARROW 3 X#define FOUND_RARROW 4 X X#define MMODIFY 1 /* order of entries in day menu */ X#define MCUT 2 X#define MPASTE 3 X#define MCOPY 4 X#define MDELETE 5 X#define MUNDELETE 6 X X#define PR_POSTSCRIPT 1 /* print options */ X#define PR_RASTER 2 X X#define SUN 0 /* days of the week */ X#define MON 1 X#define TUE 2 X#define WED 3 X#define THU 4 X#define FRI 5 X#define SAT 6 X X#define JAN 0 /* selected months */ X#define FEB 1 X#define DEC 11 X X#define ALL_YEARS 0x1 /* flags for special case appts */ X#define ALL_MONTHS 0x2 X#define ALL_DAYS 0x4 X#define REPEAT 0x8 X#define A_COMMENT 0x10 X#define EVERY_SUN 0x20 X#define EVERY_MON 0x40 X#define EVERY_TUE 0x60 X#define EVERY_WED 0x80 X#define EVERY_THU 0xa0 X#define EVERY_FRI 0xc0 X#define EVERY_SAT 0xe0 X#define EVERY_SOMEDAY 0xe0 X /* convert flag value to day-of-week number */ X# define Pickday(d) ((((d)&EVERY_SOMEDAY)>>5)-1) X /* convert day of week to flag value */ X# define Setday(d) (((d)+1)<<5) X#define LOOKAHEAD 0x100 X#define READONLY 0x200 X#define A_NOTE 0x400 X#define MARKED 0x800 /* don't show in month/year display */ X#define MARKED_NOTE 0xc00 X#define DELETED 0x1000 /* don't show the appt that matches this */ X X/* format of repeat field for every_someday type appts */ X#define WEEK1 0x1 X#define WEEK2 0x2 X#define WEEK3 0x4 X#define WEEK4 0x8 X#define WEEK5 0x10 X#define ALL_WEEKS 0x1f X#define LAST_WEEK 0x20 X#define WEEK_LIMIT 0x3f X X/* error reporting flags */ X#define NON_FATAL 0 X#define FATAL 1 X X#define STD_ICON 0 /* flags for icon currently displayed */ X#define REV_ICON 1 X#define NA_ICON 2 X X/* header line in appts file implies one-based entries and 99 memo flag */ X#define HEADER "# CalenTool V2 - DO NOT REMOVE THIS LINE\n" X X#define MAX_STRLEN 256 /* max size of strings */ Xstruct appt_entry { X /* describes an entry in the appointments file */ X int year, month, day, hour, minute, arrows; X int repeat, lookahead, flags, sindex; X char str[MAX_STRLEN]; X struct appt_entry *next; /* ptr to next appt in list */ X}; /* NULL if last entry */ X Xstruct rect_pos { X /* location of a given rect in the canvas */ X int top, bottom, left, right; X}; X Xstruct dayslot { X /* struct for storing relevant info for 30 min day slot */ X struct rect_pos slot_pos; /* slot position in day display */ X struct rect_pos larrow_pos; /* position of left scroll arrow */ X struct rect_pos rarrow_pos; /* position of right scroll arrow */ X struct rect_pos moreb_pos; /* position of "more" button */ X int active; /* status of this slot */ X int count; /* number of active appts in this slot */ X struct appt_entry *cur_appt; /* ptr to current appt in list */ X struct appt_entry *first; /* ptr to first appt in list */ X}; /* NULL if no entries */ X Xstruct weekrect { X /* info for week display */ X struct rect_pos wday_pos; /* screen position of this day */ X struct rect_pos moreb_pos; /* position of "more" button */ X int more; X struct dayslot weekslots[N_SLOTS]; X}; X Xstruct rect_limits { X int lowx; X int lowy; X int highx; X int highy; X}; X Xstruct week_arrow { X int top; X int bottom; X int left; X int right; X int active; X}; SHAR_EOF if test 7009 -ne "`wc -c < 'ct.h'`" then echo shar: error transmitting "'ct.h'" '(should have been 7009 characters)' fi fi # end of overwriting check # End of shell archive exit 0