v10i096: xcal, Part03/03

Peter Collinson pc at hillside.co.uk
Wed Dec 19 13:39:13 AEST 1990


Submitted-by: Peter Collinson <pc at hillside.co.uk>
Posting-number: Volume 10, Issue 96
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_cal.c
#	xcal_cal.man
#	xcal_edit.c
#	xcal_help.c
#	xcal_memo.c
#	xcal_strip.c
# This archive created: Sun Dec  9 12:51:36 1990
export PATH; PATH=/bin:$PATH
echo shar: extracting "'xcal_cal.c'" '(4919 characters)'
if test -f 'xcal_cal.c'
then
	echo shar: will not over-write existing file "'xcal_cal.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'xcal_cal.c'
	X#ifndef lint
	Xstatic char *sccsid = "@(#)xcal_cal.c	1.1 (Hillside Systems) 7/14/90";
	X#endif  /* lint */
	X/***
	X
	X* program name:
	X	xcal_cal.c
	X* function:
	X	read files generated by xcal and produce a file compatible
	X	with the standard "calendar" utility
	X* switches:
	X	-d dir	use "dir" instead of "Calendar"
	X	-f file use "file" instead of .xcal
	X	-m	copy all of multi-line entries
	X* history:
	X	Written July, 1990
	X	Ed Gould
	X	mt Xinu, Inc.
	X* (C) Copyright: 1990 mt Xinu, Inc.
	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 in
	X	all copies and that both that copyright notice and this
	X	permission notice appear in supporting documentation, and
	X	that the names of Ed Gould and mt Xinu, Inc. not be used
	X	in advertising or publicity pertaining to distribution of
	X	the software without specific, written prior permission.
	X	mt Xinu, Inc. makes no representations about the suitability
	X	of this software for any purpose.  It is provided "as is"
	X	without express or implied warranty.
	X
	X	Ed Gould and mt Xinu, Inc. DISCLAIM ALL WARRANTIES WITH
	X	REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
	X	OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL Ed Gould
	X	or mt Xinu, Inc. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
	X	CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
	X	FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
	X	CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
	X	OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
	X	SOFTWARE.
	X
	X***/
	X#include <stdio.h>
	X#include <ctype.h>
	X#include <sys/param.h>
	X#include <sys/types.h>
	X#include <sys/dir.h>
	X#include <time.h>
	X#include <strings.h>
	X
	Xchar	*directory	= "Calendar";
	Xchar	*file		= ".xcal";
	Xchar	*home;
	Xchar	usedir[MAXPATHLEN];
	Xchar	usefile[MAXPATHLEN];
	Xchar	line[BUFSIZ];
	X
	Xchar	*months[]	= {"jan", "feb", "mar", "apr", "may", "jun",
	X			   "jul", "aug", "sep", "oct", "nov", "dec"};
	X
	Xint	debug;
	Xint	mflag;
	X
	XFILE	*out;
	X
	Xvoid
	Xmain(argc, argv)
	X	char **argv;
	X{
	X	register int c;
	X	time_t now;
	X	register struct tm *lt;
	X	char *getenv();
	X
	X	while((c = getopt(argc, argv, "d:f:m#")) != EOF) {
	X		extern char *optarg;
	X
	X		switch (c) {
	X
	X		case 'd':
	X			directory = optarg;
	X			break;
	X
	X		case 'f':
	X			file = optarg;
	X			break;
	X
	X		case 'm':
	X			mflag++;
	X			break;
	X
	X		case '#':
	X			debug++;
	X			break;
	X
	X		case '?':
	X		default:
	X			fprintf(stderr, "usage: %s [-d dir] [-f file]\n",
	X								argv[0]);
	X			exit(1);
	X		}
	X	}
	X	home = getenv("HOME");
	X	/*
	X	 * For both directory and output file, 
	X	 *
	X	 *   /...	is absolute path
	X	 *   ./...	is relative to current directory
	X	 *
	X	 * otherwise, relative to $HOME, if available
	X	 */
	X	if(file[0] == '/' || (file[0] == '.' && file[1] == '/') ||
	X	   home == NULL)
	X		strcpy(usefile, file);
	X	else
	X		sprintf(usefile, "%s/%s", home, file);
	X	if(debug)
	X		fprintf(stderr, "output to %s\n", usefile);
	X	if((out = fopen(usefile, "w")) == NULL) {
	X		perror(usefile);
	X		exit(1);
	X	}
	X	now = time((time_t *)NULL);
	X	lt = localtime(&now);
	X	calfiles(directory, lt->tm_year + 1900, lt->tm_mon, lt->tm_mday);
	X	if(lt->tm_mday >= 25 ) {
	X		/*
	X		 * close to end of month: include next month, too
	X		 */
	X		if(lt->tm_mon == 11)
	X			calfiles(directory, lt->tm_year + 1900 + 1, 0, 1);
	X		else
	X			calfiles(directory, lt->tm_year + 1900,
	X							lt->tm_mon + 1, 1);
	X	}
	X}
	X
	Xcalfiles(dir, year, thismonth, today)
	X	register char *dir;
	X{
	X	register DIR *dp;
	X	register char *to;
	X	register char *from;
	X	register struct direct *d;
	X	char day[3];
	X	char month[4];
	X
	X	if(dir[0] == '/' || (dir[0] == '.' && dir[1] == '/') ||
	X	   home == NULL)
	X		sprintf(usedir, "%s/xy%4d", dir, year);
	X	else
	X		sprintf(usedir, "%s/%s/xy%4d", home, dir, year);
	X	if(debug)
	X		fprintf(stderr, "looking in directory %s\n", usedir);
	X	if((dp = opendir(usedir)) == NULL) {
	X		perror(usedir);
	X		exit(1);
	X	}
	X	while((d = readdir(dp)) != NULL) {
	X		register FILE *in;
	X
	X		if(d->d_name[0] != 'x' || d->d_name[1] != 'c' ||
	X		   !isascii(d->d_name[2]) || !isdigit(d->d_name[2]))
	X			continue;
	X		sprintf(usefile, "%s/%s", usedir, d->d_name);
	X		if(debug)
	X			fprintf(stderr, "looking in file %s\n", usefile);
	X		if((in = fopen(usefile, "r")) == NULL) {
	X			if(debug)
	X				perror(usefile);
	X			continue;
	X		}
	X		from = &d->d_name[2];
	X		to = day;
	X		while(isascii(*from) && isdigit(*from))
	X			*to++ = *from++;
	X		*to = '\0';
	X		to = month;
	X		while(isascii(*from) && !isdigit(*from)) {
	X			if(isupper(*from))
	X				*from = tolower(*from);
	X			*to++ = *from++;
	X		}
	X		*to = '\0';
	X		if(strcmp(month, months[thismonth]) != 0 ||
	X		   atoi(day) < today) {
	X			if(debug)
	X				fprintf(stderr, "\tskipped - date\n");
	X			fclose(in);
	X			continue;
	X		}
	X		while(fgets(line, sizeof(line), in) != NULL) {
	X			if((to = index(line, '\n')) != NULL)
	X				*to = '\0';
	X			if(debug)
	X				fprintf(stderr, "==>\t%s %s\t%s\n", month,
	X								day, line);
	X			fprintf(out, "%s %s\t%s\n", month, day, line);
	X			if(mflag == 0)
	X				break;
	X		}
	X		fclose(in);
	X	}
	X}
