v10i100: xcal, Part02/03

Peter Collinson pc at hillside.co.uk
Sun Dec 30 09:54:40 AEST 1990


Submitted-by: Peter Collinson <pc at hillside.co.uk>
Posting-number: Volume 10, Issue 100
Archive-name: xcal/part02

#! /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.c
#	xcal.man
#	xcal_popup.c
#	xcal_alarm.c
# This archive created: Tue Dec 18 21:16:14 1990
export PATH; PATH=/bin:$PATH
echo shar: extracting "'xcal.c'" '(16298 characters)'
if test -f 'xcal.c'
then
	echo shar: will not over-write existing file "'xcal.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'xcal.c'
	X#ifndef lint
	Xstatic char *sccsid = "@(#)xcal.c	3.13 (Hillside Systems) 12/7/90";
	Xstatic char *copyright = "@(#)Copyright 1989,1990 Peter Collinson, Hillside Systems";
	X#endif  /* lint */
	X/***
	X
	X* program name:
	X	xcal.c
	X* function:
	X	display the current calendar date
	X	if pressed as a button go into strip calendar mode
	X* switches:
	X	-format str	use str as a display format
	X	-order	ord	set the argument order to this
	X	-debug		run quickly incrementing time - 1 day per sec
	X* libraries used:
	X	libXaw.a, libXmu.a libXt.a libX11.a
	X* compile time parameters:
	X	standard
	X* history:
	X	Written November 1989
	X	Peter Collinson
	X	Hillside Systems
	X* (C) Copyright: 1989 Hillside Systems/Peter Collinson
	X	
	X	Permission to use, copy, modify, and distribute this software
	X	and its documentation for any purpose is hereby granted to
	X	anyone, provided that the above copyright notice appear
	X	in all copies and that both that copyright notice and this
	X	permission notice appear in supporting documentation, and that
	X	the name of Peter Collinson not be used in advertising or
	X	publicity pertaining to distribution of the software without
	X	specific, written prior permission.  Hillside Systems makes no
	X	representations about the suitability of this software for any
	X	purpose.  It is provided "as is" without express or implied
	X	warranty.
	X	
	X	Peter Collinson DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
	X	SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
	X	AND FITNESS, IN NO EVENT SHALL Peter Collinson BE LIABLE FOR
	X	ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
	X	WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
	X	WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
	X	ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
	X	PERFORMANCE OF THIS SOFTWARE.
	X
	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/Command.h>
	X#include <X11/Xaw/Label.h>
	X#include <X11/Xaw/Form.h>
	X#include "xcal.h"
	X
	Xchar	date_area[BUFSIZ];
	X
	X/*	command line options specific to the application */
	Xstatic XrmOptionDescRec Options[] = {
	X{"-debug",	"debug",	XrmoptionNoArg,	(caddr_t)"TRUE"},
	X{"-alarmscan",	"alarmScan",	XrmoptionNoArg,	(caddr_t)"TRUE"},
	X{"-format",	"format",	XrmoptionSepArg, NULL},
	X{"-order",	"order", 	XrmoptionSepArg, NULL},
	X};
	X
	Xstruct resources appResources;
	X
	XPixmap	MouseOnPix;
	XPixmap	MouseOffPix;
	X
	X#define offset(field) XtOffset(struct resources *, field)
	X
	Xstatic XtResource Resources[] = {
	X{"debug", "Debug", XtRBoolean, sizeof(Boolean),
	X	offset(debug), XtRString, "False" },
	X{"alarmScan", "AlarmScan", XtRBoolean, sizeof(Boolean),
	X	offset(alarmScan), XtRString, "False" },
	X{"reverseVideo", "ReverseVideo", XtRBoolean, sizeof(Boolean),
	X	offset(reverseVideo), XtRString, "False" },
	X{"xcalendarCompat", "XcalendarCompat", XtRBoolean, sizeof(Boolean),
	X	offset(calCompat), XtRString, "False" },
	X{"giveHelp", "GiveHelp", XtRBoolean, sizeof(Boolean),
	X	offset(giveHelp), XtRString, "True" },
	X{"useMemo", "UseMemo", XtRBoolean, sizeof(Boolean),
	X	offset(useMemo), XtRString, "True" },
	X{"memoLeft", "MemoLeft", XtRBoolean, sizeof(Boolean),
	X	offset(memoLeft), XtRString, "True" },
	X{"initialCalendar", "InitialCalendar", XtRBoolean, sizeof(Boolean),
	X	offset(initialCalendar), XtRString, "False" },
	X{"initialEdit", "InitialEdit", XtRBoolean, sizeof(Boolean),
	X	offset(initialEdit), XtRString, "False" },
	X{"markForeground", "MarkForeground", XtRPixel, sizeof(Pixel),
	X	offset(marked.fg), XtRString, "White" },
	X{"markBackground", "MarkBackground", XtRPixel, sizeof(Pixel),
	X	offset(marked.bg), XtRString, "Black" },
	X{"markToday", "MarkToday", XtRBoolean, sizeof(Boolean),
	X	offset(markToday), XtRString, "True" },
	X{"fontToday", "FontToday", XtRFontStruct, sizeof(XFontStruct *),
	X	offset(fontToday), XtRString, "XtDefaultFont"},
	X{"todayForeground", "TodayForeground", XtRPixel, sizeof(Pixel),
	X	offset(today.fg), XtRString, "White" },
	X{"todayBackground", "TodayBackground", XtRPixel, sizeof(Pixel),
	X	offset(today.bg), XtRString, "Black" },
	X{"format", "Format",XtRString, sizeof(String),
	X	offset(opfmt), XtRString, "%2d %s %d"},
	X{"order", "Order", XtRString, sizeof(String),
	X	offset(order), XtRString, "dmy"},
	X{"directory", "Directory", XtRString, sizeof(String),
	X	offset(directory), XtRString, "Calendar"},
	X{"textBufferSize", "TextBufferSize", XtRInt, sizeof(int),
	X	offset(textbufsz), XtRString, "2048"},
	X{"useWmTitle", "UseWmTitle", XtRBoolean, sizeof(Boolean),
	X	offset(useWmTitle), XtRString, "True"},
	X{"minStripWidth", "MinStripWidth", XtRDimension, sizeof(Dimension),
	X	offset(minstripwidth), XtRString, "0"},
	X{"january", "January", XtRString, sizeof(String),
	X	offset(mon[0]), XtRString, "January"},
	X{"february", "February", XtRString, sizeof(String),
	X	offset(mon[1]), XtRString, "February"},
	X{"march", "March", XtRString, sizeof(String),
	X	offset(mon[2]), XtRString, "March"},
	X{"april", "April", XtRString, sizeof(String),
	X	offset(mon[3]), XtRString, "April"},
	X{"may", "May", XtRString, sizeof(String),
	X	offset(mon[4]), XtRString, "May"},
	X{"june", "June", XtRString, sizeof(String),
	X	offset(mon[5]), XtRString, "June"},
	X{"july", "July", XtRString, sizeof(String),
	X	offset(mon[6]), XtRString, "July"},
	X{"august", "August", XtRString, sizeof(String),
	X	offset(mon[7]), XtRString, "August"},
	X{"september", "September", XtRString, sizeof(String),
	X	offset(mon[8]), XtRString, "September"},
	X{"october", "October", XtRString, sizeof(String),
	X	offset(mon[9]), XtRString, "October"},
	X{"november", "November", XtRString, sizeof(String),
	X	offset(mon[10]), XtRString, "November"},
	X{"december", "December", XtRString, sizeof(String),
	X	offset(mon[11]), XtRString, "December"},
	X{"jan", "Jan", XtRString, sizeof(String),
	X	offset(smon[0]), XtRString, "Jan"},
	X{"feb", "Feb", XtRString, sizeof(String),
	X	offset(smon[1]), XtRString, "Feb"},
	X{"mar", "Mar", XtRString, sizeof(String),
	X	offset(smon[2]), XtRString, "Mar"},
	X{"apr", "Apr", XtRString, sizeof(String),
	X	offset(smon[3]), XtRString, "Apr"},
	X{"may", "May", XtRString, sizeof(String),
	X	offset(smon[4]), XtRString, "May"},
	X{"jun", "Jun", XtRString, sizeof(String),
	X	offset(smon[5]), XtRString, "Jun"},
	X{"jul", "Jul", XtRString, sizeof(String),
	X	offset(smon[6]), XtRString, "Jul"},
	X{"aug", "Aug", XtRString, sizeof(String),
	X	offset(smon[7]), XtRString, "Aug"},
	X{"sep", "Sep", XtRString, sizeof(String),
	X	offset(smon[8]), XtRString, "Sep"},
	X{"oct", "Oct", XtRString, sizeof(String),
	X	offset(smon[9]), XtRString, "Oct"},
	X{"nov", "Nov", XtRString, sizeof(String),
	X	offset(smon[10]), XtRString, "Nov"},
	X{"dec", "Dec", XtRString, sizeof(String),
	X	offset(smon[11]), XtRString, "Dec"},
	X{"sunday", "Sunday", XtRString, sizeof(String),
	X	offset(day[0]), XtRString, "Sun"},
	X{"monday", "Monday", XtRString, sizeof(String),
	X	offset(day[1]), XtRString, "Mon"},
	X{"tuesday", "Tuesday", XtRString, sizeof(String),
	X	offset(day[2]), XtRString, "Tue"},
	X{"wednesday", "Wednesday", XtRString, sizeof(String),
	X	offset(day[3]), XtRString, "Wed"},
	X{"thursday", "Thursday", XtRString, sizeof(String),
	X	offset(day[4]), XtRString, "Thu"},
	X{"friday", "Friday", XtRString, sizeof(String),
	X	offset(day[5]), XtRString, "Fri"},
	X{"saturday", "Saturday", XtRString, sizeof(String),
	X	offset(day[6]), XtRString, "Sat"},
	X{"alarms", "Alarms", XtRBoolean, sizeof(Boolean),
	X	offset(alarms), XtRString, "True"},
	X{"update", "Update", XtRInt, sizeof(int),
	X	offset(update), XtRString, "0"},
	X{"volume", "Volume", XtRInt, sizeof(int),
	X	offset(volume), XtRString, "50"},
	X{"nbeeps", "Nbeeps", XtRInt, sizeof(int),
	X	offset(nbeeps), XtRString, "3"},
	X{"cmd", "Cmd", XtRString, sizeof(String),
	X	offset(cmd), XtRString, NULL},
	X{"countdown", "Countdown", XtRString, sizeof(String),
	X	offset(countdown), XtRString, "10,0"},
	X{"autoquit", "Autoquit",  XtRInt, sizeof(int),
	X	offset(autoquit), XtRString, "120"},
	X{"alarmleft", "Alarmleft",  XtRString, sizeof(String),
	X	offset(alarmleft), XtRString, "%d minutes before..."},
	X{"alarmnow", "Alarmnow",  XtRString, sizeof(String),
	X	offset(alarmnow), XtRString, "Time is now..."},
	X{"memoFile", "MemoFile", XtRString, sizeof(String),
	X	offset(memoFile), XtRString, "memo"},
	X{"maxDisplayLines", "MaxDisplayLines", XtRInt, sizeof(int),
	X	offset(maxDisplayLines), XtRString, "5"},
	X};
	X
	Xstatic XtCallbackRec callbacks[] = {
	X   {NULL, NULL},
	X   {NULL, NULL},
	X};
	X#define ClearCallbacks() bzero((caddr_t)callbacks, sizeof (callbacks))
	X
	Xstatic XtActionsRec appActions[]= {
	X	{"setdate", SetDate},
	X	{"leave", AskLeave},
	X	{"SetDateAction", TextCal},
	X};
	X
	Xstatic String defTranslations =
	X	"<Btn2Down>: set()\n\
	X	<Btn2Up>:setdate() unset()\n\
	X	<Btn3Down>: set()\n\
	X	<Btn3Up>: leave() unset()";
	X
	Xstatic Arg	wargs[7] = {
	X	XtNlabel, (XtArgVal) date_area,
	X	XtNcallback, (XtArgVal)callbacks,
	X};
	X
	XWidget	toplevel;
	X
	XDate	today;
	X
	X/*
	X *	Forward routines local to this file
	X */
	Xvoid	MkDate();
	Xvoid	DebugMkDate();
	Xvoid	DoTemplate();
	Xvoid	DecodeOrder();
	X#include "mouse.bm"
	X#include "mouseaway.bm"
	X
	Xvoid
	Xmain(argc, argv)
	X	unsigned int argc;
	X	char **argv;
	X{
	X	Widget parent;
	X	Widget memo;
	X	Widget lab;
	X	
	X
	X	toplevel = XtInitialize(argv[0], "XCal",
	X				Options, XtNumber(Options), &argc, argv);
	X
	X	PixInit(toplevel);
	X	
	X	if (argc != 1)
	X		fprintf(stderr, "Error in arguments\n", argv[0]);
	X
	X	XtGetApplicationResources(toplevel, (caddr_t)&appResources, Resources,
	X			      XtNumber(Resources), (ArgList)NULL, 0);
	X
	X	/*
	X	 *	If reverse video
	X	 *	invert default colour settings
	X	 */
	X	if (appResources.reverseVideo)
	X	{	Colour	old;
	X		old = appResources.marked;
	X		appResources.marked.fg = old.bg;
	X		appResources.marked.bg = old.fg;
	X		old = appResources.today;
	X		appResources.today.fg = old.bg;
	X		appResources.today.bg = old.fg;
	X	}
	X	
	X	InitMonthEntries();
	X	
	X	DecodeOrder();
	X	
	X	DoTemplate();		/* give a maximum initial size of the box */
	X
	X	/*
	X	 *	Top level widget is now a form
	X	 *	assuming that memo is wanted
	X	 */
	X	if (appResources.useMemo)
	X	{	parent = toplevel;
	X		XtSetArg(wargs[2], XtNborderWidth, 0);
	X		XtSetArg(wargs[3], XtNdefaultDistance, 0);
	X		parent = XtCreateManagedWidget("form", formWidgetClass,
	X					parent, &wargs[2], 3);
	X
	X		if (appResources.memoLeft)
	X		{	XtSetArg(wargs[2], XtNfromHoriz, NULL);
	X			XtSetArg(wargs[3], XtNleft, XtChainLeft);
	X			XtSetArg(wargs[4], XtNright, XtRubber);
	X			XtSetArg(wargs[5], XtNborderWidth, 0);
	X			XtSetArg(wargs[6], XtNbitmap, MouseOnPix);
	X			callbacks[0].callback = DoMemo;
	X			memo = XtCreateManagedWidget("today", commandWidgetClass,
	X					     parent, &wargs[1], 6);
	X			ClearCallbacks();
	X
	X			XtSetArg(wargs[2], XtNfromHoriz, memo);
	X			XtSetArg(wargs[3], XtNleft, XtRubber);
	X			XtSetArg(wargs[4], XtNright, XtChainRight);
	X			XtSetArg(wargs[5], XtNborderWidth, 0);
	X			callbacks[0].callback = DoCalendar;
	X			lab = XtCreateManagedWidget("date", commandWidgetClass,
	X					    parent, wargs, 6);
	X		}
	X		else
	X		{
	X			XtSetArg(wargs[2], XtNfromHoriz, NULL);
	X			XtSetArg(wargs[3], XtNleft, XtChainLeft);
	X			XtSetArg(wargs[4], XtNright, XtRubber);
	X			XtSetArg(wargs[5], XtNborderWidth, 0);
	X			callbacks[0].callback = DoCalendar;
	X			lab = XtCreateManagedWidget("date", commandWidgetClass,
	X					    parent, wargs, 6);
	X			ClearCallbacks();
	X
	X			XtSetArg(wargs[2], XtNfromHoriz, lab);
	X			XtSetArg(wargs[3], XtNleft, XtRubber);
	X			XtSetArg(wargs[4], XtNright, XtChainRight);
	X			XtSetArg(wargs[5], XtNborderWidth, 0);
	X			XtSetArg(wargs[6], XtNbitmap, MouseOnPix);
	X			callbacks[0].callback = DoMemo;
	X			memo = XtCreateManagedWidget("today", commandWidgetClass,
	X					     parent, &wargs[1], 6);
	X		}
	X	}
	X	else
	X	{
	X		callbacks[0].callback = DoCalendar;
	X		lab = XtCreateManagedWidget("date", commandWidgetClass,
	X					    toplevel, wargs, 2);
	X	}
	X
	X	ClearCallbacks();
	X
	X	XtSetMappedWhenManaged(toplevel, False);
	X
	X	XtRealizeWidget(toplevel);	/* set the default geometry */
	X	
	X	if (appResources.debug)
	X	{	fprintf(stderr, "Debug ON\n");
	X		DebugMkDate(lab);
	X	}
	X	else	MkDate(lab);
	X
	X	if (appResources.giveHelp)
	X	{	printf("\
	XThe small date strip is a button\n\
	XEnter the button showing the date and use\n\
	Xthe mouse buttons to select further actions:\n\
	X	Left mouse button pops up this month's calendar strip\n\
	X	Middle mouse button permits date selection\n\
	X	Right mouse button allows exit\n\
	XClick with the left mouse button in the small box holding\n\
	Xthe mouse icon to edit a memo file\n");
	X	}
	X	XtAddActions(appActions, 3);	/* register actions */
	X	XtAugmentTranslations(lab, XtParseTranslationTable(defTranslations));
	X
	X	XtMapWidget(toplevel);
	X
	X	if (appResources.initialCalendar)
	X		DoCalendar(lab, NULL, NULL);
	X
	X
	X	if (appResources.initialEdit)
	X	{	MonthEntry	*me;
	X
	X		me = GetMonthEntry(today.year, today.month);
	X		if (me->me_have[today.day])
	X			StartEditing(lab, &today);
	X	}
	X
	X	InitAlarms();
	X	
	X	XtMainLoop();
	X}
	X
	X/*
	X *	Initialise Pixmaps
	X */
	XPixInit(toplevel)
	X	Widget	toplevel;
	X{
	X	Display	*theDisplay = XtDisplay(toplevel);
	X
	X	MouseOnPix = XCreateBitmapFromData(theDisplay,
	X			      DefaultRootWindow(theDisplay),
	X			      mouse_bits, mouse_width, mouse_height);
	X	MouseOffPix = XCreateBitmapFromData(theDisplay,
	X			      DefaultRootWindow(theDisplay),
	X			      mouseaway_bits, mouseaway_width, mouseaway_height);
	X}
	X
	X/*
	X *	Flip mouse state
	X */
	XMouseShow(w, OnOff)
	X	Widget	w;
	X	Boolean OnOff;
	X{
	X	Arg	arg[1];
	X
	X	XtSetArg(arg[0], XtNbitmap, OnOff ? MouseOnPix : MouseOffPix);
	X	XtSetValues(w, arg, 1);
	X}
	X 
	X
	X/*
	X *	Exit routine
	X */
	Xvoid
	XLeave(retval)
	X{	exit(retval);
	X}
	X
	X/************************************************************************/
	X/*									*/
	X/*									*/
	X/*	This deals with the top level date `icon'			*/
	X/*									*/
	X/*									*/
	X/************************************************************************/
	X
	X/*
	X *	Time management code
	X *	Set up a Date structure from today's information
	X */
	Xstatic void
	XConvDate(tm, dp)
	X	struct	tm *tm;
	X	Date *dp;
	X{
	X	dp->day = tm->tm_mday;
	X	dp->month = tm->tm_mon;
	X	dp->year = tm->tm_year + 1900;
	X}
	X
	X
	Xstatic void
	XMkDate(w)
	X	Widget w;
	X{	long	ti;
	X	struct	tm *tm;
	X	static	timedOut;
	X	Date	yesterday;
	X	
	X	if (timedOut)
	X		yesterday = today;
	X		
	X	ti = time(0);
	X	tm = localtime(&ti);
	X
	X	ConvDate(tm, &today);
	X
	X	PlaceStr(date_area,
	X			tm->tm_mday, appResources.mon[tm->tm_mon], tm->tm_year);
	X	XtSetValues(w, wargs, 1);
	X
	X	if (timedOut)
	X	{	ChangeHighlight(&yesterday, &today);
	X		AlarmFilePoll(tm);
	X		UpdateMemo();
	X	}
	X
	X	ti = 24*60*60 - (tm->tm_hour*60*60 + tm->tm_min*60 + tm->tm_sec);
	X	XtAddTimeOut(ti*1000, MkDate, (caddr_t)w);
	X	timedOut++;
	X}
	X
	Xstatic void
	XDebugMkDate(w)
	X	Widget w;
	X{	static long ti;
	X	struct	tm *tm;
	X	static	timedOut;
	X	Date	yesterday;
	X	
	X	if (timedOut)
	X		yesterday = today;
	X		
	X	if (ti == 0)
	X		ti = time(0);
	X	else	ti += 24*60*60;
	X	
	X	tm = localtime(&ti);
	X	ConvDate(tm, &today);
	X	
	X	PlaceStr(date_area,
	X		  tm->tm_mday, appResources.mon[tm->tm_mon], tm->tm_year);
	X	XtSetValues(w, wargs, 1);
	X
	X	if (timedOut)
	X	{	ChangeHighlight(&yesterday, &today);
	X		AlarmFilePoll(tm);
	X		UpdateMemo();
	X	}
	X
	X	XtAddTimeOut(2000, DebugMkDate, (caddr_t)w);
	X	timedOut++;
	X}
	X
	X/*
	X *	DoTemplate
	X *	place an initial string into the date area so that the label
	X *	box will always be big enough
	X */
	Xstatic void
	XDoTemplate()
	X{	int	maxmon;
	X	int	i;
	X	int	len;
	X	char	trial[BUFSIZ];
	X
	X
	X	for (maxmon = i = 0; i < 12; i++)
	X	{	PlaceStr(trial, 99, appResources.mon[i], 99);
	X		len = strlen(trial);
	X		if (len > maxmon)
	X		{	maxmon = len;
	X			strcpy(date_area, trial);
	X		}
	X	}
	X}
	X	
	X/*
	X *	decode the order
	X */
	Xstatic void
	XDecodeOrder()
	X{
	X	register char	*p;
	X
	X	p = appResources.order;
	X
	X	if (*p == 'd' && strcmp(p, "dmy") == 0)
	X		appResources.val_order = O_DMY;
	X	else
	X	if (*p == 'y')
	X	{	if (strcmp(p, "ymd") == 0)
	X			appResources.val_order = O_YMD;
	X		else
	X		if (strcmp(p, "ydm") == 0)
	X			appResources.val_order = O_YDM;
	X		else
	X			appResources.val_order = -1;
	X	}
	X	else
	X	if (*p == 'm' && strcmp(p, "mdy") == 0)
	X		appResources.val_order = O_MDY;
	X	else
	X		appResources.val_order = -1;
	X	if (appResources.val_order == -1)
	X	{	fprintf(stderr, "Unknown order: %s\n", p);
	X		appResources.val_order = O_DMY;
	X	}
	X}
	X			
	X/*
	X *	make a string
	X */
	Xvoid
	XPlaceStr(dest, d, m, y)
	X	String	dest;
	X	int	d;
	X	String	m;
	X	int	y;
	X{
	X	register String fmt;
	X
	X	if (y > 99 && y < 1900)
	X		y -= 100;
	X		
	X	fmt = appResources.opfmt;
	X	
	X	switch (appResources.val_order)
	X	{
	X	case O_DMY:		/* default */
	X		(void) sprintf(dest, fmt, d, m, y);
	X		break;
	X	case O_YMD:		/* Year/Month/Day */
	X		(void) sprintf(dest, fmt, y, m, d);
	X		break;
	X	case O_MDY:		/* Month/Day/Year */
	X		(void) sprintf(dest, fmt, m, d, y);
	X		break;
	X	case O_YDM:		/* Year/Day/Month */
	X		(void) sprintf(dest, fmt, y, d, m);
	X		break;
	X	}
	X}
