[comp.sources.misc] v17i092: calentool - day/week/month/year-at-a-glance SunView tool, Part11/23

billr@saab.CNA.TEK.COM (Bill Randle) (04/06/91)

Submitted-by: Bill Randle <billr@saab.CNA.TEK.COM>
Posting-number: Volume 17, Issue 92
Archive-name: calentool/part11

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 11 (of 23)."
# Contents:  cal2ct.c dates/events expire.c tool.c
# Wrapped by billr@saab on Thu Mar 28 08:38:22 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'cal2ct.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cal2ct.c'\"
else
echo shar: Extracting \"'cal2ct.c'\" \(11379 characters\)
sed "s/^X//" >'cal2ct.c' <<'END_OF_FILE'
X/*
X * $Header: cal2ct.c,v 2.4 91/03/27 16:44:54 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, 1991 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, *ofile;
XFILE *fp;
Xstruct tm current, start, today, *localtime();
Xstruct timeval tp;
Xint run_days = -1, use_date = 0;
Xint day_first = FALSE;
Xvoid err_rpt();
X
Xextern char *getenv();
Xextern int optind;
Xextern char *optarg;
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	int flag;
X
X	gettimeofday(&tp, NULL);
X	current = today = *localtime(&tp.tv_sec);
X	ofile = NULL;
X	while ((flag = getopt(argc, argv, "d:f:r:eE")) != EOF)
X		switch (flag) {
X			case 'd':  /* starting date */
X				/* updates "current" */
X				(void)parse_date(optarg, TRUE);
X				use_date++;
X				break;
X			case 'e':
X			case 'E':  /* European style dates */
X				day_first = TRUE;
X				break;
X			case 'f':  /* output file */
X				ofile = optarg;
X				break;
X			case 'r':  /* number of days to process */
X				run_days = atoi(optarg);
X				break;
X			default:  /* unknown option */
X				fprintf(stderr, "usage: cal2ct [-d date] [-r days] [-e] [-f outfile] [file]\n");
X				break;
X		}
X
X	start = current;
X	if (optind < argc)
X		file = argv[optind];
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	if (!read_cal_file()) {
X		fprintf(stderr, "no reminders read from %s\n", file);
X		exit(1);
X	}
X	fclose(fp);
X	if (ofile)
X		strcpy(filename, ofile);
X	else {
X		strcpy(filename, getenv("HOME"));
X		strcat(filename, "/.appointments");
X	}
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->warn = 10;
X		aptr->flags = A_NOTE;
X		aptr->next = NULL;
X		if (parse_cal_date(buf))
X			continue;
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 in the buffer and reset the "current"
X * date to reflect that date. The date may take the form of a
X * month and day where the month may be spelled or numeric, e.g.:
X * Feb 27, feb 27, 2/27. The month may be a `*' to refer to any
X * month, e.g. "* 27" or "* /27".
X * Limitation: the date is expected to start at the begining of
X * the line. (calendar allows it anywhere in the line.)
X */
Xparse_cal_date(str)
Xchar *str;
X{
X	char c[4];
X	int i, m = -1, d = -1;
X	void fix_current_day();
X
X	current = start;	/* 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		--m; /* make it zero based */
X		if (*str != '/') {
X			/* no more chars => bad format */
X			fprintf(stderr, "badly formed date: %s\n", str-2);
X			return(1);
X		} else {
X			++str;
X			if (isdigit(*str)) {
X				d = *str++ - '0';
X				while (isdigit(*str))
X					d = d*10 + *str++ - '0';
X			} else {
X				fprintf(stderr, "badly formed date: %s\n", str-2);
X				return(1);
X			}
X		}
X	} else if (*str == '*') {
X		aptr->flags |= ALL_MONTHS;
X		++str;
X		while (isspace(*str) || *str == '/')
X			++str;
X		d = *str++ - '0';
X		while (isdigit(*str))
X			d = d*10 + *str++ - '0';
X	} else {
X		/* month name */
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				m = i;
X				break;;
X			}
X		}
X		if (m >= 0) {
X			/* match found */
X			while (!isspace(*str))
X				++str;
X			d = *++str - '0';
X			++str;
X			while (isdigit(*str))
X				d = d*10 + *str++ - '0';
X		} else {
X			fprintf(stderr, "badly formed date: %s\n", str-2);
X			return(1);
X		}
X	}
X	current.tm_mon = m;
X	current.tm_mday = d;
X	if (use_date || run_days >= 0) {
X		if (!run_days) {
X			if (ymd_compare(current, start) != 0)
X				return(1);
X		} else if (run_days > 0) {
X			if (ymd_compare(current, start) >= 0) {
X				struct tm Save;
X
X				Save = current;
X				current = start;
X				current.tm_mday += run_days;
X				fix_current_day();
X				if (ymd_compare(Save, current) > 0)
X					return(1);
X				current = Save;
X			} else
X				return(1);
X		} else if (ymd_compare(current, start) < 0)
X			return(1);
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(0);
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 */
Xvoid
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}
X
X/*
X * Compares two sets of year/month/day.  Returns -1 if the first is earlier than
X * the second, +1 if later, 0 if they are the same.
X */
Xymd_compare(day0, day1)
Xstruct tm day0, day1;
X{
X        if (day0.tm_year > day1.tm_year) return(1);
X        if (day0.tm_year < day1.tm_year) return(-1);
X        if (day0.tm_mon > day1.tm_mon) return(1);
X        if (day0.tm_mon < day1.tm_mon) return(-1);
X        if (day0.tm_mday > day1.tm_mday) return(1);
X        if (day0.tm_mday < day1.tm_mday) return(-1);
X        return(0);
X}
X
X/*
X * parse the date on the given string 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. If 'cmdline' is true, then the string
X * came from the command line '-d' option.
X * If the first character of the date is + or - scan the number and
X * use it as an offset in days from the current date.  Thus -1 becomes
X * yesterday and +1 becomes tomorrow. pbm.
X */
Xint
Xparse_date(str, cmdline)
Xchar *str;
Xint cmdline;
X{
X	char c[4];
X	int i, dow = -1, m = -1, d = -1, y = -1;
X
X	if (isdigit(*str)) {
X		/* must be a m/d/y 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 if (*str++ != '/') {
X			if (cmdline)
X				err_rpt("badly formed date for -d option (ignored)", NON_FATAL);
X			else
X				err_rpt("badly formed date - please reenter", NON_FATAL);
X			return(1);
X		} else {
X			d = *str++ - '0';
X			if (isdigit(*str))
X				d = d*10 + *str++ - '0';
X			if (*str++ == '/') {
X				/* year also specified */
X				y = *str++ - '0';
X				if (isdigit(*str)) {
X					y = y*10 + *str++ - '0';
X					if (*str && isdigit(*str))
X						y = y*10 + *str++ - '0';
X					if (*str && isdigit(*str))
X						y = y*10 + *str++ - '0';
X				}
X			}
X		}
X		if (y > 0) {
X			if (y > 1900)
X				y -= 1900;
X			current.tm_year = y;
X		}
X		if (day_first) {
X			if (m > 0) {
X				current.tm_mon = d - 1;
X				current.tm_mday = m;
X			} else if (d > 0)
X				current.tm_mday = d;
X		} else {
X			if (m > 0) {
X				current.tm_mon = m - 1;
X				current.tm_mday = d;
X			} else if (d > 0)
X				current.tm_mday = d;
X		}
X		fix_current_day();
X	} else if (*str == '-' || *str == '+') {
X		/*
X		 * If the argument begins with a + or - assume that it is an
X		 * offset in days from the current date. Use current date if the
X		 * number doesn't scan after the - or +. pbm
X		 */
X		if (sscanf(str, "%d", &i) == 1) {
X			current.tm_mday += i;
X			fix_current_day();
X		}
X	} else {
X		/* day of week */
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		for (i=0; i<7; i++) {
X			if (!strncmp(c, dayname[i], 2)) {
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 if (!strcmp(c, "TOM")) {
X			/* tommorrow */
X			current.tm_mday++;
X			fix_current_day();
X		} else if (!strcmp(c, "YES")) {
X			/* yesterday */
X			current.tm_mday--;
X			fix_current_day();
X		} else if (strcmp(c, "TOD")) {
X			if (cmdline)
X				err_rpt("badly formed date for -d option (ignored)", NON_FATAL);
X			else
X				err_rpt("badly formed date - please reenter", NON_FATAL);
X			return(1);
X		}
X	}
X	return(0);
X}
X
Xvoid
Xerr_rpt(str, flag)
Xchar *str;
Xint flag;
X{
X	fprintf(stderr, "%s\n", str);
X	if (flag == FATAL)
X		exit(1);
X}
END_OF_FILE
if test 11379 -ne `wc -c <'cal2ct.c'`; then
    echo shar: \"'cal2ct.c'\" unpacked with wrong size!
fi
# end of 'cal2ct.c'
fi
if test -f 'dates/events' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dates/events'\"
else
echo shar: Extracting \"'dates/events'\" \(288 characters\)
sed "s/^X//" >'dates/events' <<'END_OF_FILE'
X# CalenTool V2.2 - nflag=1 range=1,12  - DO NOT REMOVE THIS LINE
X# $Header: events,v 1.1 91/03/07 16:19:02 billr Exp $
X# Common include file just includes individual parts
X#
X#include <events1>
X#include <events2>
X#include <events3>
X#include <events4>
X#include <events5>
X#include <events6>
END_OF_FILE
if test 288 -ne `wc -c <'dates/events'`; then
    echo shar: \"'dates/events'\" unpacked with wrong size!
fi
# end of 'dates/events'
fi
if test -f 'expire.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'expire.c'\"
else
echo shar: Extracting \"'expire.c'\" \(5720 characters\)
sed "s/^X//" >'expire.c' <<'END_OF_FILE'
X/*
X * $Header: expire.c,v 2.3 91/03/27 16:45:39 billr Exp $
X *
X * expire.c
X * expire outdated appts, i.e. remove them from the appts file, if they
X * are older than <n> days and store them in .appointmentYY if <save_old>.
X *
X * Copyright (C) 1989, 1991 Tektronix, Inc.
X *	All Rights Reserved
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 <stdio.h>
X#include <sys/time.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/errno.h>
X#include "ct.h"
X
Xextern struct tm today,current;
Xextern char apts_pathname[], tmpapts_pathname[];
Xextern char inbuf[], apts_dir[];
Xextern int save_old,read_only;
Xextern int errno;
Xextern double julian_day();
Xextern double nth_mday_of_month();
X
X/*
X * Scan appointments file for outdated appointments. If <save_old> is
X * TRUE then save them to a special file of the form ".appointments.YY",
X * where YY is the year of that appointment.  Outdated appointments are
X * appointments that are older that <edays> old.  If <edays> is zero then
X * Outdated appointments are appointments from previous years. If <save_old>
X * is not set, then Outdated appointments are just deleted.
X * Setting <save_old> TRUE (-o) and <edays> to 0 (-x 0) gives the behavior
X * described by the "-o" switch.
X */
Xexpire(edays)
Xint edays;
X{
X	FILE *apts, *temp_apts, *fp;
X	int read_stat;
X	int runl, week;
X	char save_file[128];
X	struct appt_entry appt;
X	struct stat sbuf;
X	struct tm savecurrent;
X	int successful = 1;    /* assume this worked */
X
X	/*
X	 * method: for each regular appt in the file (or limited
X	 * duration appt), compare the Julian date of that appt
X	 * and the Julian date of today, looking for a difference
X	 * greater than <edays>.
X	 */
X	if (read_only) /* we can't expire from a calendar if read_only */
X		return;
X	if ((apts = fopen(apts_pathname, "r")) == NULL)
X		successful = err_rpt("can't open appointments file, aborting expire", NON_FATAL);
X	if ((temp_apts = fopen(tmpapts_pathname, "w")) == NULL)
X		successful = err_rpt("can't open temp file for writing, aborting expire", NON_FATAL);
X	/*
X	 * now go thru the appointments file
X	 */
X	savecurrent = current;  /* save so can restore after loop */
X	while (successful && (read_stat=get_aentry(apts, &appt, TRUE, 0, 0)) != EOF) {
X		if (read_stat)
X			continue;	/* read error (ignore) */
X		if (appt.flags & A_COMMENT) {
X			fputs(inbuf, temp_apts);
X			continue;
X		}
X		current.tm_year = appt.year;
X		current.tm_mon = appt.month;
X		current.tm_mday = appt.day;
X		if (appt.flags & ALL_YEARS)
X			/* force this to be saved */
X			current.tm_year = today.tm_year + 1;
X		if (appt.flags & ALL_MONTHS)
X			/* maybe saved, pick worse case */
X			current.tm_mon = DEC;
X		if (appt.flags & ALL_DAYS || appt.flags & EVERY_MON_FRI) {
X			if (current.tm_year < today.tm_year ||
X			   (current.tm_year == today.tm_year &&
X			    current.tm_mon < today.tm_mon)) {
X				/* maybe saved, pick worse case */
X				current.tm_mday = monthlength(current.tm_mon);
X				fix_current_day();
X				if (appt.flags & EVERY_MON_FRI)
X					while (current.tm_wday == SAT
X					    || current.tm_wday == SUN) {
X						current.tm_mday--;
X						fix_current_day();
X					}
X			}
X		}
X		if (appt.flags & EVERY_SOMEDAY) {
X			if ((appt.repeat & ALL_WEEKS) == ALL_WEEKS || appt.repeat & LAST_WEEK ||
X			    appt.repeat & WEEK5)
X				week = 5;
X			else if (appt.repeat & WEEK4)
X				week = 4;
X			else if (appt.repeat & WEEK3)
X				week = 3;
X			else if (appt.repeat & WEEK2)
X				week = 2;
X			else if (appt.repeat & WEEK1)
X				week = 1;
X			current.tm_mday = (int)nth_mday_of_month(week, Pickday(appt.flags), current.tm_mon, current.tm_year+1900);
X			if (current.tm_mday > monthlength(current.tm_mon))
X				current.tm_mday = (int)nth_mday_of_month(week-1, Pickday(appt.flags), current.tm_mon, current.tm_year+1900);
X			if (appt.flags & RUN) {
X				current.tm_mday += appt.runlength;
X				fix_current_day();
X			}
X		} else if (appt.flags & REPEAT) {
X			if (appt.flags & RUN)
X				runl = appt.runlength;
X			else
X				runl = 1;
X			while (ymd_compare(current, today) < 0 && runl) {
X				if (appt.flags & RUN)
X					--runl;
X				if (runl) {
X					current.tm_mday += appt.repeat;
X					fix_current_day();
X				}
X			}
X		}
X		current.tm_mday += edays;  /* offset by expire days */
X		fix_current_day();
X		if (((edays == 0) && (current.tm_year >= today.tm_year)) ||
X		    julian_day((double)current.tm_mday, current.tm_mon, current.tm_year+1900) >=
X		    julian_day((double)today.tm_mday, today.tm_mon, today.tm_year+1900)) {
X			if (put_aentry(temp_apts, &appt)) {
X				/* write error */
X				break;
X			}
X		} else {
X			if (save_old) {
X				/* prepend directory info */
X				sprintf(save_file, "%s.%02d",
X					apts_pathname, appt.year);
X				if (stat(save_file, &sbuf) && errno == ENOENT) {
X					/* new file*/
X					if ((fp = fopen(save_file, "w")) == NULL)
X						successful = err_rpt("can't open save file, aborting expire", NON_FATAL);
X					fputs(HEADER, fp);
X					fclose(fp);
X				}
X				if ((fp = fopen(save_file, "a+")) == NULL)
X					successful = err_rpt("can't open save file, aborting expire", NON_FATAL);
X				else {
X					if (put_aentry(fp, &appt))
X						successful = err_rpt("write to save appt file failed, aborting expire", NON_FATAL);
X					fclose(fp);
X				}
X			}
X		}
X        }
X	if (ferror(temp_apts))
X		successful = err_rpt("write on temp file failed", NON_FATAL);
X	fclose(temp_apts);
X        fclose(apts);
X	current = savecurrent;   /* restore current from temp */
X	/* don't rename zero length files */
X	stat(tmpapts_pathname, &sbuf);
X	if (sbuf.st_size == (off_t) 0)
X		err_rpt("zero length temp file - not renamed", NON_FATAL);
X	else if (successful)
X		xrename(tmpapts_pathname, apts_pathname);
X}
X
END_OF_FILE
if test 5720 -ne `wc -c <'expire.c'`; then
    echo shar: \"'expire.c'\" unpacked with wrong size!
fi
# end of 'expire.c'
fi
if test -f 'tool.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tool.c'\"
else
echo shar: Extracting \"'tool.c'\" \(33530 characters\)
sed "s/^X//" >'tool.c' <<'END_OF_FILE'
X/*
X * $Header: tool.c,v 2.5 91/03/27 16:46:32 billr Exp $
X */
X/*
X * tool.c
X *
X * Author: Philip Heller, Sun Microsystems. Inc. <terrapin!heller@sun.com>
X *
X * Original source Copyright (C) 1987, Sun Microsystems, Inc.
X *	All Rights Reserved
X * Permission is hereby granted to use and modify this program in source
X * or binary form as long as it is not sold for profit and this copyright
X * notice remains intact.
X *
X *
X * Changes/additions by: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM>
X *
X * Changes and additions Copyright (C) 1988, 1989, 1991 Tektronix, Inc.
X *	All Rights Reserved
X * Permission is hereby granted to use and modify the modifications in source
X * or binary form as long as they are not sold for profit and this copyright
X * notice remains intact.
X */
X#include <stdio.h>	/* for NULL */
X#include <suntool/sunview.h>
X#include <suntool/canvas.h>
X#include <suntool/panel.h>
X#include <sunwindow/defaults.h>
X#include <sys/file.h>
X#include "ct.h"
X
X/*
X * define standard B/W monochrome colors as defaults in case we're running
X * on a color system with the monochrome colors set differently
X */
X#define FG_DEFAULT  { 0, 0, 0 }     /* black */
X#define BG_DEFAULT  { 255, 255, 255 }   /* white */
X
Xextern int monday_first;
Xextern struct tm current;
Xextern Frame frame;
Xextern int working_msg;
Xextern int n_slots;
Xextern int user_font;
XCanvas canvas;
XPanel panel;
XPanel_item todaybutton_pi, working_pi;
XPanel_item monthmenu_pi, yearmenu_pi, weekbutton_pi, daybutton_pi;
XPanel_item previous_pi, next_pi, current_pi, filebutton_pi;
XPanel_item clock_pi;
XPanel_item runl_pi;
XPanel_item donebutton_pi;
X#ifndef NO_PRINTER
XPanel_item printbutton_pi;
X#endif
X#ifndef NO_SUN_MOON
XPanel_item moonbutton_pi, sunbutton_pi;
X#endif
XMenu next_menu, previous_menu;
XMenu day_menu, week_menu, month_menu, year_menu;
XMenu day_sel_menu, current_menu;
XMenu done_menu;
X#ifndef NO_PRINTER
XMenu print_menu;
X#endif
XPixfont *font, *bigfont, *sfont;
XFrame fframe = 0;
XPanel fpanel, fcpanel;
XFrame attr_frame;
XPanel attr_panel;
XPanel_item repeat_pi, remind_pi, everyx_pi, whichwk_pi, marked_pi;
XPanel_item advw_pi;
XFrame del_frame;
XPanel del_panel;
XPanel_item del_choice_pi;
XFrame wmore_frame;
XPanel wmore_panel;
X#ifndef NO_SUN_MOON
XFrame sframe = 0, mframe = 0;
X#endif
XFrame fileframe;
XPanel filepanel;
XPanel_item filename_pi, file_ro_pi;
X#ifndef NO_PRINTER
XPanel_item prcmd_pi;
XPanel_item prfile_pi;
Xint print_to_file = 0;
XFrame prframe;
X#endif
X#ifndef NO_SUN_MOON
XCanvas scanvas, mcanvas;
XPanel_item sdate_pi, mdate_pi;
Xstatic struct singlecolor       fg_default = FG_DEFAULT;
Xstatic struct singlecolor       bg_default = BG_DEFAULT;
X#endif
XFrame prompt_frame = 0;
XPixrect *morebutton;
Xstatic Cursor panel_cursor, canvas_cursor;
XFrame date_frame;
XPanel_item setdate_pi;
XFrame cut_frame;
XPanel cut_panel;
Xvoid monthmenu_notify(), yearmenu_notify(), weekbutton_notify();
Xvoid month_menu_event(), year_menu_event(), week_menu_event();
Xvoid todaybutton_notify(), currentbutton_notify(), daybutton_notify();
Xvoid filebutton_notify(), current_menu_event();
Xvoid cut_done(), cut_abort();
Xvoid donebutton_notify(), done_menu_event();
X#ifndef NO_SUN_MOON
Xvoid moonbutton_notify(), sunbutton_notify();
X#endif
X#ifndef NO_PRINTER
Xvoid printbutton_notify(), print_menu_event();
X#endif
Xvoid day_menu_event();
Xvoid mainsw_selected();
Xvoid next_menu_event(), nextbutton_notify();
Xvoid previous_menu_event(), previous_menu_notify();
Xvoid mainsw_inputevent();
Xvoid fdone_proc(), fkeep_proc(), fappt_notify();
Xvoid attr_accept(), attr_abort();
Xvoid del_done();
X#ifndef NO_SUN_MOON
Xvoid sdone_proc(), mdone_proc();
Xvoid sframe_done(), mframe_done();
X#endif
Xvoid fileframe_done(), file_accept(), file_reset(), file_done();
Xvoid file_save();
Xvoid prompt_no_notify(), prompt_yes_notify();
Xvoid error_event(), file_orig();
Xvoid dtframe_done(), dtdone_proc();
X#ifndef NO_PRINTER
Xvoid prframe_done(), prdone_proc();
X#endif
XNotify_value check_close();
Xint monthlength();
Xchar year_str[NR_YEARS][5]; /* holds strings for year menu */
Xextern Pixwin *main_pixwin;
Xextern Cursor day_cursor, wait_cursor;
Xextern int day_is_open, mainsw_state;
Xextern char clockstr[];
Xextern struct appt_entry future[];
Xextern int findex;
Xextern struct dayslot *slots;
X#ifndef NO_SUN_MOON
Xextern Pixrect moon_icon_pr, sun_icon_pr;
X#endif
Xextern char printer[];
Xextern int day_first;
Xextern int locked;
X
X/* Create and init control panel */
Xcreate_panel()
X{
X	int	width;
X
X	/* Create the control panel. */
X	panel = window_create(frame, PANEL,
X			  WIN_HEIGHT, 72, WIN_FONT, font,
X			  WIN_CONSUME_KBD_EVENTS,
X			  WIN_UP_EVENTS, KEY_LEFT(7), 0,
X			  WIN_ERROR_MSG, "Can't create main panel.",
X			  0);
X
X	/* Create the panel items and their menus */
X	done_menu = menu_create(MENU_STRINGS,
X			"Close to Icon", "Quit Tool", 0,
X			0);
X
X	donebutton_pi = panel_create_item(panel, PANEL_BUTTON,
X                        PANEL_LABEL_IMAGE, 
X                          panel_button_image(panel, "Done", 4, font),
X			PANEL_EVENT_PROC, done_menu_event,
X                        PANEL_NOTIFY_PROC, donebutton_notify,
X			PANEL_ITEM_X, ATTR_COL(0),
X			PANEL_ITEM_Y, ATTR_ROW(0)+2,
X                        0);
X	
X	if( monday_first ) 
X	    day_menu = menu_create(MENU_STRINGS, 
X	                "Monday", "Tuesday", "Wednesday",
X			"Thursday", "Friday", "Saturday", "Sunday", 0,
X			0);
X	else
X	    day_menu = menu_create(MENU_STRINGS, 
X	                "Sunday", "Monday", "Tuesday", "Wednesday",
X			"Thursday", "Friday", "Saturday", 0,
X			0);
X
X	daybutton_pi = panel_create_item(panel, PANEL_BUTTON,
X                        PANEL_LABEL_IMAGE, 
X                          panel_button_image(panel, "Day", 3, font),
X			PANEL_EVENT_PROC, day_menu_event,
X                        PANEL_NOTIFY_PROC, daybutton_notify,
X			PANEL_ITEM_X, ATTR_COL(7),
X			PANEL_ITEM_Y, ATTR_ROW(0)+2,
X                        0);
X	
X	week_menu = menu_create(MENU_STRINGS, "1st", "2nd",
X			"3rd", "4th", "5th", "Last", 0,
X			0);
X
X	weekbutton_pi = panel_create_item(panel, PANEL_BUTTON,
X                        PANEL_LABEL_IMAGE, 
X                          panel_button_image(panel, "Week", 4, font),
X			PANEL_EVENT_PROC, week_menu_event,
X                        PANEL_NOTIFY_PROC, weekbutton_notify,
X			PANEL_ITEM_X, ATTR_COL(12),
X			PANEL_ITEM_Y, ATTR_ROW(0)+2,
X                        0);
X
X	month_menu = menu_create(MENU_STRINGS,
X			"January", "February","March",
X			"April", "May", "June", "July", "August",
X			"September", "October", "November", "December", 0,
X			0);
X
X	monthmenu_pi = panel_create_item(panel, PANEL_BUTTON,  
X                        PANEL_LABEL_IMAGE,
X			  panel_button_image(panel, "Month", 5, font),
X			PANEL_EVENT_PROC, month_menu_event,
X                        PANEL_NOTIFY_PROC, monthmenu_notify,  
X			PANEL_ITEM_X, ATTR_COL(18),
X			PANEL_ITEM_Y, ATTR_ROW(0)+2,
X                        0);
X
X	year_menu = menu_create(0);	/* years filled in later */
X	add_years_to_menu();
X
X	yearmenu_pi = panel_create_item(panel, PANEL_BUTTON,
X                        PANEL_LABEL_IMAGE,
X			  panel_button_image(panel, "Year", 4, font),
X			PANEL_EVENT_PROC, year_menu_event,
X                        PANEL_NOTIFY_PROC, yearmenu_notify,
X			PANEL_ITEM_X, ATTR_COL(25),
X			PANEL_ITEM_Y, ATTR_ROW(0)+2,
X                        0);
X
X	todaybutton_pi = panel_create_item(panel, PANEL_BUTTON,
X                        PANEL_LABEL_IMAGE, 
X                          panel_button_image(panel, "Today", 5, font),
X                        PANEL_NOTIFY_PROC, todaybutton_notify,
X			PANEL_ITEM_X, ATTR_COL(34),
X			PANEL_ITEM_Y, ATTR_ROW(0)+2,
X                        0);
X
X	filebutton_pi = panel_create_item(panel, PANEL_BUTTON,
X                        PANEL_LABEL_IMAGE, 
X                          panel_button_image(panel, "File", 4, font),
X                        PANEL_NOTIFY_PROC, filebutton_notify,
X			PANEL_ITEM_X, ATTR_COL(45),
X			PANEL_ITEM_Y, ATTR_ROW(0)+2,
X                        0);
X
X#ifndef NO_PRINTER
X	printbutton_pi = panel_create_item(panel, PANEL_BUTTON,
X                        PANEL_LABEL_IMAGE, 
X                          panel_button_image(panel, "Print", 5, font),
X                        PANEL_EVENT_PROC, print_menu_event,
X                        PANEL_NOTIFY_PROC, printbutton_notify,
X			PANEL_ITEM_X, ATTR_COL(53),
X			PANEL_ITEM_Y, ATTR_ROW(0)+2,
X			PANEL_SHOW_ITEM, FALSE,
X                        0);
X	
X	print_menu = menu_create(MENU_STRINGS, "Print Postscript", "Print Raster",
X			"Change Printer", 0,
X			0);
X#endif
X
X	working_pi = panel_create_item(panel, PANEL_MESSAGE,
X			PANEL_LABEL_STRING, "Working!",
X			PANEL_LABEL_FONT, font,
X			PANEL_LABEL_BOLD, TRUE,
X			PANEL_SHOW_ITEM, FALSE,
X			PANEL_ITEM_X, ATTR_COL(37),
X			PANEL_ITEM_Y, ATTR_ROW(1)+5,
X			0);
X
X	previous_menu = menu_create(MENU_STRINGS,
X			"Yesterday", "Last Week", "Last Month", "Last Year", 0,
X			0);
X	
X	previous_pi = panel_create_item(panel, PANEL_BUTTON,
X                        PANEL_LABEL_IMAGE, 
X                          panel_button_image(panel, "Previous", 8, font),
X			PANEL_EVENT_PROC, previous_menu_event,
X                        PANEL_NOTIFY_PROC, previous_menu_notify, 
X			PANEL_ITEM_X, ATTR_COL(2),
X			PANEL_ITEM_Y, ATTR_ROW(2)-2,
X			0);
X
X	current_menu = menu_create(MENU_STRINGS, "Current Day",
X			"Current Week", "Current Month", "Current Year",
X			"Change Date", 0,
X			0);
X
X	current_pi = panel_create_item(panel, PANEL_BUTTON,
X                        PANEL_LABEL_IMAGE, 
X                          panel_button_image(panel, "Current", 7, font),
X			PANEL_EVENT_PROC, current_menu_event,
X                        PANEL_NOTIFY_PROC, currentbutton_notify,
X			PANEL_ITEM_X, ATTR_COL(13),
X			PANEL_ITEM_Y, ATTR_ROW(2)-2,
X                        0);
X
X	next_menu = menu_create(MENU_STRINGS, "Tomorrow",
X			"Next Week", "Next Month", "Next Year", 0,
X			0);
X	
X	next_pi = panel_create_item(panel, PANEL_BUTTON,
X                        PANEL_LABEL_IMAGE, 
X                          panel_button_image(panel, "Next", 4, font),
X			PANEL_EVENT_PROC, next_menu_event,
X                        PANEL_NOTIFY_PROC, nextbutton_notify, 
X			PANEL_ITEM_X, ATTR_COL(23),
X			PANEL_ITEM_Y, ATTR_ROW(2)-2,
X			0);
X
X	width = (int)window_get(panel, WIN_WIDTH);
X
X	get_today();	/* get current date and time */
X	clock_pi = panel_create_item(panel, PANEL_MESSAGE,
X			PANEL_ITEM_X, width-150-(strlen(clockstr)*font->pf_defaultsize.x),
X			PANEL_ITEM_Y, ATTR_ROW(2)+3,
X			PANEL_LABEL_STRING, clockstr,
X			PANEL_LABEL_FONT, font,
X			0);
X
X#ifndef NO_SUN_MOON
X	sunbutton_pi = panel_create_item(panel, PANEL_BUTTON,
X                        PANEL_LABEL_IMAGE, &sun_icon_pr,
X                        PANEL_NOTIFY_PROC, sunbutton_notify,
X			PANEL_ITEM_X, width-140,
X			PANEL_ITEM_Y, ATTR_ROW(0),
X			PANEL_SHOW_ITEM, FALSE,
X                        0);
X
X	moonbutton_pi = panel_create_item(panel, PANEL_BUTTON,
X                        PANEL_LABEL_IMAGE, &moon_icon_pr,
X                        PANEL_NOTIFY_PROC, moonbutton_notify,
X			PANEL_ITEM_X, width-70,
X			PANEL_ITEM_Y, ATTR_ROW(0),
X			PANEL_SHOW_ITEM, FALSE,
X                        0);
X#endif
X
X	/*
X	 * menu strings for right MB menu in the canvas
X	 * (day display). NB: if the order of this menu is
X	 * changed, also change the #defines in ct.h
X	 * (MMODIFY, MCUT, etc.).
X	 */
X	day_sel_menu = menu_create(MENU_STRINGS,
X			"Modify", "Cut", "Paste", "Copy", "Delete",
X			"Undelete", 0,
X			0);
X
X	/*
X	 * this button is displayed in the canvas, but needs a panel
X	 * for the function call to work properly
X	 */
X	morebutton = panel_button_image(panel, "More", 4, font);
X
X	/*
X	 * interpose on panel events to check for L7 (open/close)
X	 */
X	notify_interpose_event_func(panel, check_close, NOTIFY_SAFE);
X}
X
X/*
X * Add year strings to year panel menu
X */
Xadd_years_to_menu()
X{
X	int n, year;
X
X	n = 1;
X	for (year=START_YEAR; year<START_YEAR+NR_YEARS; year++,n++) {
X		sprintf(year_str[n-1], "%4d", year+1900);
X		menu_set(year_menu, MENU_STRING_ITEM, year_str[n-1], n, 0);
X	}
X}
X
X/* turn sun and moon buttons on or off */
Xsun_moon_buttons(state)
Xint state;
X{
X#ifndef NO_SUN_MOON
X	if (state) {
X		if (!mframe)
X			panel_set(moonbutton_pi, PANEL_SHOW_ITEM, TRUE, 0);
X		if (!sframe)
X			panel_set(sunbutton_pi, PANEL_SHOW_ITEM, TRUE, 0);
X	} else {
X		panel_set(moonbutton_pi, PANEL_SHOW_ITEM, FALSE, 0);
X		panel_set(sunbutton_pi, PANEL_SHOW_ITEM, FALSE, 0);
X		/* remove moon window, if it exists */
X		if (mframe) {
X			window_destroy(mframe);
X			mframe = 0;
X		}
X		/* remove sun window, if it exists */
X		if (sframe) {
X			window_destroy(sframe);
X			sframe = 0;
X		}
X	}
X#endif
X}
X
X/* turn print button on or off */
Xprint_button(state)
Xint state;
X{
X#ifndef NO_PRINTER
X/* if no printer specified then never show Print button */
X	if (state)
X		panel_set(printbutton_pi, PANEL_SHOW_ITEM, TRUE, 0);
X	else
X		panel_set(printbutton_pi, PANEL_SHOW_ITEM, FALSE, 0);
X#endif	/* NO_PRINTER */
X}
X
Xworking(state)
Xint state;
X{
X	/* turn "Working!" message on or off */
X	if (working_msg) {
X		if (state)
X			panel_set(working_pi, PANEL_SHOW_ITEM, TRUE, 0);
X		else
X			panel_set(working_pi, PANEL_SHOW_ITEM, FALSE, 0);
X	}
X}
X
X/* Create and init main subwindow. */
Xcreate_main_window()
X{
X	canvas = window_create(frame, CANVAS,
X			CANVAS_FIXED_IMAGE, TRUE,
X			WIN_CONSUME_KBD_EVENTS, WIN_ASCII_EVENTS,
X			WIN_UP_EVENTS, KEY_LEFT(5), KEY_LEFT(6),
X			KEY_LEFT(7), KEY_LEFT(8), 0,
X			WIN_CONSUME_PICK_EVENTS, WIN_NO_EVENTS,
X			WIN_MOUSE_BUTTONS, LOC_STILL, LOC_DRAG,
X			WIN_IN_TRANSIT_EVENTS, 0,
X			WIN_EVENT_PROC, mainsw_inputevent,
X			CANVAS_RETAINED, TRUE,
X			WIN_BELOW, panel,
X			WIN_ERROR_MSG, "Can't create main window.",
X			0);
X	main_pixwin = (Pixwin *) canvas_pixwin(canvas);
X	
X	window_set(canvas, WIN_CURSOR, day_cursor, 0);
X	mainsw_state = DISPLAYING_DAY;
X	day_is_open = FALSE;
X	draw_day1();  /* like draw_day(), only no future popup */
X}
X
Xget_fonts()
X{
X	char *default_ptr, fontstr[128];
X
X	/* Open normal and big font files. */
X	if (user_font)
X		/* use command line override */
X		font = pw_pfsysopen();
X	else if ((default_ptr = defaults_get_string("/CalenTool/Font", NULL, 0)) != NULL) {
X		if (*default_ptr != '/') {
X			strcpy(fontstr, "/usr/lib/fonts/fixedwidthfonts/");
X			strcat(fontstr, default_ptr);
X			if ((font = pf_open(fontstr)) == NULL)
X				font = pw_pfsysopen();
X		} else {
X			if ((font = pf_open(default_ptr)) == NULL)
X				font = pw_pfsysopen();
X		}
X	} else
X		font = pw_pfsysopen();
X	if ((default_ptr = defaults_get_string("/CalenTool/BigFont", NULL, 0)) != NULL) {
X		if (*default_ptr != '/') {
X			strcpy(fontstr, "/usr/lib/fonts/fixedwidthfonts/");
X			strcat(fontstr, default_ptr);
X			if ((bigfont = pf_open(fontstr)) == NULL)
X				bigfont = pf_open("/usr/lib/fonts/fixedwidthfonts/gallant.r.10");
X		} else {
X			if ((bigfont = pf_open(default_ptr)) == NULL)
X				bigfont = pf_open("/usr/lib/fonts/fixedwidthfonts/gallant.r.10");
X		}
X	} else
X		bigfont = pf_open("/usr/lib/fonts/fixedwidthfonts/gallant.r.10");
X	/* double check */
X	if (bigfont == NULL) {
X		err_rpt("unable to open large size font", NON_FATAL);
X		bigfont = pw_pfsysopen();
X	}
X
X	/* font for displaying time under the icon and days under moon */
X	sfont = pf_open("/usr/lib/fonts/fixedwidthfonts/screen.r.7");
X}
X
X/*
X * create popup window for future appts display
X * called when we draw a day display.
X */
Xcreate_future_popup()
X{
X	int i, p_width;
X	Panel_item item;
X	char *fappt_str, *format_appt();
X	static Panel_item fdone_pi, fkeep_pi;
X	static int cp_width, cp_x;
X
X	if (!fframe) {
X		/* create new frame and control panel */
X		fframe = window_create(frame, FRAME, FRAME_NO_CONFIRM, TRUE,
X				WIN_X, ATTR_COL(12),
X				WIN_Y, slots[n_slots-4].slot_pos.top,
X				FRAME_LABEL, "Future Appointments",
X				FRAME_SHOW_LABEL, TRUE,
X				WIN_ERROR_MSG, "Can't create future frame.",
X				0);
X
X		fcpanel = window_create(fframe, PANEL, 0);
X	
X		fkeep_pi = panel_create_item(fcpanel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
X				fkeep_proc, PANEL_LABEL_IMAGE,
X				panel_button_image(fcpanel, "Keep", 4, font),
X				PANEL_SHOW_ITEM, TRUE,
X				PANEL_ITEM_X, ATTR_COL(20),
X				PANEL_ITEM_Y, ATTR_ROW(0),
X				0);
X	
X		fdone_pi = panel_create_item(fcpanel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
X				fdone_proc, PANEL_LABEL_IMAGE,
X				panel_button_image(fcpanel, "Done", 4, font),
X				PANEL_SHOW_ITEM, TRUE,
X				PANEL_ITEM_X, ATTR_COL(30),
X				PANEL_ITEM_Y, ATTR_ROW(0),
X				0);
X	
X		window_fit(fcpanel);
X		cp_width = (int) window_get(fcpanel, WIN_WIDTH);
X		cp_x = (int) window_get(fcpanel, WIN_X);
X
X	} else {
X		/* existing frame, so just delete and recreate the
X		 * message panel and its items
X		 */
X		window_destroy(fpanel);
X	}
X	fpanel = window_create(fframe, PANEL, WIN_BELOW, fcpanel,
X			WIN_FONT, font, WIN_X, cp_x, 0);
X	/* create a panel message item for each future appt */
X	for (i=0; i<findex; i++) {
X		fappt_str = format_appt(&future[i]);
X		(void) panel_create_item(fpanel, PANEL_MESSAGE,
X				PANEL_NOTIFY_PROC, fappt_notify,
X				PANEL_SHOW_ITEM, TRUE,
X				PANEL_CLIENT_DATA, (caddr_t)i,
X				PANEL_LABEL_X, ATTR_COL(1),
X				PANEL_LABEL_Y, ATTR_ROW(i),
X				PANEL_LABEL_FONT, font,
X				PANEL_LABEL_STRING, fappt_str,
X				0);
X	}
X	window_fit(fpanel);
X	/* find out which panel is wider and use it for frame width */
X	p_width = (int) window_get(fpanel, WIN_WIDTH);
X	if (p_width > cp_width) {
X		/* reset control panel size */
X		window_set(fcpanel, WIN_WIDTH, p_width, 0);
X		/* move buttons */
X		panel_set(fdone_pi, PANEL_ITEM_X, ATTR_COL(-7)+p_width,
X				PANEL_SHOW_ITEM, TRUE,
X				0);
X		panel_set(fkeep_pi, PANEL_ITEM_X, ATTR_COL(-17)+p_width,
X				PANEL_SHOW_ITEM, TRUE,
X				0);
X	} else {
X		window_set(fpanel, WIN_WIDTH, cp_width, 0);
X		/* move buttons */
X		panel_set(fdone_pi, PANEL_ITEM_X, ATTR_COL(-7)+cp_width,
X				PANEL_SHOW_ITEM, TRUE,
X				0);
X		panel_set(fkeep_pi, PANEL_ITEM_X, ATTR_COL(-17)+cp_width,
X				PANEL_SHOW_ITEM, TRUE,
X				0);
X	}
X	window_fit(fframe);
X	window_set(fframe, WIN_SHOW, TRUE, 0);
X}
X
X/*
X * create a popup to modify or set attributes for a given
X * appointment.
X */
Xcreate_attr_frame()
X{
X	void everyx_notify();
X
X	/* create new frame and control panel */
X	attr_frame = window_create(frame, FRAME, FRAME_NO_CONFIRM, TRUE,
X			FRAME_SHOW_LABEL, FALSE,
X			WIN_ERROR_MSG, "Can't create attributes frame.",
X			0);
X
X	attr_panel = window_create(attr_frame, PANEL,
X			WIN_FONT, font,
X			PANEL_BLINK_CARET, TRUE,
X			0);
X	
X	(void) panel_create_item(attr_panel, PANEL_MESSAGE,
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_LABEL_STRING, "Appointment Options",
X			PANEL_LABEL_X, ATTR_COL(4),
X			PANEL_LABEL_Y, ATTR_ROW(0)+4,
X			PANEL_LABEL_BOLD, TRUE,
X			0);
X
X	(void) panel_create_item(attr_panel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
X			attr_accept, PANEL_LABEL_IMAGE,
X			panel_button_image(attr_panel, "Accept", 6, font),
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_ITEM_X, ATTR_COL(35),
X			PANEL_ITEM_Y, ATTR_ROW(0),
X			0);
X
X	(void) panel_create_item(attr_panel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
X			attr_abort, PANEL_LABEL_IMAGE,
X			panel_button_image(attr_panel, "Abort", 5, font),
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_ITEM_X, ATTR_COL(45),
X			PANEL_ITEM_Y, ATTR_ROW(0),
X			0);
X
X	everyx_pi = panel_create_item(attr_panel, PANEL_TOGGLE,
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_DISPLAY_LEVEL, PANEL_ALL,
X			PANEL_NOTIFY_PROC, everyx_notify,
X			PANEL_LABEL_STRING, "Repeat appointment:",
X			PANEL_CHOICE_STRINGS, "Mon-Fri", "Every Day",
X			"Selected Week", "Every Month", "Every Year", 0,
X			PANEL_ITEM_X, ATTR_COL(1),
X			PANEL_ITEM_Y, ATTR_ROW(2)-5,
X			0);
X
X	whichwk_pi = panel_create_item(attr_panel, PANEL_TOGGLE,
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_DISPLAY_LEVEL, PANEL_ALL,
X			PANEL_LABEL_STRING,
X			"Indicate which week(s) in the month:",
X			PANEL_CHOICE_STRINGS, "1st", "2nd",
X			"3rd", "4th", "5th", "Last", "All", 0,
X			PANEL_ITEM_X, ATTR_COL(1),
X			PANEL_ITEM_Y, ATTR_ROW(3)-5,
X			0);
X
X	repeat_pi = panel_create_item(attr_panel, PANEL_TEXT,
X			PANEL_SHOW_ITEM, FALSE,
X			PANEL_LABEL_STRING,
X			"Repeat at specified interval of days:",
X			PANEL_VALUE, 0, PANEL_VALUE_STORED_LENGTH, 4,
X			PANEL_VALUE_DISPLAY_LENGTH, 4,
X			PANEL_ITEM_X, ATTR_COL(1),
X			PANEL_ITEM_Y, ATTR_ROW(3),
X			PANEL_BLINK_CARET, TRUE,
X			0);
X	
X	runl_pi = panel_create_item(attr_panel, PANEL_TEXT,
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_LABEL_STRING,
X			"Repeat specified number of times (default forever):",
X			PANEL_VALUE, 0, PANEL_VALUE_STORED_LENGTH, 4,
X			PANEL_VALUE_DISPLAY_LENGTH, 4,
X			PANEL_ITEM_X, ATTR_COL(1),
X			PANEL_ITEM_Y, ATTR_ROW(4),
X			PANEL_BLINK_CARET, TRUE,
X			0);
X
X	remind_pi = panel_create_item(attr_panel, PANEL_TEXT,
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_LABEL_STRING,
X			"Warn in advance by specified number of days:",
X			PANEL_VALUE, 0, PANEL_VALUE_STORED_LENGTH, 4,
X			PANEL_VALUE_DISPLAY_LENGTH, 4,
X			PANEL_ITEM_X, ATTR_COL(1),
X			PANEL_ITEM_Y, ATTR_ROW(5),
X			PANEL_BLINK_CARET, TRUE,
X			0);
X
X	advw_pi = panel_create_item(attr_panel, PANEL_TEXT,
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_LABEL_STRING,
X			"Remind a specified number of minutes before:",
X			PANEL_VALUE, 0, PANEL_VALUE_STORED_LENGTH, 4,
X			PANEL_VALUE_DISPLAY_LENGTH, 4,
X			PANEL_ITEM_X, ATTR_COL(1),
X			PANEL_ITEM_Y, ATTR_ROW(6),
X			PANEL_BLINK_CARET, TRUE,
X			0);
X
X	/* This panel item is currently only supported
X	 * for note appointment entries.
X	 */
X	marked_pi = panel_create_item(attr_panel, PANEL_CYCLE,
X			PANEL_SHOW_ITEM, FALSE,
X			PANEL_LABEL_STRING,
X			"Mark in month/year display:",
X			PANEL_CHOICE_STRINGS, "Yes", "No", 0,
X			PANEL_ITEM_X, ATTR_COL(1),
X			PANEL_ITEM_Y, ATTR_ROW(7),
X			0);
X
X	window_fit(attr_panel);
X	window_fit(attr_frame);
X}
X
X/*
X * create a popup to choose delete mode
X */
Xcreate_del_frame()
X{
X	/* create new frame and control panel */
X	del_frame = window_create(frame, FRAME, FRAME_NO_CONFIRM, TRUE,
X			FRAME_SHOW_LABEL, FALSE,
X			WIN_ERROR_MSG, "Can't create delete frame.",
X			0);
X
X	del_panel = window_create(del_frame, PANEL,
X			WIN_FONT, font,
X			0);
X	
X	(void) panel_create_item(del_panel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
X			del_done, PANEL_LABEL_IMAGE,
X			panel_button_image(del_panel, "Accept", 6, font),
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_ITEM_X, ATTR_COL(30),
X			PANEL_ITEM_Y, ATTR_ROW(0),
X			0);
X
X	(void) panel_create_item(del_panel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
X			attr_abort, PANEL_LABEL_IMAGE,
X			panel_button_image(del_panel, "Abort", 5, font),
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_ITEM_X, ATTR_COL(40),
X			PANEL_ITEM_Y, ATTR_ROW(0),
X			0);
X
X	(void) panel_create_item(del_panel, PANEL_MESSAGE,
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_LABEL_STRING, "This is a recurring appointment.",
X			PANEL_LABEL_X, ATTR_COL(1),
X			PANEL_LABEL_Y, ATTR_ROW(1)+5,
X			PANEL_LABEL_BOLD, TRUE,
X			0);
X
X	del_choice_pi = panel_create_item(del_panel, PANEL_CYCLE,
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_LABEL_STRING, "Do you wish to:",
X			PANEL_CHOICE_STRINGS, "Delete this occurrance only", "Delete all occurrances", 0,
X			PANEL_ITEM_X, ATTR_COL(1),
X			PANEL_ITEM_Y, ATTR_ROW(2)+5,
X			0);
X
X	window_fit(del_panel);
X	window_fit(del_frame);
X}
X
X#ifndef NO_SUN_MOON
X/*
X * create popup for sun data frame
X */
Xsun_data_frame()
X{
X	Panel spanel;
X
X	/* create new frame and canvas */
X	if (!sframe) {
X		sframe = window_create(frame, FRAME, FRAME_NO_CONFIRM, TRUE,
X				WIN_X, ATTR_COL(12),
X				FRAME_LABEL, "Solar Data",
X				FRAME_SHOW_LABEL, TRUE,
X				FRAME_DONE_PROC, sframe_done,
X				WIN_ERROR_MSG, "Can't create sun data frame.",
X				0);
X
X		spanel = window_create(sframe, PANEL, WIN_FONT, font,
X				WIN_WIDTH, 55*font->pf_defaultsize.x,
X				WIN_ERROR_MSG, "Can't create sun data panel.",
X				0);
X	
X		(void) panel_create_item(spanel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
X				sdone_proc, PANEL_LABEL_IMAGE,
X				panel_button_image(spanel, "Done", 4, font),
X				PANEL_SHOW_ITEM, TRUE,
X				PANEL_ITEM_X, ATTR_COL(45),
X				PANEL_ITEM_Y, ATTR_ROW(0),
X				0);
X
X		sdate_pi = panel_create_item(spanel, PANEL_MESSAGE,
X				PANEL_ITEM_X, ATTR_COL(8),
X				PANEL_ITEM_Y, ATTR_ROW(0),
X				/* string filled in later */
X				PANEL_LABEL_STRING, "",
X				PANEL_LABEL_FONT, font,
X				0);
X	
X		window_fit_height(spanel);
X		scanvas = window_create(sframe, CANVAS, WIN_BELOW, spanel,
X				WIN_X, 0,
X				WIN_HEIGHT, 17*font->pf_defaultsize.y,
X				WIN_CONSUME_PICK_EVENT, WIN_NO_EVENTS,
X				WIN_CONSUME_KBD_EVENT, WIN_NO_EVENTS,
X				WIN_ERROR_MSG, "Can't create sun data canvas.",
X				0);
X	
X		write_sun_data();
X		window_fit(sframe);
X		window_set(sframe, WIN_SHOW, TRUE, 0);
X	} else
X		write_sun_data();
X}
X
X/*
X * create popup for moon data frame
X */
Xmoon_data_frame()
X{
X	Panel mpanel;
X
X	/* create new frame and canvas */
X	if (!mframe) {
X		mframe = window_create(frame, FRAME, FRAME_NO_CONFIRM, TRUE,
X				WIN_X, ATTR_COL(12),
X				FRAME_LABEL, "Lunar Data",
X				FRAME_SHOW_LABEL, TRUE,
X				FRAME_FOREGROUND_COLOR, &fg_default,
X				FRAME_BACKGROUND_COLOR, &bg_default,
X				FRAME_DONE_PROC, mframe_done,
X				WIN_ERROR_MSG, "Can't create moon data frame.",
X				0);
X
X		mpanel = window_create(mframe, PANEL, WIN_FONT, font,
X				WIN_WIDTH, 70*font->pf_defaultsize.x,
X				WIN_ERROR_MSG, "Can't create moon data panel.",
X				0);
X	
X		(void) panel_create_item(mpanel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
X				mdone_proc, PANEL_LABEL_IMAGE,
X				panel_button_image(mpanel, "Done", 4, font),
X				PANEL_SHOW_ITEM, TRUE,
X				PANEL_ITEM_X, ATTR_COL(60),
X				PANEL_ITEM_Y, ATTR_ROW(0),
X				0);
X
X		mdate_pi = panel_create_item(mpanel, PANEL_MESSAGE,
X				PANEL_ITEM_X, ATTR_COL(8),
X				PANEL_ITEM_Y, ATTR_ROW(0),
X				/* string filled in later */
X				PANEL_LABEL_STRING, "",
X				PANEL_LABEL_FONT, font,
X				0);
X	
X		window_fit_height(mpanel);
X		mcanvas = window_create(mframe, CANVAS, WIN_BELOW, mpanel,
X				WIN_X, 0,
X				WIN_HEIGHT, 17*font->pf_defaultsize.y,
X				CANVAS_RETAINED, TRUE,
X				WIN_CONSUME_PICK_EVENT, WIN_NO_EVENTS,
X				WIN_CONSUME_KBD_EVENT, WIN_NO_EVENTS,
X				WIN_ERROR_MSG, "Can't create moon data canvas.",
X				0);
X	
X		write_moon_data();
X		window_fit(mframe);
X		window_set(mframe, WIN_SHOW, TRUE, 0);
X	} else
X		write_moon_data();
X}
X#endif	/* NO_SUN_MOON */
X
X/*
X * create a popup to allow selecting a different appointment file
X */
Xcreate_file_frame()
X{
X
X	/* create new frame and control panel */
X	fileframe = window_create(frame, FRAME, FRAME_NO_CONFIRM, TRUE,
X			FRAME_LABEL, "File Selection",
X			FRAME_SHOW_LABEL, TRUE,
X			FRAME_DONE_PROC, fileframe_done,
X			WIN_ERROR_MSG, "Can't create file frame.",
X			0);
X
X	filepanel = window_create(fileframe, PANEL, WIN_FONT, font,
X			PANEL_BLINK_CARET, TRUE,
X			0);
X	
X	file_ro_pi = panel_create_item(filepanel, PANEL_CYCLE, PANEL_CHOICE_STRINGS,
X			"Read Only", "Read/Write", 0,
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_ITEM_X, ATTR_COL(1),
X			PANEL_ITEM_Y, ATTR_ROW(0),
X			0);
X
X	(void) panel_create_item(filepanel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
X			file_orig, PANEL_LABEL_IMAGE,
X			panel_button_image(filepanel, "Original", 7, font),
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_ITEM_X, ATTR_COL(17),
X			PANEL_ITEM_Y, ATTR_ROW(0),
X			0);
X
X	(void) panel_create_item(filepanel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
X			file_accept, PANEL_LABEL_IMAGE,
X			panel_button_image(filepanel, "Accept", 6, font),
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_ITEM_X, ATTR_COL(27),
X			PANEL_ITEM_Y, ATTR_ROW(0),
X			0);
X
X	(void) panel_create_item(filepanel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
X			file_reset, PANEL_LABEL_IMAGE,
X			panel_button_image(filepanel, "Reset", 5, font),
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_ITEM_X, ATTR_COL(35),
X			PANEL_ITEM_Y, ATTR_ROW(0),
X			0);
X
X	(void) panel_create_item(filepanel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
X			file_save, PANEL_LABEL_IMAGE,
X			panel_button_image(filepanel, "Update", 6, font),
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_ITEM_X, ATTR_COL(42),
X			PANEL_ITEM_Y, ATTR_ROW(0),
X			0);
X
X	(void) panel_create_item(filepanel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
X			file_done, PANEL_LABEL_IMAGE,
X			panel_button_image(filepanel, "Done", 4, font),
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_ITEM_X, ATTR_COL(50),
X			PANEL_ITEM_Y, ATTR_ROW(0),
X			0);
X
X	(void) panel_create_item(filepanel, PANEL_MESSAGE,
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_LABEL_STRING, "Enter the desired appointment file",
X			PANEL_LABEL_X, ATTR_COL(6),
X			PANEL_LABEL_Y, ATTR_ROW(2),
X			PANEL_LABEL_BOLD, TRUE,
X			0);
X
X	filename_pi = panel_create_item(filepanel, PANEL_TEXT,
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_LABEL_STRING, "Filename:",
X			PANEL_LABEL_BOLD, TRUE,
X			PANEL_VALUE, 0, PANEL_VALUE_STORED_LENGTH, 128,
X			PANEL_VALUE_DISPLAY_LENGTH, 30,
X			PANEL_ITEM_X, ATTR_COL(1),
X			PANEL_ITEM_Y, ATTR_ROW(3),
X			PANEL_BLINK_CARET, TRUE,
X			0);
X
X	window_fit(filepanel);
X	window_fit(fileframe);
X}
X
X/*
X * create a popup to display an error message
X */
Xcreate_prompt_frame(str1, buttonflag)
Xchar *str1;
X{
X	static Panel_item prompt_panel;
X	static Panel_item msg_pi, yes_pi, no_pi = 0;
X
X	if (!prompt_frame) {
X		/* create new frame and control panel */
X		prompt_frame = window_create(frame, FRAME, FRAME_NO_CONFIRM, TRUE,
X				FRAME_SHOW_LABEL, FALSE,
X				WIN_SHOW, TRUE,
X				WIN_X, ATTR_COL(15), WIN_Y, ATTR_ROW(15),
X				WIN_ERROR_MSG, "Can't create error frame.",
X				0);
X
X		prompt_panel = window_create(prompt_frame, PANEL,
X				PANEL_ACCEPT_KEYSTROKE, FALSE,
X				WIN_FONT, font,
X				0);
X	} else {
X		/* existing frame, delete the items */
X		panel_destroy_item(msg_pi);
X		panel_destroy_item(yes_pi);
X		if (no_pi) {
X			panel_destroy_item(no_pi);
X			no_pi = 0;
X		}
X	}
X	
X	/* create new message and button panel items */
X	msg_pi = panel_create_item(prompt_panel, PANEL_MESSAGE,
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_ITEM_X, ATTR_COL(1),
X			PANEL_ITEM_Y, ATTR_ROW(0),
X			PANEL_LABEL_STRING, str1,
X			PANEL_LABEL_BOLD, TRUE,
X			0);
X
X	if (buttonflag) {
X		yes_pi = panel_create_item(prompt_panel, PANEL_BUTTON,
X				PANEL_SHOW_ITEM, TRUE,
X				PANEL_ITEM_X, ATTR_COL(4),
X				PANEL_ITEM_Y, ATTR_ROW(2),
X				PANEL_NOTIFY_PROC, prompt_yes_notify,
X				PANEL_LABEL_IMAGE,
X				panel_button_image(prompt_panel, "Yes", 3, font),
X				0);
X
X		no_pi = panel_create_item(prompt_panel, PANEL_MESSAGE,
X				PANEL_SHOW_ITEM, TRUE,
X				PANEL_ITEM_X, ATTR_COL(12),
X				PANEL_ITEM_Y, ATTR_ROW(2),
X				PANEL_NOTIFY_PROC, prompt_no_notify,
X				PANEL_LABEL_IMAGE,
X				panel_button_image(prompt_panel, "No", 2, font),
X				0);
X	} else {
X		yes_pi = panel_create_item(prompt_panel, PANEL_MESSAGE,
X				PANEL_SHOW_ITEM, TRUE,
X				PANEL_ITEM_X, ATTR_COL(12),
X				PANEL_ITEM_Y, ATTR_ROW(2),
X				PANEL_NOTIFY_PROC, prompt_yes_notify,
X				PANEL_LABEL_IMAGE,
X				panel_button_image(prompt_panel, "Ok", 2, font),
X				0);
X	}
X
X	window_fit(prompt_panel);
X	window_fit(prompt_frame);
X}
X
X#ifndef NO_PRINTER
X/* create popup to change the printer */
Xcreate_print_frame()
X{
X	Panel prpanel;
X
X	prframe = window_create(frame, FRAME, FRAME_NO_CONFIRM, TRUE,
X			WIN_SHOW, FALSE, WIN_X, ATTR_COL(12),
X			FRAME_LABEL, "Change Printer",
X			FRAME_SHOW_LABEL, TRUE,
X			FRAME_DONE_PROC, prframe_done,
X			WIN_ERROR_MSG, "Can't create printer frame.",
X			0);
X
X	prpanel = window_create(prframe, PANEL, WIN_FONT, font,
X			WIN_ERROR_MSG, "Can't create printer panel.",
X			0);
X	
X	(void) panel_create_item(prpanel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
X			prdone_proc, PANEL_LABEL_IMAGE,
X			panel_button_image(prpanel, "Done", 4, font),
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_ITEM_X, ATTR_COL(34),
X			PANEL_ITEM_Y, ATTR_ROW(0),
X			0);
X
X	prfile_pi = panel_create_item(prpanel, PANEL_CYCLE,
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_ITEM_X, ATTR_COL(1),
X			PANEL_ITEM_Y, ATTR_ROW(1)+5,
X			PANEL_LABEL_STRING, "Destination:",
X			PANEL_LABEL_BOLD, TRUE,
X			PANEL_CHOICE_STRINGS, "Printer", "File Only", 0,
X			0);
X	
X	prcmd_pi = panel_create_item(prpanel, PANEL_TEXT,
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_ITEM_X, ATTR_COL(1),
X			PANEL_ITEM_Y, ATTR_ROW(2)+5,
X			PANEL_LABEL_STRING, "Print command:",
X			PANEL_LABEL_FONT, font,
X			PANEL_LABEL_BOLD, TRUE,
X			PANEL_VALUE_STORED_LENGTH, 128,
X			PANEL_VALUE_DISPLAY_LENGTH, 30,
X			PANEL_BLINK_CARET, TRUE,
X			0);
X	
X	panel_set_value(prcmd_pi, printer);
X	panel_set_value(prfile_pi, 0);
X	window_fit(prpanel);
X	window_fit(prframe);
X}
X#endif	/* NO_PRINTER */
X
X/* create popup to change the date */
Xcreate_date_frame()
X{
X	Panel dtpanel;
X	char date[9];
X
X	date_frame = window_create(frame, FRAME, FRAME_NO_CONFIRM, TRUE,
X			WIN_SHOW, FALSE, WIN_X, ATTR_COL(12),
X			FRAME_LABEL, "Change Current Date",
X			FRAME_SHOW_LABEL, TRUE,
X			FRAME_DONE_PROC, dtframe_done,
X			WIN_ERROR_MSG, "Can't create date frame.",
X			0);
X
X	dtpanel = window_create(date_frame, PANEL, WIN_FONT, font,
X			WIN_ERROR_MSG, "Can't create date panel.",
X			0);
X	
X	(void) panel_create_item(dtpanel, PANEL_BUTTON, PANEL_NOTIFY_PROC,
X			dtdone_proc, PANEL_LABEL_IMAGE,
X			panel_button_image(dtpanel, "Done", 4, font),
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_ITEM_X, ATTR_COL(34),
X			PANEL_ITEM_Y, ATTR_ROW(0),
X			0);
X
X	setdate_pi = panel_create_item(dtpanel, PANEL_TEXT,
X			PANEL_SHOW_ITEM, TRUE,
X			PANEL_ITEM_X, ATTR_COL(1),
X			PANEL_ITEM_Y, ATTR_ROW(1)+5,
X			PANEL_LABEL_STRING, (day_first ? "Enter date (D, D/M, or D/M/Y):" : "Enter date (D, M/D, or M/D/Y):"),
X			PANEL_LABEL_FONT, font,
X			PANEL_LABEL_BOLD, TRUE,
X			PANEL_VALUE_STORED_LENGTH, 10,
X			PANEL_VALUE_DISPLAY_LENGTH, 10,
X			PANEL_BLINK_CARET, TRUE,
X			0);
X	
X	if (day_first)
X		sprintf(date, "%d/%d/%02d", current.tm_mday, current.tm_mon+1, current.tm_year);
X	else
X		sprintf(date, "%d/%d/%02d", current.tm_mon+1, current.tm_mday, current.tm_year);
X	panel_set_value(setdate_pi, date);
X	window_fit(dtpanel);
X	window_fit(date_frame);
X}
X
X/* replace cursors with hourglass symbol to show we're waiting */
Xlock_cursors()
X{
X	panel_cursor = cursor_copy((Cursor) window_get(panel, WIN_CURSOR));
X	canvas_cursor = cursor_copy((Cursor) window_get(canvas, WIN_CURSOR));
X	window_set(panel, WIN_CURSOR, wait_cursor, 0);
X	window_set(canvas, WIN_CURSOR, wait_cursor, 0);
X	locked = 1;
X}
X
X/* restore cursors */
Xunlock_cursors()
X{
X	window_set(panel, WIN_CURSOR, panel_cursor, 0);
X	window_set(canvas, WIN_CURSOR, canvas_cursor, 0);
X	cursor_destroy(panel_cursor);
X	cursor_destroy(canvas_cursor);
X	locked = 0;
X}
END_OF_FILE
if test 33530 -ne `wc -c <'tool.c'`; then
    echo shar: \"'tool.c'\" unpacked with wrong size!
fi
# end of 'tool.c'
fi
echo shar: End of archive 11 \(of 23\).
cp /dev/null ark11isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 23 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.