v13i003: xcal, Part03/04

Peter Collinson pc at hillside.co.uk
Mon May 13 06:26:19 AEST 1991


Submitted-by: Peter Collinson <pc at hillside.co.uk>
Posting-number: Volume 13, Issue 3
Archive-name: xcal/part03

#! /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:
#	xcal_popup.c
#	xcal_alarm.c
#	xcal_cal.man
#	xcal_edit.c
# This archive created: Wed May  8 09:14:08 1991
export PATH; PATH=/bin:$PATH
echo shar: extracting "'xcal_popup.c'" '(8790 characters)'
if test -f 'xcal_popup.c'
then
	echo shar: will not over-write existing file "'xcal_popup.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'xcal_popup.c'
	X#ifndef lint
	Xstatic char *sccsid = "@(#)xcal_popup.c	3.5 (Hillside Systems) 1/16/91";
	Xstatic char *copyright = "@(#)Copyright 1989,1990 Peter Collinson, Hillside Systems";
	X#endif  /* lint */
	X/***
	X
	X* module name:
	X	xcal_popup.c
	X* function:
	X	Deal with various popups for xcal
	X	There are two main ones:
	X	a)	the centre button causes a popup date selection popup
	X	b)	the right button causes an exit popup
	X* history:
	X	Written November 1989
	X	Peter Collinson
	X	Hillside Systems
	X* (C) Copyright: 1989 Hillside Systems/Peter Collinson
	X	
	X	For full permissions and copyright notice - see xcal.c
	X***/
	X#include <stdio.h>
	X#include <ctype.h>
	X#include <X11/Intrinsic.h>
	X#include <X11/StringDefs.h>
	X#include <X11/Shell.h>
	X#include <X11/Xaw/Label.h>
	X#include <X11/Xaw/Dialog.h>
	X#include <X11/Xaw/AsciiText.h>
	X#include "xcal.h"
	X
	Xstatic void AskDialog();
	Xstatic void NoCal();
	Xstatic void YesCal();
	Xstatic char *DateParse();
	Xstatic int MonScan();
	Xstatic void LeaveDialog();
	Xstatic void NoLeave();
	Xstatic void YesLeave();
	Xstatic  void NoEdit();
	X
	X/*
	X *	This routine deals with most of the work to create
	X *	a dialog popup, it is passed a function which is called
	X *	to create the dialog box
	X *
	X *	The widget here is used for positioning, these popups are
	X *	always children of the toplevel widget
	X */
	Xvoid
	XDialogPopup(w, fn, arg)
	X	Widget	w;
	X	void (*fn)();
	X	caddr_t	arg;
	X{
	X	Widget	pop;
	X	Arg	args[5];
	X	Position x,y;
	X	Position nx, ny;
	X	Dimension width, height, border;
	X	
	X	/*
	X	 *	Get the position of the toplevel so we can
	X	 *	position the dialog box properly
	X	 */
	X	XtSetArg(args[0], XtNwidth, &width);
	X	XtSetArg(args[1], XtNheight, &height);
	X	XtGetValues(w, args, 2);
	X	XtTranslateCoords(w, (Position)(width/2),
	X                          (Position)(height/2), &x, &y);
	X						  
	X	/*
	X	 *	Create a popup to hold the dialog
	X	 */
	X	XtSetArg(args[0], XtNallowShellResize, True);
	X	XtSetArg(args[1], XtNinput, True);
	X	XtSetArg(args[2], XtNx, x);
	X	XtSetArg(args[3], XtNy, y);
	X	XtSetArg(args[4], XtNsaveUnder, TRUE);
	X	pop = XtCreatePopupShell("question", transientShellWidgetClass, toplevel, args, 5);
	X
	X	/*
	X	 *	Set up the dialog
	X	 */
	X	(*fn)(pop, arg);
	X
	X	XtRealizeWidget(pop);
	X
	X	/*
	X	 *	We can now worry if this box is actually off the screen
	X	 */
	X	XtSetArg(args[0], XtNwidth, &width);
	X	XtSetArg(args[1], XtNheight, &height);
	X	XtSetArg(args[2], XtNborderWidth, &border);
	X	XtGetValues(pop, args, 3);
	X
	X	border <<= 1;
	X	XtTranslateCoords(pop, (Position)0, (Position)0, &nx, &ny);
	X
	X	if ((nx + width + border) > WidthOfScreen(XtScreen(toplevel)))
	X		nx = WidthOfScreen(XtScreen(toplevel)) - width - border;
	X	else nx = x;
	X
	X	if ((ny + height + border) > HeightOfScreen(XtScreen(toplevel)))
	X		ny = HeightOfScreen(XtScreen(toplevel)) - height - border;
	X	else ny = y;
	X
	X	if (nx != x || ny != y)
	X	{	XtSetArg(args[0], XtNx, nx);
	X		XtSetArg(args[1], XtNy, ny);
	X		XtSetValues(pop, args, 2);
	X	}
	X	XtPopup(pop, XtGrabNone);
	X}
	X
	X/************************************************************************/
	X/*									*/
	X/*									*/
	X/*	Deals with middle button presses - ask for a date		*/
	X/*									*/
	X/*									*/
	X/************************************************************************/
	X
	X/*
	X *	SetDate - ask for a date and start a calendar
	X *	This is an action routine
	X */
	X/* ARGSUSED */
	Xvoid
	XSetDate(w, event, params, numb)
	X	Widget w;
	X	XEvent *event;
	X	String *params;
	X	Cardinal *numb;
	X{
	X	DialogPopup(toplevel, AskDialog, NULL);
	X}
	X
	X/* ARGSUSED */
	Xstatic void
	XAskDialog(pop, noop)
	X	Widget pop;
	X	Cardinal noop;
	X{
	X	Widget	dia;
	X	Arg	args[2];
	X	WidgetList children;    /* which is Widget children[] */
	X	Cardinal num_children;
	X	int	i;
	X
	X	/* Take from args: "Enter mm yyyy?" */
	X	XtSetArg(args[0], XtNvalue, "");
	X	dia =  XtCreateManagedWidget("newdate", dialogWidgetClass, pop, args, 1);
	X	XawDialogAddButton(dia, "ok", YesCal, dia);
	X	XawDialogAddButton(dia, "cancel", NoCal, pop);
	X	/*
	X	 *	I would like to add CR translations to the text box
	X	 *	the only way to get the widget seems to be to use
	X	 *	an R4 feature to get the WidgetList
	X	 */
	X	XtSetArg(args[0], XtNchildren, &children);
	X	XtSetArg(args[1], XtNnumChildren, &num_children);
	X	XtGetValues(dia, (ArgList)args, 2);
	X	for (i = 0; i < num_children; i++)
	X	{	if (XtClass(children[i]) == asciiTextWidgetClass)
	X		{	/* Bingo */
	X			XtOverrideTranslations(
	X			    children[i],
	X		            XtParseTranslationTable("<Key>Return: SetDateAction()")
	X					       );
	X
	X		}
	X		else
	X		if (XtClass(children[i]) == labelWidgetClass)
	X		{	XtSetArg(args[0], XtNresizable, True);
	X			XtSetValues(children[i], args, 1);
	X		}
	X	}
	X			  
	X}
	X
	X/*
	X *	No we don't want a specified date
	X *	Closure here is the pop shell
	X */
	X/* ARGSUSED */
	Xstatic void
	XNoCal(w, closure, call_data)
	X	Widget w;
	X	caddr_t	closure;
	X	caddr_t call_data;
	X{
	X	XtDestroyWidget((Widget)closure);
	X}
	X
	X/*
	X *	Yes we do want a specified date
	X *	Closure here is the dialog widget
	X */
	X/* ARGSUSED */
	Xstatic void
	XYesCal(w, closure, call_data)
	X	Widget w;
	X	caddr_t	closure;
	X	caddr_t call_data;
	X{
	X	Widget	dia;
	X	Arg	args[2];
	X	Date	wanted;
	X	char	*errstr;
	X	
	X	dia = (Widget)closure;
	X	/*
	X	 *	Parse the string
	X	 */
	X	if (errstr = DateParse(XawDialogGetValueString(dia), &wanted))
	X	{	/* insert an error message in the widget */
	X		XtSetArg(args[0], XtNlabel, errstr);
	X		XtSetValues(dia, args, 1);
	X		XBell(XtDisplay(toplevel), 0);
	X		return;
	X	}
	X	XtDestroyWidget(XtParent(dia));
	X	NewMonthStrip(&wanted);
	X}
	X
	X/*
	X *	Action mapped to by CR in the dialog
	X */
	X/* ARGSUSED */
	Xvoid
	XTextCal(w, event, params, numb)
	X	Widget w;
	X	XEvent *event;
	X	String *params;
	X	Cardinal *numb;
	X{
	X	YesCal(w, (caddr_t)XtParent(w), 0);	/* parent of text widget is the */
	X					/* dialog box */
	X}
	X
	X/*
	X *	Parse a date string
	X */
	Xstatic char *
	XDateParse(str, da)
	X	register char *str;
	X	Date	*da;
	X{
	X	register char	*wk;
	X	int	lastc;
	X	int	mo;
	X	
	X	*da = today;
	X
	X	wk = str;
	X	while (isspace(*wk)) wk++;
	X	if (*wk == '\0')
	X		return("No data found");
	X	str = wk;
	X	if (isdigit(*str))
	X	{	while (isdigit(*str))
	X			str++;
	X		lastc = *str;
	X		*str++ = '\0';
	X		mo = atoi(wk);
	X		if (mo < 1 || mo > 12)
	X			return("Illegal month number");
	X		da->month = mo - 1;
	X	}
	X	else
	X	if (isalpha(*str))
	X	{	/* be kind - allow month names */
	X		while (isalpha(*str))
	X		{	if (isupper(*str))
	X				*str = tolower(*str);
	X			str++;
	X		}
	X		lastc = *str;
	X		*str++ = '\0';
	X		mo = MonScan(wk);
	X		if (mo < 0)
	X			return("Cannot find month name");
	X		da->month = mo;
	X	}
	X	if (lastc)
	X	{	wk = str;
	X		while(isspace(*wk))
	X			wk++;
	X		str = wk;
	X		if (*str)
	X			da->year = atoi(wk);
	X	}
	X	return(NULL);
	X}
	X
	X/*
	X *	Given a string look in our database for a number
	X */
	Xstatic int
	XMonScan(monstr)
	Xchar *monstr;
	X{
	X    char *a, *b;
	X    int ca, cb;
	X    int	mon;
	X
	X    for (mon = 0; mon < 12; mon++)
	X	for (a = monstr, b = appResources.mon[mon]; ;)
	X	{	ca = *a++;
	X		if(ca == '\0')
	X			return(mon);
	X		if (isupper(ca))
	X			ca = tolower(ca);
	X		cb = *b++;
	X		if (cb == '\0')
	X			break;
	X		if (isupper(cb))
	X			cb = tolower(cb);
	X		if (ca != cb)
	X			break;
	X	}
	X	return(-1);
	X}
	X
	X/************************************************************************/
	X/*									*/
	X/*									*/
	X/*	Deals with right button presses - exit				*/
	X/*									*/
	X/*									*/
	X/************************************************************************/
	X/*
	X *	Get out - possibly
	X */
	X/* ARGSUSED */
	Xvoid
	XAskLeave(w, event, params, numb)
	X	Widget w;
	X	XEvent *event;
	X	String *params;
	X	Cardinal *numb;
	X{
	X
	X	DialogPopup(toplevel, LeaveDialog, NULL);
	X}
	X
	X/* ARGSUSED */
	Xstatic void
	XLeaveDialog(pop, noop)
	X	Widget pop;
	X	Cardinal noop;
	X{	Widget	di;
	X
	X	/* Take "Really exit? from resources */
	X	di =  XtCreateManagedWidget("exit", dialogWidgetClass, pop, NULL, 0);
	X	XawDialogAddButton(di, "yes", YesLeave, 0);
	X	XawDialogAddButton(di, "no", NoLeave, pop);
	X}
	X
	X/* ARGSUSED */
	Xstatic void
	XYesLeave(w, closure, call_data)
	X	Widget w;
	X	caddr_t	closure;
	X	caddr_t call_data;
	X{
	X	Leave(0);
	X}
	X
	X/* ARGSUSED */
	Xstatic void
	XNoLeave(w, closure, call_data)
	X	Widget w;
	X	caddr_t	closure;
	X	caddr_t call_data;
	X{
	X	XtDestroyWidget((Widget)closure);
	X}
	X
	X/************************************************************************/
	X/*									*/
	X/*									*/
	X/*	Deal with an attempt to double edit some data			*/
	X/*									*/
	X/*									*/
	X/************************************************************************/
	X
	X
	Xvoid
	XNoEditIsPossible(w, da)
	X	Widget	w;
	X	Date	*da;
	X{
	X	static	char	errmsg[32];	
	X
	X	(void) sprintf(errmsg, "Already editing %d %s %d", da->day, appResources.mon[da->month], da->year);
	X
	X	DialogPopup(w, NoEdit, errmsg);
	X
	X}
	X
	Xvoid
	XNoDayEditIsPossible(w, day)
	X	Widget	w;
	X	Cardinal day;
	X{
	X	static	char	errmsg[32];	
	X
	X	(void) sprintf(errmsg, "Already editing %s", appResources.day[day]);
	X
	X	DialogPopup(w, NoEdit, errmsg);
	X
	X}
	X
	Xstatic void
	XNoEdit(pop, errmsg)
	X	Widget	pop;
	X	String	errmsg;
	X{
	X	Arg		args[2];
	X	Widget		dia;
	X
	X	XtSetArg(args[0], XtNlabel, errmsg);
	X	dia =  XtCreateManagedWidget("noedit", dialogWidgetClass, pop, args, 1);
	X	XawDialogAddButton(dia, "ok", NoCal, pop);
	X}