SHAR_EOF
if test 16298 -ne "`wc -c < 'xcal.c'`"
then
	echo shar: error transmitting "'xcal.c'" '(should have been 16298 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'xcal.man'" '(16588 characters)'
if test -f 'xcal.man'
then
	echo shar: will not over-write existing file "'xcal.man'"
else
sed 's/^	X//' << \SHAR_EOF > 'xcal.man'
	X.TH xcal 1 "September 1990" "X Version 11 R4"
	X.SH NAME
	Xxcal \-  calendar with alarms and a notebook for X11
	X.SH SYNTAX
	X.B xcal
	X[
	X.B \-debug
	X][
	X.B \-alarmscan
	X]
	X.SH DESCRIPTION
	X.I Xcal
	Xis an interactive calendar program.
	XThe user interface has several levels.
	XWhen started
	X.I xcal
	Xdisplays today's date in a small command box on the screen.
	XThe date changes at midnight.
	XThe command box is intended to sit on the screen as a companion to the
	X.I xclock
	Xprogram.
	XThe format of the command box may be altered using the resource manager, so you
	Xare not stuck with my preferred format.
	XA small button in the top level window can be pressed to inspect todays
	Xappointments and also to edit or display a memo file.
	X.LP
	XThe calendar and notebook functions are accessed by clicking the mouse
	Xbuttons inside date portion of the command window.
	X.IP 1)
	XMouse button one pops up a calendar `strip' for the current month.
	XThe strip has some header lines and then one line per day of the month.
	XThe `line per day' display contains the day in the month and the
	Xday of the week.
	XToday may be highlighted specially \- the notion of Today alters at midnight.
	XThe strip has a help button which displays a description of the panel.
	XThe command buttons in the header line allows the user to bring up a strip
	Xfor the previous or the next month.
	X.IP 2)
	XPressing mouse button two in the date area will bring up a dialog box
	Xwhich allows the user to select any month of any year (yes, September 1752
	Xis supported).
	XThe month may be input as month name or abbreviation, even though the
	Xprompt indicates a more restrictive format.
	X.IP 3)
	XPressing mouse button 3 in the command window causes the whole program to
	Xexit, a dialog box is used to ask the user for confirmation.
	X.LP
	XLike
	X.IR xcalendar ,
	Xdaily events are stored in set of files, one for each day.
	XThe file is created by entering a simple text editor
	X(the standard text widget) which is started
	Xby pressing the right hand side of the appropriate day line in the strip.
	XIf the file exists
	Xits data is displayed as the label in the command button.
	XThis allows the user to use the first few lines of the file in an
	Xintelligent manner since
	XX11R4 allows multiple lines of text to appear in a command button.
	XThe strip width is sized by the length of the header, and users who
	Xwish to display a wider strip to show more of the stored information
	Xshould widen the strip using the \fIminStripWidth\fP resource (see below).
	X.LP
	XData files are stored in a directory usually called
	X.B Calendar
	Xunder the user's home directory.
	XEach file is stored in a subdirectory containing all the data
	Xfor a particular year.
	XThis is incompatible with 
	X.IR xcalendar ,
	Xthe user may specify that compatibility should be maintained.
	X.LP
	X.I Alarms
	Xare supported by
	X.IR xcal .
	XWhen a line in the data file starts with a digit it is
	Xassumed to be a time specification and a candidate for an alarm.
	XThe line contains a string giving the alarm time, and a text string
	Xdisplayed in a dialogue alarm box.
	XWhen the time is reached, or at some user specified time before that,
	Xa dialogue box will be popped up onto the screen.
	XThe dialogue box will automatically go away after two minutes, unless the
	X`Stick' button is pressed glueing the box onto the screen.
	XThe box can be made to go away at any time by hitting the `Unpin' button.
	X.LP
	X.I Xcal
	Xtries to be liberal about the times that it understands.
	XTime specifications are: h, hh, hhmm, hmm, hh:mm, h:mm, hh.mm, h.mm;
	Xall of these may be optionally followed by an am/pm indicator \- one
	Xof: A, a, AM, am, Am, aM, P, p, PM, pm, Pm, pM.
	XTimes must always be followed by at least one space or tab.
	XSome legal examples are:
	X.br
	X.nf
	X	12:00 Lunch - Meet Joe at Burger King
	X	14.30 Meeting in the cafeteria
	X	2:30p Ring Mark
	X	7pm Pizza
	X.fi
	X.LP
	X.I Xcal
	Xalso supports timed command execution from the data file.
	XTo trigger a command, the data part of the line starts
	Xwith an exclamation mark, eg:
	X.br
	X	4.30pm !xmessage -message 'ring home'
	X.LP
	XIt is also possible to make 
	X.I xcal
	Xexecute a command whenever an alarm is triggered, see the \fIcmd\fP resource
	Xbelow.
	X.LP
	XThe Memo function of
	X.I Xcal
	Xis accessed by pressing the non-date portion of the command window.
	XCurrently this shows a bitmap diagram of three mouse buttons.
	XClicking the left mouse button in this area brings up a complex panel.
	XThe top half of the panel displays the information held in the diary
	Xfor today; you cannot edit the data from here \- and must open the
	Xdiary strip to change the data.
	XThe bottom half of the panel is an edit window displaying the contents
	Xof a file usually called `memo' in the Calendar directory.
	XThe idea of this panel is to allow you to access your current information
	Xin one button click.
	X.LP
	XIt is obviously possible to change
	X.IR Xcal 's
	Xdata files without using the inbuilt text widget editor.
	XIn general,
	X.I Xcal
	Xwill not notice this.
	XEditing random day files with a standard text editor will not
	Xchange the contents of any displayed strips until the strips are
	Xpopped down and up again.
	X.I Xcal
	Xknows what days have been altered when the text widget is used to
	Xedit the day files, and will reflect any change immediately into
	Xthe displayed strips.
	X.LP
	XYou can make 
	X.I Xcal
	Xtake notice of today's date file and the current memo file.
	XThe `Update' resource sets a polling time in seconds.
	XWhen the clock fires and today's file has been altered,
	Xthe alarm list is rebuilt from the current date file
	Xand the memo panel is updated.
	XThe bottom part of the memo panel is also updated if the `memo'
	Xfile has been altered on the clock tick.
	X.SH OPTIONS
	XThe
	X.I \-debug
	Xswitch causes contents of the initial date window to be incremented once
	Xa second rather than once per day.
	X.LP
	XThe
	X.I \-alarmscan
	Xswitch prints debugging information about the alarm system on standard output.
	X.SH "PANEL MAP"
	X.PP
	X.I Xcal
	Xmakes extensive use of the resource manager.
	XThe user needs to know the names of the various panels and widgets which
	Xcomprise the application.
	X.LP
	X.de EX		\"Begin example
	X.ne 5
	X.if n .sp 1
	X.if t .sp .5
	X.nf
	X.ta +8u*\w'\0'u +8u*\w'\0'u +8u*\w'\0'u +8u*\w'\0'u +8u*\w'\0'u +8u*\w'\0'u
	X..
	X.de EE
	X.fi
	X.if n .sp 1
	X.if t .sp .5
	X..
	X.EX
	XXCal				Toplevel application
	X	form			Form containing two buttons
	X		today		Memo Command button
	X		date		Strip Command button
	X.EE
	X.LP
	XThen we have various popups.
	XThe Calendar Strip is:
	X.EX
	X"Mon Year"			the popup shell
	X	Month			panel containing the strip
	X		header		label containing month and year
	X		action		form containing < quit > buttons 
	X			back	command containing < - last month
	X			quit	command containing exit button
	X			next	command containing > - next month
	X		help		command generating help
	X		"dd DDD"	form containing day button (lots of these)
	X			label	label containing dd DDD, day of the month
	X				and day of the week
	X			info	command containing the file data
	X.EE
	X.LP
	XThe Edit Window is:
	X.EX
	Xedit				the popup shell
	X	panel			the panel inside the shell
	X		title		the form containing the first line
	X			quit	the exit button
	X.EE
	X.LP
	XThe Help Window is:
	X.EX
	Xhelp				the popup shell
	X	helpPanel			the panel inside the shell
	X		helpForm		the form containing the title line
	X			quit	the exit button
	X		helpText		the text widget showing the information
	X.EE
	X.LP
	XThe Alarm Window is:
	X.EX
	Xalarm				the popup shell
	X	alarmPanel		the panel inside the shell
	X		alarmForm	form for top line
	X			alarmQuit	the exit button
	X			alarmHold	the hold button
	X			alarmTitle	the title on the alarm window
	X		alarmText	the text widget for displaying
	X.EE
	X.LP
	XThe Memo Window is:
	X.EX
	Xmemo				the popup shell
	X	memoPanel		the panel inside the shell
	X		title		Top line form widget
	X			quit	the exit button
	X			help	the help button
	X			date	display today's date
	X		display		text from today's date file
	X		memoMiddle	Middle line form widget
	X			save	Save button
	X			memoTitle	text title of middle line
	X		memoText	Text widget showing memo file
	X.EE
	X.LP
	XThe Middle button date selection popup is:
	X.EX
	Xquestion				the popup shell
	X	newdate			the dialog widget
	X		ok		the OK button
	X		cancel		the cancel button
	X.EE
	X.LP
	XThe Right button exit selection popup is:
	X.EX
	Xquestion				the popup shell
	X	exit			the dialog widget
	X		yes		the yes button
	X		no		the no button
	X.EE
	X.LP
	XAn error is shown when a multiple attempts are made to edit the same day file.
	X.EX
	Xquestion				the popup shell
	X	noedit			the dialog widget
	X		ok		the OK button
	X.EE
	X.LP
	XA dialog box is popped up when an attempt is made to exit from an editing
	Xbox without saving the file.
	X.EX
	Xcheck				the dialog widget
	X	yes			the yes button
	X	no			the no button
	X.EE
	X.SH RESOURCES
	XAs with all standard X applications, \fIxcal\fR may be customised through 
	Xentries in the resource manager.
	XIt is a serious mistake to install
	X.I Xcal
	Xwithout putting the resource initialisation file 
	X.I Xcal
	Xin 
	X.IR /usr/lib/X11/app-defaults .
	XResource class names are listed below;
	Xresource instance names are identical, except the first letter is in
	Xlower case.
	XThe following resource manager entries are defined:
	X.LP
	X.TP "\w'ReverseVideoMarkNNN'u"
	X.B Debug
	XIf True enables accelerated time.
	XAlarms will not function correctly.
	XDefault: False.
	X.TP
	X.B AlarmScan
	XIf True enables printing of alarm related debugging information
	Xto the standard output.
	XDefault: False.
	X.TP
	X.B ReverseVideo
	XIf true display the output in reverse video.
	X.IP
	X.B Format
	XThe \fIprintf\fP string used to create the contents of the top command
	Xbutton.
	XThe default is "%2d %s %d", the arguments to this command are presented
	Xin a default order: day, month string and year.
	XThe order is controlled by the Order resource which contains the default
	Xstring "dmy".
	XThese two resources should allow all forms of date printing.
	X.TP
	X.B Order
	XLegal combinations are: dmy, ymd, mdy, ydm.
	XThe default is dmy.
	X.TP
	X.B MarkBackground
	XThe background colour for highlighting entries.
	XDefault Black.
	X.TP
	X.B MarkForeground
	XThe foreground colour for highlighting entries.
	XDefault White.
	X.TP
	X.B MarkToday
	XIf True then highlight today.
	XDefault True.
	X.TP
	X.B TodayBackground
	Xthe background colour when marking, default Black.
	X.TP
	X.B TodayForeground
	Xthe foreground colour when marking today, default White.
	X.TP
	X.B FontToday
	XToday may be marked by using a special font, if this is desired the
	Xfont is given by this resource.
	XDefault is to use the default font.
	X.TP
	X.B Directory
	XThe name of the directory under the home directory
	Xwhere the day files are stored.
	XDefault: Calendar.
	X.TP
	X.B XcalendarCompat
	XIf true then subdirectories are not created in the Calendar directory.
	XThis flag is not relevant when files are being read, so users
	Xcan use both programs with existing data files.
	XDefault: False.
	X.TP
	X.B GiveHelp
	XIf True than access to the help information is given.
	XIf False, help buttons disappear and the initial message is not printed.
	XDefault: True.
	X.TP
	X.B InitialCalendar
	XIf True then the calendar for this month is automatically displayed on
	Xstartup.
	XIf False, the calendar is not automatically displayed.
	XDefault: False.
	X.TP
	X.B InitialEdit
	XIf True then an edit window for today is automatically displayed on
	Xstartup if a file exists for today's date.
	XIf False, the edit window is not automatically displayed.
	XDefault: False.
	X.TP
	X.B UseWmTitle
	XIf True display the month and the year at the head of each strip.
	XThis information is duplicated if your window manager uses titles
	Xso it is nice to be able to turn it off.
	XDefault: True.
	X.TP
	X.B MinStripWidth
	XThe width of month strips are set by the top line, which usually
	Xdisplays the month and year.
	XThe whole strip can be widened from this default value by setting this
	Xresource to be non-zero.
	XDefault: zero (i.e. off).
	X.TP
	X.B TextBufferSize
	Xthe maximum number of bytes which we are prepared to deal with in an
	Xedit window.
	XDefault: 2048 bytes.
	X.TP
	X.B Alarms
	Xwhether or not to enable the alarm system.
	XDefault: True.
	X.TP
	X.B Update
	XWhen scanning for alarms in the current day file
	X.I Xcal
	Xinspects it at program startup time and also when it is edited using the
	Xnormal built-in editing mechanism.
	XHowever, if some external program changes the todays file
	X.I xcal
	Xwill not see the new contents and new alarms will not be set.
	XSetting this resource to non-zero will force 
	X.I xcal
	Xto scan the file every `update' seconds
	Xlooking for alterations in size and modification date.
	XWhen it detects that the file is altered, then
	Xit will rebuild the internal alarm list.
	XDefault: zero.
	X.TP
	X.B Nbeeps
	XWhen an alarm window is popped up, it is accompanied by `Nbeeps' beeps.
	XDefault: 3.
	X.TP
	X.B Volume
	XControl the loudness of the beep. Default: 50.
	X.TP
	X.B Cmd
	XThis resource contains a command that is executed by calling the shell
	Xwhen every alarm is triggered.
	XThe command is passed the contents of the data line as one argument.
	X.TP
	X.B Countdown
	Xcontains a comma separated string of numbers; for example: 10,5,0.
	XThe string allows the user to customise warning alarms: so in the
	Xexample, alarm boxes will be displayed 10 minutes before the stated time,
	X5 minutes before the stated time and exactly on the stated time.
	XCommands lines in the data prefaced by a `!' will always be triggered
	Xexactly at the stated time.
	XDefault: 10,0.
	X.TP
	X.B Autoquit
	XEach dialogue box containing an alarm message contains an `Unpin' button
	Xallowing the user to remove the message from the screen by using mouse button one.
	XAdditionally, the message box can remove itself from the screen after
	Xa specified period, this resource gives that timeout in seconds.
	XIf the resource is set to zero, then the user is always forced to take
	Xexplicit action to remove the box.
	XDefault: 120, alarm boxes disappear after 2 mins.
	X.TP
	X.B Alarmleft
	Xcontains a \fIprintf\fP string that is displayed in the label at the top
	Xof an alarm box when countdown is in operation and
	Xthere is some time before the stated time.
	XThe time before the stated time is supplied as the second argument to printf.
	XDefault: ``%d minutes before...''
	X.TP
	X.B Alarmnow
	Xcontains the fIprintf\fP string that is displayed in the label at the top
	Xof an alarm box when the stated time is reached.
	XDefault: ``Time is now...''.
	X.TP
	X.B UseMemo
	Xenables the use of the memo feature.
	XThis defaults to ``True'', but is present to allow users to make 
	X.I XCal
	Xhave as it used to.
	X.TP
	X.B MemoLeft
	Xaffects the placing of the memo button in the top level date window.
	XThe default is `True' meaning that the button box is placed on the left
	Xof the date portion.
	XSetting this to `False' will place the button box to the right of the
	Xdate portions.
	X.TP
	X.B MemoFile
	Xgives the name of the memo file within the Calendar directory.
	XThe default is `memo'.
	X.TP
	X.B MaxDisplayLines
	Xcontrols the maximum number of text lines that can placed in the
	Xtop half of the memo panel.
	XThe top hald will normally size to the number of lines in the diary
	Xfile for the day, unless the number of lines exceed the value in
	Xthis resource.
	XThis ensures that today's events do not dominate the memo panel.
	XDefault: 5 lines.
	X.TP
	X.B January
	X.B February
	Xand so on.
	XThe names of the long form of the month name.
	X.TP
	X.B Jan
	X.B Feb
	Xand so on.
	XA short form of the month name - done this way because I doubt that
	Xwriting with %3s works in all languages.
	XChanging this resource means that the data file will no longer be
	Xcompatible with
	X.I xcalendar .
	X.TP
	X.B Sunday
	X.B Monday
	Xand so on.
	XThe names of the days, these are currently set to a three character short form.
	X.SH FILES
	X.PP
	X $HOME/Calendar/*
	X.LP
	X.TP "\w'xc<dd><Mon><Year>  'u"
	Xxc<dd><Mon><Year>
	XA data file is day, Month in three letter format and the year.
	X.TP
	Xxy<Year>
	XA year directory.
	X.LP
	XThe standard resource database can be found in /usr/lib/X11/app-defaults/Xcal.
	XAssuming that this is where the system admin installed it.
	X.PP
	X.SH SEE ALSO
	Xxrdb(1), xcal_cal(1)
	X.PP
	X.SH BUGS
	XThere should be some way of removing several edit windows from the screen
	Xat once.
	X.LP
	XIt would be nice to be able to cut from the date box on the screen.
	X.LP
	XSetting an alarm 1 minute in the future may not work.
	X.LP
	XCountdown does not work in the early hours of the morning, if you have a
	Xten minute countdown and an alarm set at 0005 \- then you will not get
	Xwarning at 2325.
	X.SH AUTHOR
	X.LP
	XCopyright 1989,1990 by Peter Collinson, Hillside Systems
	XAll rights reserved.
	XPlaced into the public domain.
	X.PP
	XMuch of the
	X.B xcalendar
	Xprogram was plundered to create
	X.B xcal ;
	Xauthor is: Roman J. Budzianowski, MIT Project Athena
	X.PP
	XThanks to Ed Gould, Mt Xinu for the support for the
	X.IR calendar (1)
	Xprogram.
	XThanks to Mark Majhor, Sequent for the basis of the alarm code.
	XThanks to Rod Whitby, Austek Microsystems Pty. Ltd., Australia
	Xfor the ideas of the Stick/Unpin code for alarms and for prompting
	Xme to add the memo code.
SHAR_EOF
if test 16588 -ne "`wc -c < 'xcal.man'`"
then
	echo shar: error transmitting "'xcal.man'" '(should have been 16588 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'xcal_popup.c'" '(8595 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.4 (Hillside Systems) 12/12/90";
	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
	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 8595 -ne "`wc -c < 'xcal_popup.c'`"
then
	echo shar: error transmitting "'xcal_popup.c'" '(should have been 8595 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'xcal_alarm.c'" '(16439 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.10 (Hillside Systems) 12/12/90";
	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 struct stat stbuf;
	Xstatic Boolean  false = False;
	Xstatic Boolean  true = True;
	Xstatic char    *LocalMapStem;
	Xstatic Boolean  LocalFoundCalendarFile;
	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	struct	stat stbuf;
	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 Filename = %s\n", LocalMapStem);
	X	}
	X
	X	/*
	X	 *	check for file existence
	X	 */
	X	if (access(LocalMapStem, F_OK))
	X	{	FreeAlarmList();
	X		UpdateMemo();
	X		return;
	X	}
	X
	X	if (stat(LocalMapStem, &stbuf) < 0)
	X		Fatal("Panic: cannot stat %s\n", LocalMapStem);
	X
	X	if (stbuf.st_size != appResources.last_size ||
	X	    stbuf.st_mtime > appResources.last_time)
	X	{	appResources.last_size = stbuf.st_size;
	X		appResources.last_time = stbuf.st_mtime;
	X		AlarmScan(LocalMapStem, tm, MINUTES(tm->tm_hour, tm->tm_min));
	X		UpdateMemo();
	X	}
	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\n");
	X
	X	FreeAlarmList();
	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	int            bo;
	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, mn;
	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	int	mwanted;
	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	register Window win = XtWindow(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 16439 -ne "`wc -c < 'xcal_alarm.c'`"
then
	echo shar: error transmitting "'xcal_alarm.c'" '(should have been 16439 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0


--
dan
----------------------------------------------------
O'Reilly && Associates   argv at sun.com / argv at ora.com
Opinions expressed reflect those of the author only.



More information about the Comp.sources.x mailing list