[alt.sources] Xkal - X appointment calendar, Part04/04

ferguson@cs.rochester.edu (George Ferguson) (11/15/90)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 4 (of 4)."
# Contents:  util.c xkal.c
# Wrapped by ferguson@swan.cs.rochester.edu on Mon Nov 12 14:07:08 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'util.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'util.c'\"
else
echo shar: Extracting \"'util.c'\" \(4574 characters\)
sed "s/^X//" >'util.c' <<'END_OF_FILE'
X/*
X *	util.c : Some miscellaneous routines for handling dates.
X *
X *	George Ferguson (ferguson@cs.rochester.edu), 27 Oct 1990.
X *
X *      $Id: util.c,v 1.1 90/10/28 13:05:14 ferguson Exp $
X *
X */
X
X#include <sys/time.h>
X#include <ctype.h>
Xextern char *shortMonStr[];
X
X/*
X * Functions defined here:
X */
Xint computeDOW(), firstDOW(), lastDay();
Xvoid getCurrentDate();
Xint parseDate();
X
X/*
X * Global data
X */
Xstatic int mon_max[] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
X
X/*	-	-	-	-	-	-	-	-	*/
X/*
X *	computeDOW(day,mon,year) : Returns the day of the week for the
X *		requested date (0=Sunday, 1=Monday, etc).
X *		This newer, faster, method is courtesy findeis@alberta.
X */
Xint
XcomputeDOW(d,m,y)
Xint d,m,y;
X{
X    static int dp [12] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
X    register int y4, s;
X
X    y = y - 1;		/* actually y - 1901 */
X    s = (y/4) * 5;
X    y4 = y % 4;
X    if ((y4 == 3) && (m>1)) s++;
X    s = s + y4 + dp[m] + d + 1;
X    return (s % 7);
X}
X
X/*
X *	firstDOW(mon,year) : Returns the doy of the week for the first
X *		day of the given month and year.
X */
Xint
XfirstDOW(mon,year)
Xint mon,year;
X{
X    return(computeDOW(1,mon,year));
X}
X
X/*
X *	lastDay(mon,year) : Returns the last day of the requested
X *		month (and handles leap years, etc).
X */
Xint
XlastDay(mon,year)
Xint mon,year;
X{
X    if ((mon == 1)&&(dysize(year+1900) == 366))
X	    return(29);
X    else return(mon_max[mon]);
X}
X
X/*
X *	nextDay(d,m,y) : Increment d,m,y to the next day
X */
Xvoid
XnextDay(dp,mp,yp)
Xint *dp,*mp,*yp;
X{
X    if (*dp != lastDay(*mp,*yp))
X	*dp += 1;
X    else {
X	*dp = 1;
X	if (*mp != 11)
X	    *mp += 1;
X	else {
X	    *mp = 0;
X	    *yp += 1;
X	}
X    }
X}
X
X/*
X *	prevDay(d,m,y) : Decrement d,m,y to the previous day
X */
Xvoid
XprevDay(dp,mp,yp)
Xint *dp,*mp,*yp;
X{
X    if (*dp != 1)
X	*dp -= 1;
X    else {
X	if (*mp != 0)
X	    *mp -= 1;
X	else {
X	    *yp -= 1;
X	    *mp = 0;
X	}
X	*dp = lastDay(*mp,*yp);
X    }
X}
X
X/*	-	-	-	-	-	-	-	-	*/
X/*
X * getCurrentDate() : What else?
X */
Xvoid
XgetCurrentDate(dp,mp,yp)
Xint *dp,*mp,*yp;
X{
X  struct timeval t;
X  struct timezone tz;
X  struct tm *r;
X
X  gettimeofday(&t,&tz);
X  r = localtime(&(t.tv_sec));
X  *dp = r->tm_mday;
X  *mp = r->tm_mon;
X  *yp = r->tm_year;
X}
X
X/*	-	-	-	-	-	-	-	-	*/
X/*
X *	parseDate(text,dp,mp,yp) : Parse the string text into a date which is
X *		either an absolute or a relative date as follows:
X *
X *	rel date = [+-]{<num>[dmy]}*
X *	abs date = [<day><mon><year>]* where <day> = <num> less than 32
X *					     <mon> = <string>
X *					     <year>= <num> greater than 32
X *	The variables pointed to by dp,mp,yp are filled in with the new date.
X *	Whitespace is skipped.
X *	Returns -1 if the date was garbled, else 0.
X */
Xint
XparseDate(text,dp,mp,yp)
Xchar *text;
Xint *dp,*mp,*yp;
X{
X    int day,mon,year,last,num,sign,i;
X
X    day = mon = year = 0;
X    last = lastDay(*mp,*yp);
X    if (*text == '+' || *text == '-') {	/* relative date */
X	sign = *text++;			/* save sign */
X	while (*text) {			/* parse string... */
X	    while (isspace(*text))			/* skip white space */
X		text += 1;
X	    num = 0;
X	    while (*text >= '0' && *text <= '9') {	/* get a number */
X		num = num * 10 + *text - '0';
X		text += 1;
X	    }
X	    switch(*text) {				/* and a specifier */
X		case '\0':		/* no specifier => days */
X		case 'D' :
X		case 'd' : day = num;
X			   break;
X		case 'M' :
X		case 'm' : mon = num;
X			   break;
X		case 'Y' :
X		case 'y' : year = num;
X			   break;
X		default: return(-1);
X	    }
X	    if (*text != '\0')			/* continue unless at end */
X		text += 1;
X	}
X	if (sign == '+') {		/* now set the `current' date */
X	    *dp += day;
X	    if (*dp > last) {
X		*dp -= last;
X		*mp += 1;
X	    }
X	    *mp += mon;
X	    if (*mp > 11) {
X		*mp -= 12;
X		*yp += 1;
X	    }
X	    *yp += year;
X	} else {
X	    *yp -= year;
X	    *mp -= mon;
X	    if (*mp < 0) {
X		*mp += 12;
X		*yp -= 1;
X	    }
X	    *dp -= day;
X	    if (*dp < 1) {
X		*mp -= 1;
X		if (*mp < 0) {
X		    *mp = 11;
X		    *yp -= 1;
X		}
X		*dp += last;
X	    }
X	}
X    } else {				/* absolute date */
X	while (*text) {
X	    while (isspace(*text))		/* skip white space */
X		text += 1;
X	    num = 0;
X	    while (*text >= '0' && *text <= '9') {	/* try a number */
X		num = num * 10 + *text - '0';
X		text += 1;
X	    }
X	    if (num == 0) {		/* no number try a month */
X		if (islower(*text))
X		    *text = toupper(*text);
X		for (i=0; i < 12 && strcmp(text,shortMonStr[i]) != 0; i++) ;
X		if (i == 12) {
X		    return(-1);
X		} else {
X		    *mp = i;
X		    text += 3;
X		}
X	    } else if (num < 32)	/* number was either day or year */
X		*dp = num;
X	    else if (num >= 1900)
X		*yp = num - 1900;
X	    else *yp = num;
X	}
X    }
X    return(0);
X}
END_OF_FILE
if test 4574 -ne `wc -c <'util.c'`; then
    echo shar: \"'util.c'\" unpacked with wrong size!
