[comp.sources.sun] v01i017: Calendar/planning tool: Part 08/09

mcgrew@dartagnan.rutgers.edu (Charles Mcgrew) (05/28/89)

Submitted-by: Bill Randle <billr@saab.cna.tek.com>
Posting-number: Volume 1, Issue 17
Archive-name: calentool/part08

#! /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:
#	std.icon
#	sunny.icon
#	tool.c
#	utils.c
#	version.c
#	week.cursor
#	wevent.c
#	wpaint.c
#	year.cursor
#	ypaint.c
# This archive created: Sat May 27 13:14:18 1989
export PATH; PATH=/bin:$PATH
echo shar: extracting "'std.icon'" '(2591 characters)'
if test -f 'std.icon'
then
	echo shar: will not over-write existing file "'std.icon'"
else
sed 's/^	X//' << \SHAR_EOF > 'std.icon'
	X/* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16
	X *
	X * $Header: std.icon,v 2.1 89/05/09 14:30:54 billr Exp $
	X *      Copyright (C) 1988, The Regents of the University of California
	X *                            All rights Reserved
	X *                       Author: R. P. C. Rodgers, M.D.
	X *
	X * Redistribution and use in source and binary forms are permitted
	X * provided that this notice is preserved and that due credit is given
	X * to the University of California at San Francisco. The name of the University
	X * may not be used to endorse or promote products derived from this
	X * software without specific prior written permission. This software
	X * is provided ``as is'' without express or implied warranty.
	X */
	X	0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8000,0x0000,0x0000,0x0001,
	X	0x8000,0x0000,0x0000,0x0001,0x8000,0x1800,0x0400,0x0181,
	X	0x81C6,0x0862,0x8F18,0x6081,0x8201,0x0893,0x4424,0x9081,
	X	0x8207,0x08E2,0x4424,0x9081,0x8209,0x0882,0x4424,0x9081,
	X	0x81C5,0x0872,0x4318,0x6081,0x8000,0x0000,0x0000,0x0001,
	X	0x8000,0x0001,0xE000,0x0001,0x8000,0x0007,0xF800,0x0001,
	X	0x8000,0x000C,0x0C00,0x0001,0x8000,0x0018,0x0600,0x0001,
	X	0x83FF,0xFFDB,0x36FF,0xFFF1,0x8600,0x0019,0x6600,0x0011,
	X	0x8E00,0x0019,0xA600,0x0011,0x9A00,0x0019,0x2600,0x0011,
	X	0x9200,0x0019,0x6600,0x0011,0x963F,0xFE19,0xA61F,0xFF11,
	X	0x9A00,0x0019,0x2600,0x0011,0x9200,0x003D,0x6F00,0x0011,
	X	0x963F,0xFE3D,0xAF1F,0xFF11,0x9A00,0x003D,0x2F00,0x0011,
	X	0x9200,0x0019,0x6600,0x0011,0x963F,0xFE01,0xA01F,0xFF11,
	X	0x9A00,0x0001,0x2000,0x0011,0x9200,0x0001,0x6000,0x0011,
	X	0x963F,0xFE01,0xA01F,0xFF11,0x9A00,0x0001,0x2000,0x0011,
	X	0x9200,0x0001,0x6000,0x0011,0x963F,0xFE00,0x001F,0xFF11,
	X	0x9A00,0x0001,0xE000,0x0011,0x9200,0x0007,0xF800,0x0011,
	X	0x963F,0xFE0C,0x0C1F,0xFF11,0x9A00,0x0019,0xA600,0x0011,
	X	0x9200,0x0019,0x2600,0x0011,0x963F,0xFE19,0x661F,0xFF11,
	X	0x9A00,0x0019,0xA600,0x0011,0x9200,0x0019,0x2600,0x0011,
	X	0x963F,0xFE19,0x661F,0xFF11,0x9A00,0x0019,0xA600,0x0011,
	X	0x9200,0x0019,0x2600,0x0011,0x963F,0xFE3D,0x6F1F,0xFF11,
	X	0x9A00,0x003D,0xAF00,0x0011,0x9200,0x003D,0x2F00,0x0011,
	X	0x9600,0x0019,0x6600,0x0011,0x9A00,0x0001,0xA000,0x0011,
	X	0x9200,0x0001,0x2000,0x0011,0x9600,0x0001,0x6000,0x0011,
	X	0x9A00,0x0001,0xA000,0x0011,0x9200,0x0001,0x2000,0x0011,
	X	0x9600,0x0001,0x6000,0x0011,0x9A00,0x0001,0xA000,0x0011,
	X	0x9200,0x0001,0x2000,0x0011,0x9600,0x0001,0x6000,0x0011,
	X	0x9A00,0x0001,0xA000,0x0011,0x93FF,0xFFFF,0x3FFF,0xFFF1,
	X	0x9649,0x2492,0x4924,0x9261,0x9C92,0x4924,0x9249,0x24C1,
	X	0x9FFF,0xFFFF,0xFFFF,0xFF81,0x8000,0x0000,0x0000,0x0001,
	X	0x8000,0x0000,0x0000,0x0001,0xFFFF,0xFFFF,0xFFFF,0xFFFF
SHAR_EOF
if test 2591 -ne "`wc -c < 'std.icon'`"
then
	echo shar: error transmitting "'std.icon'" '(should have been 2591 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'sunny.icon'" '(2593 characters)'
if test -f 'sunny.icon'
then
	echo shar: will not over-write existing file "'sunny.icon'"
else
sed 's/^	X//' << \SHAR_EOF > 'sunny.icon'
	X/* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16
	X *
	X * $Header: sunny.icon,v 2.1 89/05/09 14:30:58 billr Exp $
	X *      Copyright (C) 1989, The Regents of the University of California
	X *                            All rights Reserved
	X *                       Author: R. P. C. Rodgers, M.D.
	X *
	X * Redistribution and use in source and binary forms are permitted
	X * provided that this notice is preserved and that due credit is given
	X * to the University of California at San Francisco. The name of the University
	X * may not be used to endorse or promote products derived from this
	X * software without specific prior written permission. This software
	X * is provided ``as is'' without express or implied warranty.
	X */
	X	0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8001,0x0000,0x8800,0x0041,
	X	0x8840,0x9020,0x8844,0x0881,0x8840,0x9120,0x8848,0x0881,
	X	0x8420,0x4924,0x8848,0x1101,0x8220,0x4924,0x8A88,0x1101,
	X	0x8210,0x4914,0x9290,0x2205,0x8111,0x2494,0x9290,0x2209,
	X	0x8089,0x2494,0x9292,0x4409,0x8044,0x9494,0x9512,0x4811,
	X	0xA044,0x9294,0x9524,0x8821,0x9222,0x5252,0x9524,0x9041,
	X	0x8912,0x4A52,0x9529,0x1241,0x8491,0x2A4A,0x9549,0x2489,
	X	0x8289,0x255F,0xFE4A,0x4511,0xA244,0x95EA,0x83D2,0x4A21,
	X	0x9124,0x5720,0x02B4,0x9241,0x8892,0x7A00,0x000E,0x9481,
	X	0x8449,0x6800,0x0009,0x2881,0x8225,0xA000,0x0001,0xD101,
	X	0x8116,0x8000,0x0000,0xA221,0x808E,0x0000,0x0000,0x3443,
	X	0x846C,0x0000,0x0000,0x088D,0xE210,0x01E0,0x03C0,0x1511,
	X	0x91A8,0x8610,0x0430,0x8221,0x8C40,0x7808,0x000F,0x01C1,
	X	0x82A0,0x00C4,0x0980,0x0185,0xE180,0x01E4,0x0BE0,0x0059,
	X	0x9940,0x07E4,0x0BF0,0x0061,0x8600,0x0000,0x0800,0x0027,
	X	0xE504,0x07C0,0x09F8,0x0119,0x9C21,0x0000,0x0400,0x0431,
	X	0x8604,0x0000,0x0200,0x0093,0x8810,0x8028,0x0900,0x120D,
	X	0xC944,0x8028,0x0900,0x14A9,0xBC22,0x8028,0x0900,0x1005,
	X	0x9000,0x8018,0x0A00,0x114F,0x90C9,0x0004,0x3000,0x1805,
	X	0xF003,0xC003,0xC000,0x6605,0xA828,0x3000,0x0003,0x807F,
	X	0xA000,0x0E00,0x000C,0x01EB,0xA7E0,0x01E0,0x00F0,0x0355,
	X	0xBEBC,0x001F,0xFF00,0x06AB,0xD5D7,0x8000,0x0000,0x0D55,
	X	0xAAAA,0xE000,0x0000,0x1BAB,0xD555,0x5800,0x0700,0x355D,
	X	0xAEAA,0xAE00,0xF800,0x6AAB,0xD555,0x7500,0x0000,0xD55D,
	X	0xAAAB,0xAAC0,0x0001,0xAAAB,0xD555,0x5570,0x0003,0x5555,
	X	0xBAAB,0xAAA8,0x0006,0xAABB,0xD577,0xD554,0x000D,0x5755,
	X	0xAAAA,0xAAAA,0x001A,0xEAAB,0xD755,0x5D55,0x0075,0x5755,
	X	0xABAA,0xAAEA,0xE1EB,0xAFAB,0xD755,0x5555,0x5F55,0x5555,
	X	0xAFAB,0xAAEA,0xBAAA,0xAAAB,0xD7D5,0x5557,0x5755,0x5555,
	X	0xAFAA,0xAAAA,0xABEA,0xABAB,0xDFD5,0x5555,0x555D,0x555D,
	X	0xAAAA,0xAEAE,0xBABB,0xAAAB,0xD555,0x5555,0x5557,0x755D,
	X	0xAAAA,0xAEAA,0xAAAA,0xAABF,0xFFFF,0xFFFF,0xFFFF,0xFFFF
SHAR_EOF
if test 2593 -ne "`wc -c < 'sunny.icon'`"
then
	echo shar: error transmitting "'sunny.icon'" '(should have been 2593 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'tool.c'" '(30604 characters)'