SHAR_EOF
if test 8790 -ne "`wc -c < 'xcal_popup.c'`"
then
	echo shar: error transmitting "'xcal_popup.c'" '(should have been 8790 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'xcal_alarm.c'" '(16260 characters)'
if test -f 'xcal_alarm.c'
then
	echo shar: will not over-write existing file "'xcal_alarm.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'xcal_alarm.c'
	X#ifndef lint
	Xstatic char    *sccsid = "@(#)xcal_alarm.c	1.13 (Hillside Systems) 1/16/91";
	Xstatic char    *copyright = "@(#)Copyright 1989/1990 Mark Majhor, Peter Collinson";
	X#endif  /* lint */
	X/***
	X
	X* module name:
	X	xcal_alarm.c
	X* function:
	X	Deal with editable days
	X	This is derived from xcalendar's view of how to store things
	X* history:
	X	Original idea and code from
	X	Mark Majhor, Sequent written August 1990, received Sept 1990
	X	I have reworked most of the code and algorithms
	X	Peter Collinson
	X	Hillside Systems
	X
	X* (C) Copyright: 1989/1990 Hillside Systems/Peter Collinson/Mark Majhor
	X	
	X	For full permissions and copyright notice - see xcal.c
	X	
	X***/
	X#include <X11/IntrinsicP.h>	/* for toolkit stuff */
	X#include <X11/Intrinsic.h>
	X#include <X11/Xos.h>
	X#include <X11/StringDefs.h>	/* for useful atom names */
	X#include <X11/Shell.h>
	X#include <X11/Xaw/AsciiText.h>
	X#include <X11/Xaw/Text.h>
	X#include <X11/Xaw/Command.h>
	X#include <X11/Xaw/Label.h>
	X#include <X11/Xaw/Form.h>
	X#include <X11/Xaw/Paned.h>
	X#include <stdio.h>		/* for printing error messages */
	X#include <ctype.h>
	X#include <sys/stat.h>		/* for stat() */
	X#include <pwd.h>		/* for getting username */
	X#include <errno.h>
	X#include "xcal.h"
	X
	X#ifndef wordBreak
	X#define wordBreak	0x01
	X#define scrollVertical	0x02
	X#endif
	X
	Xstatic char	*LocalMapStem;
	Xstatic char	*TodayFile;
	Xstatic Alarm	head;
	Xstatic int	*countDown;
	Xstatic int	countDownCt;
	X
	Xstatic XtCallbackRec callbacks[] = {
	X	{NULL, NULL},
	X	{NULL, NULL}
	X};
	X
	X#define	dprintf	if (appResources.alarmScan) printf
	X
	X#define	MINUTES(hr, mn)	((hr)*60 + (mn))
	X
	X/*
	X *	Local routines
	X */
	Xstatic void AlarmScan();
	Xstatic void FreeAlarmList();
	Xstatic void setCall();
	Xstatic void beep();
	Xstatic void AddAlarm();
	Xstatic void DisplayAlarmWindow();
	Xstatic void DestroyAlarm();
	Xstatic void HoldAlarm();
	Xstatic void AutoDestroy();
	Xstatic XtTimerCallbackProc AlarmEvent();
	Xstatic XtTimerCallbackProc ClockTick();
	Xstatic int readDataLine();
	X
	X/*
	X *	Initialise variables for the alarm mechanism
	X */
	Xvoid
	XInitAlarms()
	X{
	X	register char *str;
	X	register char *wk;
	X	register ct;
	X	register int *p;
	X	char     *XtMalloc();
	X	
	X	if (appResources.alarms == False)
	X	{	dprintf("Alarms not enabled\n");
	X		return;
	X	}
	X	dprintf("Alarms on\n");
	X	/*
	X	 *	Interpret the countDown string established
	X	 *	by user - turn this into a vector
	X	 *	countDown -> points to a vector of integers
	X	 *		indicating the number of mins each alarm will be set
	X	 *	countDownCt - the number of integers in the vector
	X	 */
	X	if (str = appResources.countdown)
	X	{	for (wk = str, ct = 0; *wk; wk++)
	X			if (*wk == ',')
	X				ct++;
	X		ct++;	/* no of things to store */
	X
	X		countDown = (int *)XtMalloc(sizeof(int)*(ct+2));
	X		if (countDown == (int *)0)
	X			Fatal("Error allocating memory\n");
	X
	X		p = countDown;
	X		while (*str)
	X			if (!isdigit(*str))
	X				str++;
	X			else break;
	X		while (*str)
	X		{	*p = 0;
	X			ct = 0;
	X			while (isdigit(*str))
	X				ct = ct*10 + *str++ - '0';
	X			*p++ = ct;
	X			countDownCt++;
	X			while (*str && !isdigit(*str))
	X				str++;
	X		}
	X	}
	X	if (appResources.update)
	X		ClockTick(0, 0);
	X	else	AlarmFilePoll(0);
	X}
	X	
	X
	X/*
	X *	clock_tic is polled every minute (update) to see if
	X *	the data file has altered - if so then a new data list is
	X *	built
	X */
	Xstatic XtTimerCallbackProc
	XClockTick(client_data, id)
	X	caddr_t         client_data;
	X	XtIntervalId   *id;
	X{	
	X	int	secs = appResources.update;
	X	time_t	ti;
	X	struct	tm	*tm;
	X
	X	dprintf("ClockTick\n");
	X
	X	ti = time(0);
	X	tm = localtime(&ti);
	X	
	X	/* syncronise on the clock if this makes sense */
	X	if (secs && 60%secs == 0 && tm->tm_sec%secs)
	X		secs -= tm->tm_sec%secs;
	X	
	X	/* install a new timer */
	X	(void) XtAddTimeOut(secs * 1000, ClockTick, (caddr_t) NULL);
	X
	X	AlarmFilePoll(tm);
	X	MemoPoll();
	X}
	X
	Xvoid
	XAlarmFilePoll(tm)
	X	struct	tm	*tm;
	X{
	X	time_t	ti;
	X	int	files;
	X	char	*home;
	X	char	buf[256];
	X	char	*getenv();
	X	
	X	if (appResources.alarms == False)
	X		return;
	X
	X	if (tm == NULL)
	X	{	ti = time(0);
	X		tm = localtime(&ti);
	X	}
	X	/*
	X	 * Create the name of the data file
	X	 * in a cache to save energy
	X	 */
	X	if (LocalMapStem == NULL || (tm->tm_hour == 0 && tm->tm_min == 0))
	X	{	home = getenv("HOME");
	X		if (home == NULL)
	X		{	/* should do things with password files */
	X			/* but for now we will simply die */
	X			Fatal("Xcal needs HOME defined in the environment");
	X		}
	X
	X		if (appResources.calCompat == False)
	X		{	(void) sprintf(buf, "%s/%s/xy%d/xc%d%s%d",
	X				       home, appResources.directory,
	X				       tm->tm_year + 1900, tm->tm_mday,
	X				       appResources.smon[tm->tm_mon],
	X				       tm->tm_year + 1900);
	X		}
	X		else
	X		{	(void) sprintf(buf, "%s/%s/xc%d%s%d",
	X				       home, appResources.directory,
	X				 tm->tm_mday, appResources.smon[tm->tm_mon],
	X				       tm->tm_year + 1900);
	X		}
	X		if (LocalMapStem)
	X			XtFree(LocalMapStem);
	X		LocalMapStem = XtNewString(buf);
	X		dprintf("Todays Daily Filename = %s\n", LocalMapStem);
	X
	X		if (TodayFile)
	X			XtFree(TodayFile);
	X
	X		TodayFile = MakeWeeklyName(today.wday);
	X	}
	X
	X	files = 0;
	X	/*
	X	 *	check for file existence
	X	 */
	X	if (access(LocalMapStem, F_OK) == 0)
	X		files = 1;
	X	if (access(TodayFile, F_OK) == 0)
	X		files |= 2;
	X
	X	FreeAlarmList();
	X
	X	if (files)
	X	{	if (files&1)
	X			AlarmScan(LocalMapStem, tm, MINUTES(tm->tm_hour, tm->tm_min));
	X		if (files&2)
	X			AlarmScan(TodayFile, tm, MINUTES(tm->tm_hour, tm->tm_min));
	X	}
	X	else
	X		dprintf("No files to scan");
	X
	X	UpdateMemo();
	X}
	X
	Xstatic void
	XAlarmScan(file, tm, mnow)
	X	String          file;
	X	struct	tm	*tm;
	X	int		mnow;
	X{
	X	FILE           *fp;
	X	char            hrstr[16];
	X	char            remline[256];
	X	char           *rem;
	X	int		hr, mn;
	X	Boolean		isAction;
	X
	X
	X	dprintf("Scanning data file %s\n", file);
	X
	X	if ((fp = fopen(file, "r")) == NULL)
	X	{	fprintf(stderr, "Unexpected failure to open: %s\n", file);
	X		exit(1);
	X	}
	X
	X	while (readDataLine(fp, &hr, &mn, hrstr, remline))
	X	{	/* see if we have an action string to do */
	X		isAction = False;
	X		rem = remline;
	X		if (*rem == '!')
	X		{	isAction = True;
	X			rem++;
	X			while (*rem == ' ' || *rem == '\t')
	X			{	if (*rem == '\0')
	X					goto abort;
	X				rem++;
	X			}
	X		}
	X		else
	X		if (strncmp(remline, "%cron", 5) == 0)
	X		{	isAction = True;
	X			rem += 5;
	X			while (*rem == ' ' || *rem == '\t')
	X			{	if (*rem == '\0')
	X					goto abort;
	X				rem++;
	X			}
	X		}
	X		AddAlarm(mnow, isAction, hr, mn, hrstr, rem);
	Xabort:
	X		;
	X	}
	X	(void) fclose(fp);
	X
	X	/*
	X	 *	if we have a timeout - then set up an alarm for it
	X	 */
	X	if (head.next)
	X		setCall(tm, mnow);
	X}
	X
	X/*
	X *	the idea here is to generate a sorted event
	X *	list - one element for each event
	X *	we will discard anything that has already happened
	X */
	Xstatic void
	XAddAlarm(mnow, exec, hr, mn, hrstr, rem)
	X	int		mnow;
	X	Boolean		exec;
	X	int		hr;
	X	int		mn;
	X	char		*hrstr;
	X	char		*rem;
	X{
	X
	X	Alarm		*al, *prev, *new;
	X	char           *XtMalloc();
	X	int		al_hr, al_mn, mm;
	X	int		loop;
	X	int		zero = 0;
	X	int		*p;
	X		
	X	if (exec || countDownCt == 0)
	X	{	loop = 1;
	X		p = &zero;
	X	}
	X	else
	X	{	loop = countDownCt;
	X		p = countDown;
	X	}
	X
	X	for (;loop--;p++)
	X	{
	X		al_hr = hr;
	X		al_mn = mn;
	X		if (*p)
	X		{	al_mn -= *p;
	X			if (al_mn < 0)
	X			{	al_mn += 60;
	X				al_hr--;
	X				if (al_hr < 0)
	X					continue;
	X			}
	X		}
	X		if ((mm = MINUTES(al_hr, al_mn)) < mnow)
	X			continue;
	X
	X		new = (Alarm *) XtMalloc(sizeof(Alarm));
	X		if (new == NULL)
	X			Fatal("Error allocating alarm memory\n");
	X		new->alarm = XtNewString(hrstr);
	X		new->what = XtNewString(rem);
	X		new->alarm_mm = mm;
	X		new->alarm_state = *p;
	X		new->isAction = exec;
	X		new->next = NULL;
	X		
	X		/* now insert into correct place in List */
	X		if (head.next == NULL)
	X		{	head.next = new;
	X			dprintf("%s - %s; alarm at %02d:%02d\n",
	X			       hrstr, rem, al_hr, al_mn);
	X		}
	X		else
	X		{	for (prev = &head, al = head.next; al; prev = al, al = prev->next)
	X				if (mm < al->alarm_mm)
	X					break;
	X			prev->next = new;
	X			new->next = al;
	X			dprintf("%s - %s; alarm at %02d:%02d\n",
	X			       hrstr, rem, al_hr, al_mn);
	X		}
	X	}
	X}
	X
	X/*
	X * read a line looking for a time spec and some data
	X * return 1 if found
	X * return 0 at end
	X * Time spec is: hhmm hmm
	X * hh:mm hh.mm
	X * h:mm h.mm
	X * all above may be optionally followed by:
	X * A a AM am Am aM P p PM pm Pm pM
	X * the string is terminated by a space or a tab
	X */
	Xstatic int
	XreadDataLine(fin, hrp, minp, timestr, remline)
	X	FILE           *fin;
	X	int            *hrp;
	X	int            *minp;
	X	char           *timestr;
	X	char           *remline;
	X{
	X	register enum readState
	X	{	Ignore,	Hr1,	Hr2,	HrSep,
	X		Mn1,	Mn2,	AmPm,	LoseM,
	X		LookSp,	LoseSp,	Store,	AllDone
	X	} state;
	X	register int    c = 0;
	X	int             hr = 0, mn = 0;
	X	char           *destp;
	X
	X	if (feof(fin))
	X		return 0;
	X
	X	state = Hr1;
	X
	X	while (state != AllDone)
	X	{	if ((c = getc(fin)) == EOF)
	X		{	if (state == Store)
	X				break;
	X			return 0;
	X		}
	X		switch (state)
	X		{
	X		case Ignore:
	X			if (c == '\n')
	X				state = Hr1;
	X			continue;
	X		case Hr1:
	X			destp = timestr;
	X			if (isdigit(c))
	X			{	hr = c - '0';
	X				mn = 0;
	X				destp = timestr;
	X				*destp = '\0';
	X				state = Hr2;
	X				break;
	X			}
	X			state = (c == '\n' ? Hr1 : Ignore);
	X			continue;
	X		case Hr2:
	X			if (isdigit(c))
	X			{	hr = hr * 10 + c - '0';
	X				state = HrSep;
	X				break;
	X			}
	X			/* Falls through to .. */
	X		case HrSep:
	X			if (c == ':' || c == '.')
	X			{	state = Mn1;
	X				break;
	X			}
	X			/* Falls through to .. */
	X		case Mn1:
	X			if (isdigit(c))
	X			{	mn = c - '0';
	X				state = Mn2;
	X				break;
	X			}
	X			/* Falls through to .. */
	X		case Mn2:
	X			if (isdigit(c))
	X			{	mn = mn * 10 + c - '0';
	X				state = AmPm;
	X				break;
	X			}
	X			else
	X			if (state == Mn2)
	X			{	state = (c == '\n' ? Hr1 : Ignore);
	X				continue;
	X			}
	X			/* Falls through to .. */
	X		case AmPm:
	X			if (c == 'a' || c == 'A')
	X			{	if (hr == 12)
	X					hr = 0;
	X				state = LoseM;
	X				break;
	X			}
	X			else
	X			if (c == 'p' || c == 'P')
	X			{	if (hr < 12)
	X					hr += 12;
	X				state = LoseM;
	X				break;
	X			}
	X			/* Falls through to .. */
	X		case LoseM:
	X			if (c == 'M' || c == 'm')
	X			{	state = LookSp;
	X				break;
	X			}
	X			/* Falls through to .. */
	X		case LookSp:
	X			if (c == ' ' || c == '\t')
	X			{	state = LoseSp;
	X				if (hr >= 24 || mn >= 60)
	X					state = Ignore;
	X				destp = remline;
	X				*destp = '\0';
	X				continue;
	X			}
	X			else
	X			{	state = (c == '\n' ? Hr1 : Ignore);
	X				continue;
	X			}
	X			break;
	X		case LoseSp:
	X			if (c == ' ' || c == '\t')
	X				continue;
	X			state = Store;
	X			/* Falls through to .. */
	X		case Store:
	X			if (c == '\n')
	X			{	state = AllDone;
	X				continue;
	X			}
	X			break;
	X		}
	X		*destp++ = c;
	X		*destp = '\0';
	X	}
	X	*hrp = hr;
	X	*minp = mn;
	X	return 1;
	X}
	X
	X/*
	X *	set up the timeout for the next event
	X */
	Xstatic void
	XsetCall(tm, mnow)
	X	struct	tm *tm;
	X	int	mnow;
	X{
	X	Alarm	*sc;
	X	int	togo;
	X	
	X	for (sc = head.next; sc; sc = sc->next)
	X	{	togo = sc->alarm_mm - mnow;
	X		if (togo <= 0)
	X			continue;
	X		appResources.interval_id = XtAddTimeOut(togo*60*1000 - tm->tm_sec*1000,
	X						AlarmEvent, (caddr_t) NULL);
	X		dprintf("Alarm in %d mins\n", togo);
	X		break;
	X	}
	X}
	X
	X
	Xstatic XtTimerCallbackProc
	XAlarmEvent(client_data, id)
	X	caddr_t         client_data;
	X	XtIntervalId   *id;
	X{
	X	int		tnow;
	X	long            ti;
	X	struct tm      *tm;
	X	Alarm		*al, *prev;
	X	char            buf[255];
	X
	X	ti = time(0);
	X	tm = localtime(&ti);
	X	tnow = MINUTES(tm->tm_hour, tm->tm_min);
	X
	X	dprintf("Alarm %d:%02d\n", tm->tm_hour, tm->tm_min);
	X	
	X	for (prev = &head, al = head.next; al; prev = al, al = al->next)
	X	{	
	X		if (tnow == al->alarm_mm)
	X		{	if (appResources.cmd != NULL)
	X			{	(void) sprintf(buf, "%s %s &", appResources.cmd, al->what);
	X				system(buf);
	X			}
	X			if (al->isAction == False)
	X			{	DisplayAlarmWindow(al->alarm_state, al->alarm, al->what);
	X				beep();	/* notify the user */
	X			}
	X			else
	X				system(al->what);
	X
	X		}
	X
	X		if (al->alarm_mm <= tnow)
	X		{	prev->next = al->next;
	X			XtFree(al->alarm);
	X			XtFree(al->what);
	X			XtFree(al);
	X			al = prev;
	X		}
	X		else
	X			break;
	X	}
	X	setCall(tm, tnow);
	X}
	X
	Xstatic void
	Xbeep()
	X{
	X	register Display *dpy = XtDisplay(toplevel);
	X	int i;
	X
	X	for (i = 0; i < appResources.nbeeps; i++)
	X	{	XBell(dpy, appResources.volume);
	X		sleep(1);
	X	}
	X}
	X
	Xstatic void
	XFreeAlarmList()
	X{
	X	register Alarm *al, *nx;
	X
	X	for (al = head.next; al; al = nx)
	X	{	nx = al->next;
	X		XtFree(al->alarm);
	X		XtFree(al->what);
	X		XtFree(al);
	X	}
	X	head.next = NULL;
	X	if (appResources.interval_id)
	X	{	XtRemoveTimeOut(appResources.interval_id);
	X		appResources.interval_id = 0;
	X	}
	X}
	X
	Xtypedef struct
	X{	Widget		sa_top;
	X	XtIntervalId	sa_id;
	X} AlarmStatus;
	X
	Xstatic void
	XDisplayAlarmWindow(tleft, str1, str2)
	X	int		tleft;
	X	String          str1, str2;
	X{
	X	Widget          shell, form, title, aq, ah;
	X	Arg             args[10];
	X	Cardinal        nargs;
	X	char		*fmt;
	X	char            buf[255];
	X	AlarmStatus	*als;
	X
	X	/*
	X	 * making the top level shell the override widget class causes it to
	X	 * popup without window manager interaction or window manager
	X	 * handles.  this also means that it pops on the foreground of an
	X	 * xlocked terminal and is not resizable by the window manager.  If
	X	 * any one finds that to be desirable behavior, then change the
	X	 * transient class below to override.
	X	 * 
	X	 * For now transient class is much better behaved
	X	 */
	X	nargs = 0;
	X	XtSetArg(args[nargs], XtNallowShellResize, True); nargs++;
	X	XtSetArg(args[nargs], XtNinput, True); nargs++;
	X	XtSetArg(args[nargs], XtNsaveUnder, TRUE); nargs++;
	X	shell = XtCreatePopupShell("alarm", transientShellWidgetClass,
	X				   toplevel, args, nargs);
	X
	X	form = XtCreateManagedWidget("alarmPanel", panedWidgetClass,
	X				     shell, NULL, 0);
	X	/*
	X	 * create alarm status save area
	X	 */
	X	als = (AlarmStatus *)XtMalloc(sizeof (AlarmStatus));
	X	if (als == NULL)
	X		Fatal("Out of memory\n");
	X
	X	als->sa_top = shell;
	X	als->sa_id = NULL;
	X	if (appResources.autoquit)
	X	{	als->sa_id = XtAddTimeOut(appResources.autoquit*1000,
	X					AutoDestroy, (caddr_t) als);
	X	}
	X	 
	X	nargs = 0;
	X	XtSetArg(args[nargs], XtNshowGrip, False); nargs++;
	X	XtSetArg(args[nargs], XtNdefaultDistance, 2); nargs++;
	X	title = XtCreateManagedWidget("alarmForm", formWidgetClass,
	X				      form, args, nargs);
	X	/*
	X	 * Exit button Take "Quit" from resources
	X	 */
	X	callbacks[0].callback = DestroyAlarm;
	X	callbacks[0].closure = (caddr_t) als;
	X	nargs = 0;
	X	XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
	X	XtSetArg(args[nargs], XtNfromHoriz, NULL); nargs++;
	X	XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
	X	XtSetArg(args[nargs], XtNright, XtChainLeft); nargs++;
	X	aq = XtCreateManagedWidget("alarmQuit", commandWidgetClass,
	X				     title, args, nargs);
	X	
	X	/*
	X	 * Hold button Take "Hold" from resources
	X	 */
	X	callbacks[0].callback = HoldAlarm;
	X	callbacks[0].closure = (caddr_t) als;
	X	nargs = 0;
	X	XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
	X	XtSetArg(args[nargs], XtNfromHoriz, aq); nargs++;
	X	if (!appResources.autoquit) {
	X	  XtSetArg(args[nargs], XtNsensitive, False); nargs++;
	X	}
	X	XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
	X	XtSetArg(args[nargs], XtNright, XtChainLeft); nargs++;
	X	ah = XtCreateManagedWidget("alarmHold", commandWidgetClass,
	X				     title, args, nargs);
	X	
	X	if (tleft == 0)
	X		fmt = appResources.alarmnow;
	X	else
	X		fmt = appResources.alarmleft;
	X
	X	if (fmt && *fmt)
	X	{	nargs = 0;
	X		XtSetArg(args[nargs], XtNfromHoriz, ah); nargs++;
	X		XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
	X		XtSetArg(args[nargs], XtNright, XtChainLeft); nargs++;
	X		XtSetArg(args[nargs], XtNborderWidth, 0); nargs++;
	X		XtSetArg(args[nargs], XtNfromVert, NULL); nargs++;
	X		XtSetArg(args[nargs], XtNvertDistance, 3); nargs++;
	X		(void) sprintf(buf, fmt, tleft);
	X		XtSetArg(args[nargs], XtNlabel, buf); nargs++;
	X		(void) XtCreateManagedWidget("alarmTitle", labelWidgetClass, title, args, nargs);
	X	}
	X
	X	/*
	X	 * Now the text which is the remainder of the panel
	X	 */
	X	(void) sprintf(buf, "%s\n%s\n", str1, str2);
	X	nargs = 0;
	X	XtSetArg(args[nargs], XtNshowGrip, False); nargs++;
	X	XtSetArg(args[nargs], XtNstring, buf); nargs++;
	X	XtSetArg(args[nargs], XtNdisplayCaret, False); nargs++;
	X	(void) XtCreateManagedWidget("alarmText", asciiTextWidgetClass,
	X				     form, args, nargs);
	X
	X	XtPopup(shell, XtGrabNone);
	X}
	X
	X/* ARGSUSED */
	Xstatic void
	XDestroyAlarm(w, als, call_data)
	X	Widget          w;
	X	AlarmStatus	*als;
	X	caddr_t         call_data;
	X{
	X	if (als->sa_id)
	X		XtRemoveTimeOut(als->sa_id);
	X	AutoDestroy(als, NULL);
	X}
	X
	X/* ARGSUSED */
	Xstatic void
	XHoldAlarm(w, als, call_data)
	X	Widget          w;
	X	AlarmStatus	*als;
	X	caddr_t         call_data;
	X{
	X	if (als->sa_id)
	X		XtRemoveTimeOut(als->sa_id);
	X	XtSetSensitive(w, FALSE);
	X}
	X
	X/* ARGSUSED */
	Xstatic void
	XAutoDestroy(als, id)
	X	AlarmStatus *als;
	X	XtIntervalId   *id;
	X{	
	X	
	X	XtDestroyWidget(als->sa_top);
	X	XtFree(als);
	X}