fi
# end of 'util.c'
fi
if test -f 'xkal.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xkal.c'\"
else
echo shar: Extracting \"'xkal.c'\" \(12988 characters\)
sed "s/^X//" >'xkal.c' <<'END_OF_FILE'
X/*
X *	xkal.c : graphical appoinment tool
X *
X *	George Ferguson, ferguson@cs.rochester.edu,  27 Oct 1990.
X *
X *	$Id: xkal.c,v 1.10 90/11/12 13:14:52 ferguson Exp $
X *
X */
Xstatic char *rcsid = "$Id: xkal.c,v 1.10 90/11/12 13:14:52 ferguson Exp $";
X#include <stdio.h>
X#include <ctype.h>
X#include <X11/Intrinsic.h>
X#include <X11/StringDefs.h>
X#include <X11/Xmu/Drawing.h>
X#include <X11/Xaw/Form.h>
X#include <X11/Xaw/MenuButton.h>
X#include <X11/Xaw/Cardinals.h>	
X#include "EzMenu.h"
X#include "app-resources.h"
X#include "resources.h"
X#include "month.h"
X#include "day.h"
X#include "schedule.h"
X#include "db.h"
X#include "util.h"
X#include "date-strings.h"
X
X/*	-	-	-	-	-	-	-	-	*/
X/*
X * Functions defined in this file:
X */
Xint main();
Xint countAppoints();
X
Xstatic void initGraphics(), initGCs(), initWidgets();
Xstatic void createMonthFormDatas(), setMonths();
Xstatic void quit(), quit_nosave(), next(), prev(), today(), setNumMonths();
Xstatic void save(), editSchedule();
Xstatic void syntax(),listAppoints();
Xstatic Pixmap readBitmap();
X
X/*
X * Global graphics data
X */
XDisplay *display;
XScreen *screen;
XWindow root;
XGC dateGC1,dateGC3,dateGC12,emptyGC,shadeGC[23];
X
X/*
X * Global widget data
X */
XXtAppContext app_con;
XWidget toplevel;
XWidget bothForm,allForm;
XAppResources appResources;
XMonthFormData *monthFormData1,*monthFormData3[3],*monthFormData12[12];
X
X/*
X * Other global data
X */
Xchar *program;
Xint currentDay,currentMon,currentYear;		/* today */
Xint mainDay,mainMon,mainYear;			/* display */
Xint appointsChanged = False;
Xint numMonths;
X
X/*
X * Action binding table
X */
Xstatic XtActionsRec cmdActionsTable[] = {
X	{ "xkal-quit", quit },
X	{ "xkal-exit", quit_nosave },
X	{ "xkal-save", save },
X	{ "xkal-next", next },
X	{ "xkal-prev", prev },
X	{ "xkal-today", today },
X	{ "xkal-numMonths", setNumMonths },
X	{ "xkal-edit-schedule", editSchedule },
X};
X
X/*
X *	Widget and non-widget resources if the application defaults
X *	file can't be found.
X *	[ Generated automatically from Xkal.ad. ]
X */
Xstatic String fallbackResources[] = {
X#include "Xkal.ad.h"
X	NULL
X};
X
X/*	-	-	-	-	-	-	-	-	*/
X
Xint
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X    program = *argv;
X    initGraphics(&argc,argv);
X    initDb();
X    getCurrentDate(&currentDay,&currentMon,&currentYear);
X    readAppoints(appResources.appoints);
X    if (appResources.date != NULL && *(appResources.date) != '\0')
X	parseDate(appResources.date,&currentDay,&currentMon,&currentYear);
X    if (appResources.silent) {
X	XtDestroyApplicationContext(app_con);
X	exit(countAppoints(currentDay,currentMon,currentYear));
X    }
X    if (appResources.listOnly) {
X	listAppoints(currentDay,currentMon,currentYear);
X	XtDestroyApplicationContext(app_con);
X	exit(countAppoints(currentDay,currentMon,currentYear));
X    }
X    mainDay = currentDay;
X    mainMon = currentMon;
X    mainYear = currentYear;
X    numMonths = appResources.numMonths;
X    initGCs();
X    initWidgets();
X    XtRealizeWidget(toplevel);
X    if (currentDayFormData != NULL) {
X	switch (numMonths) {
X	    case 1: selectDay(monthFormData1,mainDay,mainMon,mainYear);
X		    break;
X	    case 3: selectDay(monthFormData3[1],mainDay,mainMon,mainYear);
X		    break;
X	    case 12: selectDay(monthFormData12[mainMon],mainDay,mainMon,
X								mainYear);
X		    break;
X	}
X    }
X    XtAppMainLoop(app_con);
X}
X
Xstatic void
XinitGraphics(argcp,argv)
Xint *argcp;
Xchar **argv;
X{
X    char *rev,*strchr();
X
X    toplevel = XtAppInitialize(&app_con, "Xkal",
X			       options, XtNumber(options),
X			       argcp,argv,fallbackResources,NULL,ZERO);
X    if (*argcp > 1) {
X	syntax(*argcp,argv);
X	XtDestroyApplicationContext(app_con);
X	exit(-1);
X    }
X    XtGetApplicationResources(toplevel,(XtPointer)&appResources,
X                              resources,XtNumber(resources),NULL,ZERO);
X    rev = strchr(fallbackResources[0],'$');
X    if (strcmp(appResources.revision,rev) != 0) {
X	fprintf(stderr,"%s: app-defaults release not %s\n",program,rev);
X	fprintf(stderr,"%s: you may have an outdated app-defaults file\n",
X								program);
X    }
X    XtAppAddActions(app_con,cmdActionsTable,XtNumber(cmdActionsTable));
X    display = XtDisplay(toplevel);
X    screen = XtScreen(toplevel);
X    root = RootWindowOfScreen(screen);
X}
X
Xstatic void
XinitGCs()
X{
X    XGCValues values;
X    XtGCMask mask;
X    int i;
X
X    values.foreground = (unsigned long)1;
X    values.background = (unsigned long)0;
X    values.function = GXset;
X    mask = GCForeground | GCBackground | GCFunction | GCFont;
X    values.font = appResources.dateFont1;
X    dateGC1 = XCreateGC(display,root,mask,&values);
X    values.font = appResources.dateFont3;
X    dateGC3 = XCreateGC(display,root,mask,&values);
X    values.font = appResources.dateFont12;
X    dateGC12 = XCreateGC(display,root,mask,&values);
X    values.function = GXcopy;
X    values.fill_style = FillTiled;
X    values.tile = readBitmap(appResources.noDayShade);
X    mask = GCForeground | GCBackground | GCFunction | GCFillStyle | GCTile;
X    emptyGC = XCreateGC(display,root,mask,&values);
X    values.function = GXcopy;
X    mask = GCFunction;
X    shadeGC[0] = XCreateGC(display,root,mask,&values);
X    for (i=1; i < 23; i++) {
X	if (DefaultDepthOfScreen(screen) > 1) {	/* COLOR */
X	    values.foreground = appResources.color[i];
X	    values.fill_style = FillSolid;
X	    values.function = GXcopy;
X	    mask = GCForeground | GCBackground | GCFunction;
X	} else {				/* B&W */
X	    values.foreground = (unsigned long)1;
X	    values.background = (unsigned long)0;
X	    values.tile = readBitmap(appResources.shade[i]);
X	    values.fill_style = FillTiled;
X	    values.function = GXcopy;
X	    mask = GCForeground | GCBackground | GCTile | GCFillStyle |
X								GCFunction;
X	}
X	shadeGC[i] = XCreateGC(display,root,mask,&values);
X    }
X}
X
Xstatic void
XinitWidgets()
X{
X    char *s,name[256];
X    int i;
X
X    bothForm = XtCreateManagedWidget("bothForm",formWidgetClass,toplevel,
X								NULL,ZERO);
X    XtCreateManagedWidget("fileButton",menuButtonWidgetClass,bothForm,
X								NULL,ZERO);
X    XtCreatePopupShell("fileMenu",ezMenuWidgetClass,bothForm,NULL,ZERO);
X    XtCreateManagedWidget("viewButton",menuButtonWidgetClass,bothForm,
X								NULL,ZERO);
X    XtCreatePopupShell("viewMenu",ezMenuWidgetClass,bothForm,NULL,ZERO);
X    XtCreateManagedWidget("otherButton",menuButtonWidgetClass,bothForm,
X								NULL,ZERO);
X    XtCreatePopupShell("otherMenu",ezMenuWidgetClass,bothForm,NULL,ZERO);
X    allForm = XtCreateManagedWidget("allMonthsForm",formWidgetClass,bothForm,
X								NULL,ZERO);
X    createMonthFormDatas(numMonths);
X    if (appResources.bothShown)
X	currentDayFormData = createDayFormData(bothForm);
X    setMonths();
X}
X
Xstatic void
XcreateMonthFormDatas(n)
Xint n;
X{
X    char *name = "monthFormXX_XX";
X    int i;
X
X    switch (n) {
X	case 1: monthFormData1 = createMonthFormData(allForm,"monthForm1",1);
X		XtManageChild(monthFormData1->form);
X		break;
X	case 3: for (i=0; i < 3; i++) {
X		    sprintf(name,"monthForm3_%d",i+1);
X		    monthFormData3[i] = createMonthFormData(allForm,name,3);
X		    XtManageChild(monthFormData3[i]->form);
X		}
X		break;
X	case 12: for (i=0; i < 12; i++) {
X		    sprintf(name,"monthForm12_%d",i+1);
X		    monthFormData12[i] = createMonthFormData(allForm,name,12);
X		    XtManageChild(monthFormData12[i]->form);
X		}
X		break;
X    }
X}
X
Xstatic void
XsetMonths()
X{
X    Arg args[2];
X    int i,prevMon,prevYear,nextMon,nextYear;
X
X    XawFormDoLayout(allForm,False);
X    switch (numMonths) {
X	case 1:  setMonthFormData(monthFormData1,1,mainMon,mainYear);
X		 break;
X	case 3:  prevMon = mainMon - 1;
X		 nextMon = mainMon + 1;
X		 prevYear = nextYear = mainYear;
X		 if (mainMon == 0) {
X		     prevMon = 11;
X		     prevYear = mainYear - 1;
X		 } else if (mainMon == 11) {
X		     nextMon = 0;
X		     nextYear = mainYear + 1;
X		 }
X		 setMonthFormData(monthFormData3[0],3,prevMon,prevYear);
X		 setMonthFormData(monthFormData3[1],3,mainMon,mainYear);
X		 setMonthFormData(monthFormData3[2],3,nextMon,nextYear);
X		 break;
X	case 12: for (i=0; i < 12; i++)
X		     setMonthFormData(monthFormData12[i],12,i,mainYear);
X		 break;
X    }
X    XawFormDoLayout(allForm,True);
X}
X
X/*	-	-	-	-	-	-	-	-	*/
X
X#define ACTION_PROC(NAME)	static void NAME(w,event,params,num_params) \
X					Widget w; \
X					XEvent *event; \
X					String *params; \
X					Cardinal *num_params;
X
XACTION_PROC(quit)
X{
X    if (currentDayFormData != NULL)
X	checkpointAppoints(currentDayFormData);
X    if (appointsChanged)
X	writeAppoints(appResources.appoints);
X    XtDestroyApplicationContext(app_con);
X    exit(0);
X}
X
XACTION_PROC(quit_nosave)
X{
X    XtDestroyApplicationContext(app_con);
X    exit(0);
X}
X
XACTION_PROC(next)
X{
X    if (numMonths == 1 || numMonths == 3) {
X	if (mainMon == 11) {
X	    mainMon = 0;
X	    mainYear += 1;
X	} else {
X	    mainMon += 1;
X	}
X    } else {
X	mainYear += 1;
X    }
X    setMonths();
X}
X
XACTION_PROC(prev)
X{
X    if (numMonths == 1 || numMonths == 3) {
X	if (mainMon == 0) {
X	    mainMon = 11;
X	    mainYear -= 1;
X	} else {
X	    mainMon -= 1;
X	}
X    } else {
X	mainYear -= 1;
X    }
X    setMonths();
X}
X
XACTION_PROC(today)
X{
X    mainDay = currentDay;
X    mainMon = currentMon;
X    mainYear = currentYear;
X    setMonths();
X    switch (numMonths) {
X	case 1: selectDay(monthFormData1,mainDay,mainMon,mainYear);
X		break;
X	case 3: selectDay(monthFormData3[1],mainDay,mainMon,mainYear);
X		break;
X	case 12: selectDay(monthFormData12[mainMon],mainDay,mainMon,mainYear);
X		 break;
X    }
X}
X
XACTION_PROC(setNumMonths)
X{
X    int n,i;
X
X    if (*num_params != ONE) {
X	fprintf(stderr,"%s: bad parms to xkal-numMonths()\n",program);
X	return;
X    }
X    if ((n=atoi(params[0])) == numMonths)
X	return;
X    XawFormDoLayout(bothForm,False);
X    switch (numMonths) {
X	case 1: XtUnmanageChild(monthFormData1->form);
X		break;
X	case 3: for (i=0; i < 3; i++)
X		    XtUnmanageChild(monthFormData3[i]->form);
X		break;
X	case 12: for (i=0; i < 12; i++)
X		    XtUnmanageChild(monthFormData12[i]->form);
X		break;
X    }
X    numMonths = n;
X    switch (numMonths) {
X	case 1: if (monthFormData1 == NULL)
X		    createMonthFormDatas(1);
X		setMonths();
X		XtManageChild(monthFormData1->form);
X		break;
X	case 3: if (monthFormData3[0] == NULL)
X		    createMonthFormDatas(3);
X		setMonths();
X		for (i=0; i < 3; i++)
X		    XtManageChild(monthFormData3[i]->form);
X		break;
X	case 12: if (monthFormData12[0] == NULL)
X		     createMonthFormDatas(12);
X		 setMonths();
X		 for (i=0; i < 12; i++)
X		     XtManageChild(monthFormData12[i]->form);
X		 break;
X    }
X    XawFormDoLayout(bothForm,True);
X}
X
XACTION_PROC(save)
X{
X    if (currentDayFormData != NULL)
X	checkpointAppoints(currentDayFormData);
X    if (appointsChanged)
X	writeAppoints(appResources.appoints);
X    appointsChanged = False;
X}
X
XACTION_PROC(editSchedule)
X{
X    createPopupSchedule();
X}
X
X/*	-	-	-	-	-	-	-	-	*/
X
Xstatic void
XlistAppoints(day,mon,year)
Xint day,mon,year;
X{
X    int i,dow;
X    char *s;
X
X    dow = computeDOW(day,mon,year);
X    printf("%s %d %s %d\n",shortDayStr[dow],day,shortMonStr[mon],year+1900);
X    for (i=0; i < 20; i++) {
X	if ((s=lookup(i,day,mon,year)) != NULL)
X	    if (i % 2 == 0)
X		printf("\t%2d:00 %s\n",8+(i / 2),s);
X	    else
X		printf("\t%2d:30 %s\n",8+((i-1)/2),s);
X    }
X    for (i=20; i < 22; i++) {
X	if ((s=lookup(i,day,mon,year)) != NULL)
X	    printf("\tNOTES %s\n",s);
X    }
X}
X
Xint
XcountAppoints(day,mon,year)
Xint day,mon,year;
X{
X    int i,n;
X
X    n = 0;
X    for (i=0; i < 22; i++) {
X	if (lookupAppoint(i,day,mon,year) != NULL)
X	    n += 1;
X    }
X    return(n);
X}
X
X/*	-	-	-	-	-	-	-	-	*/
X
Xstatic Pixmap
XreadBitmap(name)
Xchar *name;
X{
X    Pixmap b;
X    int w,h,xhot,yhot;
X
X    b = XmuLocateBitmapFile(screen,name,NULL,ZERO,&w,&h,&xhot,&yhot);
X    if (b == NULL) {
X	fprintf(stderr,"%s: couldn't find bitmap \"%s\"\n",program,name);
X	return(XCreatePixmap(display,screen,2,2,DefaultDepthOfScreen(screen)));
X    } else
X	return(XmuCreatePixmapFromBitmap(display,root,b,w,h,
X					DefaultDepthOfScreen(screen),1,0));
X}
X
X/*	-	-	-	-	-	-	-	-	*/
X/*
X *	syntax() : print the usage message
X */
Xstatic void
Xsyntax(argc,argv)
Xint argc;
Xchar **argv;
X{
X    argv += 1;
X    if (argc > 2 || (strcmp(*argv,"-help") != 0 && strcmp(*argv,"-?") != 0)) {
X	fprintf(stderr,"%s: bad argument(s): ",program);
X	while (--argc)
X	    fprintf(stderr,"%s ",*argv++);
X	fprintf(stderr,"\n");
X    }
X    fprintf(stderr,"usage: %s",program);
X    fprintf(stderr,"\t-appoints file\tuse file for appointments\n");
X    fprintf(stderr,"\t\t-date date\tuse given date for `today'\n");
X    fprintf(stderr,"\t\t-numMonths 1|3|12\tstart displaying 1, 3 or 12 months\n");
X    fprintf(stderr,"\t\t-bothShown\tput day display next to month(s)\n");
X    fprintf(stderr,"\t\t-nobothShown\tpopup days as needed\n");
X    fprintf(stderr,"\t\t-listOnly\tprint appoints to stdout\n");
X    fprintf(stderr,"\t\t\t-silent\texit with status == number of appoints\n");
X    fprintf(stderr,"\t\t-opaqueDates\tprint day numbers opaquely\n");
X    fprintf(stderr,"\t\t-noopaqueDates\tprint day numbers transparently\n");
X    fprintf(stderr,"\t\t-dowLabels\tprint day of week at top of columns\n");
X    fprintf(stderr,"\t\t-nodowLabels\tdon't print dow at top of columns\n");
X}
END_OF_FILE
if test 12988 -ne `wc -c <'xkal.c'`; then
    echo shar: \"'xkal.c'\" unpacked with wrong size!
fi
# end of 'xkal.c'
fi
echo shar: End of archive 4 \(of 4\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 4 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
George Ferguson			ARPA: ferguson@cs.rochester.edu
University of Rochester		UUCP: {decvax,rutgers}!rochester!ferguson
Rochester  NY  14627		VOX:  (716) 275-2527