if test -f 'tool.c'
then
	echo shar: will not over-write existing file "'tool.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'tool.c'
	X/*
	X * $Header: tool.c,v 2.1 89/05/09 14:23:08 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 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
	Xextern struct tm current;
	Xextern Frame frame;
	Xextern int working_msg;
	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;
	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;
	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;
	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;
	XFrame prframe;
	X#endif
	X#ifndef NO_SUN_MOON
	XCanvas scanvas, mcanvas;
	XPanel_item sdate_pi, mdate_pi;
	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();
	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 todays_date[];
	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[];
	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	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", 4, font),
	X			PANEL_EVENT_PROC, day_menu_event,
	X                        PANEL_NOTIFY_PROC, daybutton_notify,
	X			PANEL_ITEM_X, ATTR_COL(2),
	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", 5, font),
	X			PANEL_EVENT_PROC, week_menu_event,
	X                        PANEL_NOTIFY_PROC, weekbutton_notify,
	X			PANEL_ITEM_X, ATTR_COL(8),
	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", 6, font),
	X			PANEL_EVENT_PROC, month_menu_event,
	X                        PANEL_NOTIFY_PROC, monthmenu_notify,  
	X			PANEL_ITEM_X, ATTR_COL(15),
	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", 5, font),
	X			PANEL_EVENT_PROC, year_menu_event,
	X                        PANEL_NOTIFY_PROC, yearmenu_notify,
	X			PANEL_ITEM_X, ATTR_COL(23),
	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", 6, font),
	X                        PANEL_NOTIFY_PROC, todaybutton_notify,
	X			PANEL_ITEM_X, ATTR_COL(33),
	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", 5, 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", 6, 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", 9, 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", 8, 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,
	X			"Tommorow", "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", 5, 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	clock_pi = panel_create_item(panel, PANEL_MESSAGE,
	X			PANEL_ITEM_X, width-150-(strlen(todays_date)*font->pf_defaultsize.x),
	X			PANEL_ITEM_Y, ATTR_ROW(2)+3,
	X			PANEL_LABEL_STRING, todays_date,
	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(7), 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 ((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	/* font for displaying time under the icon */
	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_SHOW, TRUE, 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}
	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, "Every Day", "Selected Week",
	X			"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", 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	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(4),
	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(5),
	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_SHOW, TRUE, 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	} 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_SHOW, TRUE, WIN_X, ATTR_COL(12),
	X				FRAME_LABEL, "Lunar Data",
	X				FRAME_SHOW_LABEL, TRUE,
	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	} 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	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(1)+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	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, "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	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}
	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}
SHAR_EOF
if test 30604 -ne "`wc -c < 'tool.c'`"
then
	echo shar: error transmitting "'tool.c'" '(should have been 30604 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'utils.c'" '(31671 characters)'