SHAR_EOF
if test 4919 -ne "`wc -c < 'xcal_cal.c'`"
then
	echo shar: error transmitting "'xcal_cal.c'" '(should have been 4919 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'" '(22066 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.7 (Hillside Systems) 12/7/90";
	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	struct	stat	mw_stat;	/* stat of the enclosing directory */
	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
	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 */
	XMeWrap *NewMeWrap();
	XMeWrap *MeWrapSearch();
	Xvoid	SetAllButtons();
	Xvoid	StartDayEditor();
	Xvoid	DeleteCalendarFile();
	Xvoid	Fatal();
	Xvoid	CheckExit();
	Xvoid	CleanEditPanel();
	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	struct		stat ns;
	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 (stat(dir, &ns) < 0)
	X		Fatal("Cannot stat: %s/%s\n", MapStem, dir);
	X
	X	if (mw->mw_stat.st_mtime == ns.st_mtime)
	X		return(&mw->mw_me);
	X
	X	mw->mw_stat = ns;
	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		int d_namlen = strlen(dp->d_name) +1;
	X		switch(d_namlen)
	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 (stat(mw->mw_dir, &mw->mw_stat) < 0)
	X					Fatal("Cannot stat directory %s/%s", MapStem, mw->mw_dir);
	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 *	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	void	DeRegisterMonth();
	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, 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	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 *	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	/*
	X	 *	First let's see if we have 
	X	 *	to create the toplevel directory
	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	/*
	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 *	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			NoEditIsPossible(w, da);
	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	PlaceStr(buf, da->day, appResources.mon[da->month], da->year);
	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	extern	Widget	toplevel;
	X	Arg	args[3];
	X	
	X	mw = ed->ed_meWrap;
	X	day = ed->ed_day;
	X	
	X	if (WriteCalendarFile(mw, day, ed->ed_data) == False)
	X		return;
	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	if (today.day == day && today.month == mw->mw_month &&
	X	    today.year == mw->mw_year)
	X		UpdateMemo();
	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	void	CheckDia();
	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	void	YesCheck();
	X	void	NoCheck();
	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 22066 -ne "`wc -c < 'xcal_edit.c'`"
then
	echo shar: error transmitting "'xcal_edit.c'" '(should have been 22066 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'xcal_help.c'" '(6540 characters)'
if test -f 'xcal_help.c'
then
	echo shar: will not over-write existing file "'xcal_help.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'xcal_help.c'
	X#ifndef lint
	Xstatic char *sccsid = "@(#)xcal_help.c	3.5 (Hillside Systems) 12/7/90";
	Xstatic char *copyright = "@(#)Copyright 1989,1990 Peter Collinson, Hillside Systems";
	X#endif  /* lint */
	X/***
	X
	X* module name:
	X	xcal_help.c
	X* function:
	X	Generate help screens in separate popup windows
	X* history:
	X	Written December 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/Form.h>
	X#include <X11/Xaw/Paned.h>
	X#include "xcal.h"
	X
	Xstatic XtCallbackRec callbacks[] = {
	X   {NULL,NULL},
	X   {NULL,NULL}
	X};
	X
	Xvoid	addversion();
	X
	Xvoid
	XDisplayHelpWindow(str)
	X	String	str;
	X{
	X	Widget		shell, form, title;
	X	Arg		args[10];
	X	Cardinal	nargs;
	X	void		DestroyHelp();
	X	
	X	shell = XtCreatePopupShell("help", topLevelShellWidgetClass, toplevel, NULL, 0);
	X
	X	form =  XtCreateManagedWidget("helpPanel", panedWidgetClass, shell, NULL, 0);
	X
	X	nargs = 0;
	X	XtSetArg(args[nargs], XtNshowGrip, False); nargs++;
	X	XtSetArg(args[nargs], XtNdefaultDistance, 2); nargs++;
	X	title = XtCreateManagedWidget("helpForm", formWidgetClass, form, args, nargs);
	X	/*
	X	 *	Exit button
	X	 *	Take "Quit" from resources
	X	 */
	X	callbacks[0].callback = DestroyHelp;
	X	callbacks[0].closure = (caddr_t)shell;
	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	(void) XtCreateManagedWidget("helpQuit", commandWidgetClass, title, args, nargs);
	X	/*
	X	 *	Now the text
	X	 *	which is the remainder of the panel
	X	 */
	X	nargs = 0;
	X	XtSetArg(args[nargs], XtNshowGrip, False); nargs++;
	X	XtSetArg(args[nargs], XtNstring, str); nargs++;
	X	XtSetArg(args[nargs], XtNdisplayCaret, False); nargs++;
	X	(void) XtCreateManagedWidget("helpText", asciiTextWidgetClass, form, args, nargs);
	X
	X	XtPopup(shell, XtGrabNone);
	X}
	X
	X/* ARGSUSED */
	Xvoid
	XDestroyHelp(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 *	Help scripts
	X */
	Xstatic char stripHelp[] = "\
	XThe date strip consists of a number of lines of text. \n\n\
	XLine 1:	The Month and the Year of the strip.\n\
	X	The information may be duplicated in the window\n\
	X	manager title line. In this case the line may be omitted\n\
	X	by setting the resource `useWmTitle' to False.\n\n\
	XLine 2:	The main control buttons for the strip actioned by the\n\
	X	left mouse button.\n\
	X	<	Generates last month's strip in a separate window\n\
	X	Quit	Close this script\n\
	X	>	Generates next month's strip in a separate window\n\n\
	XLine 3: The Help button.\n\
	X	Help can be suppressed by setting `giveHelp' to False.\n\n\
	XThen -  A line for each day in the month.\n\
	X	Each line is two areas:\n\
	X	The left hand side shows the day in the month and the name of\n\
	X	the day of the week.`Today' may be highlighted specially in\n\
	X	this region.\n\
	X	The right hand side is an active button. When pressed it starts\n\
	X	up an editor for the day. This will create a file for the day\n\
	X	in the user's Calendar directory. The label on the button will\n\
	X	be the first few characters of the file, if there are any.\n\
	X\n\
	XXCal was written by Peter Collinson\n\
	X+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
	X
	X/* ARGSUSED */
	Xvoid
	XStripHelp(w, closure, call_data)
	X	Widget w;
	X	caddr_t	closure;
	X	caddr_t call_data;
	X{
	X	static int vadded;
	X
	X	if (vadded == 0)
	X	{	vadded = 1;
	X		addversion(stripHelp);
	X	}
	X	DisplayHelpWindow(stripHelp);
	X}
	X	
	Xstatic char editHelp[] = "\
	XThis editing window will create or delete a day file for the day shown\n\
	Xin the title. The file is stored in a directory specified by the resource\n\
	X`directory', this is usually `Calendar' in your home directory.\n\n\
	XCalendar will usually contain directories, one for each year,\n\
	Xand the day file will be stored in one of these directories. However,\n\
	Xthis makes xcal incompatible with xcalendar - so if the resource\n\
	XxcalendarCompat is True then the use of subdirectories is suppressed.\n\
	XThe large area in the edit window is a normal text input area. Text is\n\
	Xsimply be typed into it, the text is saved by hitting the save button\n\
	Xwhich is set to sensitive when the text is changed.  Saving an empty\n\
	Xbuffer will delete the file.  The Quit button will exit. Some more\n\
	Xquestions will be asked if leaving will result in losing information.\n\
	X\n\
	XXCal was written by Peter Collinson\n\
	X+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
	X
	X/* ARGSUSED */
	Xvoid
	XEditHelp(w, closure, call_data)
	X	Widget w;
	X	caddr_t	closure;
	X	caddr_t call_data;
	X{
	X	static int vadded;
	X
	X	if (vadded == 0)
	X	{	vadded = 1;
	X		addversion(editHelp);
	X	}
	X
	X	DisplayHelpWindow(editHelp);
	X}
	X	
	X/*
	X *	Add the external version string
	X */
	Xstatic void
	Xaddversion(str)
	X	register char *str;
	X{
	X	extern char version[];
	X	register int vlen;
	X	register char *ptr;
	X
	X	if (ptr = index(str, '+'))
	X	{	vlen = strlen(version);
	X		bcopy(version, ptr, vlen);
	X		ptr[vlen] = '\n';
	X		ptr[vlen+1] = '\0';
	X	}
	X}
	X
	Xstatic char memoHelp[] = "\
	XThe memo window is intended to do two things. First, it allows a\n\
	Xsingle button click to display today's actions from your diary.\n\
	XSecond, it provides an editable window whose contents can be saved in\n\
	Xa file.  The idea is that this file will contain reminders and other\n\
	Xnotes.  The file is usually called `memo' and is stored in a directory\n\
	Xspecified by the resource `directory', usually `Calendar' in your home\n\
	Xdirectory.\n\
	X\n\
	XThe window is split into two areas. The top half shows the current\n\
	Xdiary entry and cannot be altered. The bottom half contains the memo\n\
	Xfile text area. Text is simply be typed into it and is stored saved by\n\
	Xhitting the save button. This will go black when the text is changed.\n\
	XSaving an empty buffer will delete the file.\n\
	X\n\
	XThe Quit button will exit. Some more questions will be asked if\n\
	Xleaving will result in losing information.\n\
	X\n\
	XXCal was written by Peter Collinson\n\
	X+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
	X
	X/* ARGSUSED */
	Xvoid
	XMemoHelp(w, closure, call_data)
	X	Widget w;
	X	caddr_t	closure;
	X	caddr_t call_data;
	X{
	X	static int vadded;
	X
	X	if (vadded == 0)
	X	{	vadded = 1;
	X		addversion(memoHelp);
	X	}
	X
	X	DisplayHelpWindow(memoHelp);
	X}
SHAR_EOF
if test 6540 -ne "`wc -c < 'xcal_help.c'`"
then
	echo shar: error transmitting "'xcal_help.c'" '(should have been 6540 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'xcal_memo.c'" '(11975 characters)'
if test -f 'xcal_memo.c'
then
	echo shar: will not over-write existing file "'xcal_memo.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'xcal_memo.c'
	X#ifndef lint
	Xstatic char *sccsid = "@(#)xcal_memo.c	1.3 (Hillside Systems) 12/7/90";
	Xstatic char *copyright = "@(#)Copyright 1989,1990 Peter Collinson, Hillside Systems";
	X#endif  /* lint */
	X/***
	X
	X* module name:
	X	xcal_memo.c
	X* function:
	X	Deal with popup memo file
	X	A single popup file is stored in a file called
	X	memo on the Calendar directory
	X* history:
	X	Written December 1990
	X	Peter Collinson
	X	Hillside Systems
	X* (C) Copyright: 1989,1990 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 <unistd.h>				/* works on my Sun */
	X						/* I need the access code */
	X
	Xstatic XtCallbackRec callbacks[] = {
	X   {NULL,NULL},
	X   {NULL,NULL}
	X};
	X#define ClearCallbacks() bzero((caddr_t)callbacks, sizeof (callbacks))
	X
	X/*
	X *	Structure for storing relavant data about the
	X *	memo Edit
	X */
	Xtypedef struct	memoEdit
	X{
	X	Widget	m_button;	/* widget of the control button */
	X	Widget	m_popup;	/* widget of editor popup */
	X	Widget	m_quit;		/* widget of quit button */
	X	Widget	m_save;		/* widget of save button */
	X	Widget	m_display;	/* widget of display title area */
	X	Widget	m_text;		/* the text area */
	X	Widget	m_today;	/* today's data */
	X	Cardinal m_size;	/* size of the buffer */
	X	char	*m_data;	/* pointer to malloc'ed data buffer */
	X} MemoEdit;
	X
	Xstatic	MemoEdit memo;
	XString	GetMemoFile();
	X
	Xextern	Boolean FoundCalendarDir;               /* whether the Calendar directory exists */
	X
	Xstatic	String	memoContents;
	X
	X
	X/*
	X *	Internal routines
	X */
	Xvoid	MemoPopup();
	Xvoid	CleanMemo();
	Xvoid	MemoCheckExit();
	Xvoid	MCheckDia();
	XBoolean	WriteMemoFile();
	Xint	NewlineCount();
	X
	X/*
	X *	Callback routine to display the memo file
	X */
	X
	Xvoid
	XDoMemo(w, closure, call_data)
	X	Widget w;
	X	caddr_t	closure;
	X	caddr_t call_data;
	X{	
	X	
	X	/*
	X	 *	Make button not sensitive
	X	 */
	X	XtSetSensitive(memo.m_button = w, False);
	X	MouseShow(w, False);
	X	/*
	X	 *	Get existing memo contents
	X	 *	if any
	X	 */
	X	if (memoContents == NULL)
	X		memoContents = GetMemoFile();
	X
	X	/*
	X	 *	Set up the popup widget for editing
	X	 */
	X	MemoPopup();
	X}
	X
	X
	X/*
	X *	Get old contents from a memo file if any
	X */
	Xstatic String
	XGetMemoFile()
	X{
	X
	X	if (FoundCalendarDir && access(appResources.memoFile, F_OK) == 0)
	X		return ReadCalendarFile(NULL, appResources.memoFile);
	X	return NULL;
	X}
	X
	X
	X/*
	X *	Do the biz to popup an edit style window
	X */
	Xvoid
	XMemoPopup()
	X{
	X	Widget		et, lw;
	X	Widget		frame;
	X	Arg		args[10];
	X	Cardinal	nargs;
	X	Cardinal	len;
	X	String		str;
	X	MonthEntry	*me;
	X	char		buf[32];
	X	void		FinishMemoEditing();
	X	void		SaveMemoEdits();
	X	void		MemoTextChanged();
	X	void		MemoHelp();
	X	
	X	/*
	X	 *	set up edit buffer
	X	 */
	X	if (memoContents)
	X		memo.m_size = appResources.textbufsz + strlen(memoContents) + 1;
	X	else	
	X		memo.m_size = appResources.textbufsz;
	X	memo.m_data = XtMalloc(memo.m_size);
	X	if (memoContents)
	X		strcpy(memo.m_data, memoContents);
	X	else
	X		*memo.m_data = '\0';
	X	memo.m_popup = XtCreatePopupShell("memo", topLevelShellWidgetClass, toplevel, NULL, 0);
	X
	X	/*
	X	 *	The first title line
	X	 */
	X	et = XtCreateManagedWidget("memoPanel", panedWidgetClass, memo.m_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	 *	containing some buttons for controlling the world
	X	 */
	X	/*
	X	 *	Take label "quit" from resources
	X	 */
	X	callbacks[0].callback = FinishMemoEditing;
	X	callbacks[0].closure = (caddr_t)&memo;
	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	lw = memo.m_quit = XtCreateManagedWidget("quit", commandWidgetClass, frame, args, nargs);
	X	/*
	X	 *	If we are dealing with  help then do it now
	X	 */
	X	if (appResources.giveHelp)
	X	{	/*
	X		 *	Take label "help" from resources
	X		 */
	X		callbacks[0].callback = MemoHelp;
	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	 *	The remaining bit here is a date label
	X	 */
	X	PlaceStr(buf, today.day, appResources.mon[today.month], today.year);
	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 = memo.m_display = XtCreateManagedWidget("date", labelWidgetClass, frame, args, nargs);
	X	/*
	X	 *	Details for today
	X	 */
	X	me = GetMonthEntry(today.year, today.month);
	X	nargs = 0;
	X	str = me->me_have[today.day];
	X	if (str == NULL)
	X		str = "";
	X	XtSetArg(args[nargs], XtNstring, str); nargs++;
	X	XtSetArg(args[nargs], XtNdisplayCaret, False); nargs++;
	X	XtSetArg(args[nargs], XtNeditType, XawtextRead); nargs++;
	X	memo.m_today = XtCreateManagedWidget("display", asciiTextWidgetClass, et, args, nargs);
	X	{	Dimension height;
	X
	X		XtSetArg(args[0], XtNheight, &height);
	X		XtGetValues(memo.m_today, args, 1);
	X		height = height*NewlineCount(str);
	X		XtSetArg(args[0], XtNheight, height);
	X		XtSetValues(memo.m_today, args, 1);
	X	}
	X		
	X	/*
	X	 *	Another form with some buttons
	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("memoMiddle", formWidgetClass, et, args, nargs);
	X	/*
	X	 *	Take label "save" from resources
	X	 */
	X	callbacks[0].callback = SaveMemoEdits;
	X	callbacks[0].closure = (caddr_t)&memo;
	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	XtSetArg(args[nargs], XtNsensitive, False); nargs++;
	X	lw = memo.m_save = XtCreateManagedWidget("save", commandWidgetClass, frame, args, nargs);
	X	/*
	X	 *	Say this is a memo edit
	X	 */
	X	nargs = 0;
	X	XtSetArg(args[nargs], XtNshowGrip, True); 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("memoTitle", 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 = MemoTextChanged;
	X	callbacks[0].closure = (caddr_t)&memo;
	X	nargs = 0;
	X	XtSetArg(args[nargs], XtNstring, memo.m_data); nargs++;
	X	XtSetArg(args[nargs], XtNeditType, XawtextEdit); nargs++;
	X	XtSetArg(args[nargs], XtNlength, memo.m_size); nargs++;
	X	XtSetArg(args[nargs], XtNuseStringInPlace, True); nargs++;
	X	XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
	X	memo.m_text = XtCreateManagedWidget("memoText", asciiTextWidgetClass, et, args, nargs);
	X
	X	
	X	XtPopup(memo.m_popup, XtGrabNone);
	X	
	X}
	X
	X/*
	X *	Count newlines in a string
	X */
	Xstatic int
	XNewlineCount(str)
	X	String	str;
	X{
	X	register int sum = 0;
	X
	X	while (*str)
	X		if (*str++ == '\n')
	X			sum++;
	X	/* Add one line - assume last line does NOT have an nl */
	X	sum++;
	X	/* ignore a final newline */
	X	if (str[-1] == '\n')
	X		sum--;
	X	if (sum <= 0) sum = 1;
	X	return(sum > appResources.maxDisplayLines ? appResources.maxDisplayLines : sum);
	X}
	X
	X/*
	X *	Entry point from outside when today's text changed
	X */
	Xvoid
	XUpdateMemo()
	X{
	X	Arg		args[1];
	X	String		str;
	X	Cardinal	nargs;
	X	MonthEntry	*me;
	X	char		buf[32];
	X	
	X	/*
	X	 * if the button widget is zero then we are displaying nothing
	X	 */
	X	if (memo.m_button == 0)
	X		return;
	X
	X	me = GetMonthEntry(today.year, today.month);
	X	nargs = 0;
	X	str = me->me_have[today.day];
	X	if (str == NULL)
	X		str = "";
	X	XtSetArg(args[0], XtNstring, str); nargs++;
	X	XtSetValues(memo.m_today, args, 1);
	X
	X	(void) sprintf(buf, "%d %s %d", today.day, appResources.mon[today.month], today.year);
	X	XtSetArg(args[0], XtNlabel, buf);
	X	XtSetValues(memo.m_display, args, 1);
	X}
	X		
	X/*
	X *	Call backs for various buttons
	X */
	X/* ARGSUSED */
	Xstatic void
	XMemoTextChanged(w, closure, call_data)
	X	Widget	w;
	X	caddr_t	closure;
	X	caddr_t call_data;
	X{
	X	register MemoEdit *memo = (MemoEdit *)closure;
	X
	X	XtSetSensitive(memo->m_save, True);
	X}
	X
	X/*
	X *	Callback routines
	X */
	X/* ARGSUSED */
	Xvoid
	XSaveMemoEdits(w, closure, call_data)
	X	Widget	w;
	X	caddr_t	closure;
	X	caddr_t call_data;
	X{
	X	MemoEdit	*memo = (MemoEdit *)closure;
	X
	X	if (WriteMemoFile(memo) == False)
	X		return;
	X	if (memoContents)
	X	{	XtFree(memoContents);
	X		memoContents = XtNewString(memo->m_data);
	X	}
	X	XtSetSensitive(memo->m_save, False);
	X}
	X
	X/*
	X *	Write the memo file out
	X */
	Xstatic Boolean
	XWriteMemoFile(memo)
	X	MemoEdit	*memo;
	X{
	X	Cardinal	len = strlen(memo->m_data);
	X	String		fname;
	X	int		fd;
	X	extern		String MapStem;
	X	
	X	if (len == 0)
	X	{	unlink(appResources.memoFile);
	X		return(True);
	X	}
	X	/*
	X	 *	First let's see if we have 
	X	 *	to create the toplevel directory
	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
	X	fname = appResources.memoFile;
	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, memo->m_data, 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
	X	close(fd);
	X	return (True);
	X}
	X
	Xstatic void
	XFinishMemoEditing(w, closure, call_data)
	X	Widget	w;
	X	caddr_t	closure;
	X	caddr_t call_data;
	X{
	X
	X	if (memoContents == NULL || strcmp(memoContents, memo.m_data))
	X	{	MemoCheckExit();
	X		return;
	X	}
	X	CleanMemo();
	X}
	X
	Xstatic void
	XCleanMemo()
	X{
	X	XtSetSensitive(memo.m_button, True);
	X	MouseShow(memo.m_button, True);
	X	XtPopdown(memo.m_popup);
	X	XtDestroyWidget(memo.m_popup);
	X	XtFree(memo.m_data);
	X	bzero((char *)&memo, sizeof(MemoEdit));
	X
	X}
	X
	Xstatic void
	XMemoCheckExit()
	X{
	X	DialogPopup(memo.m_quit, MCheckDia, &memo);
	X}
	X
	Xstatic void
	XMCheckDia(pop, ed)
	X	Widget	pop;
	X	MemoEdit *ed;
	X{
	X	Widget	dia;
	X	void	YesCheck();
	X	void	NoCheck();
	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	SaveMemoEdits(w, closure, call_data);
	X	CleanMemo();
	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	CleanMemo();
	X	XtDestroyWidget(XtParent(XtParent(w)));
	X}
SHAR_EOF
if test 11975 -ne "`wc -c < 'xcal_memo.c'`"
then
	echo shar: error transmitting "'xcal_memo.c'" '(should have been 11975 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'xcal_strip.c'" '(14269 characters)'
if test -f 'xcal_strip.c'
then
	echo shar: will not over-write existing file "'xcal_strip.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'xcal_strip.c'
	X#ifndef lint
	Xstatic char *sccsid = "@(#)xcal_strip.c	3.6 (Hillside Systems) 12/7/90";
	Xstatic char *copyright = "@(#)Copyright 1989,1990 Peter Collinson, Hillside Systems";
	X#endif  /* lint */
	X/***
	X
	X* module name:
	X	xcal_strip.c
	X* function:
	X	Deal with the popup strip calendars obtained either by
	X	selection and the middle button, or by the < and > buttons
	X	on each strip.
	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/Paned.h>
	X#include <X11/Xaw/Command.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 XtCallbackRec callbacks[] = {
	X   {NULL,NULL},
	X   {NULL,NULL},
	X   {NULL,NULL},
	X   {NULL,NULL}
	X};
	X#define ClearCallbacks() bzero((caddr_t)callbacks, sizeof (callbacks))
	X
	XDate	callb;		/* contains date when calendar day button pressed */
	X
	X/*
	X *	Forward routines local to this file
	X */
	Xvoid MakeMonth();
	Xvoid	DayBack();
	X#ifdef LONG_IS_32_BITS
	Xvoid	YmBack();
	X#endif
	Xvoid	StripQuit();
	X
	Xvoid	MakeNewMonth();
	X
	XCardinal DateSum();
	XCardinal NumberOfDays();
	XCardinal FirstDay();
	XCardinal JanuaryOne();
	X/*
	X *	Start a strip calendar happening
	X *	a callback of left button 
	X */
	X/* ARGSUSED */
	Xvoid
	XDoCalendar(w, closure, call_data)
	X	Widget w;
	X	caddr_t	closure;
	X	caddr_t call_data;
	X{
	X	NewMonthStrip(&today);		/* today is global */
	X}
	X
	X/*
	X *	Start a strip calendar happening
	X *	a callback of the > or < buttons in another strip
	X */
	X/* ARGSUSED */
	Xstatic void
	XMakeNewMonth(w, closure, call_data)
	X	Widget w;
	X	caddr_t	closure;
	X	caddr_t call_data;
	X{
	X	Date	thisday;
	X
	X	thisday.year = YrUnpack((Cardinal)closure);
	X	thisday.month = MoUnpack((Cardinal)closure);
	X	thisday.day = today.day;
	X	NewMonthStrip(&thisday);
	X}
	X
	X/* 
	X *	Do all the X stuff to popup a Strip calendar
	X *	A calendar strip is:
	X *
	X *	Popup ("<month year>")		// Name is the month and the year
	X *	    Paned ("<month>")		// Name is the month
	X *		Label ("header")	// optional contains Month Year
	X *		Form ("action")		// < Quit >
	X *		    Command ("back")	// contains < 
	X *		    Label ("quit")	// contains Quit
	X *		    Command ("next")	// contains >
	X *	(Then many of..)
	X *		Form ("<dd DDD>")	// where dd is the day number, DDD is the
	X *					// day of the week
	X *		    Label ("label")	// contains the string above
	X *		    Command ("info")	// contains the text from the file
	X *		
	X */
	Xvoid
	XNewMonthStrip(td)
	X	Date	*td;
	X{
	X	Widget		shell, mon, dw, lw, lwi, form;
	X	Arg	args[15];
	X	char		nbuf[256];
	X	char		iconName[80];
	X	MonthEntry	*me;
	X	Instance	*ins;
	X	register int	i;
	X	register Cardinal nargs;
	X	Cardinal	thisDay;
	X	String		dayStr;
	X	Cardinal	numberOfDays;
	X	Boolean		defaultsAreSet = False;
	X	Boolean		markThisMonth = False;
	X	Cardinal	adjustLabelY;
	X	Cardinal	adjustInfoY;
	X	Dimension	labelH, infoH;
	X	Dimension	width;
	X	Dimension	totalWidth;
	X	void		StripHelp();
	X
	X	(void) sprintf(iconName, "%s %d", appResources.smon[td->month], td->year);
	X
	X	XtSetArg(args[0], XtNiconName, iconName);
	X	shell = XtCreatePopupShell(XtNewString(iconName), topLevelShellWidgetClass, toplevel, args, 1);
	X
	X	ins = RegisterMonth(td->year, td->month, shell);	
	X
	X	mon = XtCreateManagedWidget(appResources.mon[td->month], panedWidgetClass, shell, NULL, 0);
	X
	X	thisDay = FirstDay(td->month, td->year);
	X	numberOfDays = NumberOfDays(td->month, td->year);
	X	/*
	X	 *	Get the map for this year
	X	 */
	X	me = GetMonthEntry(td->year, td->month);
	X	/*
	X	 *	Title bar is month and date
	X	 */
	X	(void) sprintf(nbuf, "%s %d", appResources.mon[td->month], td->year);
	X	/*
	X	 *	see if we will need to worry about marking today's entry
	X	 */
	X	if (appResources.markToday && td->year == today.year && td->month == today.month)
	X		markThisMonth = True;
	X	/*
	X	 *	Find size of title bar
	X	 *	by creating the widget and then throwing it away
	X	 */
	X	XtSetArg(args[0], XtNlabel, "mmmmmmmmm NNNN");
	X	lw = XtCreateManagedWidget("sizer", labelWidgetClass, shell, args, 1);
	X	XtSetArg(args[0], XtNwidth, &totalWidth);
	X	XtGetValues(lw, args, 1);
	X	XtDestroyWidget(lw);
	X	/*
	X	 *	Width is affected by a resource value
	X	 */
	X	if (appResources.minstripwidth && appResources.minstripwidth > totalWidth)
	X		totalWidth = appResources.minstripwidth;
	X	/*
	X	 *	Now set the title bar should we need it
	X	 */
	X	if (appResources.useWmTitle)
	X	{	XtSetArg(args[0], XtNlabel, XtNewString(nbuf));
	X		(void) XtCreateManagedWidget("header", labelWidgetClass, mon, args, 1);
	X	}
	X		
	X	/*
	X	 *	Action bar
	X	 */
	X	nargs = 0;
	X	XtSetArg(args[nargs], XtNshowGrip, False); nargs++;
	X	XtSetArg(args[nargs], XtNdefaultDistance, 2); nargs++;
	X	dw = XtCreateManagedWidget("action", formWidgetClass, mon, args, nargs);
	X
	X	/*
	X	 *	back one month
	X	 *	label "<" from resources
	X	 */
	X	callbacks[0].callback = MakeNewMonth;
	X	callbacks[0].closure = (caddr_t)DateSum(td, -1);
	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	lw = XtCreateManagedWidget("back", commandWidgetClass, dw, args, nargs);
	X	ClearCallbacks();
	X
	X	/*
	X	 *	Quit button
	X	 *	label "quit" from resources
	X	 */
	X	callbacks[0].callback = StripQuit;
	X	callbacks[0].closure = (caddr_t)shell;
	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, XtChainRight); nargs++;
	X	lw = XtCreateManagedWidget("quit", commandWidgetClass, dw, args, nargs);
	X	ClearCallbacks();
	X
	X	/*
	X	 *	On one month
	X	 *	label ">" from reources
	X	 */
	X	callbacks[0].callback = MakeNewMonth;
	X	callbacks[0].closure = (caddr_t)DateSum(td, 1);
	X	nargs = 0;
	X	XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
	X	XtSetArg(args[nargs], XtNfromHoriz, lw); nargs++;
	X	XtSetArg(args[nargs], XtNleft, XtChainRight); nargs++;
	X	XtSetArg(args[nargs], XtNright, XtChainRight); nargs++;
	X	lw = XtCreateManagedWidget("next", commandWidgetClass, dw, args, nargs);
	X	ClearCallbacks();
	X
	X	/*
	X	 *	Help button
	X	 *	label help from resources
	X	 */
	X	if (appResources.giveHelp)
	X	{	
	X		callbacks[0].callback = StripHelp;
	X		callbacks[0].closure = (caddr_t)0;
	X		nargs = 0;
	X		XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
	X		XtSetArg(args[nargs], XtNshowGrip, False); nargs++;
	X		lw = XtCreateManagedWidget("help", commandWidgetClass, mon, args, nargs);
	X		ClearCallbacks();
	X	}
	X
	X#ifdef	LONG_IS_32_BITS
	X	callbacks[0].callback = DayBack;
	X#else
	X	callbacks[0].callback = YmBack;
	X	callbacks[1].callback = DayBack;
	X#endif
	X	for (i = 1; i <= numberOfDays; i++)
	X	{
	X		dayStr = appResources.day[thisDay];
	X		(void) sprintf(nbuf, "%2d %s", i, dayStr);
	X		thisDay = (thisDay+1)%7;
	X		
	X#ifdef LONG_IS_32_BITS
	X		callbacks[0].closure = (caddr_t)DatePack(i, td->month, td->year);
	X#else
	X		callbacks[0].closure = (caddr_t)DatePack(td->month, td->year);
	X		callbacks[1].closure = (caddr_t)i;
	X#endif		
	X		/*
	X		 *	Each line in the strip is
	X		 *	form containing
	X		 *	label - command
	X		 */
	X		nargs = 0;
	X		XtSetArg(args[nargs], XtNshowGrip, False); nargs++;
	X		XtSetArg(args[nargs], XtNdefaultDistance, 0); nargs++;
	X		form = XtCreateManagedWidget(dayStr, formWidgetClass, mon, args, nargs);
	X		
	X		nargs = 0;
	X		XtSetArg(args[nargs], XtNlabel, XtNewString(nbuf)); nargs++;
	X						/* a little naughty here */
	X						/* this string memory is lost */
	X						/* on quit */
	X		XtSetArg(args[nargs], XtNborderWidth, 0); nargs++;
	X		XtSetArg(args[nargs], XtNjustify, XtJustifyLeft); nargs++;
	X		XtSetArg(args[nargs], XtNfromHoriz, NULL); nargs++;
	X		XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
	X		XtSetArg(args[nargs], XtNright, XtChainLeft); nargs++;
	X
	X		ins->i_day_label[i] = lw = XtCreateManagedWidget("label", labelWidgetClass, form, args, nargs);
	X
	X		/*
	X		 *	To get a handle on the old values which are lost by
	X		 *	highlighting we get them after we have created the
	X		 *	widget. Then we highlight today.
	X		 */
	X		if (markThisMonth && today.day == i)
	X		{
	X			nargs = 0;
	X			XtSetArg(args[nargs], XtNforeground, &ins->i_col.fg); nargs++;
	X			XtSetArg(args[nargs], XtNbackground, &ins->i_col.bg); nargs++;
	X			XtSetArg(args[nargs], XtNfont, &ins->i_font); nargs++;
	X			XtGetValues(lw, args, nargs);
	X
	X			nargs = 0;
	X			XtSetArg(args[nargs], XtNforeground, appResources.today.fg); nargs++;
	X			XtSetArg(args[nargs], XtNbackground, appResources.today.bg); nargs++;
	X			XtSetArg(args[nargs], XtNfont, appResources.fontToday); nargs++;
	X			XtSetValues(lw, args, nargs);
	X		}
	X		/*
	X		 *	Done the first time through
	X		 *	Gets the width of the line we have just made
	X		 */
	X		if (defaultsAreSet == False)
	X		{	/* compute text width */
	X			nargs = 0;
	X			XtSetArg(args[nargs], XtNwidth, &width); nargs++;
	X			XtSetArg(args[nargs], XtNheight, &labelH); nargs++;
	X			XtGetValues(lw, args, nargs);
	X			defaultsAreSet = True;
	X		}
	X		/*
	X		 *	Start processing the RHS of the line
	X		 *	This contains text from the file
	X		 *	should any exist
	X		 */
	X		nargs = 0;
	X		XtSetArg(args[nargs], XtNborderWidth, 0); nargs++;
	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, XtChainRight); nargs++;
	X		XtSetArg(args[nargs], XtNjustify, XtJustifyLeft); nargs++;
	X		XtSetArg(args[nargs], XtNwidth, totalWidth - width); nargs++;
	X
	X		if (me->me_have[i])
	X		{	XtSetArg(args[nargs], XtNforeground, appResources.marked.fg); nargs++;
	X			XtSetArg(args[nargs], XtNbackground, appResources.marked.bg); nargs++;
	X			XtSetArg(args[nargs], XtNlabel, me->me_have[i]); nargs++;
	X		}
	X		else
	X		{	XtSetArg(args[nargs], XtNlabel, "    "); nargs++;	}
	X		ins->i_day_info[i] = lwi = XtCreateManagedWidget("info", commandWidgetClass, form, args, nargs);
	X
	X		/* deal with height */
	X		XtSetArg(args[0], XtNheight, &infoH);
	X		XtGetValues(lwi, args, 1);
	X		if (labelH < infoH)
	X		{	adjustLabelY = ((infoH-labelH)/2);
	X			/* fix up widget */
	X			nargs = 0;
	X			XtSetArg(args[nargs], XtNvertDistance, adjustLabelY); nargs++;
	X                        XtSetArg(args[nargs], XtNfromVert, NULL); nargs++;
	X			XtSetValues(lw, args, nargs);
	X		}
	X		else
	X		if (labelH > infoH)
	X		{	adjustInfoY = ((labelH - infoH)/2);
	X			/* fix up widget 1 */
	X			nargs = 0;
	X			XtSetArg(args[nargs], XtNvertDistance, adjustInfoY); nargs++;
	X                        XtSetArg(args[nargs], XtNfromVert, NULL); nargs++;
	X			XtSetValues(lwi, args, nargs);
	X		}
	X
	X		/*
	X		 *	cope with 1752
	X		 */
	X		if (td->year == 1752 && td->month == 8 && i == 2)
	X		{	i = 13;
	X			numberOfDays += 11;	/* giving back the 11 days */
	X		}
	X	}
	X	ClearCallbacks();
	X
	X	XtPopup(shell, XtGrabNone);
	X}
	X
	X/*
	X *	Called when the date changes to ensure that
	X *	the correct day has the appropriate highlights
	X */
	Xvoid
	XChangeHighlight(old, new)
	X	Date	*old;
	X	Date	*new;
	X{
	X	register Instance *ins;
	X	Arg		args[5];
	X	Cardinal	nargs;
	X
	X	for (ins = FindInstanceList(old); ins; ins = ins->i_next)
	X	{	nargs = 0;	
	X		XtSetArg(args[nargs], XtNforeground, ins->i_col.fg); nargs++;
	X		XtSetArg(args[nargs], XtNbackground, ins->i_col.bg); nargs++;
	X		XtSetArg(args[nargs], XtNfont, ins->i_font); nargs++;
	X		XtSetValues(ins->i_day_label[old->day], args, nargs);
	X	}
	X
	X	for (ins = FindInstanceList(new); ins; ins = ins->i_next)
	X	{	nargs = 0;
	X		XtSetArg(args[nargs], XtNforeground, &ins->i_col.fg); nargs++;
	X		XtSetArg(args[nargs], XtNbackground, &ins->i_col.bg); nargs++;
	X		XtSetArg(args[nargs], XtNfont, &ins->i_font); nargs++;
	X		XtGetValues(ins->i_day_label[new->day], args, nargs);
	X
	X		nargs = 0;	
	X		XtSetArg(args[nargs], XtNforeground, appResources.today.fg); nargs++;
	X		XtSetArg(args[nargs], XtNbackground, appResources.today.bg); nargs++;
	X		XtSetArg(args[nargs], XtNfont, appResources.fontToday); nargs++;
	X		XtSetValues(ins->i_day_label[new->day], args, nargs);
	X	}
	X}
	X
	X/*
	X *	Call back from a quit button to lose a month strip
	X */
	X/* ARGSUSED */
	Xstatic void
	XStripQuit(w, closure, call_data)
	X	Widget w;
	X	caddr_t	closure;
	X	caddr_t call_data;
	X{
	X	XtPopdown((Widget)closure);
	X	XtDestroyWidget((Widget)closure);
	X}
	X	
	X
	X/*
	X *	Month arithmetic and packing
	X */
	Xstatic Cardinal
	XDateSum(td, inx)
	X	Date	*td;
	X	int	inx;
	X{
	X	int	m, y;
	X
	X	m = td->month;
	X	y = td->year;
	X	m += inx;
	X	if (m < 0)
	X	{	m = 11;
	X		y--;
	X	}
	X	else
	X	if (m > 11)
	X	{	m = 0;
	X		y++;
	X	}
	X#ifdef LONG_IS_32_BITS
	X	return(DatePack(0, m, y));
	X#else
	X	return(DatePack(m, y));
	X#endif
	X}
	X
	X/*
	X *	Call back from day selection button press
	X *	This is done in two stages if cannot fold dates into a closure
	X */
	X/* ARGSUSED */
	Xstatic void
	XDayBack(w, closure, call_data)
	X	Widget w;
	X	caddr_t	closure;
	X	caddr_t call_data;
	X{
	X#ifdef LONG_IS_32_BITS
	X	callb.month = MoUnpack((Cardinal)closure);
	X	callb.year = YrUnpack((Cardinal)closure);
	X	callb.day = DyUnpack((Cardinal)closure);
	X#else
	X	callb.day = (Cardinal)closure;
	X#endif
	X	StartEditing(w, &callb);
	X}
	X
	X#ifndef LONG_IS_32_BITS
	X/* ARGSUSED */
	Xstatic void
	XYmBack(w, closure, call_data)
	X	Widget w;
	X	caddr_t	closure;
	X	caddr_t call_data;
	X{
	X	callb.month = MoUnpack((Cardinal)closure);
	X	callb.year = YrUnpack((Cardinal)closure);
	X}
	X#endif
	X
	X/*
	X *	Stolen from xcalendar.c
	X */
	X/* taken from cal.c */
	X
	Xchar	mon[] = {
	X   31, 29, 31, 30,
	X   31, 30, 31, 31,
	X   30, 31, 30, 31,
	X};
	X
	Xstatic Cardinal calInit = 0;
	X
	Xstatic Cardinal
	XNumberOfDays(m, y)
	X	Cardinal m, y;
	X{
	X	if(calInit != y)
	X		(void) FirstDay(m, y); /* set side effect */
	X	return mon[m];
	X}
	X
	X/* should be called first */
	Xstatic Cardinal
	XFirstDay(m, y)
	X     Cardinal m, y;
	X{
	X	register d, i;
	X
	X	calInit = y;
	X	d = JanuaryOne(y);
	X	mon[1] = 29;
	X	mon[8] = 30;
	X   
	X	switch((JanuaryOne(y+1)+7-d)%7)
	X	{
	X      
	X	/*
	X	 *	non-leap year
	X	 */
	X	case 1:
	X		mon[1] = 28;
	X		break;
	X      
	X	/*
	X	 *	1752
	X	 */
	X	default:
	X		mon[8] = 19;
	X		break;
	X
	X	/*
	X	 *	leap year
	X	 */
	X	case 2:
	X		;
	X	}
	X   
	X	for(i=0; i<m; i++)
	X		d += mon[i];
	X
	X	return(d%7);
	X}
	X
	X/*
	X *	return day of the week
	X *	of jan 1 of given year
	X */
	Xstatic Cardinal
	XJanuaryOne(yr)
	X	Cardinal yr;
	X{
	X	register Cardinal y, d;
	X
	X/*
	X *	normal gregorian calendar
	X *	one extra day per four years
	X */
	X
	X	y = yr;
	X	d = 4+y+(y+3)/4;
	X
	X/*
	X *	julian calendar
	X *	regular gregorian
	X *	less three days per 400
	X */
	X
	X	if(y > 1800) {
	X		d -= (y-1701)/100;
	X		d += (y-1601)/400;
	X	}
	X
	X/*
	X *	great calendar changeover instant
	X */
	X
	X	if(y > 1752)
	X		d += 3;
	X
	X	return(d%7);
	X}
SHAR_EOF
if test 14269 -ne "`wc -c < 'xcal_strip.c'`"
then
	echo shar: error transmitting "'xcal_strip.c'" '(should have been 14269 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