SHAR_EOF
if test 16260 -ne "`wc -c < 'xcal_alarm.c'`"
then
	echo shar: error transmitting "'xcal_alarm.c'" '(should have been 16260 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'xcal_cal.man'" '(1102 characters)'
if test -f 'xcal_cal.man'
then
	echo shar: will not over-write existing file "'xcal_cal.man'"
else
sed 's/^	X//' << \SHAR_EOF > 'xcal_cal.man'
	X.TH XCAL_CAL (1)
	X.SH NAME
	Xxcal_cal \- interface to calendar(1) for xcal
	X.SH SYNOPSIS
	X.B xcal_cal
	X[
	X.B \-d
	Xdirectory
	X] [
	X.B \-f
	Xfile
	X] [
	X.B \-m
	X]
	X.SH DESCRIPTION
	X.I Xcal_cal
	Xreads through the files created by
	X.IR xcal (1)
	Xand creates a file suitable for use by
	X.IR calendar (1).
	XBy default, the files are found in a directory named
	X``Calendar'' in the user's home directory;
	Xan alternate directory may be specified with the
	X.B \-d
	Xflag.
	XOutput goes by default into a file named ``.xcal''
	Xin the user's home directory;
	Xit may be overridden with the
	X.B \-f
	Xflag.
	XIn both cases, if the argument given begins with a slash (`/'),
	Xthen it will be taken as a full path name, not as a path relative to the
	Xuser's home directory.
	XIf the argument begins with the two character sequence `./' then
	Xit will be taken relative to the current directory.
	XThis last form is primarily intended for use while debugging.
	XThe
	X.B \-m
	Xflag directs that multi-line entries in
	X.I xcal
	Xfiles be collected in their
	Xentirety.
	XBy default, only the first line is copied.
	X.SH "SEE ALSO
	Xxcal(1)
	X.SH AUTHOR
	XEd Gould, Mt.Xinu. Thanks Ed.
SHAR_EOF
if test 1102 -ne "`wc -c < 'xcal_cal.man'`"
then
	echo shar: error transmitting "'xcal_cal.man'" '(should have been 1102 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'xcal_edit.c'" '(24926 characters)'
if test -f 'xcal_edit.c'
then
	echo shar: will not over-write existing file "'xcal_edit.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'xcal_edit.c'
	X#ifndef lint
	Xstatic char *sccsid = "@(#)xcal_edit.c	3.15 (Hillside Systems) 1/16/91";
	Xstatic char *copyright = "@(#)Copyright 1989,1990 Peter Collinson, Hillside Systems";
	X#endif  /* lint */
	X/***
	X
	X* module name:
	X	xcal_edit.c
	X* function:
	X	Deal with editable days
	X	This is derived from xcalendar's view of how to store things
	X* history:
	X	Written November 1989
	X	Peter Collinson
	X	Hillside Systems
	X* (C) Copyright: 1989 Hillside Systems/Peter Collinson
	X	
	X	For full permissions and copyright notice - see xcal.c
	X***/
	X#include <stdio.h>
	X#include <ctype.h>
	X#include <X11/Intrinsic.h>
	X#include <X11/StringDefs.h>
	X#include <X11/Shell.h>
	X#include <X11/Xaw/AsciiText.h>
	X#include <X11/Xaw/Text.h>
	X#include <X11/Xaw/Command.h>
	X#include <X11/Xaw/Label.h>
	X#include <X11/Xaw/Paned.h>
	X#include <X11/Xaw/Form.h>
	X#include <X11/Xaw/Dialog.h>
	X#include "xcal.h"
	X#include <sys/stat.h>
	X#ifdef SYSV
	X# include <dirent.h>
	X#else
	X# include <sys/dir.h>
	X#endif
	X
	Xtypedef struct editline
	X{	struct editline *ed_next;	/* Pointer to next */
	X	struct meWrap	*ed_meWrap;	/* Pointer to head of the chain */
	X	Cardinal ed_day;		/* What day we are */
	X	Widget	ed_popup;		/* widget of editor popup */
	X	Widget	ed_quit;		/* widget of quit button */
	X	Widget	ed_save;		/* widget of save button */
	X	Widget	ed_text;		/* the text area */
	X	Cardinal ed_size;		/* size of the buffer */
	X	char	*ed_data;		/* pointer to malloc'ed data buffer */
	X} EditLine;
	X
	Xtypedef struct meWrap
	X{	struct	meWrap	*mw_next;
	X	String	mw_dir;			/* name of the directory */
	X	Boolean	mw_useTopDir;		/* have found some data in the top dir */
	X	MonthEntry mw_me;		/* what the external world sees */
	X	Instance *mw_list;		/* list of toplevel widget for the */
	X					/* current set of displayed strips */
	X	EditLine *mw_ed;		/* data being edited */
	X} MeWrap;
	X
	X#define	mw_year	mw_me.me_year
	X#define mw_month mw_me.me_month
	X#define mw_have	mw_me.me_have
	X
	X#define	StripType(mw)	(mw->mw_me.me_type)
	X
	Xstatic MeWrap *WrapBase;		/* base of the list */
	Xstatic MeWrap *WrapEnd;			/* the last one in the list */
	X
	Xchar	*MapStem;			/* pointer to the string which is */
	X					/* where the map data is stored */
	X
	XBoolean	FoundCalendarDir;		/* whether the Calendar directory exists */
	X
	Xstatic XtCallbackRec callbacks[] = {
	X   {NULL,NULL},
	X   {NULL,NULL}
	X};
	X#define ClearCallbacks() bzero((caddr_t)callbacks, sizeof (callbacks))
	X
	X/*
	X *	Routine specs
	X */
	Xstatic MeWrap *NewMeWrap();
	Xstatic MeWrap *MeWrapSearch();
	Xstatic	void DeRegisterMonth();
	Xstatic Boolean WriteCalendarFile();
	Xstatic Boolean WriteWeeklyFile();
	Xstatic void DeleteCalendarFile();
	Xstatic void SetAllButtons();
	Xstatic void TextChanged();
	Xstatic void FinishEditing();
	Xstatic void CleanEditPanel();
	Xstatic void CheckExit();
	Xstatic void CheckDia();
	Xstatic void YesCheck();
	Xstatic void NoCheck();
	Xstatic int DayMatch();
	Xvoid	StartDayEditor();
	Xvoid	Fatal();
	X
	X
	X
	X/*
	X *	Fire up the month entry environment
	X *	called once
	X */
	Xvoid
	XInitMonthEntries()
	X{	char	buf[BUFSIZ];
	X	char	*home;
	X	char	*getenv();
	X
	X	if (MapStem == NULL)
	X	{	home = getenv("HOME");
	X		if (home == NULL)
	X		{	/* should do things with password files */
	X			/* but for now we will simply die */
	X			Fatal("Xcal needs HOME defined in the environment");
	X		}
	X		(void) sprintf(buf, "%s/%s", home, appResources.directory);
	X		MapStem = XtNewString(buf);
	X	}
	X	if (access(MapStem, F_OK) < 0)
	X		FoundCalendarDir = False;
	X	else
	X	{	FoundCalendarDir = True;
	X		/*
	X		 *	If we can see the directory, then lurch into it
	X		 */
	X		if (chdir(MapStem) < 0)
	X			Fatal("Cannot change into %s", MapStem);
	X	}
	X}
	X	
	X/*
	X *	Get the entry for a specific month
	X *
	X *	xcalendar files are all
	X *	xc<d><Mon><Year>
	X *	or
	X *	xc<dd><Mon><Year>
	X *
	X *	where d or dd is the day (%02d would have been better)
	X *	<Mon> is a capitalised first three letters of the
	X *		English month name. If you need compatibility
	X *		don't redefine the short names in the resources
	X *		for this program.
	X *	<Year> is the full numeric year.
	X *
	X *	We will follow this BUT we will also make this program
	X *	create subdirectories for new years
	X *		xy<Year>
	X *	to speed up file access
	X */
	XMonthEntry *
	XGetMonthEntry(yr, mo)
	X	Cardinal	yr;
	X	Cardinal	mo;
	X{
	X	MeWrap		*mw;
	X	char		*dir;
	X	DIR		*dirp;
	X#ifdef SYSV
	X	struct	dirent	*dp;
	X#else
	X	struct	direct	*dp;
	X#endif
	X	int		da;
	X	Boolean		inSubDir;
	X	char		yearbuf[5];
	X	char		monthbuf[4];
	X	
	X	if ((mw = MeWrapSearch(yr, mo)) == NULL)
	X		mw = NewMeWrap(yr, mo);
	X
	X	if (!FoundCalendarDir)
	X		return(&mw->mw_me);
	X
	X	/*
	X	 *	need this for string match
	X	 */
	X	(void) sprintf(yearbuf, "%d", yr);
	X	(void) sprintf(monthbuf, "%s", appResources.smon[mo]);
	X	
	X	/* we are in the directory */
	X	/* so let's lookee here for the any files of interest */
	X
	X	dir = ".";
	X	inSubDir = False;
	X	if (mw->mw_dir)
	X	{	dir = mw->mw_dir;
	X		inSubDir = True;
	X	}
	X
	X	if ((dirp = opendir(dir)) == NULL)
	X		Fatal("Cannot open directory: %s", MapStem);
	X
	X	for (da = 1; da < 32; da++)
	X		if (mw->mw_have[da])
	X		{	XtFree(mw->mw_have[da]);
	X			mw->mw_have[da] = NULL;
	X		}
	X
	X	while ((dp = readdir(dirp)) != NULL)
	X	{
	X#ifdef SYSV
	X		switch(strlen(dp->d_name))
	X#else
	X		switch(dp->d_namlen)
	X#endif
	X		{
	X		case	6:	/* xy<Year> ?? */
	X			if (dp->d_name[0] == 'x' &&
	X			    dp->d_name[1] == 'y' &&
	X			    dp->d_name[2] == yearbuf[0] &&
	X			    dp->d_name[3] == yearbuf[1] &&
	X			    dp->d_name[4] == yearbuf[2] &&
	X			    dp->d_name[5] == yearbuf[3] &&
	X			    appResources.calCompat == False)
	X			{	/*
	X				 * well - we're wasting our time at the
	X				 * top level - rejig things to work in the
	X				 * subdirectory
	X				 */
	X				inSubDir = True;
	X				mw->mw_useTopDir = False;
	X				mw->mw_dir = XtNewString(dp->d_name);
	X				closedir(dirp);
	X				if ((dirp = opendir(mw->mw_dir)) == NULL)
	X					Fatal("Cannot open directory %s/%s", MapStem, mw->mw_dir);
	X				
	X			}
	X			break;
	X		case 10:	/* xc<d><Mon><Year> ?? */
	X			if (dp->d_name[0] == 'x' &&
	X			    dp->d_name[1] == 'c' &&
	X			    isdigit(dp->d_name[2]) &&
	X			    dp->d_name[3] == monthbuf[0] &&
	X			    dp->d_name[4] == monthbuf[1] &&
	X			    dp->d_name[5] == monthbuf[2] &&
	X			    dp->d_name[6] == yearbuf[0] &&
	X			    dp->d_name[7] == yearbuf[1] &&
	X			    dp->d_name[8] == yearbuf[2] &&
	X			    dp->d_name[9] == yearbuf[3])
	X			{	da = dp->d_name[2] - '0';
	X				mw->mw_have[da] = ReadCalendarFile(mw->mw_dir, dp->d_name);
	X				if (inSubDir == False)
	X					mw->mw_useTopDir = True;
	X			}
	X			break;
	X		case 11:	/* xc<dd><Mon><Year> ?? */
	X			if (dp->d_name[0] == 'x' &&
	X			    dp->d_name[1] == 'c' &&
	X			    isdigit(dp->d_name[2]) &&
	X			    isdigit(dp->d_name[3]) &&
	X			    dp->d_name[4] == monthbuf[0] &&
	X			    dp->d_name[5] == monthbuf[1] &&
	X			    dp->d_name[6] == monthbuf[2] &&
	X			    dp->d_name[7] == yearbuf[0] &&
	X			    dp->d_name[8] == yearbuf[1] &&
	X			    dp->d_name[9] == yearbuf[2] &&
	X			    dp->d_name[10] == yearbuf[3])
	X			{	da = (dp->d_name[2]-'0')*10 + (dp->d_name[3]-'0');
	X				mw->mw_have[da] = ReadCalendarFile(mw->mw_dir, dp->d_name);
	X				if (inSubDir == False)
	X					mw->mw_useTopDir = True;
	X			}
	X			break;
	X		}
	X	}
	X	closedir(dirp);
	X	return(&mw->mw_me);
	X}
	X
	X/*
	X *	Get the entry for the weekly strip
	X *	Files are xw<Day> in the Calendar directory
	X */
	XMonthEntry *
	XGetWeeklyEntry(yr, mo)
	X	Cardinal	yr;
	X	Cardinal	mo;
	X{
	X	MeWrap		*mw;
	X	int		da;
	X	DIR		*dirp;
	X#ifdef SYSV
	X	struct	dirent	*dp;
	X#else
	X	struct	direct	*dp;
	X#endif
	X
	X	if ((mw = MeWrapSearch(0, 0)) == NULL)
	X		mw = NewMeWrap(0, 0);
	X
	X	if (!FoundCalendarDir)
	X		return(&mw->mw_me);
	X
	X	if ((dirp = opendir(".")) == NULL)
	X		Fatal("Cannot open directory: %s", MapStem);
	X
	X	for (da = 0; da < 7; da++)
	X		if (mw->mw_have[da])
	X		{	XtFree(mw->mw_have[da]);
	X			mw->mw_have[da] = NULL;
	X		}
	X
	X	while ((dp = readdir(dirp)) != NULL)
	X	{
	X		if (dp->d_name[0] == 'x' &&
	X		    dp->d_name[1] == 'w' &&
	X		    ((da = DayMatch(&dp->d_name[2])) != -1))
	X		{
	X			mw->mw_have[da] = ReadCalendarFile(NULL, dp->d_name);
	X		}
	X	}
	X	closedir(dirp);
	X	return(&mw->mw_me);
	X}
	X
	X/*
	X *	Look for a short name match with a day
	X */
	Xstatic int
	XDayMatch(day)
	X	String	day;
	X{
	X	register i;
	X
	X	for (i = 0; i < 7; i++)
	X		if (strcmp(day, appResources.sday[i]) == 0)
	X			return(i);
	X	return (-1);
	X}
	X
	X/*
	X *	create a new MapWrap area
	X */
	Xstatic MeWrap *
	XNewMeWrap(yr, mo)
	X	Cardinal yr;
	X	Cardinal mo;
	X{
	X	register MeWrap	*mw;
	X
	X	mw = (MeWrap *)XtMalloc(sizeof (MeWrap));
	X	bzero(mw, sizeof (MeWrap));
	X	if (WrapEnd)
	X		WrapEnd->mw_next = mw;
	X	WrapEnd = mw;
	X	if (WrapBase == NULL)
	X		WrapBase = mw;
	X	mw->mw_year = yr;
	X	mw->mw_month = mo;
	X	mw->mw_useTopDir = False;
	X	return(mw);
	X}
	X
	X/*
	X *	Search the MapWrap list for a year
	X */
	Xstatic MeWrap *
	XMeWrapSearch(yr, mo)
	X	Cardinal yr;
	X	Cardinal mo;
	X{
	X	register MeWrap *mw;
	X
	X	if (WrapBase)
	X		for (mw = WrapBase; mw; mw = mw->mw_next)
	X			if (yr == mw->mw_year && mo == mw->mw_month)
	X				return(mw);
	X	return(NULL);
	X}
	X
	X/*
	X *	Register an instance of a month
	X *	Return a pointer to an instance structure so it can be filled
	X *	in by the caller
	X */
	XInstance *
	XRegisterMonth(yr, mo, w)
	X	Cardinal	yr;
	X	Cardinal	mo;
	X	Widget		w;
	X{
	X	register MeWrap		*mw;
	X	register Instance	*ins;
	X
	X	if ((mw = MeWrapSearch(yr, mo)) == NULL)
	X		mw = NewMeWrap(yr, mo);
	X
	X	ins = (Instance *)XtMalloc(sizeof(Instance));
	X	ins->i_next = mw->mw_list;
	X	mw->mw_list = ins;
	X	ins->i_w = w;
	X
	X	callbacks[0].callback = DeRegisterMonth;
	X#ifdef LONG_IS_32_BITS
	X	callbacks[0].closure = (caddr_t)DatePack(0, 0, mo, yr);
	X#else
	X	callbacks[0].closure = (caddr_t)DatePack(mo, yr);
	X#endif		
	X
	X	XtAddCallbacks(w, XtNdestroyCallback, callbacks);
	X	return(ins);
	X}
	X
	X/*
	X *	Return the head of an instance list - given a date
	X */
	XInstance *
	XFindInstanceList(da)
	X	Date	*da;
	X{
	X	register MeWrap *mw;
	X
	X	if ((mw = MeWrapSearch(da->year, da->month)) == NULL)
	X		return(NULL);
	X	return (mw->mw_list);
	X}
	X	
	X/*
	X *	Delete an instance
	X */
	X/* ARGSUSED */
	Xstatic void
	XDeRegisterMonth(w, closure, call_data)
	X	Widget w;
	X	caddr_t	closure;
	X	caddr_t call_data;
	X{
	X	Cardinal		yr, mo;
	X	register Instance	*ins, *inlast;
	X	register MeWrap		*mw;
	X
	X	yr = YrUnpack((Cardinal)closure);
	X	mo = MoUnpack((Cardinal)closure);
	X
	X	if ((mw = MeWrapSearch(yr, mo)) == NULL)
	X		return;
	X	for (ins = mw->mw_list, inlast = NULL;
	X		ins;
	X	        inlast = ins, ins = ins->i_next)
	X	{	if (ins->i_w == w)
	X		{	if (inlast)
	X				inlast->i_next = ins->i_next;
	X			else	mw->mw_list = ins->i_next;
	X			XtFree(ins);
	X			return;
	X		}
	X		inlast = ins;
	X	}
	X}
	X	
	X
	X/*
	X *	Read a calendar file into memory into a string
	X *	if the file is zero length then unlink and return NULL
	X */
	XString
	XReadCalendarFile(dir, file)
	X	String	dir;
	X	String file;
	X{
	X	char	fname[256];
	X	int	fd;
	X	String	destb;
	X	struct	stat	fsb;
	X
	X	if (dir)
	X	{	(void) sprintf(fname, "%s/%s", dir, file);
	X		file = fname;
	X	}
	X	if ((fd = open(file, 0)) < 0)
	X		Fatal("Cannot open: %s for reading", file);
	X	if (fstat(fd, &fsb) < 0)
	X		Fatal("Cannot fstat %s", file);
	X
	X	if (fsb.st_size == 0)
	X	{	(void) unlink(file);
	X		close(fd);
	X		return (NULL);
	X	}
	X
	X	destb = (String) XtMalloc(fsb.st_size+1);
	X
	X	if (read(fd, (String)destb, fsb.st_size) != fsb.st_size)
	X		Fatal("Read error on %s", file);
	X
	X	close(fd);
	X	
	X	destb[fsb.st_size] = '\0';
	X
	X	return(destb);
	X}
	X
	X/*
	X *	Check to see if we should create the top directory
	X */
	XBoolean
	XNeedTop()
	X{		
	X	if (!FoundCalendarDir)
	X	{	if (mkdir(MapStem, 0700) == -1)
	X		{	XBell(XtDisplay(toplevel), 0);
	X			fprintf(stderr, "xcal: Could not create: %s directory.\n", MapStem);
	X			perror("xcal: mkdir");
	X			fflush(stderr);
	X			return(False);
	X		}
	X		if (chdir(MapStem) < 0)
	X		{	XBell(XtDisplay(toplevel), 0);
	X			fprintf(stderr, "xcal: Could not chdir into %s.\n", MapStem);
	X			perror("xcal: chdir");
	X			fflush(stderr);
	X			return(False);
	X		}
	X		FoundCalendarDir = True;
	X	}
	X	return(True);
	X}
	X
	X/*
	X *	Write a calendar file creating any directories
	X *	which are needed
	X *	Return True is OK
	X */
	Xstatic Boolean
	XWriteCalendarFile(mw, day, contents)
	X	register MeWrap	*mw;
	X	Cardinal	day;
	X	char		*contents;
	X{
	X	int	fd;
	X	Cardinal len;
	X	char	fname[256];
	X	char	cname[16];
	X	
	X	len = strlen(contents);
	X	if (len == 0)
	X	{	DeleteCalendarFile(mw, day);
	X		return(True);
	X	}
	X	if (!NeedTop())
	X		return(False);
	X
	X	/*
	X	 *	So that looks OK
	X	 *	We can now create the output file.
	X	 *	However, we would like to put any new data into subdirectories
	X	 *	named for the year unless we are compatible with xcalendar
	X	 */
	X	fname[0] = '\0';
	X	if (appResources.calCompat == False && mw->mw_useTopDir == False)
	X	{	/* we have no data in the top directory */
	X		/* so let's create the directory name */
	X		(void) sprintf(fname, "xy%d", mw->mw_year);
	X
	X		if (access(fname, F_OK) < 0)
	X		{	if (mkdir(fname, 0700) < 0)
	X			{	XBell(XtDisplay(toplevel), 0);
	X				fprintf(stderr, "xcal: Could not create: %s/%s directory.\n", MapStem, fname);
	X				perror("xcal: mkdir ");
	X				fflush(stderr);
	X				return(False);
	X			}
	X		}
	X		strcat(fname, "/");
	X	}
	X	/*
	X	 *	Whew - it looks as if we can now write the file
	X	 */
	X	(void) sprintf(cname, "xc%d%s%d", day,
	X			appResources.smon[mw->mw_month],
	X			mw->mw_year);
	X
	X	strcat(fname, cname);
	X
	X	if ((fd = open(fname, O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0)
	X	{	XBell(XtDisplay(toplevel), 0);
	X		fprintf(stderr, "xcal: Could not open %s/%s for writing.\n", MapStem, fname);
	X		perror("xcal: open");
	X		fflush(stderr);
	X		return(False);
	X	}
	X
	X	if (write(fd, contents, len) != len)
	X	{	XBell(XtDisplay(toplevel), 0);
	X		fprintf(stderr, "xcal: Write error %s/%s file.\n", MapStem, fname);
	X		perror("xcal: write");
	X		fflush(stderr);
	X		close(fd);
	X		return(False);
	X	}
	X	close(fd);
	X	/*
	X	 *	tickle the alarm system if we have altered `today'
	X	 */
	X	if (today.day == day && today.month == mw->mw_month &&
	X	    today.year == mw->mw_year)
	X		AlarmFilePoll(NULL);
	X	return(True);
	X}
	X
	Xstatic void
	XDeleteCalendarFile(mw, day)
	X	register MeWrap	*mw;
	X	Cardinal	day;
	X{
	X	char	fname[256];
	X	char	cname[16];
	X	
	X	fname[0] = '\0';
	X
	X	if (mw->mw_useTopDir == False)
	X	{	/* we have no data in the top directory */
	X		/* so let's create the directory name */
	X		(void) sprintf(fname, "xy%d", mw->mw_year);
	X
	X		if (access(fname, F_OK) < 0)
	X			return;
	X		strcat(fname, "/");
	X	}
	X
	X	(void) sprintf(cname, "xc%d%s%d", day,
	X		       appResources.smon[mw->mw_month],
	X		       mw->mw_year);
	X
	X	strcat(fname, cname);
	X
	X	unlink(fname);
	X
	X	/*
	X	 *	tickle the alarm system if we have altered `today'
	X	 */
	X	if (today.day == day && today.month == mw->mw_month &&
	X	    today.year == mw->mw_year)
	X		AlarmFilePoll(NULL);
	X}
	X
	X/*
	X *	Write daily file out
	X */
	Xstatic Boolean
	XWriteWeeklyFile(mw, day, contents)
	X	register MeWrap	*mw;
	X	Cardinal	day;
	X	char		*contents;
	X{
	X	int	fd;
	X	Cardinal len;
	X	char	*fname;
	X
	X	fname = MakeWeeklyName(day);
	X	
	X	len = strlen(contents);
	X	if (len == 0)
	X		(void) unlink(fname);
	X	else
	X	{	if ((fd = open(fname, O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0)
	X		{	XBell(XtDisplay(toplevel), 0);
	X			fprintf(stderr, "xcal: Could not open %s/%s for writing.\n", MapStem, fname);
	X			perror("xcal: open");
	X			fflush(stderr);
	X			return(False);
	X		}
	X
	X		if (write(fd, contents, len) != len)
	X		{	XBell(XtDisplay(toplevel), 0);
	X			fprintf(stderr, "xcal: Write error %s/%s file.\n", MapStem, fname);
	X			perror("xcal: write");
	X			fflush(stderr);
	X			close(fd);
	X			return(False);
	X		}
	X		close(fd);
	X	}
	X	/*
	X	 *	tickle the alarm system if we have altered `today'
	X	 */
	X	if (today.wday == day)
	X		AlarmFilePoll(NULL);
	X
	X	return(True);
	X}
	X
	X/*
	X *	Create a standard weekly file name
	X */
	XString
	XMakeWeeklyName(day)
	X	Cardinal day;
	X{
	X	static	char	fname[16];
	X
	X	(void) sprintf(fname, "xw%s", appResources.sday[day]);
	X	return(fname);
	X}
	X
	X/*
	X *	Get the contents of the current Weekly file if any
	X */
	XString
	XGetWeeklyFile(day)
	X	Cardinal day;
	X{
	X	char	*fname;
	X
	X	if (FoundCalendarDir == False)
	X		return (NULL);
	X
	X	fname = MakeWeeklyName(day);
	X
	X	if (access(fname, F_OK) < 0)
	X		return(NULL);
	X
	X	return (ReadCalendarFile(NULL, fname));
	X}
	X
	X/*
	X *	Start up an editor window from the callback
	X *	Pass the calling widget so we can change its contents
	X *	after the edit
	X */
	X/* ARGSUSED */
	Xvoid
	XStartEditing(w, da)
	X	Widget	w;
	X	Date	*da;
	X{
	X	register MeWrap		*mw;
	X	register EditLine	*ed;
	X
	X	if ((mw = MeWrapSearch(da->year, da->month)) == NULL)
	X		mw = NewMeWrap(da->year, da->month); /* shouldn`t happen */
	X	/*
	X	 *	see if we are already editing this day
	X	 */
	X	for (ed = mw->mw_ed; ed; ed = ed->ed_next)
	X	{	if (ed->ed_day == da->day)
	X		{	/* we are! */
	X			/* Complain via a popup */
	X			switch (StripType(mw))
	X			{
	X			case ME_MONTHLY:
	X				NoEditIsPossible(w, da);
	X				break;
	X			case ME_WEEKLY:
	X				NoDayEditIsPossible(w, da->day);
	X				break;
	X			}
	X			return;
	X		}
	X	}
	X	/*
	X	 *	Things are looking OK
	X	 *	Create a new editing record
	X	 */
	X	ed = (EditLine *)XtMalloc(sizeof(EditLine));
	X	bzero(ed, sizeof (EditLine));
	X	ed->ed_day = da->day;
	X	ed->ed_meWrap = mw;	/* help for unlinking */
	X	/*
	X	 *	Do we have a string now
	X	 */
	X	if (mw->mw_have[da->day])
	X	{	ed->ed_size = appResources.textbufsz + strlen(mw->mw_have[da->day]) + 1;
	X		ed->ed_data = XtMalloc(ed->ed_size);
	X		strcpy(ed->ed_data, mw->mw_have[da->day]);
	X	}
	X	else
	X	{	ed->ed_data = XtMalloc(ed->ed_size = appResources.textbufsz);
	X		*ed->ed_data = '\0';
	X	}
	X	/*
	X	 *	put the record into the list
	X	 */
	X	ed->ed_next = mw->mw_ed;
	X	mw->mw_ed = ed;
	X	/*
	X	 *	We fiddle with the source widget too
	X	 *	Desensitise visible source widgets
	X	 *	If the user starts up another strip for this month
	X	 *	then the NoEditIsPossible() code above copes
	X	 */
	X	SetAllButtons(mw->mw_list, da->day, False);
	X	/*
	X	 *	Now we should start up the edit window for this
	X	 *	month
	X	 */
	X	StartDayEditor(mw, da);
	X}
	X
	X	
	X/*
	X *	Set all the relevant buttons in a widget list to off or on
	X */
	Xstatic void
	XSetAllButtons(ins, day, val)
	X	Instance	*ins;
	X	Cardinal	day;
	X	Boolean		val;
	X{
	X	for (;ins; ins = ins->i_next)
	X		XtSetSensitive(ins->i_day_info[day], val);
	X}
	X
	X/*
	X *	Start up a day editor
	X *	Modelled on xcalendar.c
	X */
	Xvoid
	XStartDayEditor(mw, da)
	X	register MeWrap	*mw;
	X	register Date	*da;
	X{
	X	register EditLine *ed = mw->mw_ed;	/* top of the list is ours */
	X	Widget		lw, et;
	X	Widget		frame;
	X	Arg		args[10];
	X	Cardinal	nargs;
	X	char		buf[64];
	X	extern		Widget	toplevel;
	X	void		FinishEditing();
	X	void		SaveEdits();
	X	void		ClearEntry();
	X	void		TextChanged();
	X	void		EditHelp();
	X	
	X	ed->ed_popup = XtCreatePopupShell("edit", topLevelShellWidgetClass, toplevel, NULL, 0);
	X
	X	/*
	X	 *	Create the title line - which is a form containing
	X	 *	buttons and a date label
	X	 */
	X	et = XtCreateManagedWidget("panel", panedWidgetClass, ed->ed_popup, NULL, 0);
	X
	X	nargs = 0;
	X	XtSetArg(args[nargs], XtNshowGrip, False); nargs++;
	X	XtSetArg(args[nargs], XtNskipAdjust, True); nargs++;
	X	XtSetArg(args[nargs], XtNdefaultDistance, 1); nargs++;
	X	frame = XtCreateManagedWidget("title", formWidgetClass, et, args, nargs);
	X	/*
	X	 *	Take label "quit" from resources
	X	 */
	X	callbacks[0].callback = FinishEditing;
	X	callbacks[0].closure = (caddr_t)ed;
	X	nargs = 0;
	X	XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
	X	XtSetArg(args[nargs], XtNfromHoriz, NULL); nargs++;
	X	XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
	X	XtSetArg(args[nargs], XtNright, XtChainLeft); nargs++;
	X	ed->ed_quit = XtCreateManagedWidget("quit", commandWidgetClass, frame, args, nargs);
	X
	X	/*
	X	 *	Take label "save" from resources
	X	 */
	X	callbacks[0].callback = SaveEdits;
	X	callbacks[0].closure = (caddr_t)ed;
	X	nargs = 0;
	X	XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
	X	XtSetArg(args[nargs], XtNfromHoriz, ed->ed_quit); nargs++;
	X	XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
	X	XtSetArg(args[nargs], XtNright, XtChainLeft); nargs++;
	X	XtSetArg(args[nargs], XtNsensitive, False); nargs++;
	X	lw = ed->ed_save = XtCreateManagedWidget("save", commandWidgetClass, frame, args, nargs);
	X
	X	if (appResources.giveHelp)
	X	{
	X		/*
	X		 *	Take label "help" from resources
	X		 */
	X		callbacks[0].callback = EditHelp;
	X		callbacks[0].closure = (caddr_t)0;
	X		nargs = 0;
	X		XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
	X		XtSetArg(args[nargs], XtNfromHoriz, lw); nargs++;
	X		XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
	X		XtSetArg(args[nargs], XtNright, XtChainLeft); nargs++;
	X		lw = XtCreateManagedWidget("help", commandWidgetClass, frame, args, nargs);
	X	}
	X
	X	switch (StripType(mw))
	X	{
	X	case ME_MONTHLY:
	X		PlaceStr(buf, da, appResources.editYearIs2);
	X		break;
	X	case ME_WEEKLY:
	X		(void) strcpy(buf, appResources.day[da->day]);
	X		break;
	X	}
	X	nargs = 0;
	X	XtSetArg(args[nargs], XtNlabel, buf); nargs++;
	X	XtSetArg(args[nargs], XtNborderWidth, 0); nargs++;
	X	XtSetArg(args[nargs], XtNfromHoriz, lw); nargs++;
	X	XtSetArg(args[nargs], XtNfromVert, NULL); nargs++;
	X	XtSetArg(args[nargs], XtNvertDistance, 2); nargs++;
	X	XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
	X	XtSetArg(args[nargs], XtNright, XtChainRight); nargs++;
	X	lw = XtCreateManagedWidget("date", labelWidgetClass, frame, args, nargs);
	X
	X	/*
	X	 *	The text widget is in the pane below
	X	 *	The Scroll Attributes are controlled from the application
	X	 *	defaults file
	X	 */
	X	callbacks[0].callback = TextChanged;
	X	callbacks[0].closure = (caddr_t)ed;
	X	nargs = 0;
	X	XtSetArg(args[nargs], XtNshowGrip, False); nargs++;
	X	XtSetArg(args[nargs], XtNstring, ed->ed_data); nargs++;
	X	XtSetArg(args[nargs], XtNeditType, XawtextEdit); nargs++;
	X	XtSetArg(args[nargs], XtNlength, ed->ed_size); nargs++;
	X	XtSetArg(args[nargs], XtNuseStringInPlace, True); nargs++;
	X	XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
	X	ed->ed_text = XtCreateManagedWidget("text", asciiTextWidgetClass, et, args, nargs);
	X	
	X	XtPopup(ed->ed_popup, XtGrabNone);
	X	
	X}
	X
	X/*
	X *	Callback for text widget
	X *	This gets called before the string is updated
	X */
	X/* ARGSUSED */
	Xstatic void
	XTextChanged(w, closure, call_data)
	X	Widget	w;
	X	caddr_t	closure;
	X	caddr_t call_data;
	X{
	X	register EditLine *ed = (EditLine *)closure;
	X
	X	XtSetSensitive(ed->ed_save, True);
	X}
	X
	X
	X/*
	X *	Callback routines
	X */
	X/* ARGSUSED */
	Xvoid
	XSaveEdits(w, closure, call_data)
	X	Widget	w;
	X	caddr_t	closure;
	X	caddr_t call_data;
	X{
	X	register EditLine *ed = (EditLine *)closure;
	X	register Instance *ins;
	X	register MeWrap	*mw;
	X	register Cardinal day;
	X	Arg	args[3];
	X	
	X	mw = ed->ed_meWrap;
	X	day = ed->ed_day;
	X	
	X	switch (StripType(mw))
	X	{
	X	case ME_MONTHLY:
	X		if (WriteCalendarFile(mw, day, ed->ed_data) == False)
	X			return;
	X		break;
	X	case ME_WEEKLY:
	X		if (WriteWeeklyFile(mw, day, ed->ed_data) == False)
	X			return;
	X		break;
	X	}
	X	/*
	X	 *	Otherwise change the displayed string
	X	 */
	X	if (mw->mw_have[day])
	X		XtFree(mw->mw_have[day]);
	X	mw->mw_have[day] = XtMalloc(strlen(ed->ed_data)+1);
	X	strcpy(mw->mw_have[day], ed->ed_data);
	X
	X	XtSetArg(args[0], XtNlabel, mw->mw_have[day]);
	X	if (*mw->mw_have[day])
	X	{	XtSetArg(args[1], XtNforeground, appResources.marked.fg);
	X		XtSetArg(args[2], XtNbackground, appResources.marked.bg);
	X	}
	X	for (ins = mw->mw_list; ins; ins = ins->i_next)
	X	{	if (*mw->mw_have[day] == '\0')
	X		{	XtSetArg(args[1], XtNforeground, ins->i_col.fg);
	X			XtSetArg(args[2], XtNbackground, ins->i_col.bg);
	X		}
	X		XtSetValues(ins->i_day_info[day], args, 3);
	X	}
	X	XtSetSensitive(ed->ed_save, False);
	X
	X	/*
	X	 * worry about updating the memo system
	X	 */
	X
	X	switch (StripType(mw))
	X	{
	X	case ME_MONTHLY:
	X		if (today.day == day && today.month == mw->mw_month &&
	X		    today.year == mw->mw_year)
	X			UpdateMemo();
	X		break;
	X	case ME_WEEKLY:
	X		if (today.wday == day)
	X			UpdateMemo();
	X		break;
	X	}
	X
	X}
	X
	Xstatic void
	XFinishEditing(w, closure, call_data)
	X	Widget	w;
	X	caddr_t	closure;
	X	caddr_t call_data;
	X{
	X	register EditLine *ed = (EditLine *)closure;
	X	register MeWrap	*mw;
	X	Cardinal	day;
	X
	X	mw = ed->ed_meWrap;
	X	day = ed->ed_day;
	X
	X	if (mw->mw_have[day] == NULL)
	X	{	if (*ed->ed_data)
	X		{	CheckExit(ed);
	X			return;
	X		}
	X	}
	X	else
	X	if (strcmp(mw->mw_have[day], ed->ed_data))
	X	{	CheckExit(ed);
	X		return;
	X	}
	X	CleanEditPanel(w, ed, call_data);
	X}
	X
	Xstatic void
	XCleanEditPanel(w, closure, call_data)
	X	Widget	w;
	X	caddr_t closure;
	X	caddr_t call_data;
	X{
	X	register EditLine *ed = (EditLine *)closure;
	X	register EditLine *edl, *eds;
	X	register MeWrap	*mw;
	X	Cardinal	day;
	X	Widget	popup;
	X
	X	mw = ed->ed_meWrap;
	X	day = ed->ed_day;
	X	popup = ed->ed_popup;
	X
	X	XtFree(ed->ed_data);
	X
	X	for (edl = NULL, eds = mw->mw_ed;
	X	     eds;
	X	     edl = eds, eds = eds->ed_next)
	X	{	if (eds == ed)
	X		{	if (edl)
	X				edl->ed_next = ed->ed_next;
	X			else	mw->mw_ed = ed->ed_next;
	X			break;
	X		}
	X	}
	X	XtFree(ed);
	X	XtPopdown(popup);
	X	XtDestroyWidget(popup);
	X
	X	SetAllButtons(mw->mw_list, day, True);
	X}
	X
	X/*
	X *	We are trying to leave with saving the data
	X *	let us see if the user really wants to
	X */
	Xstatic void
	XCheckExit(ed)
	X	register EditLine *ed;
	X{
	X	
	X	DialogPopup(ed->ed_quit, CheckDia, ed);
	X}
	X
	X/*
	X *	Here we do the work
	X */
	Xstatic void
	XCheckDia(pop, ed)
	X	Widget	pop;
	X	EditLine *ed;
	X{
	X	Widget	dia;
	X
	X	/* Take "Save file?" from resources */
	X	dia =  XtCreateManagedWidget("check", dialogWidgetClass, pop, NULL, 0);
	X	XawDialogAddButton(dia, "yes", YesCheck, ed);
	X	XawDialogAddButton(dia, "no", NoCheck, ed);
	X}
	X
	X/* ARGSUSED */
	Xstatic void
	XYesCheck(w, closure, call_data)
	X	Widget w;
	X	caddr_t	closure;
	X	caddr_t call_data;
	X{
	X	SaveEdits(w, closure, call_data);
	X	CleanEditPanel(w, closure, call_data);
	X	XtDestroyWidget(XtParent(XtParent(w)));
	X
	X}
	X
	X/* ARGSUSED */
	Xstatic void
	XNoCheck(w, closure, call_data)
	X	Widget w;
	X	caddr_t	closure;
	X	caddr_t call_data;
	X{
	X	CleanEditPanel(w, closure, call_data);
	X	XtDestroyWidget(XtParent(XtParent(w)));
	X}
	X
	X
	X/*
	X *	Slighty formatted XtError
	X */
	X/* VARARGS1 */
	Xvoid
	XFatal(fmt, a, b)
	X	char	*fmt;
	X	char	*a;
	X	char	*b;
	X{
	X	char	buf[BUFSIZ];
	X
	X	(void) sprintf(buf, fmt, a, b);
	X	XtError(buf);
	X	/* NOTREACHED */
	X}
SHAR_EOF
if test 24926 -ne "`wc -c < 'xcal_edit.c'`"
then
	echo shar: error transmitting "'xcal_edit.c'" '(should have been 24926 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0

--
Dan Heller
O'Reilly && Associates       Z-Code Software    Comp-sources-x:
Senior Writer                President          comp-sources.x at uunet.uu.net
argv at ora.com                 argv at zipcode.com



More information about the Comp.sources.x mailing list