if test -f 'utils.c'
then
	echo shar: will not over-write existing file "'utils.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'utils.c'
	X/*
	X * $Header: utils.c,v 2.2 89/05/16 16:30:18 billr Exp $
	X */
	X/*
	X * utils.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/********************************************
	X *					    *
	X *              Utility routines.	    *
	X *					    *
	X ********************************************/
	X
	X
	X
	X#include "ct.h"
	X#include <stdio.h>
	X#include <suntool/sunview.h>
	X#include <suntool/canvas.h>
	X#include <ctype.h>
	X#include <sys/types.h>
	X#include <sys/file.h>
	X#include <sys/stat.h>
	X#include <sys/errno.h>
	X
	X
	Xextern struct tm today, current;
	Xextern struct tm First;
	Xextern int day_is_open, read_only;
	Xextern struct dayslot slots[];
	Xextern char apts_pathname[], tmpapts_pathname[];
	Xextern int dayslot_width, nr_weekdays, n_tslots;
	Xextern int dayslot_height;
	Xextern char *monthnames[], *daynames[];
	Xextern char *mailto, *progname;
	Xextern int one_based, version2, new_entry;
	Xextern int findex;
	Xextern struct appt_entry future[];
	Xextern char todays_date[];
	Xextern char apts_dir[], lib_dir[];
	Xextern char printer[];
	Xextern int include_old, save_old;
	Xextern Frame frame;
	Xextern Canvas canvas;
	Xextern Pixwin *main_pixwin;
	Xextern int mainsw_state;
	Xextern Pixfont *font, *sfont;
	Xextern Frame prompt_frame;
	Xextern int update_interval;
	Xextern int errno;
	X
	Xchar inbuf[512], strbuf[256], errbuf[64];
	Xchar todays_date[32];
	Xstatic int including;
	Xstatic int log_to_console;
	Xchar *daynames[] = {"Sunday","Monday","Tuesday","Wednesday",
	X			   "Thursday","Friday","Saturday"};
	Xchar *monthnames[] = {"January","February","March","April",
	X			     "May","June","July","August",
	X			     "September","October","November","December"};
	Xchar *dayname[7] = {"SU", "MO", "TU", "WE", "TH", "FR", "SA"};
	Xchar rasfile[] = "/usr/tmp/calentool.ras";
	Xchar psfile[] = "/usr/tmp/calentool.ps";
	Xchar *fname = 0;
	X
	Xextern char *strcpy(), *strcat();
	X
	X/*
	X * sets "today" and current time
	X */
	Xvoid
	Xget_today()
	X{
	X	struct tm *tm;
	X	struct timeval tv;
	X
	X	gettimeofday(&tv, 0);
	X	tm = localtime(&tv.tv_sec);
	X
	X	today = *tm;
	X
	X	strcpy(todays_date, asctime(tm));
	X	if (update_interval >= 60)
	X		/* overwrite seconds field with year */
	X		sprintf(&todays_date[16], " %d", today.tm_year+1900);
	X	else
	X		/* just delete trailing \n */
	X		todays_date[strlen(todays_date)-1] = '\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
	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
	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 *
	X * Append data from active timeslots to end of "tmp.appointments"
	X * file, then copy "tmp.appointments" to "appointments".  Note that
	X * when we opened the current day we filtered "appointments":
	X * all items that applied to the current day were displayed and
	X * stored in slots; all others were copied to "tmp.appointments".
	X * So by now "tmp.appointments" contains no entries for the
	X * current day.
	X * As an optimization, if nothing changed in the day then the
	X * original appointments file is left unchanged.
	X *
	X */
	X
	Xclose_day()
	X{
	X        int i, j;
	X        FILE *f;
	X	struct stat sbuf;
	X	struct appt_entry *aptr, *optr;
	X
	X	if (read_only || !new_entry) {
	X		new_entry = 0;
	X		day_is_open = FALSE;
	X		return(0);
	X	}
	X
	X	f = fopen(tmpapts_pathname, "a+");
	X	if (f == NULL) {
	X		err_rpt("can't open temp file for appending", NON_FATAL);
	X		day_is_open = FALSE;
	X		return(1);
	X	}
	X	
	X	for (i=0; i<N_SLOTS; i++) {
	X                if (slots[i].first != NULL) {
	X			aptr = slots[i].first;
	X			if (put_aentry(f, aptr))
	X				/* write error */
	X				break;
	X			optr = aptr;
	X			while (aptr = aptr->next) {
	X				free(optr);
	X				if (put_aentry(f, aptr))
	X					/* write error */
	X					break;
	X				optr = aptr;
	X			}
	X			free(optr);
	X		}
	X        }
	X	if (ferror(f))
	X		err_rpt("write on temp file failed", FATAL);
	X        fclose(f);
	X	new_entry = 0;
	X	day_is_open = FALSE;
	X	/* don't rename zero length files */
	X	stat(tmpapts_pathname, &sbuf);
	X	if (sbuf.st_size == (off_t) 0)
	X		return(1);
	X	xrename(tmpapts_pathname, apts_pathname);
	X}
	X
	X/*
	X * get entry from appointments file
	X */
	Xget_aentry(apts_file, appt)
	XFILE *apts_file;
	Xstruct appt_entry *appt;
	X{
	X	char *ptr, *str;
	X	char *fgets(), *index();
	X	char *incl_ptr, incl_buf[128], wday[3];
	X	int i, lib;
	X	struct stat sbuf;
	X	static FILE *include;
	X
	X	appt->flags = appt->repeat = appt->lookahead = 0;
	X	appt->sindex = 0;
	X	appt->next = NULL;
	X	if (including) {
	X		if (fgets(inbuf, 512, include) == NULL) {
	X			/* end of include file - get next entry
	X			 * from main file
	X			 */
	X			including = 0;
	X			fclose(include);
	X			if (fgets(inbuf, 512, apts_file) == NULL)
	X				return(EOF);
	X		} else {
	X			including = 2;
	X			/* don't modify stuff from include files */
	X			appt->flags |= READONLY;
	X		}
	X	} else
	X		if (fgets(inbuf, 512, apts_file) == NULL)
	X			return(EOF);
	X	ptr = inbuf;
	X	if (*ptr == '#') {
	X		if (!strcmp(inbuf, HEADER) && !including) {
	X			/* first line in file read */
	X			if (include_old && (First.tm_year < today.tm_year)) {
	X				/* read in old include file (if it exists) */
	X				/* prepend directory info */
	X				sprintf(incl_buf, "%s/.appointments.%02d",
	X					apts_dir, First.tm_year);
	X				if (!stat(incl_buf, &sbuf)) {
	X					if ((include = fopen(incl_buf, "r")) == NULL)
	X						err_rpt("can't open include file (ignored)", NON_FATAL);
	X					else
	X						including = 1;
	X				}
	X			}
	X		} else if (!strncmp(inbuf, "#include", 8)) {
	X			/* include file */
	X			if (including)
	X				err_rpt("include files may not be nested", FATAL);
	X			incl_ptr = strbuf;
	X			if ((ptr = index(inbuf, '"')) == NULL)
	X
	X				if ((ptr = index(inbuf, '<')) == NULL) {
	X					err_rpt("missing '\"' or '<' in include file spec", NON_FATAL);
	X					return(0);
	X				} else {
	X					lib = 1;
	X				}
	X			else
	X				lib = 0;
	X			ptr++;
	X			while (*ptr && *ptr != '"' && *ptr != '>')
	X				*incl_ptr++ = *ptr++;
	X			if (! *ptr) {
	X				err_rpt("missing '\"' or '>' in include file spec", NON_FATAL);
	X				return(0);
	X			}
	X			*incl_ptr = '\0';
	X			if (strbuf[0] == '/')
	X				/* full pathname provided */
	X				strcpy(incl_buf, strbuf);
	X			else
	X				/* prepend directory info */
	X				if (lib)
	X					sprintf(incl_buf, "%s/%s", lib_dir, strbuf);
	X				else
	X					sprintf(incl_buf, "%s/%s", apts_dir, strbuf);
	X			if ((include = fopen(incl_buf, "r")) == NULL)
	X				err_rpt("can't open include file (ignored)", NON_FATAL);
	X			else 
	X				including = 1;
	X		}
	X		appt->flags |= A_COMMENT;
	X		return(0);
	X	}
	X	while (isspace(*ptr))
	X		++ptr;
	X	if (!*ptr) {
	X		/* empty line */
	X		appt->flags |= A_COMMENT;
	X		return(0);
	X	}
	X	if (*ptr == '*') {
	X		appt->flags |= ALL_YEARS;
	X		appt->year = START_YEAR;
	X		++ptr;	/* point to second '*' */
	X		++ptr;	/* point to space */
	X	} else {
	X		appt->year = 0;
	X		while (isdigit(*ptr)) {
	X			appt->year *= 10;
	X			appt->year += *ptr++ - '0';
	X		}
	X		/* sanity check */
	X		if (appt->year < 0) {
	X			err_rpt("illegal year value (ignored)", NON_FATAL);
	X			return(1);
	X		}
	X	}
	X	while (isspace(*ptr))
	X		++ptr;
	X	if (*ptr == '*') {
	X		appt->flags |= ALL_MONTHS;
	X		appt->month = 0;
	X		++ptr;
	X	} else {
	X		appt->month = (*ptr - '0') * 10;
	X		appt->month += *++ptr - '0';
	X		if (one_based) (appt->month)--;
	X		/* sanity check */
	X		if (appt->month < JAN || appt->month > DEC) {
	X			/*
	X			sprintf(errbuf, "illegal month value [%d] (ignored)", appt->month);
	X			err_rpt(errbuf, NON_FATAL);
	X			*/
	X			err_rpt("illegal month value (ignored)", NON_FATAL);
	X			return(1);
	X		}
	X	}
	X	++ptr;
	X	while (isspace(*ptr))
	X		++ptr;
	X	if (*ptr == '*') {
	X		appt->flags |= ALL_DAYS;
	X		appt->day = 0;
	X		appt->repeat = 1;
	X		++ptr;
	X	} else if (isdigit(*ptr)) {
	X		appt->day = (*ptr - '0') * 10;
	X		appt->day += *++ptr - '0';
	X		if (!one_based) (appt->day)++;
	X		/* sanity check */
	X		if (appt->day < 1 || appt->day > 31) {
	X			err_rpt("illegal day value (ignored)", NON_FATAL);
	X			return(1);
	X		}
	X	} else {
	X		/* check for day names */
	X		wday[0] = islower(*ptr) ? toupper(*ptr) : *ptr;
	X		++ptr;
	X		wday[1] = islower(*ptr) ? toupper(*ptr) : *ptr;
	X		wday[2] = '\0';
	X		i = 0;
	X		if (!strcmp(wday, dayname[i++]))
	X			appt->flags |= EVERY_SUN;
	X		else if (!strcmp(wday, dayname[i++]))
	X			appt->flags |= EVERY_MON;
	X		else if (!strcmp(wday, dayname[i++]))
	X			appt->flags |= EVERY_TUE;
	X		else if (!strcmp(wday, dayname[i++]))
	X			appt->flags |= EVERY_WED;
	X		else if (!strcmp(wday, dayname[i++]))
	X			appt->flags |= EVERY_THU;
	X		else if (!strcmp(wday, dayname[i++]))
	X			appt->flags |= EVERY_FRI;
	X		else if (!strcmp(wday, dayname[i]))
	X			appt->flags |= EVERY_SAT;
	X		else {
	X			/* sanity check */
	X			err_rpt("illegal day name (ignored)", NON_FATAL);
	X			return(1);
	X		}
	X		appt->day = 0;
	X		appt->flags |= REPEAT;
	X		appt->repeat = ALL_WEEKS;	/* default to every week */
	X	}
	X	++ptr;
	X	while (isspace(*ptr))
	X		++ptr;
	X	appt->hour = (*ptr - '0') * 10;
	X	appt->hour += *++ptr - '0';
	X	/* sanity check */
	X	if (appt->hour < 0 || (appt->hour > 23 && appt->hour != 99)) {
	X		err_rpt("illegal hour value (ignored)", NON_FATAL);
	X		return(1);
	X	}
	X	if ((version2 && appt->hour == 99) || (!version2 && appt->hour == 0))
	X		appt->flags |= A_NOTE;
	X	++ptr;
	X	while (isspace(*ptr))
	X		++ptr;
	X	appt->minute = (*ptr - '0') * 10;
	X	appt->minute += *++ptr - '0';
	X	/* sanity check */
	X	if (appt->minute < 0 || (appt->minute > 59 && appt->minute != 99)) {
	X		/* minutes currently can only be 00 or 30
	X		 * unless it's a note.
	X		 */
	X		err_rpt("illegal minute value (ignored)", NON_FATAL);
	X		return(1);
	X	}
	X	if ((appt->flags & A_NOTE) && version2 && appt->minute == 99)
	X		appt->flags |= MARKED;  /* don't show in mon/yr display */
	X	++ptr;
	X	while (isspace(*ptr))
	X		++ptr;
	X	appt->arrows = (*ptr - '0') * 10;
	X	appt->arrows += *++ptr - '0';
	X	/* sanity check */
	X	if (appt->arrows < 0 || appt->arrows > N_TSLOTS) {
	X		err_rpt("illegal arrow value (ignored)", NON_FATAL);
	X		return(1);
	X	}
	X	++ptr;
	X	while (isspace(*ptr))
	X		++ptr;
	X	/* lookahead and repeat entries are free format, i.e. they */
	X	/* can occur in either order */
	X	if (*ptr == '[') {
	X		appt->flags |= REPEAT;
	X		if (appt->flags & EVERY_SOMEDAY) {
	X			if ((appt->repeat = do_wk_repeat(&ptr)) < 0)
	X				return(1);
	X		} else {
	X			if ((appt->repeat = do_repeat(&ptr)) < 0)
	X				return(1);
	X		}
	X		if (*ptr == '<') {
	X			appt->flags |= LOOKAHEAD;
	X			if ((appt->lookahead = do_lookahead(&ptr)) < 0)
	X				return(1);
	X		}
	X		if (*ptr == '#') {
	X			appt->flags |= DELETED;
	X			++ptr;
	X			while (isspace(*ptr))
	X				++ptr;
	X		}
	X	} else if (*ptr == '<') {
	X		appt->flags |= LOOKAHEAD;
	X		if ((appt->lookahead = do_lookahead(&ptr)) < 0)
	X			return(1);
	X		if (*ptr == '[') {
	X			appt->flags |= REPEAT;
	X			if (appt->flags & EVERY_SOMEDAY) {
	X				if ((appt->repeat = do_wk_repeat(&ptr)) < 0)
	X					return(1);
	X			} else {
	X				if ((appt->repeat = do_repeat(&ptr)) < 0)
	X					return(1);
	X			}
	X		}
	X		if (*ptr == '#') {
	X			appt->flags |= DELETED;
	X			++ptr;
	X			while (isspace(*ptr))
	X				++ptr;
	X		}
	X	} else if (*ptr == '#') {
	X		appt->flags |= DELETED;
	X		++ptr;
	X		while (isspace(*ptr))
	X			++ptr;
	X	}
	X	str = strbuf;
	X	while (*ptr && *ptr != '\n')
	X		*str++ = *ptr++;
	X	*str = '\0';
	X	strcpy(appt->str, strbuf);
	X
	X	return(0);
	X}
	X
	X/* parse normal repeated entry field */
	Xdo_repeat(ptr)
	Xchar **ptr;
	X{
	X	int repeat = 0;
	X
	X	while (isdigit(*++*ptr))
	X		repeat = repeat * 10 + (int)(**ptr - '0');
	X	if (**ptr != ']') {
	X		err_rpt("bad entry (ignored)", NON_FATAL);
	X		return(-1);
	X	}
	X	/* sanity check */
	X	if (repeat < 0) {
	X		err_rpt("illegal repeat interval (ignored)", NON_FATAL);
	X		return(-1);
	X	}
	X	++*ptr;
	X	while (isspace(**ptr))
	X		++*ptr;
	X	return(repeat);
	X}
	X
	X/* parse weekly repeated entry field */
	Xdo_wk_repeat(ptr)
	Xchar **ptr;
	X{
	X	int repeat = 0;
	X
	X	while (*++*ptr != ']') {
	X		if (**ptr == ',')
	X			continue;	/* get next week */
	X		if (isdigit(**ptr)) {
	X			repeat |= 0x1<<(**ptr - '1');
	X		} else if (**ptr == 'L' || **ptr == 'l') {
	X			/* last week in month */
	X			repeat |= LAST_WEEK;
	X		} else {
	X			/* format error */
	X			err_rpt("illegal repeat specification (ignored)", NON_FATAL);
	X			return(-1);
	X		}
	X	}
	X	/* sanity check */
	X	if ((unsigned int)repeat > WEEK_LIMIT) {
	X		err_rpt("illegal weekly repeat (ignored)", NON_FATAL);
	X		return(-1);
	X	}
	X	++*ptr;
	X	while (isspace(**ptr))
	X		++*ptr;
	X
	X	return(repeat);
	X}
	X
	X/* parse lookahead entry field */
	Xdo_lookahead(ptr)
	Xchar **ptr;
	X{
	X	int lookahead = 0;
	X
	X	while (isdigit(*++*ptr))
	X		lookahead = lookahead * 10 + (int)(**ptr - '0');
	X	if (**ptr != '>') {
	X		err_rpt("bad entry (ignored)", NON_FATAL);
	X		return(-1);
	X	}
	X	/* sanity check */
	X	if (lookahead < 0) {
	X		err_rpt("illegal lookahead interval (ignored)", NON_FATAL);
	X		return(-1);
	X	}
	X	++*ptr;
	X	while (isspace(**ptr))
	X		++*ptr;
	X	return(lookahead);
	X}
	X
	X/*
	X * put entry into appointments file
	X */
	Xput_aentry(apts_file, appt)
	XFILE *apts_file;
	Xstruct appt_entry *appt;
	X{
	X	char *to_str();
	X
	X	if (read_only)
	X		return(0);
	X
	X	if (appt->flags & READONLY)
	X		/* don't copy include file entries */
	X		/* (the include directive is copied as a comment) */
	X		return(0);
	X	if (appt->flags & A_COMMENT) {
	X		fputs(inbuf, apts_file);
	X		return(ferror(apts_file));
	X	}
	X	if (appt->flags & ALL_YEARS)
	X		fputs("** ", apts_file);
	X	else if (appt->year > 99)
	X		fprintf(apts_file, "%03d ", appt->year);
	X	else
	X		fprintf(apts_file, "%02d ", appt->year);
	X	if (appt->flags & ALL_MONTHS)
	X		fputs("** ", apts_file);
	X	else
	X		fprintf(apts_file, "%02d ", one_based ? appt->month+1 : appt->month);
	X	if (appt->flags & ALL_DAYS)
	X		fputs("** ", apts_file);
	X	else if (appt->flags & EVERY_SOMEDAY) {
	X		switch (appt->flags & EVERY_SOMEDAY) {
	X			case EVERY_SUN:
	X				fputs("Su ", apts_file);
	X				break;
	X			case EVERY_MON:
	X				fputs("Mo ", apts_file);
	X				break;
	X			case EVERY_TUE:
	X				fputs("Tu ", apts_file);
	X				break;
	X			case EVERY_WED:
	X				fputs("We ", apts_file);
	X				break;
	X			case EVERY_THU:
	X				fputs("Th ", apts_file);
	X				break;
	X			case EVERY_FRI:
	X				fputs("Fr ", apts_file);
	X				break;
	X			case EVERY_SAT:
	X				fputs("Sa ", apts_file);
	X				break;
	X		}
	X	} else
	X		fprintf(apts_file, "%02d ", one_based ? appt->day : appt->day-1);
	X	if (appt->flags & A_NOTE) {
	X		appt->hour = 99;
	X		appt->minute = 0;	/* assume unmarked note */
	X	}
	X	if ((appt->flags & MARKED_NOTE) == MARKED_NOTE)
	X		appt->minute = 99;
	X	if (!(appt->flags & (ALL_DAYS|DELETED)) && appt->flags & REPEAT) {
	X		if (appt->flags & EVERY_SOMEDAY)
	X			fprintf(apts_file, "%02d %02d %02d %s ", appt->hour, appt->minute, appt->arrows, to_str(appt->repeat));
	X		else
	X			fprintf(apts_file, "%02d %02d %02d [%d] ", appt->hour, appt->minute, appt->arrows, appt->repeat);
	X	} else
	X		fprintf(apts_file, "%02d %02d %02d ", appt->hour, appt->minute, appt->arrows);
	X
	X	if (appt->flags & LOOKAHEAD)
	X		fprintf(apts_file, "<%d> ", appt->lookahead);
	X	if (appt->flags & DELETED)
	X		fprintf(apts_file, "# %s\n", appt->str);
	X	else
	X		fprintf(apts_file, "%s\n", appt->str);
	X	
	X	/* check for failure (e.g. file system full) */
	X	return(ferror(apts_file));
	X}
	X
	Xchar rptstr[10];
	X
	X/* convert repeat bit map to printable string */
	Xchar *
	Xto_str(repeat)
	Xint repeat;
	X{
	X	int i, j = 0;
	X
	X	if (repeat == ALL_WEEKS)
	X		/* if it's every week, then don't write [] spec */
	X		rptstr[0] = '\0';
	X	else {
	X		rptstr[j++] = '[';
	X		for (i=0; i<5; i++) {
	X			if (repeat & (0x1<<i)) {
	X				rptstr[j++] = i+1 + '0';
	X				rptstr[j++] = ',';
	X			}
	X		}
	X		if (repeat & LAST_WEEK) {
	X			rptstr[j++] = 'L';
	X			rptstr[j++] = ',';
	X		}
	X		rptstr[j] = '\0';
	X		rptstr[--j] = ']';
	X	}
	X	return (rptstr);
	X}
	X
	X/*
	X * Print today's appointments to stdout or mail (useful if we only have an ASCII
	X * terminal connected to our Sun). Invoked by the "-p", "-P" or "-m" options.
	X */
	Xprint_apts(level)
	Xint level;
	X{
	X	int i;
	X	FILE *output, *popen();
	X	char cmd[80], *name, *cuserid(), *format_appt();
	X	struct appt_entry tmp_apt, *sptr;
	X
	X	fix_current_day();
	X	get_day_appts();
	X	if (level == 2) {
	X		if (mailto != NULL) {
	X			name = mailto;
	X		} else if ((name = cuserid(NULL)) == NULL) {
	X			err_rpt("nobody to mail to", FATAL);
	X		}
	X		sprintf(cmd, "mail -s \"Appointments for today\" %s", name);
	X		if ((output = popen(cmd, "w")) == NULL)
	X			err_rpt("Couldn't pipe to 'mail'", FATAL);
	X	} else {
	X		output = stdout;
	X	}
	X	
	X	fprintf(output,"\n\t*** Appointments for %s %s %d, 19%02d ***\n\n", 
	X		daynames[current.tm_wday], monthnames[current.tm_mon],
	X		current.tm_mday, current.tm_year);
	X	
	X	for (i=0; i<N_SLOTS; i++) {
	X		if (i == n_tslots)
	X			/* start of notes section */
	X			fprintf(output,"\n\t\t     ===== Notes =====\n");
	X		if (slots[i].first != NULL && slots[i].count > 0) {
	X			/* at least one appt here */
	X			slots[i].cur_appt = slots[i].first;
	X			do {
	X				if (level == 3 && ((slots[i].cur_appt->flags & MARKED_NOTE) == MARKED_NOTE))
	X					continue;
	X				if (chk_deleted(i))
	X					continue;
	X				tmp_apt = *slots[i].cur_appt;
	X				tmp_apt.year = current.tm_year;
	X				tmp_apt.month = current.tm_mon;
	X				tmp_apt.day = current.tm_mday;
	X				fprintf(output, "%s\n", format_appt(&tmp_apt));
	X			} while ((slots[i].cur_appt = slots[i].cur_appt->next) != NULL);
	X		}
	X	}
	X	if (findex) {
	X		/* print out future appointments */
	X		fprintf(output, "\n\t\t===== Future Reminders =====\n");
	X		for (i=0; i<findex; i++)
	X			fprintf(output, "%s\n", format_appt(&future[i]));
	X	}
	X	fflush(output);
	X	if (level == 2)
	X		pclose(output);
	X}
	X
	X/*
	X * Convert from version 1 appts files to version 2 file format.
	X */
	Xver1to2()
	X{
	X	FILE *oappts, *nappts, *fp;
	X	struct appt_entry appt;
	X	int err_flag, save_base;
	X	char save_file[128];
	X	struct stat stbuf;
	X
	X	/*
	X	 * The main difference is that the ver 2 files are one-based, i.e
	X	 * days and months start with 1, rather than 0. Another difference
	X	 * is that a hour entry of 99 is used to flag a memo entry, rather
	X	 * than 00. This allows for 24-hour appointments.
	X	 * Version 2 appts files are marked with a special header line
	X	 * defined by the HEADER string (in ct.h).  Version 2 files
	X	 * also support a "lookahead" reminder service to remind one
	X	 * in advance of a future appointment.
	X	 * If "save_old" is set, then any appointments for years prior
	X	 * to this one are save in a special file of the form
	X	 * ".appointments.YY", where YY is the year.
	X	 */
	X
	X	if (read_only != 0) {
	X		err_rpt("appts file is read-only, no conversion done", NON_FATAL);
	X		return;
	X	}
	X
	X	 /* open files, etc */
	X	if ((oappts = fopen(apts_pathname, "r")) == NULL) {
	X		err_rpt("can't open appts file for reading", FATAL);
	X		/* NOT REACHED */
	X	 }
	X	if ((nappts = fopen(tmpapts_pathname, "w")) == NULL) {
	X		err_rpt("can't open temp file for writing", NON_FATAL);
	X		return;
	X	 }
	X	 /* write new header line */
	X	 fputs(HEADER, nappts);
	X
	X	 /* copy existing entries to the new file */
	X	 save_base = one_based;
	X	 while ((err_flag = get_aentry(oappts, &appt)) != EOF) {
	X		if (err_flag)
	X			continue;	/* ignore badly formatted input */
	X		if (appt.hour == 0)
	X			appt.flags |= A_NOTE;
	X		one_based = 1;		/* force new format output */
	X		if (save_old && !(appt.flags & ALL_YEARS) && (appt.year < today.tm_year)
	X		   && !((appt.flags & REPEAT) && !(appt.flags & EVERY_SOMEDAY))
	X		   && !(appt.flags & A_COMMENT)) {
	X			/* prepend directory info */
	X			sprintf(save_file, "%s/.appointments.%02d",
	X				apts_dir, appt.year);
	X			if (stat(save_file, &stbuf) && errno == ENOENT) {
	X				/* new file*/
	X				if ((fp = fopen(save_file, "w")) == NULL)
	X					err_rpt("can't open save file, bailing out", FATAL);
	X				fputs(HEADER, fp);
	X				fclose(fp);
	X			}
	X			if ((fp = fopen(save_file, "a+")) == NULL)
	X				err_rpt("can't open save file, bailing out", FATAL);
	X			else {
	X				if (put_aentry(fp, &appt))
	X					err_rpt("write to save appt file failed, bailing out", FATAL);
	X				fclose(fp);
	X			}
	X		} else {
	X			if (put_aentry(nappts, &appt))
	X				err_rpt("write to new appt file failed, bailing out", FATAL);
	X		}
	X		one_based = save_base;	/* (maybe) force old format input */
	X	}
	X	fclose(oappts);
	X	fclose(nappts);
	X	xrename(tmpapts_pathname, apts_pathname);
	X	one_based = 1;
	X	version2 = 1;
	X}
	X
	X/*
	X * Scan appointments file for outdated appointments and save them to a
	X * special file of the form ".appointments.YY", where YY is the year
	X * of that appointment.
	X */
	Xcreate_old_files()
	X{
	X	FILE *oappts, *nappts, *fp;
	X	struct appt_entry appt;
	X	int err_flag;
	X	char save_file[128];
	X	struct stat stbuf;
	X
	X	if (read_only != 0) {
	X		err_rpt("appts file is read-only, no conversion done", NON_FATAL);
	X		return;
	X	}
	X
	X	 /* open files, etc */
	X	if ((oappts = fopen(apts_pathname, "r")) == NULL) {
	X		err_rpt("can't open appts file for reading", FATAL);
	X		/* NOT REACHED */
	X	 }
	X	if ((nappts = fopen(tmpapts_pathname, "w")) == NULL) {
	X		err_rpt("can't open temp file for writing", NON_FATAL);
	X		return;
	X	 }
	X
	X	 /* copy existing entries to the tmp file, checking dates */
	X	 while ((err_flag = get_aentry(oappts, &appt)) != EOF) {
	X		if (err_flag)
	X			continue;	/* ignore badly formatted input */
	X		if (!(appt.flags & A_COMMENT)
	X		   && !(appt.flags & ALL_YEARS) && (appt.year < today.tm_year)
	X		   && !((appt.flags & REPEAT) && !(appt.flags & EVERY_SOMEDAY))) {
	X			/* prepend directory info */
	X			sprintf(save_file, "%s/.appointments.%02d",
	X				apts_dir, appt.year);
	X			if (stat(save_file, &stbuf) && errno == ENOENT) {
	X				/* new file*/
	X				if ((fp = fopen(save_file, "w")) == NULL)
	X					err_rpt("can't open save file, bailing out", FATAL);
	X				fputs(HEADER, fp);
	X				fclose(fp);
	X			}
	X			if ((fp = fopen(save_file, "a+")) == NULL)
	X				err_rpt("can't open save file, bailing out", FATAL);
	X			else {
	X				if (put_aentry(fp, &appt))
	X					err_rpt("write to save appt file failed, bailing out", FATAL);
	X				fclose(fp);
	X			}
	X		} else {
	X			if (put_aentry(nappts, &appt))
	X				err_rpt("write to new appt file failed, bailing out", FATAL);
	X		}
	X	}
	X	fclose(oappts);
	X	fclose(nappts);
	X	xrename(tmpapts_pathname, apts_pathname);
	X}
	X
	X/*
	X * convert appt entry to ASCII string for display with date, time and msg
	X */
	Xchar *
	Xformat_appt(appt)
	Xstruct appt_entry *appt;
	X{
	X	int e_hour, e_minutes, duration;
	X	struct tm Save;
	X
	X	if (appt->arrows > 0) {
	X		duration = appt->arrows + 1;
	X		e_hour = appt->hour + duration/2;
	X		e_minutes = appt->minute + ((duration%2) * 30);
	X	} else {
	X		e_hour = appt->hour;
	X		e_minutes = appt->minute + 30;
	X	}
	X	if (e_minutes == 60) {
	X		e_minutes = 0;
	X		++e_hour;
	X	}
	X	/* get day of week */
	X	Save = current;
	X	current.tm_year = appt->year;
	X	current.tm_mon = appt->month;
	X	current.tm_mday = appt->day;
	X	fix_current_day();
	X
	X	if (appt->flags & A_NOTE) {
	X		/* note */
	X		if (appt->flags & ALL_YEARS)
	X			sprintf(strbuf,"%3.3s %2d/%02d    --  %s",
	X				daynames[current.tm_wday], appt->month+1,
	X				appt->day, appt->str);
	X		else if (appt->year > 99)
	X			sprintf(strbuf,"%3.3s %2d/%02d/%02d --  %s",
	X				daynames[current.tm_wday], appt->month+1,
	X				appt->day, appt->year-100, appt->str);
	X		else
	X			sprintf(strbuf,"%3.3s %2d/%02d/%02d --  %s",
	X				daynames[current.tm_wday], appt->month+1,
	X				appt->day, appt->year, appt->str);
	X	} else
	X		/* standard appointment */
	X		sprintf(strbuf,"%3.3s %2d/%02d/%02d -- %2d:%02d to %2d:%02d   %s",
	X			daynames[current.tm_wday], appt->month+1,
	X			appt->day, appt->year, appt->hour, appt->minute,
	X			e_hour, e_minutes, appt->str);
	X
	X	current = Save;
	X	return(strbuf);
	X}
	X
	X/*
	X * convert appt entry to ASCII string for display with time and msg
	X */
	Xchar *
	Xformat_appt_nd(appt)
	Xstruct appt_entry *appt;
	X{
	X	int e_hour, e_minutes, duration;
	X	struct tm Save;
	X
	X	if (appt->arrows > 0) {
	X		duration = appt->arrows + 1;
	X		e_hour = appt->hour + duration/2;
	X		e_minutes = appt->minute + ((duration%2) * 30);
	X	} else {
	X		e_hour = appt->hour;
	X		e_minutes = appt->minute + 30;
	X	}
	X	if (e_minutes == 60) {
	X		e_minutes = 0;
	X		++e_hour;
	X	}
	X
	X	if (appt->flags & A_NOTE) {
	X		/* note */
	X		sprintf(strbuf,"%s", appt->str);
	X	} else
	X		/* standard appointment */
	X		sprintf(strbuf,"%2d:%02d to %2d:%02d   %s",
	X			appt->hour, appt->minute, e_hour, e_minutes, appt->str);
	X
	X	return(strbuf);
	X}
	X
	X/*
	X * parse the date on the given tring 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 */
	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				}
	X			}
	X		}
	X		if (y > 0)
	X			current.tm_year = y;
	X		if (m > 0)
	X			current.tm_mon = m - 1;
	X		if (d > 0)
	X			current.tm_mday = d;
	X		fix_current_day();
	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		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			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
	X#ifndef NO_PRINTER
	X/*
	X * Print to Postscript compatable printer.  If we are displaying
	X * the day or week page, then create a raster file of the canvas and
	X * feed it to a raster->ps filter (sun2ps).  If on a month page, then
	X * print a pretty month calendar with appts written in (as best
	X * can be).
	X */
	Xprint_calendar(file_type)
	Xint file_type;
	X{
	X	Pixrect *save_pr;
	X	char prntcmd[64];
	X	int type = RT_STANDARD;
	X	int copy_flag = TRUE;
	X	Rect *rect;
	X	struct pr_prpos where;
	X	char buf[128], *cuserid();
	X	FILE *fp, *pfp;
	X
	X	lock_cursors();
	X	working(TRUE);
	X	sprintf(buf, "Appointments file \"%s\" printed for %s on %s", apts_pathname, cuserid(NULL), todays_date);
	X	if (mainsw_state != DISPLAYING_MONTH) {
	X		if ((fp = fopen(rasfile, "w")) != NULL) {
	X			rect = (Rect *) window_get(canvas, WIN_RECT);
	X			save_pr = mem_create(rect->r_width, rect->r_height+3*sfont->pf_defaultsize.y, 1);
	X			pr_rop(save_pr,0,0,rect->r_width-3,rect->r_height,PIX_SRC,main_pixwin->pw_prretained,0,0);
	X			where.pr = save_pr;
	X			where.pos.x = 6 * font->pf_defaultsize.x;
	X			where.pos.y = rect->r_height + 2*sfont->pf_defaultsize.y;
	X			pf_text(where, PIX_SRC, sfont, buf);
	X			pr_dump(save_pr, fp, NULL, type, copy_flag);
	X			fclose(fp);
	X			if (file_type == PR_POSTSCRIPT) {
	X				if ((pfp = fopen(psfile, "w")) != NULL) {
	X					fp = fopen(rasfile, "r");
	X					/* ras2ps closes the files that
	X					 * we opened here.
	X					 */
	X					ras2ps(fp, pfp);
	X					sprintf(prntcmd, "%s %s", printer, psfile);
	X					system(prntcmd);
	X					unlink(psfile);
	X				} else
	X					err_rpt("can't open tmp ps file", NON_FATAL);
	X			} else {
	X				sprintf(prntcmd, "%s %s", printer, rasfile);
	X				system(prntcmd);
	X			}
	X			pr_destroy(save_pr);
	X			unlink(rasfile);
	X		} else
	X			err_rpt("can't open tmp raster file", NON_FATAL);
	X	} else if (mainsw_state == DISPLAYING_MONTH) {
	X		if (file_type != PR_POSTSCRIPT) {
	X			err_rpt("only PostScript output available for month printout", NON_FATAL);
	X		} else {
	X			if ((pfp = fopen(psfile, "w")) != NULL) {
	X				print_month(pfp);
	X				fclose(pfp);
	X				sprintf(prntcmd, "%s %s", printer, psfile);
	X				system(prntcmd);
	X				unlink(psfile);
	X			} else
	X				err_rpt("can't open tmp ps file", NON_FATAL);
	X		}
	X	}
	X	working(FALSE);
	X	unlock_cursors();
	X}
	X#endif	/* NO_PRINTER */
	X
	X/* set error logging flag */
	Xerr2console(state)
	Xint state;
	X{
	X	/*
	X	 * if TRUE, forces error messages to the console, even
	X	 * if the base frame is running
	X	 */
	X	log_to_console = state;
	X}
	X
	X/*
	X * Error reporting. Try first to put message in a popup frame, then
	X * the console, then stderr as a last resort.
	X */
	Xerr_rpt(errstr, fatal_flag)
	Xchar *errstr;
	Xint fatal_flag;
	X{
	X	FILE	*f;
	X	int	closed;
	X
	X	closed = (int) window_get(frame, FRAME_CLOSED);
	X	if (frame && !log_to_console && !closed) {
	X		/* base frame exists */
	X		create_prompt_frame(errstr, FALSE);
	X		(void) window_loop(prompt_frame);
	X		window_set(prompt_frame, WIN_SHOW, FALSE, 0);
	X	} else if ((f=fopen("/dev/console", "w")) != NULL) {
	X		fprintf(f, "%s: %s\n", progname, errstr);
	X		fclose(f);
	X	} else
	X		fprintf(stderr, "%s: %s\n", progname, errstr);
	X	if (fatal_flag)
	X		exit(1);
	X}
	X
	X/* Clean-up */
	Xcleanup()
	X{
	X	if (day_is_open)
	X		close_day();
	X
	X	/* create outdated include files (if necessary) */
	X	if (save_old)
	X		create_old_files();
	X			
	X	/* delete tmp file */
	X	if (access(tmpapts_pathname, R_OK) == 0 && unlink(tmpapts_pathname) < 0)
	X		perror(tmpapts_pathname);
	X}
	X
	Xchar sysbuf[512];
	X
	X/* Rename files, copying if necessary */
	Xxrename(from, to)
	Xchar *from, *to;
	X{
	X	if (rename(from, to) == -1) {
	X		/* rename sys call fialed, try doing a copy */
	X		sprintf(sysbuf, "cp %s %s", from, to);
	X		if (system(sysbuf) != 0)
	X			err_rpt("couldn't rename/copy tmp file", NON_FATAL);
	X	}
	X}
