[comp.sources.unix] v11i090: Sunview visual calendar

rsalz@uunet.UU.NET (Rich Salz) (10/04/87)

Submitted-by: Sarah Metcalfe <cognos!sarahm>
Posting-number: Volume 11, Issue 90
Archive-name: monthtool

[  To get this to work I had to #ifdef-out the TEXTSW_EDIT_COUNT stuff.
   Also, the Makefile is a little funky; don't do make clean.  --r$  ]


#!/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:
#	README
#	Makefile
#	monthtool.1
#	monthtool.c
#	monthtool.font.uu
#	monthtool.h
export PATH; PATH=/bin:$PATH
if test -f 'README'
then
	echo shar: over-writing existing file "'README'"
fi
cat << \SHAR_EOF > 'README'
 
Monthtool is a visual direct manipulation "month-at-a-glance"
type  calendar  and  reminder  system  using Sunview.  It is
based on work done by Mike Essex on the vcal group  of  pro-
grams.  Some ideas on setting up the interface were borrowed
from the calctool program by Rich Burridge.

This program works on Sun  3  systems  only.    To  install:
check  the  Makefile  and change the INSTALLDIR, MANDIR, and
SRCDIR Make macros to the following directories, respective-
ly:  the  directory  where Monthtool is to be installed, the
directory where the man page is to  go,  and  the  directory
where  the  source  and  the specialized font are to remain.
Then, simply do  a  "make  install",  followed  by  a  "make
clean", if required.

I hope it turns out to  be  useful.   Improvements  and  bug
fixes most welcome.


                                        Regards, 
                                           Sarah Metcalfe

______
Sarah Metcalfe         decvax!utzoo!dciem!nrcaer!cognos!sarahm
Cognos Incorporated    3755 Riverside Drive, Ottawa, Ontario, CANADA  K1G 3N3
                       (613) 738-1440
SHAR_EOF
if test -f 'Makefile'
then
	echo shar: over-writing existing file "'Makefile'"
fi
cat << \SHAR_EOF > 'Makefile'
SRCDIR        = /system/util/monthtool
INSTALLDIR    = /usr/local/bin
MANDIR        = /usr/local/man/man1
LIBS          = -lm -lsuntool -lsunwindow -lpixrect
CFLAGS        = -O
PROG          = monthtool 
MAN           = monthtool.1

monthtool:      monthtool.font monthtool.o
						cc -o $(PROG) monthtool.o $(LIBS)

monthtool.o:    monthtool.c monthtool.h 
						cc $(CFLAGS) -DFONTDIR="\"$(SRCDIR)\"" -c monthtool.c

monthtool.font: monthtool.font.uu 
						uudecode monthtool.font.uu

install:        $(PROG) $(MAN)
						install -s -m 555 $(PROG) $(INSTALLDIR)
						install -c -m 644 monthtool.1 $(MANDIR)

clean:    
						rm -f monthtool.o $(PROG) core monthtool.font.uu
SHAR_EOF
if test -f 'monthtool.1'
then
	echo shar: over-writing existing file "'monthtool.1'"
fi
cat << \SHAR_EOF > 'monthtool.1'
.TH MONTHTOOL 1L 
.SH NAME
monthtool \- a mouse-oriented direct manipulation calendar and 
reminder organizer
.SH SYNOPSIS
.B monthtool
.SH DESCRIPTION
.sp
.TP
.B Overview
.br
.sp
\fIMonthtool\fR
displays a Suntools-oriented calendar of any month of any year and
allows the user to browse the days of that month, and
to schedule and recall reminders for that day.
.br
.TP
.B Windows
.sp
Month Name Window:
.br
The name and year of the displayed calendar is indicated.
Two arrow buttons allow the user to move to other months (up arrow moves
to the previous month, down arrow to the following month).  A button
labelled "Today" moves the calendar to the current month of the current
year, highlights today's date in the calendar, and displays today's reminders.
.sp
Dates Window:
.br
The days of the month are shown in calendar format.  
When the user clicks on a date in this window, that date is highlighted
and the reminders for that particular day are shown in the Reminder Window.
Days that have (most types of) reminders associated with them have a bolder
border.
.sp
Reminder Type Buttons Window:
.br
Four push-buttons indicating the types of reminders are shown.
Clicking on one type will set the reminder that currently has
the insertion caret on it (in the Reminder Window) to that type. 
.sp
Reminder Window: 
.br
Reminders for the currently highlighted date are shown.  Indicators
of the type of each reminder are indicated at the beginning of each
reminder line.  Reminders may be added, deleted or modified, using the
standard 
\fItextedit\fR 
features.  A type may be set by positioning the insertion
caret on the reminder and clicking on the required type in the
Reminder Type Buttons Window.
.br
.TP
.B Reminder Types
.br
.sp
Reminders may be one of four types:
.sp
This day only reminders:
.br
These reminders are one time only events, such as appointments. 
A reminder of this type has a black box at the front of the message.
When one of these is associated with a given day, the border of that
date in the calendar will be made bolder, as an indicator.
.sp
Yearly reminders:
.br
Reminders that happen once a year, such as birthdays. 
A reminder of this type has a hollow box containing a "Y" at the 
front of the message.
When one of these is associated with a given month and day, the border of that
date in the calendar will be made bolder, as an indicator.
.sp
Monthly reminders:
.br
Reminders that happen once a month, such as loan payments. 
A reminder of this type has a hollow box containing a "M" at the 
front of the message.
When one of these is associated with a given date, the border of that
date in the calendar will be made bolder, as an indicator.
.sp
Daily reminders:
.br
Constant reminders, things to remember to do. 
A reminder of this type has a hollow box containing a "D" at the 
front of the message.
.sp
.TP
.B Menu Commands
.sp
Available with the right mouse button, except when in the Reminders Window
(when the standard 
\fItextedit\fR 
menu is available).
.sp
Close with Save:
.br
Close the window to the icon and save the reminders in the .monthtool file.
.sp
Save:
.br
Save the reminders in the .monthtool file.
.sp
Reload:
.br
Reload the reminders from the last version of the .monthtool file.
.sp
Quit with Save:
.br
Save the reminders in the .monthtool file and quit.
.sp
Note that the standard frame menu (available when in the borders of any window)
allows the user to quit and close without saving.  Resize, Redisplay, etc.
are also available, as is usually the case.
.br
.TP
.B The .monthtool File
.br
.sp
The reminders are kept in a file in the home directory called the .monthtool 
file.   This file is kept in a format similar to that used by 
\fIautocall\fR, used
to warn the user of impending appointments.  If this feature is required,
the time for the appointments must be the first token of the message
(after the type indicator) and must be in the format hh:mm or h:mm, 24-hour
time.
.sp
Each reminder is a line (of length 80 characters or less) in the .monthtool
file in 
the following format:
.sp
.ta +1i 
m,d,y,tttt,s
.ta -1i
.sp
where m is the one or two digit month number, d is the one or two digit date, y
is the year (up to 4 digits), tttt is either 4 blanks (if no time is required)
or 24 time in hhmm format, and s is the reminder message.   
For yearly reminders, the
y field is 0 (zero); for monthly reminders, the
m field and the y field are 0 (zero); for daily reminders, the d field, the
m field, and the y field are 0 (zero).
.SH AUTHORS
.ta +1.15i
Sarah Metcalfe
.br
Mike Essex
.br
Rich Burridge
.SH FILES
$HOME/.monthtool
.SH SEE ALSO
\fIvcal\fR(1), \fIautocall\fR(1), \fItextedit\fR(1), \fIsuntools\fR(1)
.LP
\fI"Windows and Window-Based Tools: Beginner's Guide"\fR
.SH DIAGNOSTICS
Monthtool warning! Invalid record: \fIrecord\fR 
.br
Monthtool error:  Cannot open \fI~/.monthtool\fR file
.SH BUGS
Although the .monthtool file has a similar format to
the .appointments file of \fIvcal\fR, 
\fIvcal\fR cannot support the yearly, monthly, or daily reminders.  If vcal
is used on the file, reminders of that type will be lost.
.SH DATE
24/6/87
SHAR_EOF
if test -f 'monthtool.c'
then
	echo shar: over-writing existing file "'monthtool.c'"
fi
cat << \SHAR_EOF > 'monthtool.c'
 
/*
	Name:		monthtool
  
	Purpose: 	visual appointment calendar 
  
	Author:		Sarah Metcalfe apres Mike Essex & Rich Burridge
  
	Date:		June 24, 1987 
  
	Discussion: Displays a calendar to the screen for a given month.  
				User may move the mouse to any day of the
				month and view or enter appointments for that date. 
*/




#include "monthtool.h"

void			 dateEvent();

void			 monthEvent();
void			 todayBtnHit();
void			 upBtnHit();
void			 downBtnHit();
void			 monthBackgroundHit();

void			 notesBackgroundHit();
void			 notesPanelEvent();
void			 notesRadioHit();

Canvas			 datesDsply;
Textsw			 notesDsply;
Panel			 monthPanel,
				 notesPanel;
Frame			 frame;
Menu			 mainMenu,
				 fileMenu;
Panel_item		 monthItem,
				 notesTypeItem;
Pixwin			*datesCrayon;
struct pixfont 	*font,
				*notesFont;


short			 dayIcon[] = {
	0xFFFF,0xFFFF,0xFF00,0x0000,0x8000,0x0000,0x0100,0x0000,
	0x8000,0x0000,0x0100,0x0000,0x8000,0x0000,0x0100,0x0000,
	0x8000,0x0000,0x0100,0x0000,0x8000,0x0000,0x0100,0x0000,
	0x8000,0x0000,0x0100,0x0000,0x8000,0x0000,0x0100,0x0000,
	0x8000,0x0000,0x0100,0x0000,0x8000,0x0000,0x0100,0x0000,
	0x8000,0x0000,0x0100,0x0000,0x8000,0x0000,0x0100,0x0000,
	0x8000,0x0000,0x0100,0x0000,0x8000,0x0000,0x0100,0x0000,
	0x8000,0x0000,0x0100,0x0000,0x8000,0x0000,0x0100,0x0000,
	0x8000,0x0000,0x0100,0x0000,0x8000,0x0000,0x0100,0x0000,
	0x8000,0x0000,0x0100,0x0000,0x8000,0x0000,0x0100,0x0000,
	0x8000,0x0000,0x0100,0x0000,0x8000,0x0000,0x0100,0x0000,
	0x8000,0x0000,0x0100,0x0000,0x8000,0x0000,0x0100,0x0000,
	0x8000,0x0000,0x0100,0x0000,0xFFFF,0xFFFF,0xFF00,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
};
mpr_static(dayPr, 64, 64, 1, dayIcon);

short			 bigDayIcon[] = {
	0xFFFF,0xFFFF,0xFF00,0x0000,0xFFFF,0xFFFF,0xFF00,0x0000,
	0xFFFF,0xFFFF,0xFF00,0x0000,0xE000,0x0000,0x0700,0x0000,
	0xE000,0x0000,0x0700,0x0000,0xE000,0x0000,0x0700,0x0000,
	0xE000,0x0000,0x0700,0x0000,0xE000,0x0000,0x0700,0x0000,
	0xE000,0x0000,0x0700,0x0000,0xE000,0x0000,0x0700,0x0000,
	0xE000,0x0000,0x0700,0x0000,0xE000,0x0000,0x0700,0x0000,
	0xE000,0x0000,0x0700,0x0000,0xE000,0x0000,0x0700,0x0000,
	0xE000,0x0000,0x0700,0x0000,0xE000,0x0000,0x0700,0x0000,
	0xE000,0x0000,0x0700,0x0000,0xE000,0x0000,0x0700,0x0000,
	0xE000,0x0000,0x0700,0x0000,0xE000,0x0000,0x0700,0x0000,
	0xE000,0x0000,0x0700,0x0000,0xE000,0x0000,0x0700,0x0000,
	0xE000,0x0000,0x0700,0x0000,0xFFFF,0xFFFF,0xFF00,0x0000,
	0xFFFF,0xFFFF,0xFF00,0x0000,0xFFFF,0xFFFF,0xFF00,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
};
mpr_static(bigDayPr, 64, 64, 1, bigDayIcon);

short			 daySelIcon[] = {
	0xFFFF,0xFFFF,0xFF00,0x0000,0xA222,0x2222,0x2300,0x0000,
	0xC444,0x4444,0x4500,0x0000,0x9111,0x1111,0x1100,0x0000,
	0x8888,0x8888,0x8900,0x0000,0xA222,0x2222,0x2300,0x0000,
	0xC444,0x4444,0x4500,0x0000,0x9111,0x1111,0x1100,0x0000,
	0x8888,0x8888,0x8900,0x0000,0xA222,0x2222,0x2300,0x0000,
	0xC444,0x4444,0x4500,0x0000,0x9111,0x1111,0x1100,0x0000,
	0x8888,0x8888,0x8900,0x0000,0xA222,0x2222,0x2300,0x0000,
	0xC444,0x4444,0x4500,0x0000,0x9111,0x1111,0x1100,0x0000,
	0x8888,0x8888,0x8900,0x0000,0xA222,0x2222,0x2300,0x0000,
	0xC444,0x4444,0x4500,0x0000,0x9111,0x1111,0x1100,0x0000,
	0x8888,0x8888,0x8900,0x0000,0xA222,0x2222,0x2300,0x0000,
	0xC444,0x4444,0x4500,0x0000,0x9111,0x1111,0x1100,0x0000,
	0x8888,0x8888,0x8900,0x0000,0xFFFF,0xFFFF,0xFF00,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
};
mpr_static(daySelPr, 64, 64, 1, daySelIcon);

short			 bigDaySelIcon[] = {
	0xFFFF,0xFFFF,0xFF00,0x0000,0xFFFF,0xFFFF,0xFF00,0x0000,
	0xFFFF,0xFFFF,0xFF00,0x0000,0xF111,0x1111,0x1700,0x0000,
	0xE888,0x8888,0x8F00,0x0000,0xE222,0x2222,0x2700,0x0000,
	0xE444,0x4444,0x4700,0x0000,0xF111,0x1111,0x1700,0x0000,
	0xE888,0x8888,0x8F00,0x0000,0xE222,0x2222,0x2700,0x0000,
	0xE444,0x4444,0x4700,0x0000,0xF111,0x1111,0x1700,0x0000,
	0xE888,0x8888,0x8F00,0x0000,0xE222,0x2222,0x2700,0x0000,
	0xE444,0x4444,0x4700,0x0000,0xF111,0x1111,0x1700,0x0000,
	0xE888,0x8888,0x8F00,0x0000,0xE222,0x2222,0x2700,0x0000,
	0xE444,0x4444,0x4700,0x0000,0xF111,0x1111,0x1700,0x0000,
	0xE888,0x8888,0x8F00,0x0000,0xE222,0x2222,0x2700,0x0000,
	0xE444,0x4444,0x4700,0x0000,0xFFFF,0xFFFF,0xFF00,0x0000,
	0xFFFF,0xFFFF,0xFF00,0x0000,0xFFFF,0xFFFF,0xFF00,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
	0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
};
mpr_static(bigDaySelPr, 64, 64, 1, bigDaySelIcon);


short			 upBtnIcon[] = {
	0x3FFF,0xE000,0x7FFF,0xF000,
	0xE000,0x3800,0xC000,0x1800,
	0xC020,0x1800,0xC070,0x1800,
	0xC0F8,0x1800,0xC1FC,0x1800,
	0xC3FE,0x1800,0xC7FF,0x1800,
	0xCFFF,0x9800,0xC0F8,0x1800,
	0xC0F8,0x1800,0xC0F8,0x1800,
	0xC0F8,0x1800,0xC000,0x1800,
	0xE000,0x3800,0x7FFF,0xF000,
	0x3FFF,0xE000,0x0000,0x0000
};
mpr_static(upBtnPr, BTN_WIDTH, BTN_HEIGHT, 1, upBtnIcon);

short			 downBtnIcon[] = {
	0x3FFF,0xE000,0x7FFF,0xF000,
	0xE000,0x3800,0xC000,0x1800,
	0xC0F8,0x1800,0xC0F8,0x1800,
	0xC0F8,0x1800,0xC0F8,0x1800,
	0xCFFF,0x9800,0xC7FF,0x1800,
	0xC3FE,0x1800,0xC1FC,0x1800,
	0xC0F8,0x1800,0xC070,0x1800,
	0xC020,0x1800,0xC000,0x1800,
	0xE000,0x3800,0x7FFF,0xF000,
	0x3FFF,0xE000,0x0000,0x0000
};
mpr_static(downBtnPr, BTN_WIDTH, BTN_HEIGHT, 1, downBtnIcon);


short			 toolIcon[] = {
	0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8C08,0x87C2,0x21F0,0xF031,
	0x920D,0x8102,0x2040,0x8049,0x880A,0x8102,0xA040,0xE021,
	0x840A,0x8102,0xA040,0x8011,0x9208,0x8103,0x6040,0x8049,
	0x8C08,0x8102,0x2040,0x8031,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
	0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8040,0x2010,0x0804,0x0201,
	0x8040,0x2814,0x0A05,0x0281,0x8040,0x2814,0x0A05,0x0281,
	0x8040,0x2010,0x0804,0x0201,0x8040,0x2010,0x0804,0x0201,
	0x8040,0x2013,0xA804,0x0201,0x8040,0x2010,0x0804,0x0201,
	0x8040,0x2016,0x8804,0x0201,0x8040,0x2010,0x0804,0x0201,
	0x8040,0x2010,0x0804,0x0201,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
	0x8040,0x2010,0x0804,0x0201,0xA050,0x2814,0x0B05,0x82C1,
	0xA050,0x2814,0x0B05,0x82C1,0x8040,0x2010,0x0804,0x0201,
	0x8040,0x2010,0x0804,0x0201,0x8040,0x2010,0x0805,0xD201,
	0x8040,0x2010,0x0804,0x0201,0x8040,0x2010,0x0804,0x0201,
	0x8040,0x2010,0x0804,0x0201,0x8040,0x2010,0x0804,0x0201,
	0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8040,0x2010,0x0804,0x0201,
	0xB058,0x2C16,0x0B05,0x82C1,0xB058,0x2C16,0x0B05,0x82C1,
	0x8040,0x2010,0x0804,0x0201,0x8040,0x2F50,0x0804,0x0201,
	0x8040,0x2010,0x0804,0x0201,0x8040,0x2D50,0x0804,0x0201,
	0x8040,0x2010,0x0804,0x0201,0x8040,0x2010,0x0804,0x0201,
	0x8040,0x2010,0x0804,0x0201,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
	0x8040,0x2010,0x0804,0x0201,0xB058,0x2C16,0x0B05,0x82C1,
	0xB058,0x2C16,0x0B05,0x82C1,0x8040,0x2010,0x0804,0x0201,
	0x8040,0x2010,0x0BE4,0x0201,0x8040,0x2010,0x0804,0x0201,
	0x8040,0x2010,0x0BA4,0x0201,0x8040,0x2010,0x0804,0x0201,
	0x8040,0x2010,0x0804,0x0201,0x8040,0x2010,0x0804,0x0201,
	0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8040,0x2010,0x0804,0x0201,
	0xB058,0x2C16,0x0B04,0x0201,0xB058,0x2C16,0x0B04,0x0201,
	0x8040,0x2010,0x0804,0x0201,0x8040,0x2010,0x0804,0x0201,
	0xBA40,0x2017,0xC804,0x0201,0x8040,0x2010,0x0804,0x0201,
	0x8040,0x2013,0xC804,0x0201,0x9240,0x2010,0x0804,0x0201,
	0x8040,0x2010,0x0804,0x0201,0xFFFF,0xFFFF,0xFFFF,0xFFFF
};
DEFINE_ICON_FROM_IMAGE(monthIcon, toolIcon);



struct dateBox	 monthBoxes[DATE_ROWS][DATE_COLS];


struct apptsData 	*firstApptRecord[NUM_NOTES_TYPE + 1 /*for NOTES_ERROR*/];
struct apptsData 	*lastApptRecord[NUM_NOTES_TYPE + 1 /*for NOTES_ERROR*/];

	
int					 tmonth, tday, tyear;

int					 yearToShow, monthToShow;
int					 dayToShow = 0;
int					 dateNumToShow[NUM_NOTES_TYPE];

int					 editCount = 0;
int					 notesModified = 0;

char				 typeChar[NUM_NOTES_TYPE] = { 0x90, 0x91, 0x92, 0x93 }; 
char				 typeMark[3] = "  ";
							
char				*smon[] = { "January", "February", "March",
								"April", "May", "June",
								"July", "August", "September",
								"October", "November", "December"
							  };
int					 mon[] = { 0, 	31, 29, 31, 
									30, 31, 30,
									31, 31, 30, 
									31, 30, 31, 
							  };

main(argc, argv)

int		 argc;
char	*argv[];

{
	char	fontString[80];
	char	choiceString[2];
	int		type;


	/* Set up menus */
						
	fileMenu = menu_create(MENU_ITEM,
								MENU_STRING,	"Save",
								MENU_VALUE,		 MENU_SAVE,
								0,
							MENU_ITEM,
								MENU_STRING,	"Reload",
								MENU_VALUE,		 MENU_RELOAD,
								0,
							0);

	mainMenu = menu_create(MENU_ITEM,
								MENU_STRING,	"Close (with Save)",
								MENU_VALUE,		 MENU_CLOSE,
								0,
							MENU_ITEM,
								MENU_STRING,	"Update Appts.",
								MENU_PULLRIGHT,	 fileMenu,
								0,
							MENU_ITEM,
								MENU_STRING,	"Quit (with Save)",
								MENU_VALUE,		 MENU_QUIT,
								0,
							0);
						

	/*	Set up windows */

	font = pf_open(LARGEFONT);				/* Open large sized font. */
	strcpy(fontString, FONTDIR);
	strcat(fontString, NORMALFONT);
	notesFont = pf_open(fontString);		/* Open regular sized font. */

	frame = window_create(0, FRAME,
				FRAME_ICON, &monthIcon,
				FRAME_SHOW_LABEL, FALSE,
				FRAME_SUBWINDOWS_ADJUSTABLE, FALSE,
				FRAME_NO_CONFIRM, FALSE,
				WIN_HEIGHT, DATES_HEIGHT + MONTH_HEIGHT + 
					NOTES_PANEL_HEIGHT + NOTES_HEIGHT + 25,
				WIN_WIDTH, WINDOW_WIDTH + 10,
				FRAME_ARGS, argc, argv,
				0);

	monthPanel = window_create(frame, PANEL,
				WIN_X, 0,
				WIN_Y, 0,
				WIN_HEIGHT, MONTH_HEIGHT,
				WIN_WIDTH, WINDOW_WIDTH,
				WIN_FONT, font,
				PANEL_BACKGROUND_PROC, monthBackgroundHit,
				PANEL_EVENT_PROC, monthEvent,
				0);

	datesDsply = window_create(frame, CANVAS,
				WIN_X, 0,
				WIN_BELOW, monthPanel,
				WIN_HEIGHT, DATES_HEIGHT,
				WIN_WIDTH, WINDOW_WIDTH,
				WIN_FONT, font,
				WIN_EVENT_PROC, dateEvent,
				0);
	datesCrayon = canvas_pixwin(datesDsply);

	notesPanel = window_create(frame, PANEL,
				WIN_X, 0,
				WIN_BELOW, datesDsply,
				WIN_HEIGHT, NOTES_PANEL_HEIGHT,
				WIN_WIDTH, WINDOW_WIDTH,
				WIN_FONT, notesFont,
				PANEL_BACKGROUND_PROC, notesBackgroundHit,
				PANEL_EVENT_PROC, notesPanelEvent,
				0);

	notesDsply = window_create(frame, TEXTSW,
				WIN_X, 0,
				WIN_BELOW, notesPanel,
				WIN_HEIGHT, WIN_EXTEND_TO_EDGE,
				WIN_WIDTH, 10000 /* very large number, cuts to actual width */,
				WIN_FONT, notesFont,
				TEXTSW_IGNORE_LIMIT, TEXTSW_INFINITY,
				0);

	/* Set up panels */


	monthItem = panel_create_item(monthPanel, PANEL_MESSAGE,
					PANEL_LABEL_X, 5,
					PANEL_LABEL_Y, 10,
				  0);
						

	panel_create_item( monthPanel, PANEL_BUTTON,
						PANEL_ITEM_X, WINDOW_WIDTH - 2 * (BTN_WIDTH + GAP) - 55,
						PANEL_ITEM_Y, 10,
  						PANEL_NOTIFY_PROC, todayBtnHit, 
                       	PANEL_LABEL_IMAGE,
							panel_button_image(monthPanel,"Today",0,notesFont),
						0);

	panel_create_item( monthPanel, PANEL_BUTTON,
						PANEL_ITEM_X, WINDOW_WIDTH - 2 * (BTN_WIDTH + GAP),
						PANEL_ITEM_Y, 10,
  						PANEL_NOTIFY_PROC, upBtnHit, 
                       	PANEL_LABEL_IMAGE, &upBtnPr,
						0);

	panel_create_item( monthPanel, PANEL_BUTTON,
						PANEL_ITEM_X, WINDOW_WIDTH - (BTN_WIDTH + GAP),
						PANEL_ITEM_Y, 10,
  						PANEL_NOTIFY_PROC, downBtnHit, 
                       	PANEL_LABEL_IMAGE, &downBtnPr,
						0);


	notesTypeItem = panel_create_item( notesPanel, PANEL_CHOICE,
						PANEL_LABEL_STRING, "Reminder Types:",
						PANEL_FEEDBACK, PANEL_NONE,
						PANEL_NOTIFY_PROC, notesRadioHit,
					0);
	choiceString[1] = '\0';
	for (type = 0; type < NUM_NOTES_TYPE; type++) {
		choiceString[0] = typeChar[type];
		panel_set( notesTypeItem, PANEL_CHOICE_STRING, type, choiceString, 0);
		panel_set( notesTypeItem, PANEL_CHOICE_X, type, 100 + 40*(type+1), 0);
		panel_set( notesTypeItem, PANEL_CHOICE_Y, type, 4, 0);
	}
	panel_set( notesTypeItem, PANEL_LABEL_X, 4, 0);
	panel_set( notesTypeItem, PANEL_LABEL_Y, 4, 0);

	/* Get today's date */

	todaySet();
	yearToShow = tyear;
	monthToShow = tmonth;

	/* Load the appointments file and show this month's calendar */
	
	loadData();	
	dayHit(tday);	

	/* Wait for events */

	window_main_loop(frame);

	/* When done, leave */

	freeData();
	exit(0);

}

static void	monthEvent(item, event)

Panel_item	 item;
Event		*event;

{
	switch (event_id(event)) {
	case MS_RIGHT:
		if (event_is_down(event)) {
			rootMenuDisplay(monthPanel,event);
		}
		break;
	case MS_LEFT:
		panel_default_handle_event(item,event);
		break;
	default:
		return;
	}

}

static void	todayBtnHit(item, event)

Panel_item	 item;
Event		*event;

{
	todaySet();
	if ( (monthToShow != tmonth) || (yearToShow != tyear) ) {
		notesSave();
		monthToShow = tmonth;
		yearToShow = tyear;
		monthDisplay();
		dayHit(tday);
	}else{
		if (dayToShow != tday) {
			notesSave();
			dayHit(tday);
		}
	}
}

static void	upBtnHit(item, event)

Panel_item	 item;
Event		*event;

{
	notesSave();
	if (--monthToShow < 1) {
		monthToShow = 12;
		yearToShow--;
	}
	monthDisplay();
	dayHit(1);

}

static void	downBtnHit(item, event)

Panel_item	 item;
Event		*event;

{
	notesSave();
	if (++monthToShow == 13) {
		monthToShow = 1;
		yearToShow++;
	}
	monthDisplay();
	dayHit(1);

}

static void	monthBackgroundHit(panel, event)

Panel		 panel;
Event		*event;

{
	switch (event_id(event)) {
	case MS_RIGHT:
		if (event_is_down(event)) {
			rootMenuDisplay(monthPanel,event);
		}
		break;
	default:
		return;
	}

}

static void	dateEvent(win, event, arg)

Canvas		 win;
Event		*event;
caddr_t		 arg;

{
	int			column,
				row;

	if (event_is_up(event)) {
		return;
	}

	switch (event_id(event)) {
	case MS_LEFT:
		notesSave();
		column = event_x(event) / (DATE_BOX_WIDTH + GAP);
		row = (event_y(event)) / (DATE_BOX_HEIGHT + GAP);
		dayHit(monthBoxes[row][column].date);
		break;
	case MS_RIGHT:
		rootMenuDisplay(win,event);
		break;
	case WIN_REPAINT:
		notesSave();
		monthDisplay();
		dayHit(dayToShow);
		break;
	default:
		return;
	}

}

dayHit(date)

int	date;

{
	int					 row,
						 column;
 
	if (date != 0) {
		if (dayToShow != 0) {
			for (row = 0; row < DATE_ROWS; row++) {
				for (column = 0; column < DATE_COLS; column++) {
					if (dayToShow == monthBoxes[row][column].date) {
						dateBoxDisplay(row, column, NOHIGHLIGHT);
					}
				}
			}
		}
		for (row = 0; row < DATE_ROWS; row++) {
			for (column = 0; column < DATE_COLS; column++) {
				if (date == monthBoxes[row][column].date) {
					dateBoxDisplay(row, column, HIGHLIGHT);
				}
			}
		}

		dayToShow = date;

		dateNumToShow[NOTES_ALL_ALL_ALL] = 0;
		dateNumToShow[NOTES_D_ALL_ALL] = dayToShow;
		dateNumToShow[NOTES_D_M_ALL] = dayToShow + 100 * monthToShow;
		dateNumToShow[NOTES_D_M_Y] = dayToShow + 100 * monthToShow + 10000 * yearToShow;

		notesDisplay();

	}

}

static void	notesPanelEvent(item, event)

Panel_item	 item;
Event		*event;

{

	switch (event_id(event)) {
	case MS_RIGHT:
		if (event_is_down(event)) {
			rootMenuDisplay(notesPanel,event);
		}
		break;
	case MS_LEFT:
		panel_default_handle_event(item,event);
		break;
	default:
		return;
	}

}

static void	notesRadioHit(item, value, event)

Panel_item	 item;
int			 value;
Event		*event;

{
	int			caretIndex,
				endIndex,
				lineStartIndex,
				nextLineStartIndex,
				ptrnStartIndex,
				ptrnEndIndex,
				ptrnLen,
				type,
				result,
				lineNo;

	typeMark[0] = typeChar[value];
	ptrnLen = strlen(typeMark);

	caretIndex = (int)window_get( notesDsply, TEXTSW_INSERTION_POINT );

	lineNo = 0;
	lineStartIndex = 0;
	while (1) {
		nextLineStartIndex = (int)textsw_index_for_file_line(notesDsply, lineNo+1);
		if ( (nextLineStartIndex < 0) || (nextLineStartIndex > caretIndex) ) {
			break;
		}
		lineNo++;
		lineStartIndex = nextLineStartIndex;
	}

	window_set( notesDsply, TEXTSW_INSERTION_POINT, lineStartIndex, 0 );
	textsw_insert( notesDsply, typeMark, ptrnLen );
	caretIndex += ptrnLen;

	endIndex = (int)window_get( notesDsply, TEXTSW_LENGTH );
	if ( (nextLineStartIndex < 0) || (nextLineStartIndex > endIndex) ) {
		nextLineStartIndex = endIndex + 1;
	}
	
	lineStartIndex += strlen(typeMark);
	for (type = 0; type < NUM_NOTES_TYPE; type++) {

		typeMark[0] = typeChar[type];
		ptrnLen = strlen(typeMark);
		while ( ptrnLen ) {
			do {
				ptrnStartIndex = lineStartIndex;
				result = textsw_find_bytes(notesDsply, &ptrnStartIndex, &ptrnEndIndex,
					typeMark, ptrnLen, 0);
				if (result != -1) {
					if ((ptrnEndIndex < nextLineStartIndex) && (ptrnStartIndex >= lineStartIndex)) {
						textsw_erase(notesDsply, ptrnStartIndex, ptrnEndIndex);
						caretIndex -= ptrnLen;
					}else{
						result = -1;
					}
				}
			} while (result != -1);
			ptrnLen--;
		}
			
	}

	window_set( notesDsply, TEXTSW_INSERTION_POINT, caretIndex, 0);

}

static void	notesBackgroundHit(panel, event)

Panel		 panel;
Event		*event;

{
	switch (event_id(event)) {
	case MS_RIGHT:
		if (event_is_down(event)) {
			rootMenuDisplay(notesPanel,event);
		}
		break;
	default:
		return;
	}

}

rootMenuDisplay(window, event)

Window		 window;
Event		*event;

{

	switch( (int)menu_show(mainMenu, window, event, 0) ) {
	case MENU_SAVE:
		saveData();
		break;
	case MENU_RELOAD:
		loadData();
		monthDisplay();
		dayHit(dayToShow);
		break;
	case MENU_CLOSE:
		saveData();
		window_set(frame, FRAME_CLOSED, TRUE, 0);
		break;
	case MENU_QUIT:
		saveData();
		window_destroy(frame);
		break;
	}

}

monthDisplay()


{				
	int					 column,
						 row;
	int					 i, day, dow;
	char				 monthString[20];
	struct apptsData 	*cur ;

	sprintf(monthString, "%s %4u", smon[monthToShow-1], yearToShow);
	panel_set(monthItem, PANEL_LABEL_STRING, monthString, 0);

	dow = jan1Set(yearToShow);
	mon[2] = 29;
	mon[9] = 30;
	switch ((jan1Set(yearToShow + 1) + 7 - dow) % 7) {
	case 1:				/* non-leap year */
		mon[2] = 28;
		break;
	case 2:				/* leap year */
		break;
	default:			/* 1752 */
		mon[9] = 19;
		break;
	}
	for (i = 1; i < monthToShow; i++) {	
		dow += mon[i];
	}
	dow %= 7;

	row = 0;
	for (column = 0; column < dow; column++) {
		monthBoxes[row][column].date = 0;
		monthBoxes[row][column].hasNotes = 0;
	}

	for ( day = 1; day <= mon[monthToShow]; day++) {
		monthBoxes[row][column].date = day;
		monthBoxes[row][column].hasNotes = 0;
		if (column >= (DATE_COLS-1)) {
			row++;
			column = 0;
		}else{
			column++;
		}
	}

	for (; row < DATE_ROWS; row++) {
		for (; column < DATE_COLS; column++) {
			monthBoxes[row][column].date = 0;
			monthBoxes[row][column].hasNotes = 0;
		}
		column = 0;		
	}

	for (i = 0; i < NUM_NOTES_TYPE; i++) {
		if  ( i != NOTES_ALL_ALL_ALL ) {  
			for (cur = firstApptRecord[i]; cur != NULL; cur = cur->next) {
				if (	i==NOTES_D_ALL_ALL ||
				( 			cur->month==monthToShow &&  
				(				 i==NOTES_D_M_ALL ||
				( 					cur->year==yearToShow 
				)))) {  
					monthBoxes[(cur->day + dow-1) / DATE_COLS]
							   [(cur->day + dow-1) % DATE_COLS].hasNotes = 1;
				}
			}
		}
	}

	pw_writebackground(datesCrayon, 0, 0, WINDOW_WIDTH, DATES_HEIGHT, PIX_CLR);

	for (row = 0; row < DATE_ROWS; row++) {
		for (column = 0; column < DATE_COLS; column++) {
			dateBoxDisplay(row, column, NOHIGHLIGHT);
		}
	}

}

jan1Set(year)

int             year;

{

	register        y, dow;

	/* normal gregorian calendar one extra day per four years */

	y = year;
	dow = 4 + y + (y + 3) / 4;

	/* julian calendar regular gregorian less three days per 400 */

	if (y > 1800) {
		dow -= (y - 1701) / 100;
		dow += (y - 1601) / 400;
	}

	/* great calendar changeover instant */

	if (y > 1752)
		dow += 3;

	return (dow % 7);

} 

todaySet()


{
	struct tm      *tp;		/* time structure */
	long            tloc;	/* number of seconds since 1970 */

	time(&tloc);		
	tp = localtime(&tloc);
	tyear = tp->tm_year;
	tmonth = tp->tm_mon + 1;
	tday = tp->tm_mday;
	tyear += 1900;

}

dateBoxDisplay(row, column, hilite)

int              row;
int              column;
int              hilite;

{
	char			dateString[4];

	if (monthBoxes[row][column].date == 0) {
		pw_write(datesCrayon, 
			column * DATE_BOX_WIDTH + DATE_BORDER + (column * GAP),
			row * DATE_BOX_HEIGHT + DATE_BORDER + (row * GAP),
			DATE_BOX_WIDTH, DATE_BOX_HEIGHT, PIX_SRC, &dayPr, 0, 0);
		pw_text(datesCrayon, 
			column * DATE_BOX_WIDTH + DATE_BORDER + (column * GAP) + 8,
			row * DATE_BOX_HEIGHT + DATE_BORDER + (row * GAP) + 20,
			PIX_SRC | PIX_DST, font, "  ");
	}else{
		if (monthBoxes[row][column].hasNotes) {
			pw_write(datesCrayon, 
				column * DATE_BOX_WIDTH + DATE_BORDER + (column * GAP),
				row * DATE_BOX_HEIGHT + DATE_BORDER + (row * GAP),
				DATE_BOX_WIDTH, DATE_BOX_HEIGHT, PIX_SRC, 
				hilite ? &bigDaySelPr : &bigDayPr, 
				0, 0);
		}else{
			pw_write(datesCrayon, 
				column * DATE_BOX_WIDTH + DATE_BORDER + (column * GAP),
				row * DATE_BOX_HEIGHT + DATE_BORDER + (row * GAP),
				DATE_BOX_WIDTH, DATE_BOX_HEIGHT, PIX_SRC, 
				hilite ? &daySelPr : &dayPr, 
				0, 0);
		}
		sprintf(dateString, "%2u", monthBoxes[row][column].date);
		pw_text(datesCrayon, 
			column * DATE_BOX_WIDTH + DATE_BORDER + (column * GAP) + 8,
			row * DATE_BOX_HEIGHT + DATE_BORDER + (row * GAP) + 20,
			PIX_SRC | PIX_DST, font, dateString);
	}

}

notesDisplay()


{
	int					 type,
					 	 i;
	char				 timeString[7];
	struct apptsData 	*cur;


	i = (int)window_get(notesDsply, TEXTSW_LENGTH);
	if ( i > 0 ) {
		textsw_erase( notesDsply, 0, i + 1 );
	}

	for (type = 0; type < NUM_NOTES_TYPE; type++) {

		typeMark[0] = typeChar[type];

		cur = firstApptRecord[type];
		while ( (cur != NULL) && (cur->dateNum < dateNumToShow[type]) ) {
			cur = cur->next;					
		}

		while ( (cur != NULL) && (cur->dateNum == dateNumToShow[type]) ) {
			
			textsw_insert( notesDsply, typeMark, 2 );
			if (cur->time != 0) {
				sprintf(timeString, "%d:%02d ", 
					(int)(cur->time / 100), (cur->time % 100));
				textsw_insert( notesDsply, timeString, strlen(timeString) );
			}
			textsw_insert( notesDsply, cur->apptMsg, strlen(cur->apptMsg) );
			textsw_insert( notesDsply, "\n", 1 );
			cur = cur->next;					
		}
	
	}

	editCount = (int)window_get(notesDsply, TEXTSW_EDIT_COUNT);
	window_set(notesDsply, TEXTSW_FIRST_LINE, 0, 0);
	window_set(notesDsply, TEXTSW_UPDATE_SCROLLBAR, 0);

}

notesSave()


{
	int					 bufLen,
						 row, column,
						 numNotes,
						 type,
						 newEditCount,
						 thisTime, thisYear, thisMonth, thisDay;
	char				*thisMsg,
						*untypedMsg,
						*notesBuffer;
	struct apptsData 	*cur,
						*new,
						*old,
						*nextAppt[NUM_NOTES_TYPE];

	newEditCount = (int)window_get(notesDsply, TEXTSW_EDIT_COUNT);
	if (newEditCount <= editCount) {
		return;
	}
	editCount = newEditCount;

	for (type = 0; type < NUM_NOTES_TYPE; type++) {

		cur = firstApptRecord[type];
		while ( (cur != NULL) && (cur->dateNum < dateNumToShow[type]) ) {
			cur = cur->next;					
		}

		while ( (cur != NULL) && (cur->dateNum == dateNumToShow[type]) ) {
			if (cur->prev != NULL) {
				cur->prev->next = cur->next;
			}else{
				firstApptRecord[type] = cur->next;
			}
			if (cur->next != NULL) {
				cur->next->prev = cur->prev;
			}else{
				lastApptRecord[type] = cur->prev;
			}
			old = cur;		
			cur = cur->next;		
			free(old->apptMsg);
			free(old);			
		}
		nextAppt[type] = cur;

	}

	numNotes = 0;
	bufLen = (int)window_get(notesDsply, TEXTSW_LENGTH);
	
	if (bufLen > 0) {

		notesBuffer = (char *)malloc( bufLen + 1 );
		window_get( notesDsply, TEXTSW_CONTENTS, 0, notesBuffer, bufLen + 1 );
	
		thisMsg = strtok( notesBuffer, "\n" );

		while ( thisMsg != NULL ) {
	
			stripType(thisMsg, &untypedMsg, &type);
			findTime(&untypedMsg, &thisTime);
				
			if (strlen (untypedMsg) != 0) {

				thisYear = thisMonth = thisDay = 0;
				switch (type) {
					case NOTES_D_M_Y:
						thisYear = yearToShow;
					case NOTES_D_M_ALL:
						thisMonth = monthToShow;
					case NOTES_D_ALL_ALL:
						thisDay = dayToShow;
				}

				new = (struct apptsData *)malloc( sizeof( struct apptsData ) );
				new->year = thisYear;
				new->month = thisMonth;
				new->day = thisDay;
				new->dateNum = dateNumToShow[type];
				new->time = thisTime;
				new->apptMsg = (char *)malloc( strlen(untypedMsg) + 1 );
				strcpy( new->apptMsg, untypedMsg );

				if (nextAppt[type] != NULL) {
					new->prev = nextAppt[type]->prev;
					if (new->prev != NULL) {
						new->prev->next = new;
					}else{
						firstApptRecord[type] = new;
					}				
					new->next = nextAppt[type];
					if (new->next != NULL) {
						new->next->prev = new;
					}else{
						lastApptRecord[type] = new;
					}				
				}else{	
					if ( lastApptRecord[type] != NULL ) {
						new->next = NULL;
						new->prev = lastApptRecord[type];
						lastApptRecord[type]->next = new;
						lastApptRecord[type] = new;
					}else{				
						firstApptRecord[type] = lastApptRecord[type] = new;
						new->prev = new->next = NULL;
					}
				}	
	
				if (type != NOTES_ALL_ALL_ALL) {	
					numNotes++;
				}

			}
			free(untypedMsg);
			thisMsg = strtok( NULL, "\n" );

		}

		free(notesBuffer);

	}

	for (row = 0; row < DATE_ROWS; row++) {
		for (column = 0; column < DATE_COLS; column++) {
			if (dayToShow == monthBoxes[row][column].date) {
				if (numNotes > 0) {
					monthBoxes[row][column].hasNotes = 1;
				}else{
					monthBoxes[row][column].hasNotes = 0;
				}
				dateBoxDisplay(row, column, HIGHLIGHT);
			}
		}
	}
	

	notesModified = 1; 

}

int 	stripType( oldMsg, newMsg, type )

char		 *oldMsg;
char		**newMsg;
int			 *type;

{
	int			 i,j,
				 typeFound, thisIsTypeChar;
 
	*newMsg = (char *)malloc( strlen(oldMsg) + 1 );

	i = 0;
	typeFound = 0;

	while ( *oldMsg != '\0' ) {
		thisIsTypeChar = 0;
		for (j = 0; j < NUM_NOTES_TYPE; j++) {
			if ( *oldMsg == typeChar[j] ) {
				*type = j;
				thisIsTypeChar = 1;
				typeFound = 1;
			}
		}			
		if (thisIsTypeChar) {
			oldMsg++;
			while (*oldMsg == ' ') {
				oldMsg++;
			}
		}else{
			(*newMsg)[i] = *oldMsg;
			oldMsg++;
			i++;
		}		
	} 
	(*newMsg)[i] = '\0';

	if ( !typeFound ) {
		*type = NOTES_D_M_Y;
	}

}

findTime(msg, time)

char 	**msg;
int		 *time;

{
	char	 timeString[5];
	char	*curChar;
	int		 timeFound;

	curChar = *msg;						
	while (*curChar == ' ') {
		curChar++;
	}

	if (strlen(curChar) >= 4) {		

		timeFound = 1;
		if (*(curChar+1) == ':') {
			timeString[0] = '0';	
		}else if (*(curChar+2) == ':') {
			if (isdigit(*curChar)) {
				timeString[0] = *curChar;
				curChar++;
			}else{
				timeFound = 0;
			}
		}else{
			timeFound = 0;
		}

		if (timeFound) {
			if ( isdigit(*curChar) && isdigit(*(curChar+2)) && isdigit(*(curChar+3)) &&
					( (*(curChar+4) == ' ') || (*(curChar+4) == '\0') ) ) {
				timeString[1] = *curChar;
				timeString[2] = *(curChar+2);
				timeString[3] = *(curChar+3);
				timeString[4] = '\0';						
			}else{
				timeFound = 0;
			}
		}
	}else{
		timeFound = 0;
	}

	if (timeFound) {
		*time = atoi( timeString );
		if ( ( (int)(*time / 100) >= 24 ) || ( (*time % 100 ) >= 60 ) ) {
			*time = 0;
		}else{
			curChar += 4;
			while (*curChar == ' ') {
				curChar++;
			}
			*msg = curChar;
		}
	}else{
		*time = 0;
	}
										 
}

loadData()


{
	char				 home[80];
	FILE				*fptr;

	char				 basedata[80];
	char				*timestr;
	char				*apptstring;

	int					 i;
	struct apptsData 	*new;

	strcpy(home, getenv("HOME"));
	strcat(home, "/.monthtool");

	if ((fptr = fopen(home, "r")) != NULL) {

		for ( i = 0; i < (NUM_NOTES_TYPE + 1 /*for NOTES_ERROR*/); i++ ){
			firstApptRecord[i] = lastApptRecord[i] = NULL;
		}

		while ((fgets(basedata, 80, fptr) != NULL)) {

			basedata[strlen(basedata) - 1] = NULL;

			new = (struct apptsData *)malloc( sizeof( struct apptsData ) );

			new->month = atoi( strtok(basedata, ",") );
			new->day = atoi( strtok(NULL, ",") );
			new->year = atoi( strtok(NULL, ",") );
			new->dateNum = 10000 * new->year + 100 * new->month + new->day;

			timestr = strtok(NULL,","); 
			if (strcmp(timestr, "    ") == 0) {
				new->time = 0;
			}else{
				new->time = atoi(timestr);
			} 	

			apptstring = strtok(NULL, "\n" );
			new->apptMsg = malloc(strlen(apptstring) + 1);
			strcpy(new->apptMsg, apptstring);

			if ( new->year != 0 ) {
				if ( new->month != 0 ) {
					if ( new->day != 0 ) {
						i = NOTES_D_M_Y;
					}else{
						i = NOTES_ERROR;    /* *mmyyyy */
					}
				}else{
					i = NOTES_ERROR;		/* dd*yyyy or **yyyy */
				}
			}else{
				if ( new->month != 0 ) {
					if ( new->day != 0 ) {
						i = NOTES_D_M_ALL;
					}else{
						i = NOTES_ERROR;    /* *mm* */
					}
				}else{
					if ( new->day != 0 ) {
						i = NOTES_D_ALL_ALL;
					}else{
						i = NOTES_ALL_ALL_ALL;   
					}
				}
			}
				
			if ( i == NOTES_ERROR ) {
				fprintf(stderr, "Monthtool warning! Invalid record: %u,%u,%4u,",
					new->month, new->day, new->year );
				if (new->time != 0) {
					fprintf(stderr, "%04u", new->time);
				}else{
					fprintf(stderr, "    ");
				}
				fprintf(stderr, ",%s\n", new->apptMsg );
			}

			insertApptRecord(new, i);
						
		}

		fclose(fptr);
	}

} 

insertApptRecord(new, type)

struct apptsData 	*new;
int					 type;

{
	struct apptsData 	*cur;
	int					 inserted;

	if (lastApptRecord[type] == NULL) {
		firstApptRecord[type] = lastApptRecord[type] = new;
		new->prev = NULL;				
		new->next = NULL;	
	}else{
		inserted = 0;
		cur = lastApptRecord[type];
		do {
			if (new->dateNum >= cur->dateNum) {
				if (cur->next != NULL) {
					cur->next->prev = new;
				}else{
					lastApptRecord[type] = new;
				}
				new->next = cur->next;
				new->prev = cur;
				cur->next = new;
				inserted = 1;
			}else{
				cur = cur->prev;
			}
		} while ( !inserted && cur != NULL );
		if (!inserted) {
			new->next = firstApptRecord[type];
			new->prev = NULL;
			firstApptRecord[type]->prev = new;
			firstApptRecord[type] = new;
		}						
	}

}

saveData()


{
	FILE				*fptr;
	char				 home[80];

	int					 i;
	struct apptsData 	*cur ;

	notesSave();

	if (notesModified) {

		strcpy(home, getenv("HOME"));
		strcat(home, "/.monthtool");

		if ((fptr = fopen(home, "w")) == NULL) {
			fprintf(stderr, "Monthtool error:  Cannot open %s file", home);
			return;
		}

		for ( i = 0; i < (NUM_NOTES_TYPE + 1 /*for NOTES_ERROR*/); i++ ) {
			for (cur = firstApptRecord[i]; cur != NULL; cur = cur->next) {
				fprintf(fptr, "%u,%u,%u,", cur->month, cur->day, cur->year );
				if (cur->time != 0) {
					fprintf(fptr, "%04u", cur->time);
				}else{
					fprintf(fptr, "    ");
				}
				fprintf(fptr, ",%s\n", cur->apptMsg );
			}
		}

		fclose(fptr);

		notesModified = 0;

	}

}

freeData()


{

	int					 i;
	struct apptsData 	*cur ;

	for ( i = 0; i < (NUM_NOTES_TYPE + 1 /*for NOTES_ERROR*/); i++ ) {
		while( firstApptRecord[i] != NULL) {
			cur = firstApptRecord[i]; 
			firstApptRecord[i] = firstApptRecord[i]->next;
			free(cur->apptMsg);
			free( cur );
		}
	}
	
}
	
SHAR_EOF
if test -f 'monthtool.font.uu'
then
	echo shar: over-writing existing file "'monthtool.font.uu'"
fi
cat << \SHAR_EOF > 'monthtool.font.uu'
begin 666 monthtool.font
M 1X&!@ '  \                                                 
M                                                            
M                                                            
M                                                            
M                                            #PH%  < !P /  \*
M!0 '  < '@ /"@4 !P ' "T #PH%  < !P                          
M                                                            
M                     #P #PH%  < !P!+  \*!0 '  < 6@ /"@4 !P '
M &D #PH%  < !P!X  \*!0 '  < AP /"@4 !P ' )8 #PH%  < !P"E  \*
M!0 '  < M  /"@4 !P ' ,, #PH%  < !P#2  \*!0 '  < X0 /"@4 !P '
M /  #PH%  < !P#_  \*!0 '  <!#@ /"@4 !P ' 1T #PH%  < !P$L  \*
M!0 '  <!.P /"@4 !P ' 4H #PH%  < !P%9  \*!0 '  <!:  /"@4 !P '
M 7< #PH%  < !P&&  \*!0 '  <!E0 /"@4 !P ' :0 #PH%  < !P&S  \*
M!0 '  <!P@ /"@4 !P ' =$ #PH%  < !P'@  \*!0 '  <![P /"@4 !P '
M ?X #PH%  < !P(-  \*!0 '  <"'  /"@4 !P ' BL #PH%  < !P(Z  \*
M!0 '  <"20 /"@4 !P ' E@ #PH%  < !P)G  \*!0 '  <"=@ ."@0 !P '
M H0 #PH%  < !P*3  \*!0 '  <"H@ /"@4 !P ' K$ #PH%  < !P+   \*
M!0 '  <"SP /"@4 !P ' MX #PH%  < !P+M  X*!  '  <"^P /"@4 !P '
M PH #PH%  < !P,9  \*!0 '  <#*  /"@4 !P ' S< #PH%  < !P-&  \*
M!0 '  <#50 /"@4 !P ' V0 #PH%  < !P-S  \*!0 '  <#@@ /"@4 !P '
M Y$ #PH%  < !P.@  \*!0 '  <#KP /"@4 !P ' [X #PH%  < !P/-  \*
M!0 '  <#W  /"@4 !P ' ^L #PH%  < !P/Z  \*!0 '  <$"0 /"@4 !P '
M!!@ #PH%  < !P0G  \*!0 '  <$-@ /"@4 !P '!$4 #@H$  < !P13  \*
M!0 '  <$8@ /"@4 !P '!'$ #PH%  < !P2   \*!0 '  <$CP /"@4 !P '
M!)X #PH%  < !P2M  \*!0 '  <$O  /"@4 !P '!,L #PH%  < !P3:  \*
M!0 '  <$Z0 /"@4 !P '!/@ #PH%  < !P4'  \*!0 '  <%%@ /"@4 !P '
M!24 #PH%  < !P4T  \*!0 '  <%0P /"@4 !P '!5( #PH%  < !P5A  \*
M!0 '  <%<  /"@4 !P '!7\ #PH%  < !P6.  \*!0 '  <%G0 /"@4 !P '
M!:P #PH%  < !P6[  \*!0 '  <                                 
M                                                            
M                                                            
M                                                            
M              7*  \*!0 '  <%V0 /"@4 !P '!>@ #PH%  < !P7W  \*
M!0 '  <                                                     
M                                                            
M                                                            
M                                                            
M                                                            
M                                                            
M                                                            
M                                                            
M                                                            
M                                                            
M                                                            
M                                                            
M                                                            
M                                                            
M                                                            
M                                                            
M                                                            
M                                                            
M                                                            
M                                                            
M                                                            
M                                                            
M                                                            
M                                                            
M                                                            
M                                                 ! 0$! 0$   
M$        "@H*                "@H?"@H*'PH*       $! \1$ P& 1$
M>! 0     #!(2C0($"Q2$@P      !@D(! P2D1$.@        @($       
M        "! 0(" @(" 0$ @     (! 0" @(" @0$"         05#A4$   
M             ! 0?! 0                   8" @0            _@  
M                   8&         0$" @0$" @0$       #A$1$1$1$1$
M.        ! P4! 0$! 0?        #A$1 0($"!$?        #A$! 08! 1$
M.         0,%"1$?@0$#@       #P@(#@D! 1$.        !P@0%AD1$1$
M.        'Q$! @($! 0$        #A$1$0X1$1$.        #A$1$1,- 0(
M<            !@8   8&            !@8   8" @0       $"! @0" 0
M" 0           !\ 'P           ! (! (! @0($       #A$1 0($   
M$        !@D0DY24DQ (AP      ' 0*"@H1'Q$Q@       '@D)"0X)"(B
M?        #Q$0$! 0$!$.        '@D(B(B(B(D>        'XB("0\)" B
M?@       'XB("0\)" @<       /$1 0$!.1$0X        [D1$1'Q$1$3N
M        ?! 0$! 0$!!\        / @(" @(2$@P        9B0H,"@H)"1F
M        <" @(" @(")^        QD1L;%141$3&        SD1D9%143$SD
M       X9$1$1$1$3#@       !\(B(B/" @('         X1$1$1$1$1#@0
M* 8   !\(B(B/"@D)&8        \1$! . 0$1'@       #^DA 0$! 0$'P 
M      #N1$1$1$1$1#@       #N1$0H*"@0$!        #N1$145&PH*"@ 
M      #N1"@H$"@H1.X       #N1$0H*! 0$#@       !^0@0($"! 0GX 
M     #P@(" @(" @(" \      ! 0" @$! (" 0$     #P$! 0$! 0$! 0\
M       0*$0                              /X    0$ @         
M           X!#Q$1#H       # 0$!89$1$9-@            \1$! 1#@ 
M       ,! 0T3$1$3#8            X1'Q 1#@       X0$'P0$! 0?   
M         #9,1$1,- 0$.    ,! 0%AD1$1$[@       ! 0 ' 0$! 0?   
M      @( '@(" @(" @(<    & @("8D*#@D9@       ' 0$! 0$! 0?   
M         *A45%145            -AD1$1$[@           #A$1$1$.   
M         -AD1$1D6$! X        #9,1$1,- 0$#@       &PR(" @<   
M         #Q$, A$>        ! 0$'P0$! 0#            ,Q$1$1,-@  
M         .Y$*"@0$            .Y$5%0H*            &8D&!@D9@  
M         .Y$1"@H$! @\        'Q($"!$?       #! 0$!!@$! 0$ P 
M   0$! 0$! 0$! 0$! 0$!  8! 0$! ,$! 0$&       #):3           
M    _O[^_O[^_O[^_O[^    _H*"JJJ2DI*"@H+^    _H*"JKJJJJJ"@H+^
1    _H*"LJJJJJJR@H+^    
 
end
SHAR_EOF
if test -f 'monthtool.h'
then
	echo shar: over-writing existing file "'monthtool.h'"
fi
cat << \SHAR_EOF > 'monthtool.h'
/*
 	Name:		monthtool
  
	Purpose: 	visual appointment calendar 
  
	Author:		Sarah Metcalfe apres Mike Essex & Rich Burridge
  
	Date:		June 24, 1987 
  
	Discussion: Displays a calendar to the screen for a given month.  
				User may move the mouse to any day of the
				month and view or enter appointments for that date. 

*/

#include <stdio.h>
#include <ctype.h>

#include <suntool/sunview.h>
#include <suntool/canvas.h>
#include <suntool/panel.h>
#include <suntool/walkmenu.h>
#include <suntool/textsw.h>

char *sprintf() ;
char *malloc() ;
char *strcat();
char *strtok();
char *getenv();



#define  LARGEFONT		"/usr/lib/fonts/fixedwidthfonts/gallant.r.10"
#define  NORMALFONT		"/monthtool.font"


#define  DATE_ROWS			6			/* No of rows of dates. */
#define  DATE_COLS			7			/* No of columns of dates. */

#define  DATE_BOX_HEIGHT	26			/* Number of pixels for height. */
#define  DATE_BOX_WIDTH		40			/* No of pixels for width. */
#define  DATE_BORDER		5			/* No of pixels in border. */
#define  GAP				5			/* No of pixels between dates. */

#define  BTN_WIDTH			21			/* No of pixels in up and down buttons. */
#define  BTN_HEIGHT			19			/* No of pixels in up and down buttons. */


#define  WINDOW_WIDTH	(DATE_COLS * DATE_BOX_WIDTH) + \
						((DATE_COLS - 1) * GAP) + (2 * DATE_BORDER)
#define  MONTH_HEIGHT		35			
#define  DATES_HEIGHT   (DATE_ROWS * DATE_BOX_HEIGHT) + \
						((DATE_ROWS - 1) * GAP) + (2 * DATE_BORDER)
#define  NOTES_PANEL_HEIGHT	20			
#define  NOTES_HEIGHT		100			


#define  NUM_NOTES_TYPE		4				/* Types of records value */
#define  NOTES_D_M_Y		0				/* ddmmyyyy */
#define  NOTES_D_M_ALL		1				/* ddmm* */
#define  NOTES_D_ALL_ALL	2				/* dd** */
#define  NOTES_ALL_ALL_ALL	3				/* *** */
#define  NOTES_ERROR		NUM_NOTES_TYPE	/* *mmyy **yy dd*yy *mm* */


#define  MENU_CLOSE			1				/* Menu selection value */
#define  MENU_SAVE			2
#define  MENU_RELOAD		3
#define  MENU_QUIT			4

#define  HIGHLIGHT			1
#define  NOHIGHLIGHT		0

struct dateBox {
			int  		date ;
			int			hasNotes ;
} ;

struct apptsData {
			int  				 year ;
			int  				 month ;
			int  				 day ;
			int  				 dateNum ;	/* 10000*year + 100*month + day */
			int  				 time ;
			char  				*apptMsg ;
			struct apptsData	*next ; 
			struct apptsData	*prev ; 
} ;
SHAR_EOF
#	End of shell archive
exit 0
-- 

Sarah Metcalfe         decvax!utzoo!dciem!nrcaer!cognos!sarahm
Cognos Incorporated    3755 Riverside Drive, Ottawa, Ontario, CANADA  K1G 3N3
                       (613) 738-1440