[comp.sources.sun] v01i011: Calendar/planning tool: Part 02/09

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