SHAR_EOF
if test 31671 -ne "`wc -c < 'utils.c'`"
then
	echo shar: error transmitting "'utils.c'" '(should have been 31671 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'version.c'" '(946 characters)'
if test -f 'version.c'
then
	echo shar: will not over-write existing file "'version.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'version.c'
	X/*
	X * $Header: version.c,v 2.3 89/05/16 16:31:58 billr Exp $
	X */
	X/*
	X * version.c - current version of calentool program
	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
	Xchar version[] = "Calendar Tool V2.1p2";
SHAR_EOF
if test 946 -ne "`wc -c < 'version.c'`"
then
	echo shar: error transmitting "'version.c'" '(should have been 946 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'week.cursor'" '(284 characters)'
if test -f 'week.cursor'
then
	echo shar: will not over-write existing file "'week.cursor'"
else
sed 's/^	X//' << \SHAR_EOF > 'week.cursor'
	X/* $Header: week.cursor,v 2.1 89/05/09 14:31:09 billr Exp $ */
	X/* Format_version=1, Width=16, Height=16, Depth=1, Valid_bits_per_item=16
	X */
	X        0x4004, 0x2008, 0x1FF0, 0x1010, 0x17D0, 0x1550, 0x1550, 0x1550,
	X        0x1550, 0x1550, 0x1550, 0x17D0, 0x1010, 0x1FF0, 0x2008, 0x4004
SHAR_EOF
if test 284 -ne "`wc -c < 'week.cursor'`"
then
	echo shar: error transmitting "'week.cursor'" '(should have been 284 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'wevent.c'" '(3699 characters)'
if test -f 'wevent.c'
then
	echo shar: will not over-write existing file "'wevent.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'wevent.c'
	X/*
	X * $Header: wevent.c,v 2.1 89/05/09 14:19:57 billr Exp $
	X */
	X/*
	X * wevent.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 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 *							*
	X *      Week event routines for main subwindow.		*
	X *							*
	X ********************************************************/
	X
	X
	X#include <stdio.h>
	X#include <suntool/sunview.h>
	X#include <suntool/canvas.h>
	X#include <suntool/panel.h>
	X#include "ct.h"
	X#include "event.h"
	X
	Xextern Frame prompt_frame;
	X
	Xweek_inputevent(canvas, event) 
	XCanvas canvas;
	XEvent *event;
	X{ 
	X	int i = -1;
	X	int x, y;
	X	static int day_chosen_from_week;
	X
	X	/* translate coordinates to pixwin space */
	X	event = canvas_window_event(canvas, event);
	X        if (event_id(event) != MS_LEFT)        /* Ignore kbd events. */
	X                return;
	X
	X        if (event_is_down(event)) {               /* Button down. */
	X		day_chosen_from_week = -1;
	X                for (i=0; i<nr_weekdays; i++) {
	X			x = event_x(event);
	X			y = event_y(event);
	X                        if (x >= week_boxes[i].wday_pos.left && x <= week_boxes[i].wday_pos.right &&
	X                            y >= week_boxes[i].wday_pos.top && y <= week_boxes[i].wday_pos.bottom) {
	X				day_chosen_from_week = i;
	X				pw_write(main_pixwin, week_boxes[i].wday_pos.left+1,
	X                                  week_boxes[i].wday_pos.top+1, weekslot_width-2,
	X                                  (weekslot_height)*N_SLOTS-2, PIX_NOT(PIX_DST), NULL,0,0);
	X				return;
	X			}
	X			/* is cursor inside a "more" button ? */
	X			if (x>=week_boxes[i].moreb_pos.left && x<=week_boxes[i].moreb_pos.right &&
	X			    y>=week_boxes[i].moreb_pos.top && y<=week_boxes[i].moreb_pos.bottom) {
	X				if (week_boxes[i].more) {
	X					/* "more" button is active */
	X					day_chosen_from_week = i+10;
	X					return;
	X				}
	X			}
	X		}
	X		return;			/* Mouse wasn't in any square. */
	X	} else {                        /* Button up. */
	X		if (day_chosen_from_week == -1)
	X			return;
	X		if (day_chosen_from_week >= 10) {
	X			/* more button selected */
	X			/* print info message */
	X			do_more_msg(day_chosen_from_week-10);
	X			return;
	X		}
	X		current.tm_mday -= current.tm_wday;
	X		current.tm_mday += day_chosen_from_week;
	X		fix_current_day();
	X		if (nr_weekdays == 5) {
	X			current.tm_mday++;
	X			fix_current_day();
	X		}
	X		mainsw_state = DISPLAYING_DAY;
	X		window_set(canvas, WIN_CURSOR, day_cursor, 0);
	X		draw_day();
	X	}
	X}
	X
	X/* display more popup message */
	Xdo_more_msg(i)
	Xint i;
	X{
	X	int width, height, left, bottom;
	X
	X	/* get x,y position of canvas window on the screen so we
	X	 * can center this one in it.
	X	 */
	X	create_prompt_frame("Select this day to view additional appointments.", FALSE);
	X	width = (int) window_get(prompt_frame, WIN_WIDTH);
	X	height = (int) window_get(prompt_frame, WIN_HEIGHT);
	X	left = (week_boxes[i].wday_pos.right + week_boxes[i].wday_pos.left - width) / 2;
	X	bottom = (week_boxes[i].wday_pos.top + week_boxes[i].wday_pos.bottom - height) / 2;
	X	window_set(prompt_frame, WIN_X, left, WIN_Y, bottom, 0);
	X	(void) window_loop(prompt_frame);
	X	window_set(prompt_frame, WIN_SHOW, FALSE, 0);
	X}
SHAR_EOF
if test 3699 -ne "`wc -c < 'wevent.c'`"
then
	echo shar: error transmitting "'wevent.c'" '(should have been 3699 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'wpaint.c'" '(7846 characters)'
if test -f 'wpaint.c'
then
	echo shar: will not over-write existing file "'wpaint.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'wpaint.c'
	X/*
	X * $Header: wpaint.c,v 2.1 89/05/09 14:20:03 billr Exp $
	X */
	X/*
	X * wpaint.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 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 *						   *
	X *	Artistic routines that draw in the main    *
	X * subwindow for the week display.		   *
	X *						   *
	X ***************************************************/
	X
	X#include <suntool/sunview.h>
	X#include <suntool/canvas.h>
	X#include <ctype.h>
	X#include <stdio.h>
	X#include "ct.h"
	X#include "paint.h"
	X
	Xextern int week_message_size;
	X
	X/*
	X * Routine to draw "Week-at-a-Glance".
	X */
	X
	Xdraw_week()
	X{
	X	struct tm Save;
	X
	X	lock_cursors();
	X	/* destory future appts popup, if it exists */
	X	if (fframe) {
	X		window_destroy(fframe);
	X		fframe = 0;
	X	}
	X	fix_current_day();
	X	Save = current;
	X	current.tm_mday -= current.tm_wday; /* Sunday of this week */
	X	fix_current_day();
	X	if (nr_weekdays < 7) {
	X		current.tm_mday++;
	X		fix_current_day();
	X	}
	X	working(TRUE);
	X	get_week_appts();
	X	working(FALSE);
	X	pw_batch_on(main_pixwin);
	X	paint_week_outline();
	X	paint_week_trim();
	X	working(TRUE);
	X	draw_week_appts();
	X	pw_batch_off(main_pixwin);
	X	current = Save;
	X	get_day_appts();
	X	working(FALSE);
	X	unlock_cursors();
	X}
	X
	X
	X/* Paint the outline for "Week-at-a-Glance". */
	Xpaint_week_outline()
	X{
	X	Rect *rect;
	X        int x, y, i, j, colx;
	X 
	X        rect = (Rect *) window_get(canvas, WIN_RECT);
	X        pw_writebackground(main_pixwin,0,0,rect->r_width,rect->r_height,PIX_CLR);
	X        startx = (rect->r_width - nr_weekdays*weekslot_width) / 2;
	X	starty = 10 + (rect->r_height - (N_SLOTS*(weekslot_height+1))) / 2;
	X 
	X	First = current;
	X        for (i=0; i<nr_weekdays; i++) {
	X                x = startx + i*weekslot_width;
	X		y = starty;
	X                week_boxes[i].wday_pos.left = x;
	X                week_boxes[i].wday_pos.top = y;
	X                week_boxes[i].wday_pos.right = x + weekslot_width;
	X                week_boxes[i].wday_pos.bottom = starty + N_SLOTS*weekslot_height;
	X		week_boxes[i].moreb_pos.left = x + (weekslot_width - morebutton->pr_size.x) / 2;
	X		week_boxes[i].moreb_pos.top = week_boxes[i].wday_pos.bottom + font->pf_defaultsize.y + font->pf_defaultsize.y/2;
	X		week_boxes[i].moreb_pos.right = week_boxes[i].moreb_pos.left + morebutton->pr_size.x;
	X		week_boxes[i].moreb_pos.bottom = week_boxes[i].moreb_pos.top + morebutton->pr_size.y;
	X                for (j=0; j<N_SLOTS; j++) {
	X			if (ymd_compare(today, current) == 0)
	X				pw_write(main_pixwin,x,y,weekslot_width,
	X				  weekslot_height,PIX_SRC,weekslot_td_pr,0,0);
	X			else
	X				pw_write(main_pixwin,x,y,weekslot_width,
	X				  weekslot_height,PIX_SRC,weekslot_pr,0,0);
	X                        y += weekslot_height;
	X		}
	X		current.tm_mday++;
	X		fix_current_day();
	X        }
	X	pw_vector(main_pixwin,startx,starty,startx+nr_weekdays*weekslot_width,starty,PIX_SET,1);
	X        pw_vector(main_pixwin,startx,y-1,startx+nr_weekdays*weekslot_width,y-1,PIX_SET,1);
	X	current = First;
	X	sun_moon_buttons(FALSE);
	X	print_button(TRUE);
	X}
	X
	X
	Xpaint_week_trim()
	X{
	X	int i, j, x, y, month, day, rightx;
	X        char c[7];
	X        
	X	First = current;
	X        c[3] = '\0';            /* Mon Tue Wed Thu Fri */
	X        for (i=0; i<nr_weekdays; i++) {
	X                x = startx + i*weekslot_width + (weekslot_width - 2*(font->pf_defaultsize.x+2))/2;
	X		sprintf(c, "%3.3s", daynames[First.tm_wday + i]);
	X                pw_text(main_pixwin, x, starty-5, PIX_SRC, font, c);
	X        }
	X        
	X        y = starty + weekslot_height - 4;
	X        rightx = startx + nr_weekdays*weekslot_width + 10;
	X	for (i=0; i<N_SLOTS; i++) {
	X		if (i < n_tslots) {
	X			sprintf(c, "%2d:%s",
	X				(START_HOUR+(i/2))%12 == 0 ? 12 : (START_HOUR+(i/2))%12,
	X				i%2 == 0 ? "00" : "30");
	X		} else if (i == n_tslots) {
	X			sprintf(c, "Notes");
	X		} else {
	X			sprintf(c, "     ");
	X		}
	X                pw_text(main_pixwin, startx-6*font->pf_defaultsize.x, y, PIX_SRC, font, c);
	X                pw_text(main_pixwin, rightx, y, PIX_SRC, font, c);
	X                y += weekslot_height;
	X	}
	X
	X        x = startx + (weekslot_width - 7*(font->pf_defaultsize.x+2))/2 + font->pf_defaultsize.x+7;
	X
	X	sprintf(c, "%d", 1900 + current.tm_year);
	X	pw_text(main_pixwin, startx-2*font->pf_defaultsize.x, y+weekslot_height, PIX_SRC, font, c);
	X
	X	/* display week dates (month, day) */
	X        for (i=0; i<nr_weekdays; i++) {
	X		sprintf(c, "%3.3s %2d",
	X			monthnames[current.tm_mon], current.tm_mday);
	X		pw_text(main_pixwin, x, y, PIX_SRC, font, c);
	X                x += weekslot_width;
	X		current.tm_mday++;
	X		fix_current_day();
	X        }
	X	current = First;
	X	fix_current_day();
	X}       
	X
	X
	Xget_week_appts()
	X{
	X	int i, j, save_read;
	X	struct tm Current;
	X
	X	save_read = read_only;
	X	read_only = 1;
	X	Current = current;
	X	for (i=0; i<nr_weekdays; i++) {
	X		get_day_appts();	/* fills in slots[] array */
	X		for (j=0; j<N_SLOTS; j++)
	X			week_boxes[i].weekslots[j] = slots[j];
	X		current.tm_mday++;
	X		fix_current_day();
	X	}
	X	read_only = save_read;
	X	current = Current;
	X	fix_current_day();
	X}                       
	X
	X/* draw in week appointments */
	Xdraw_week_appts()
	X{
	X	int index, slotno;
	X	struct appt_entry *aptr, *optr;
	X
	X	for (index=0; index<nr_weekdays; index++) {
	X		x_coord = week_boxes[index].wday_pos.left;
	X		for (slotno=0; slotno<N_SLOTS; slotno++) {
	X			y_coord = week_boxes[index].wday_pos.top + slotno*weekslot_height;
	X			if (week_boxes[index].weekslots[slotno].count > 0) {
	X				switch (week_boxes[index].weekslots[slotno].active) {
	X					case ACTIVE:
	X						write_week_str(index, slotno);
	X						break;
	X					case ARROW_SHAFT:
	X						pw_write(main_pixwin, x_coord+1, y_coord+1,
	X						  weekslot_width-2, weekslot_height-2, PIX_SRC|PIX_DST,
	X						weekarrowshaft_pr, 0, 0);
	X						break;
	X					case ARROW_HEAD:
	X						pw_write(main_pixwin, x_coord+1, y_coord+1, weekslot_width-2,
	X						  weekslot_height-2, PIX_SRC|PIX_DST, weekarrowhead_pr, 0, 0);
	X						break;
	X					case INACTIVE:
	X						break;
	X				}
	X			}
	X			/* free memory alloc'd for appts */
	X			if (week_boxes[index].weekslots[slotno].first)
	X				for (aptr=week_boxes[index].weekslots[slotno].first; aptr; ) {
	X					optr = aptr;
	X					aptr = aptr->next;
	X					free(optr);
	X				}
	X		}
	X		wmore_check(index);
	X	}
	X}
	X
	Xwrite_week_str(day, bi)
	Xint day;
	Xint bi;
	X{
	X	char slot_str[MAX_STRLEN];
	X	char *ptr;
	X	int strl;
	X
	X	strl = strlen(week_boxes[day].weekslots[bi].cur_appt->str);
	X	if (strl <= week_message_size)
	X		strcpy(slot_str, week_boxes[day].weekslots[bi].cur_appt->str);
	X	else {
	X		/* show leading part */
	X		
	X		strncpy(slot_str, week_boxes[day].weekslots[bi].cur_appt->str, week_message_size);
	X		slot_str[week_message_size+1] = '\0';
	X	}
	X	pw_write(main_pixwin, x_coord+1, y_coord+1, weekslot_width-2,
	X		weekslot_height-2, PIX_SET, NULL, 0, 0);
	X	pw_text(main_pixwin, x_coord+4, y_coord+font->pf_defaultsize.y, PIX_NOT(PIX_SRC),
	X		font, slot_str);
	X}
	X
	X/* display "more" button if necessary */
	Xwmore_check(day)
	Xint day;
	X{
	X	int i, more = 0;
	X	int x, y;
	X
	X	x = morebutton->pr_size.x;
	X	y = morebutton->pr_size.y;
	X	for (i=0; i<N_SLOTS; i++)
	X		if (week_boxes[day].weekslots[i].count > 1) {
	X			more = 1;
	X			break;
	X		}
	X	if (more) {
	X		week_boxes[day].more = 1;
	X		/* display more button to bottom of slot */
	X		pw_write(main_pixwin, week_boxes[day].moreb_pos.left,
	X			week_boxes[day].moreb_pos.top,
	X			x, y, PIX_SRC, morebutton, 0, 0);
	X	} else
	X		week_boxes[day].more = 0;
	X}
	X
SHAR_EOF
if test 7846 -ne "`wc -c < 'wpaint.c'`"
then
	echo shar: error transmitting "'wpaint.c'" '(should have been 7846 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'year.cursor'" '(256 characters)'
if test -f 'year.cursor'
then
	echo shar: will not over-write existing file "'year.cursor'"
else
sed 's/^	X//' << \SHAR_EOF > 'year.cursor'
	X/* $Header: year.cursor,v 2.1 89/05/09 14:31:12 billr Exp $ */
	X/* Format_version=1, Width=16, Height=16, Depth=1, Valid_bits_per_item=16
	X */
	X	0xFFFF,0xC003,0x8AA9,0x8001,0xFFFF,0xFFFF,0x9249,0xFFFF,
	X	0x9249,0xFFFF,0x9249,0xFFFF,0x9249,0xFFFF,0x9249,0xFFFF
SHAR_EOF
if test 256 -ne "`wc -c < 'year.cursor'`"
then
	echo shar: error transmitting "'year.cursor'" '(should have been 256 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'ypaint.c'" '(7772 characters)'
if test -f 'ypaint.c'
then
	echo shar: will not over-write existing file "'ypaint.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'ypaint.c'
	X/*
	X * $Header: ypaint.c,v 2.1 89/05/09 14:20:15 billr Exp $
	X */
	X/*
	X * ypaint.c
	X *
	X * Author: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM>
	X *
	X * Copyright (C) 1988, 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 *						   *
	X *	Artistic routines that draw in the main    *
	X * subwindow for the year display.		   *
	X *						   *
	X ***************************************************/
	X
	X#include <suntool/sunview.h>
	X#include <suntool/canvas.h>
	X#include <ctype.h>
	X#include <stdio.h>
	X#include "ct.h"
	X#include "paint.h"
	X
	X/*
	X * draw calendar for a whole year.
	X */
	Xdraw_year()
	X{
	X	int monthnr, daynr, boxnr, i, j, k, thismonth;
	X	int row, col, x, y;
	X	int busy_today[366], startbox, nrdays, yrday, extra_days;
	X	char title[5], c[3], buf[100];
	X	Rect *rect;
	X	struct tm Save;
	X	struct appt_entry appt;
	X	int read_stat;
	X	FILE *apts;
	X
	X	lock_cursors();
	X	/* destory future appts popup, if it exists */
	X	if (fframe) {
	X		window_destroy(fframe);
	X		fframe = 0;
	X	}
	X	fix_current_day();
	X
	X	working(TRUE);
	X	pw_batch_on(main_pixwin);
	X	rect = (Rect *) window_get(canvas, WIN_RECT);
	X	/* Erase the window */
	X	pw_writebackground(main_pixwin,0,0,rect->r_width,rect->r_height,PIX_CLR);
	X	startx = (rect->r_width - 3*8*ybox_width)/2 + font->pf_defaultsize.x+1;
	X	starty = (rect->r_height - 4*7*ybox_height) / 2;
	X	sun_moon_buttons(FALSE);
	X	print_button(TRUE);
	X
	X	/* Which days have appointments? */
	X	for (i=0; i<dysize(current.tm_year + 1900); i++)
	X		busy_today[i] = 0;
	X	Save = current;
	X	current.tm_mon = JAN;
	X	current.tm_mday = 1;
	X	fix_current_day();
	X	First = current;
	X	current.tm_mon = DEC;
	X	current.tm_mday = monthlength(DEC);
	X	fix_current_day();
	X	Last = current;
	X	if ((apts = fopen(apts_pathname, "r")) == NULL)
	X		err_rpt("can't open appointments file", FATAL);
	X
	X	working(FALSE);
	X	while ((read_stat = get_aentry(apts, &appt)) != EOF) {
	X		if (read_stat)
	X			continue;	/* read error */
	X		if (appt.flags & A_COMMENT)
	X			continue;
	X		if ((appt.flags & MARKED_NOTE) == MARKED_NOTE)
	X			continue;
	X		current.tm_year = appt.year;
	X		current.tm_mon = appt.month;
	X		current.tm_mday = appt.day;
	X		if (appt.flags & ALL_YEARS)
	X			current.tm_year = First.tm_year;
	X		if (current.tm_year == First.tm_year) {
	X			if (appt.flags & ALL_MONTHS) {
	X				for (current.tm_mon = JAN; 
	X					current.tm_mon <= DEC; 
	X					current.tm_mon++) {
	X					if (appt.flags & ALL_DAYS) {
	X						for (current.tm_mday = 1; current.tm_mday <= monthlength(current.tm_mon); current.tm_mday++) {
	X							fix_current_day();
	X							busy_today[current.tm_yday]++;
	X						}
	X					} else if (appt.flags & EVERY_SOMEDAY) {
	X						i = Pickday(appt.flags);
	X						for (current.tm_mday = 1; current.tm_mday <= monthlength(current.tm_mon); current.tm_mday++) {
	X							fix_current_day();
	X							if (current.tm_wday == i)
	X								if (chk_week(appt.repeat, current.tm_mday))
	X									busy_today[current.tm_yday]++;
	X						}
	X					} else {
	X						fix_current_day();
	X						busy_today[current.tm_yday]++;
	X					}
	X				}
	X			} else if (appt.flags & REPEAT) {
	X				if (appt.flags & EVERY_SOMEDAY) {
	X					i = Pickday(appt.flags);
	X					current.tm_mday = 1;
	X					fix_current_day();
	X					while (current.tm_wday != i) {
	X						current.tm_mday++;
	X						current.tm_wday = (current.tm_wday + 1) % 7;
	X					}
	X					fix_current_day();
	X					while (ymd_compare(current, Last) <= 0) {
	X						if (chk_week(appt.repeat, current.tm_mday))
	X							busy_today[current.tm_yday]++;
	X						current.tm_mday += 7;
	X						fix_current_day();
	X						if (current.tm_mon != appt.month)
	X							break;
	X					}
	X				} else {
	X					fix_current_day();
	X					while (ymd_compare(current, Last) <= 0) {
	X						busy_today[current.tm_yday]++;
	X						current.tm_mday += appt.repeat;
	X						fix_current_day();
	X					}
	X				}
	X			} else {
	X				fix_current_day();
	X				if (appt.flags & DELETED)
	X					busy_today[current.tm_yday]--;
	X				else
	X					busy_today[current.tm_yday]++;
	X			}
	X		} else if ((appt.flags & REPEAT) && !(appt.flags & EVERY_SOMEDAY)) {
	X			/* find 1st appt in this year */
	X			while (ymd_compare(current, First) < 0) {
	X				current.tm_mday += appt.repeat;
	X				fix_current_day();
	X			}
	X			while (ymd_compare(current, Last) <= 0) {
	X				busy_today[current.tm_yday]++;
	X				current.tm_mday += appt.repeat;
	X				fix_current_day();
	X			}
	X		}
	X
	X	}
	X	fclose(apts);
	X	current = First;
	X	fix_current_day();
	X#ifndef NO_HOLIDAYS
	X	/*
	X	 * now that we've gone thru the appointments file,
	X	 * check to see if the user has selected any holiday
	X	 * options and add them in.
	X	 */
	X	for (i=0; i<dysize(current.tm_year + 1900); i++) {
	X		working(TRUE);
	X		if (holiday_a == 1 && a_dates(&appt, holiday_a))
	X			busy_today[i]++;
	X		if (holiday_c == 1 && c_dates(&appt, holiday_c))
	X			busy_today[i]++;
	X		working(FALSE);
	X		if (holiday_i == 1 && i_dates(&appt, holiday_i))
	X			busy_today[i]++;
	X		working(TRUE);
	X		if (holiday_j == 1 && j_dates(&appt, holiday_j))
	X			busy_today[i]++;
	X		if (holiday_s == 1 && s_dates(&appt, holiday_s))
	X			busy_today[i]++;
	X		current.tm_mday++;
	X		fix_current_day();
	X		working(FALSE);
	X	}
	X	current = First;
	X	fix_current_day();
	X#endif	/* NO_HOLIDAYS */
	X
	X	/* display year title */
	X	sprintf(title, "%d", 1900 + First.tm_year);
	X	pw_text(main_pixwin, (rect->r_width - bigfont->pf_defaultsize.x*strlen(title))/2, starty - bigfont->pf_defaultsize.y,
	X	  PIX_SRC, bigfont, title);
	X
	X	/* display day names */
	X	strcpy(buf, "Su Mo Tu We Th Fr Sa    ");
	X	strcat(buf, "Su Mo Tu We Th Fr Sa    ");
	X	strcat(buf, "Su Mo Tu We Th Fr Sa");
	X	pw_text(main_pixwin, startx+4, starty-2, PIX_SRC, font, buf);
	X
	X	/* draw months */
	X	monthnr = 0;
	X	yrday = 0;
	X	extra_days = 0;
	X	startbox = First.tm_wday;
	X	for (row=0; row<4; row++) {
	X		for (col=0; col<3; col++) {
	X			x = startx + 8*ybox_width*col;
	X			y = starty + 7*ybox_height*row;
	X			mboxlims[monthnr].lowx = x;
	X			mboxlims[monthnr].lowy = y;
	X			mboxlims[monthnr].highx = x + 7*ybox_width;
	X			mboxlims[monthnr].highy = y + 6*ybox_width;
	X			/* draw month box and label */
	X			pw_write(main_pixwin, x, y, 7*ybox_width, 
	X				ybox_height, PIX_SRC, ymonthbox_pr, 0, 0);
	X			pw_text(main_pixwin, x+8, y+font->pf_defaultsize.y, PIX_SRC, font, 
	X				monthnames[row*3 + col]);
	X			if (!extra_days) {
	X				nrdays = monthlength(monthnr);
	X				daynr = 1;
	X			}
	X			boxnr = 0;
	X			for (j=0; j<5; j++) {
	X				y += ybox_height;
	X				/* foreach week in the month */
	X				for (k=0; k<7; k++) {
	X					/* foreach day in the week */
	X					/* draw day boxes */
	X					pw_write(main_pixwin, x, y, ybox_width, ybox_height, PIX_SRC, ydaybox_pr, 0, 0);
	X					/* label day boxes */
	X					if (boxnr >= startbox && daynr <= nrdays) {
	X						if (ymd_compare(today, current) == 0)
	X							/* gray box */
	X							pw_write(main_pixwin, x, y, ybox_width, ybox_height, PIX_SRC, ydaybox_td_pr, 0, 0);
	X						c[0] = (daynr<10 ? ' ' : daynr/10 + '0');
	X						c[1] = daynr%10 + '0';
	X						c[2] = '\0';
	X						pw_text(main_pixwin, x+4, y+14,
	X						  PIX_SRC|PIX_DST, font, c);
	X						/* if appointment exists, reverse video box */
	X						if (busy_today[yrday] > 0)
	X							pw_write(main_pixwin, x+2, y+2,
	X							  ybox_width-4, ybox_height-4,
	X							  PIX_NOT(PIX_DST), NULL, 0, 0);
	X						if (daynr == nrdays)
	X							startbox = (k + 1) % 7;
	X						++daynr;
	X						++yrday;
	X						current.tm_mday++;
	X						fix_current_day();
	X					}
	X					x += ybox_width;
	X					++boxnr;
	X					if (extra_days && daynr > nrdays) {
	X						/* time to start new month */
	X						extra_days = 0;
	X						nrdays = monthlength(monthnr);
	X						daynr = 1;
	X					}
	X				}
	X				x -= 7*ybox_width;
	X			}
	X			if (daynr <= nrdays) {
	X				/* leftover goes in next month */
	X				extra_days++;
	X				startbox = 0;
	X			}
	X			++monthnr;
	X		}
	X	}
	X	pw_batch_off(main_pixwin);
	X	current = Save;
	X	fix_current_day();
	X	unlock_cursors();
	X}
	X
SHAR_EOF
if test 7772 -ne "`wc -c < 'ypaint.c'`"
then
	echo shar: error transmitting "'ypaint.c'" '(should have been 7772 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0