Xkal 1.13 - Part03/05
George Ferguson
ferguson at cs.rochester.edu
Thu Mar 14 05:12:17 AEST 1991
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 3 (of 5)."
# Contents: day.h db.c db.h edit-defaults.c edit-defaults.h edit.c
# edit.h month.c month.h patchlevel.h resources.h strcasecmp.c
# string-convert.c util.h xkal-automail
# Wrapped by ferguson at swan.cs.rochester.edu on Wed Mar 13 13:50:00 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'day.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'day.h'\"
else
echo shar: Extracting \"'day.h'\" \(1104 characters\)
sed "s/^X//" >'day.h' <<'END_OF_FILE'
X/*
X * day.h : Data types and external defs for day stuff
X *
X * George Ferguson, ferguson at cs.rochester.edu, 27 Oct 1990.
X * Version 1.1 - 27 Feb 1991.
X *
X * $Id: day.h,v 2.1 91/02/28 11:21:12 ferguson Exp $
X */
X#ifndef DAY_H
X#define DAY_H
X
X#include "month.h"
X#include "db.h"
X
Xtypedef struct _DayTextData {
X Widget time; /* Label */
X Widget text; /* Text */
X} DayTextData;
Xtypedef struct _DayFormData {
X int day,month,year; /* who am i */
X DayTextData **items; /* widgets */
X Widget date; /* Label (if used) */
X Widget form; /* Form */
X Widget shell; /* Shell for popups */
X DayButtonData *buttonData; /* button pressed if any */
X String *msgText; /* original texts */
X Msgrec **msg; /* pointers to db entries */
X Boolean changed; /* any edit here? */
X Boolean editing; /* being edited? */
X} DayFormData;
X
Xextern DayFormData *createDayFormData(),*createPopupDayFormData();
Xextern void setDayFormData(),clearDayFormData();
Xextern void checkpointAppoints();
Xextern int timetopos();
Xextern void postotime();
X
X
Xextern DayFormData *currentDayFormData;
Xextern int numDisplayedAppoints;
X
X#endif /* DAY_H */
END_OF_FILE
if test 1104 -ne `wc -c <'day.h'`; then
echo shar: \"'day.h'\" unpacked with wrong size!
fi
# end of 'day.h'
fi
if test -f 'db.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'db.c'\"
else
echo shar: Extracting \"'db.c'\" \(15341 characters\)
sed "s/^X//" >'db.c' <<'END_OF_FILE'
X/*
X * db.c : Database routines for xkal.
X * Handles searching and updating the appointment graph.
X * See db.h for a description of the data structure.
X *
X * George Ferguson, ferguson at cs.rochester.edu, 27 Oct 1990.
X * Version 1.1 - 27 Feb 1991.
X *
X * $Id: db.c,v 2.2 91/03/13 13:31:16 ferguson Exp $
X *
X * The following can be used in place of the ones from X11/Intrinsic.h:
X * #define XtNew(T) (T *)malloc(sizeof(T))
X * #define XtFree(X) if ((X) != NULL) free(X)
X * #define XtNewString(S) strcpy(malloc(strlen(S)+1),S)
X *
X */
X#include <stdio.h>
X#include <string.h>
X#include <ctype.h>
X#include <errno.h>
X#include <sys/types.h> /* for writeDb() backup only */
X#include <sys/stat.h> /* " " " " */
X#include <X11/Intrinsic.h>
X#include "db.h"
X#include "util.h"
X#include "date-strings.h"
X#include "app-resources.h" /* for levelDelim and daySlashMonth */
X#ifdef USE_ALERT
X#include "alert.h"
X#endif
Xextern char *program;
X
X/*
X * Functions defined here:
X */
Xvoid initDb();
XMsgrec *addEntry();
XBoolean deleteEntry();
Xint lookupEntry();
Xvoid readDb(), writeDb(), writeAppoint();
X
X/*
X * Data defined here (could be static but we might hack on the DB later,
X * like we do with xkal2xremind and the like).
X */
XYearrec *Db[8];
X
X/* - - - - - - - - */
X
X/*VARARGS1*/
Xstatic void
Xdprintf(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
Xchar *fmt,*a1,*a2,*a3,*a4,*a5,*a6,*a7,*a8,*a9;
X{
X#ifdef debug
X printf(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
X#endif
X}
X
X/* - - - - - - - - */
X/*
X * initDb() : Pretty lame, and unneeded for most UNIX boxes, but I put
X * it here anyway. We never erase the db, so we don't have to
X * worry about this.
X */
Xvoid
XinitDb()
X{
X int i;
X
X for (i=0; i < 8; i++)
X Db[i] = NULL; /* should free them all */
X}
X
X/* - - - - - - - - */
X/*
X * addEntry() : Add an entry to the appropriate place in the database
X * by traversing it and possibly adding nodes. Not much to it.
X */
XMsgrec *
XaddEntry(dow,year,mon,day,hour,mins,text,flag,level)
Xint dow,year,mon,day,hour,mins;
Xchar *text;
Xint flag,level;
X{
X Yearrec *yp;
X Monrec *mp;
X Dayrec *dp;
X Msgrec *xp;
X
X if (Db[dow] == NULL) {
X Db[dow] = XtNew(Yearrec);
X Db[dow]->year = year;
X Db[dow]->mons = NULL;
X Db[dow]->next = NULL;
X }
X for (yp = Db[dow]; yp->year != year && yp->next != NULL; yp = yp->next) ;
X if (yp->year != year) {
X yp->next = XtNew(Yearrec);
X yp->next->year = year;
X yp->next->mons = NULL;
X yp->next->next = NULL;
X yp = yp->next;
X }
X if (yp->mons == NULL) {
X yp->mons = XtNew(Monrec);
X yp->mons->mon = mon;
X yp->mons->days = NULL;
X yp->mons->next = NULL;
X }
X for (mp = yp->mons; mp->mon != mon && mp->next != NULL; mp = mp->next) ;
X if (mp->mon != mon) {
X mp->next = XtNew(Monrec);
X mp->next->mon = mon;
X mp->next->days = NULL;
X mp->next->next=NULL;
X mp = mp->next;
X }
X
X if (mp->days == NULL) {
X mp->days = XtNew(Dayrec);
X mp->days->day = day;
X mp->days->msgs = NULL;
X mp->days->next = NULL;
X }
X for (dp = mp->days; dp->day != day && dp->next != NULL; dp = dp->next) ;
X if (dp->day != day) {
X dp->next = XtNew(Dayrec);
X dp->next->day = day;
X dp->next->msgs = NULL;
X dp->next->next=NULL;
X dp = dp->next;
X }
X
X if (dp->msgs == NULL) {
X dp->msgs = XtNew(Msgrec);
X dp->msgs->next = NULL;
X } else {
X xp = dp->msgs;
X dp->msgs = XtNew(Msgrec);
X dp->msgs->next = xp;
X }
X dp->msgs->dow = dow;
X dp->msgs->year = year;
X dp->msgs->month = mon;
X dp->msgs->day = day;
X dp->msgs->hour = hour;
X dp->msgs->mins = mins;
X dp->msgs->text = XtNewString(text);
X dp->msgs->system = flag;
X dp->msgs->level = level;
X return(dp->msgs);
X}
X
X/*
X * deleteEntry() : Removes an entry matching the given parameters from
X * the database, and tidies up afterwards. Note that everything must
X * match, the text as well.
X */
XBoolean
XdeleteEntry(dow,year,mon,day,hour,mins,text)
Xint dow,year,mon,day,hour,mins;
Xchar *text;
X{
X Yearrec *yp,*yp2;
X Monrec *mp,*mp2;
X Dayrec *dp,*dp2;
X Msgrec *xp,*xp2;
X
X for (yp = Db[dow]; yp != NULL && yp->year != year; yp = yp->next) ;
X if (yp == NULL)
X return(False);
X for (mp = yp->mons; mp != NULL && mp->mon != mon; mp = mp->next) ;
X if (mp == NULL)
X return(False);
X for (dp = mp->days; dp != NULL && dp->day != day; dp = dp->next) ;
X if (dp == NULL)
X return(False);
X for (xp = dp->msgs; xp != NULL; xp = xp2) {
X xp2 = xp->next;
X if (xp->hour == hour && xp->mins == mins &&
X strcmp(xp->text, text) == 0) {
X XtFree(xp->text); /* free the text */
X if (dp->msgs == xp) /* and the msgrec */
X dp->msgs = xp->next;
X else {
X for (xp2 = dp->msgs; xp2->next != xp; xp2 = xp2->next);
X xp2->next = xp->next;
X }
X XtFree(xp);
X if (dp->msgs == NULL) { /* if no more entries, free the day */
X if (mp->days == dp)
X mp->days = dp->next;
X else {
X for (dp2 = mp->days; dp2->next != dp; dp2 = dp2->next);
X dp2->next = dp->next;
X }
X XtFree(dp);
X }
X if (mp->days == NULL) { /* if no more days, free the month */
X if (yp->mons == mp)
X yp->mons = mp->next;
X else {
X for (mp2 = yp->mons; mp2->next != mp; mp2 = mp2->next);
X mp2->next = mp->next;
X }
X XtFree(mp);
X }
X if (yp->mons == NULL) { /* if no more months, free the year */
X if (Db[dow] == yp)
X Db[dow] = Db[dow]->next;
X else {
X for (yp2 = Db[dow]; yp2->next != yp; yp2 = yp2->next);
X yp2->next = yp->next;
X }
X XtFree(yp);
X }
X return(True);
X }
X }
X return(False);
X}
X
X/* - - - - - - - - */
X/*
X * lookupEntry() : Fills in at most max entries in result[] with pointers
X * to messages for the given date/time. Returns the number of
X * entries filled or -1 if there were more than max entries (but the
X * ones that were filled, ie max of them, are valid). As a special
X * case, if max is -1, then no entries are filled (result can be NULL)
X * and the number of entries is returned. (If useLevel is True, then
X * the total of the levels of all applicable appointments is returned
X * rather than the number of appointments.)
X *
X * The definition of a match is complicated by the fact that items in
X * the database may be only partially specified. The approach is as
X * follows:
X * (a) First consider all db records which do not specify a dow (ie.
X * from Db[0]). Within these, the day, month, and year must match
X * if given, otherwise they are assumed to match. The hour and
X * minutes must match explicitly.
X * (b) Then consider all db records specifying the dow of the given date.
X * If the record does not also specify a day, then the month and
X * year must match if given, as above, and the time must match
X * exactly. If the record specifies both dow and day, then the
X * interpretation is "the first dow after date", so we have to
X * check if the current date is within a week of the date in the
X * record.
X *
X * Note that the strings are not copied.
X */
Xint
XlookupEntry(day,mon,year,hour,mins,max,result,useLevel)
Xint day,mon,year,hour,mins,max;
XMsgrec *result[];
X{
X Yearrec *yp;
X Monrec *mp;
X Dayrec *dp;
X int num,n,i;
X
X dprintf("lookup for %d:%02d, %d %s %d...\n",hour,mins,day,
X shortMonthStr[mon-1],year);
X num = 0;
X dprintf(" checking DB with dow = 0...\n");
X for (yp = Db[0]; yp != NULL; yp = yp->next) {
X dprintf(" year = %d\n", yp->year);
X if (yp->year == year || yp->year == 0)
X for (mp = yp->mons; mp != NULL; mp = mp->next) {
X dprintf(" mon = %d\n", mp->mon);
X if (mp->mon == mon || mp->mon == 0)
X for (dp = mp->days; dp != NULL; dp = dp->next) {
X dprintf("\tday = %d\n", dp->day);
X if (dp->day == day || dp->day == 0) {
X n = lookupEntryDay(dp,hour,mins,max-num,
X result+num,useLevel);
X if (n < 0)
X return(-1);
X else
X num += n;
X }
X }
X }
X }
X dprintf(" checking DB with real dow...\n");
X for (yp = Db[computeDOW(day,mon,year)]; yp != NULL; yp = yp->next) {
X dprintf(" year = %d\n", yp->year);
X for (mp = yp->mons; mp != NULL; mp = mp->next) {
X dprintf(" mon = %d\n", mp->mon);
X for (dp = mp->days; dp != NULL; dp = dp->next) {
X dprintf("\tday = %d\n", dp->day);
X if (dp->day == 0) {
X if ((yp->year == 0 || yp->year == year) &&
X (mp->mon == 0 || mp->mon == mon)) {
X n = lookupEntryDay(dp,hour,mins,max-num,
X result+num,useLevel);
X if (n < 0)
X return(-1);
X else
X num += n;
X }
X } else { /* have dow and day */
X int d,m,y;
X
X d = day;
X m = mon;
X y = year;
X dprintf("\tscanning back from %d %d %d\n",d,m,y);
X for (i=0; i < 7; i++)
X if (dp->day == d && (yp->year == 0 || yp->year == y) &&
X (mp->mon == 0 || mp->mon == m))
X break;
X else
X prevDay(&d,&m,&y);
X if (i < 7) {
X n = lookupEntryDay(dp,hour,mins,max-num,
X result+num,useLevel);
X if (n < 0)
X return(-1);
X else
X num += n;
X }
X }
X }
X }
X }
X dprintf("returning %d\n", num);
X return(num);
X}
X
X/*
X * lookupEntryDay() : Scans the list of messages associated with the
X * given Dayrec and fills in at most max entries of result[] with
X * pointers to the messages. Returns the number of entries filled in,
X * or -1 if there were more entries than max (but all that were filled
X * in, ie. max of them, are valid).
X *
X * If the given hour or mins is -1, then it's assumed to match, making
X * it easy to get all the entries for a day.
X */
Xstatic int
XlookupEntryDay(dp,hour,mins,max,result,useLevel)
XDayrec *dp;
Xint hour,mins,max;
XMsgrec *result[];
XBoolean useLevel;
X{
X Msgrec *xp;
X int num;
X
X num = 0;
X for (xp = dp->msgs; xp != NULL; xp = xp->next) {
X dprintf("\t h:m = %d:%02d\n",xp->hour,xp->mins);
X if ((hour == -1 || xp->hour == -1 || xp->hour == hour) &&
X (mins == -1 || xp->mins == -1 || xp->mins == mins)) {
X dprintf("\t YES\n");
X if (max >= 0 && num >= max)
X return (-1);
X else if (max > 0)
X result[num] = xp;
X if (useLevel)
X num += xp->level;
X else
X num += 1;
X }
X }
X return(num);
X}
X
X/* - - - - - - - - */
X/*
X * readDb() : Reads the given file into the database, setting the flag
X * bit on new entries appropriately. This function understands
X * comments starting with #, and the #include capability. It uses
X * parseLine to actually decode the date spec.
X */
Xvoid
XreadDb(name,systemFlag)
Xchar *name;
Xint systemFlag;
X{
X FILE *fp;
X char *fname,buf[256];
X int line,i,n,c;
X int dow,y,m,d,h,mins,lev;
X char *t;
X
X fname = expandFilename(name);
X if ((fp=fopen(fname,"r")) == NULL) {
X if (errno != ENOENT) /* appointment file may not exist */
X perror(fname);
X return;
X }
X c = line = 0;
X while (c != EOF) {
X n = 0;
X line += 1;
X while (n < 255 && (c=getc(fp)) != EOF && c != '\n')
X buf[n++] = c;
X buf[n] = '\0';
X if (n == 0) {
X continue;
X } else if (c != EOF && c != '\n') {
X fprintf(stderr,"%s: line %d too long, file %s\n",program,
X line,fname);
X while ((c=getc(fp)) != EOF && c != '\n') ;
X }
X i = 0;
X while (isspace(buf[i]))
X i += 1;
X if (buf[i] == '#') {
X if (strncmp(buf+i+1,"include",7) == 0) {
X i += 8;
X while (isspace(buf[i]))
X i += 1;
X readDb(buf+i,systemFlag);
X }
X continue;
X }
X parseLine(buf+i,&dow,&y,&m,&d,&h,&mins,&t,&lev);
X#ifdef debug
X if (dow != 0)
X printf("%s ",shortDowStr[dow-1]);
X if (d != 0)
X printf("%2d ",d);
X if (m != 0)
X printf("%s ",shortMonthStr[m-1]);
X if (y != 0)
X printf("%4d ",y);
X if (h != -1)
X printf("%2d:%02d ",h,mins);
X if (lev != 0)
X printf("@%d@ ",lev);
X printf("%s\n",t);
X#endif
X addEntry(dow,y,m,d,h,mins,t,systemFlag,lev);
X }
X fclose(fp);
X}
X
X/*
X * writeDb() : Writes any non-system database entries to the given file
X * in the canonical format. If writeAll is True, then system entries are
X * also written.
X */
Xvoid
XwriteDb(name,writeAll)
Xchar *name;
XBoolean writeAll;
X{
X FILE *fp;
X char *fname,*backup;
X struct stat stbuf;
X int dow;
X Yearrec *yp;
X Monrec *mp;
X Dayrec *dp;
X Msgrec *xp;
X
X fname = expandFilename(name);
X if (*appResources.backupExtension && stat(fname,&stbuf) == 0) {
X backup = XtMalloc(strlen(fname)+strlen(appResources.backupExtension)+1);
X strcpy(backup,fname);
X strcat(backup,appResources.backupExtension);
X (void)unlink(backup);
X if (link(fname,backup) < 0) {
X#ifdef USE_ALERT
X alert("Error: Can't backup \"%s\"; save aborted.",fname);
X#else
X fprintf(stderr,"\007%s: can't backup \"%s\"; save aborted\n",program,fname);
X#endif
X XtFree(backup);
X return;
X }
X (void)unlink(fname);
X XtFree(backup);
X }
X if ((fp=fopen(fname,"w")) == NULL) {
X perror(fname);
X return;
X }
X for (dow = 0; dow < 8; dow++)
X for (yp = Db[dow]; yp != NULL; yp = yp->next)
X for (mp = yp->mons; mp != NULL; mp = mp->next)
X for (dp = mp->days; dp != NULL; dp = dp->next)
X for (xp = dp->msgs; xp != NULL; xp = xp->next)
X if (!xp->system || writeAll)
X writeAppoint(fp,xp);
X
X fclose(fp);
X}
X
X/*
X * writeAppoint(fp,msg) : Formats the msg onto the given stream.
X *
X * The following escapes are possible in appResources.outputFormat:
X * %w short form of day of the week
X * %W long form of day of the week
X * %d day
X * %m short form of month
X * %M long form of month
X * %n numeric form of month
X * %y year
X * %Y year modulo 100
X * %t time
X * %l criticality level
X * %~ space iff previous pattern was printed
X * %/ slash iff previous pattern was printed
X * Any other character is simply printed. The text of the appointment follows,
X * then a newline.
X */
Xvoid
XwriteAppoint(fp,msg)
XFILE *fp;
XMsgrec *msg;
X{
X char *s;
X Boolean flag;
X
X s = appResources.outputFormat;
X flag = False;
X while (*s) {
X if (*s == '%') {
X s += 1;
X switch (*s) {
X case '\0': fprintf(fp,"%");
X break;
X case '~': if (flag)
X fprintf(fp," ");
X break;
X case '/': if (flag)
X fprintf(fp,"/");
X break;
X case 'w': if (msg->dow > 0)
X fprintf(fp,"%s",shortDowStr[msg->dow-1]);
X flag = (msg->dow > 0);
X break;
X case 'W': if (msg->dow > 0)
X fprintf(fp,"%s",longDowStr[msg->dow-1]);
X flag = (msg->dow > 0);
X break;
X case 'd': if (msg->day > 0)
X fprintf(fp,"%d",msg->day);
X flag = (msg->day > 0);
X break;
X case 'm': if (msg->month > 0)
X fprintf(fp,"%s",shortMonthStr[msg->month-1]);
X flag = (msg->month > 0);
X break;
X case 'M': if (msg->month > 0)
X fprintf(fp,"%s",longMonthStr[msg->month-1]);
X flag = (msg->month > 0);
X break;
X case 'n': if (msg->month > 0)
X fprintf(fp,"%d",msg->month);
X flag = (msg->month > 0);
X break;
X case 'y': if (msg->year > 0)
X fprintf(fp,"%d",msg->year);
X flag = (msg->year > 0);
X break;
X case 'Y': if (msg->year > 0)
X fprintf(fp,"%d",msg->year%100);
X flag = (msg->year > 0);
X break;
X case 't': if (msg->hour != -1)
X fprintf(fp,"%s",timetostr(msg->hour*60+msg->mins));
X flag = (msg->hour != -1);
X break;
X case 'l': if (msg->level > 0) {
X fprintf(fp,"%c",*appResources.levelDelim);
X fprintf(fp,"%d",msg->level);
X if (*(appResources.levelDelim+1))
X fprintf(fp,"%c",*(appResources.levelDelim+1));
X else
X fprintf(fp,"%c",*appResources.levelDelim);
X }
X flag = (msg->level > 0);
X break;
X default: fprintf(fp,"%c",*s);
X } /* switch */
X } else {
X fprintf(fp,"%c",*s);
X }
X if (*s)
X s += 1;
X } /* while */
X fprintf(fp,"%s\n",msg->text);
X}
END_OF_FILE
if test 15341 -ne `wc -c <'db.c'`; then
echo shar: \"'db.c'\" unpacked with wrong size!
fi
# end of 'db.c'
fi
if test -f 'db.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'db.h'\"
else
echo shar: Extracting \"'db.h'\" \(1242 characters\)
sed "s/^X//" >'db.h' <<'END_OF_FILE'
X/*
X * db.h : External defs for database users.
X *
X * George Ferguson, ferguson at cs.rochester.edu, 27 Oct 1990.
X * Version 1.1 - 27 Feb 1991.
X *
X * $Id: db.h,v 2.1 91/02/28 11:21:15 ferguson Exp $
X */
X
X#ifndef DB_H
X#define DB_H
X
X/*
X * The appointment database is a hierarchical data structure. It has an
X * array indexed by dow (and 0 for unspecified dow) of year structures,
X * which in turn each contain a list of month structures, each containing
X * a list day structures, each containing a list of message structures
X * that store the actual reminders.
X *
X * The key to using incompletely-specified patterns is described in
X * lookupEntry().
X */
Xtypedef struct _msgrec {
X int dow,year,month,day; /* redundant, but useful */
X int hour,mins;
X char *text;
X int system;
X int level;
X struct _msgrec *next;
X} Msgrec;
Xtypedef struct _dayrec {
X int day;
X Msgrec *msgs;
X struct _dayrec *next;
X} Dayrec;
Xtypedef struct _monrec {
X int mon;
X Dayrec *days;
X struct _monrec *next;
X} Monrec;
Xtypedef struct _yearrec {
X int year;
X Monrec *mons;
X struct _yearrec *next;
X} Yearrec;
X
Xextern Yearrec *Db[8];
X
Xextern void initDb(), readDb(), writeDb();
Xextern Msgrec *addEntry();
Xextern Boolean deleteEntry();
Xextern int lookupEntry();
X
X#endif /* DB_H */
END_OF_FILE
if test 1242 -ne `wc -c <'db.h'`; then
echo shar: \"'db.h'\" unpacked with wrong size!
fi
# end of 'db.h'
fi
if test -f 'edit-defaults.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'edit-defaults.c'\"
else
echo shar: Extracting \"'edit-defaults.c'\" \(9136 characters\)
sed "s/^X//" >'edit-defaults.c' <<'END_OF_FILE'
X/*
X * edit-defaults.c : Modify default parameters
X *
X * George Ferguson, ferguson at cs.rochester.edu, 27 Feb 1991.
X *
X * $Id: edit-defaults.c,v 2.1 91/02/28 11:21:17 ferguson Exp $
X */
X#include <stdio.h>
X#include <X11/Intrinsic.h>
X#include <X11/Shell.h>
X#include <X11/StringDefs.h>
X#include <X11/Xaw/Form.h>
X#include <X11/Xaw/Command.h>
X#include <X11/Xaw/Label.h>
X#include <X11/Xaw/AsciiText.h>
X#include <X11/Xaw/Cardinals.h>
X#include "xkal.h"
X#include "month.h"
X#include "day.h"
X#include "app-resources.h"
X#ifdef USE_ALERT
X#include "alert.h"
X#endif
X
X/*
X * Functions declared in this file
X */
Xvoid editDefaults();
Xvoid focusNextDefaultsItem(),focusPrevDefaultsItem();
X
Xstatic void initDefaultsShell(),setDefaultsItems(),setText();
Xstatic void applyProc(),revertProc(),dismissProc();
X
X/*
X * Data declared in this file
X */
Xstatic Widget defaultsShell,defaultsForm;
Xstatic Widget applyButton,revertButton,dismissButton;
Xstatic Widget pAppsLabel,pAppsText,bakExtLabel,bakExtText,dateLabel,dateText;
Xstatic Widget numMonLabel,numMonText;
Xstatic Widget chkIntLabel,chkIntText,reaSilLabel,reaSilText;
Xstatic Widget defLevLabel,defLevText,levDelLabel,levDelText;
X
X#define ACTION_PROC(NAME) void NAME(w,event,params,num_params) \
X Widget w; \
X XEvent *event; \
X String *params; \
X Cardinal *num_params;
X
X#define CALLBACK_PROC(NAME) static void NAME(w,client_data,call_data) \
X Widget w; \
X caddr_t client_data,call_data;
X
X/* - - - - - - - - */
X/* External interface (action) procedure */
X/*
X * editDefaults() : Pops up (possibly creating) the defaults editor,
X * and fills it with the information from the current values of
X * the application defaults.
X */
X/*ARGSUSED*/
XACTION_PROC(editDefaults)
X{
X if (defaultsShell == NULL)
X initDefaultsShell();
X setDefaultsItems();
X XtPopup(defaultsShell,XtGrabNone);
X}
X
X/* - - - - - - - - */
X/* Initialization procedures */
X/*
X * initDefaultsShell() : Create the popup defaults editor.
X */
Xstatic void
XinitDefaultsShell()
X{
X defaultsShell = XtCreatePopupShell("defaultsShell",topLevelShellWidgetClass,
X toplevel,NULL,ZERO);
X defaultsForm = XtCreateManagedWidget("defaultsForm",formWidgetClass,
X defaultsShell,NULL,ZERO);
X applyButton = XtCreateManagedWidget("applyButton",commandWidgetClass,
X defaultsForm,NULL,ZERO);
X XtAddCallback(applyButton,"callback",applyProc,NULL);
X revertButton = XtCreateManagedWidget("revertButton",commandWidgetClass,
X defaultsForm,NULL,ZERO);
X XtAddCallback(revertButton,"callback",revertProc,NULL);
X dismissButton = XtCreateManagedWidget("dismissButton",commandWidgetClass,
X defaultsForm,NULL,ZERO);
X XtAddCallback(dismissButton,"callback",dismissProc,NULL);
X
X pAppsLabel = XtCreateManagedWidget("personalAppointsLabel",labelWidgetClass,
X defaultsForm,NULL,ZERO);
X pAppsText = XtCreateManagedWidget("personalAppointsText",
X asciiTextWidgetClass,defaultsForm,NULL,ZERO);
X bakExtLabel = XtCreateManagedWidget("backupExtensionLabel",labelWidgetClass,
X defaultsForm,NULL,ZERO);
X bakExtText = XtCreateManagedWidget("backupExtensionText",
X asciiTextWidgetClass,defaultsForm,NULL,ZERO);
X dateLabel = XtCreateManagedWidget("dateLabel",labelWidgetClass,
X defaultsForm,NULL,ZERO);
X dateText = XtCreateManagedWidget("dateText",
X asciiTextWidgetClass,defaultsForm,NULL,ZERO);
X numMonLabel = XtCreateManagedWidget("numMonthsLabel",labelWidgetClass,
X defaultsForm,NULL,ZERO);
X numMonText = XtCreateManagedWidget("numMonthsText",
X asciiTextWidgetClass,defaultsForm,NULL,ZERO);
X chkIntLabel = XtCreateManagedWidget("checkpointIntervalLabel",
X labelWidgetClass,defaultsForm,NULL,ZERO);
X chkIntText = XtCreateManagedWidget("checkpointIntervalText",
X asciiTextWidgetClass,defaultsForm,NULL,ZERO);
X reaSilLabel = XtCreateManagedWidget("rearrangeSilentlyLabel",
X labelWidgetClass,defaultsForm,NULL,ZERO);
X reaSilText = XtCreateManagedWidget("rearrangeSilentlyText",
X asciiTextWidgetClass,defaultsForm,NULL,ZERO);
X defLevLabel = XtCreateManagedWidget("defaultLevelLabel",labelWidgetClass,
X defaultsForm,NULL,ZERO);
X defLevText = XtCreateManagedWidget("defaultLevelText",
X asciiTextWidgetClass,defaultsForm,NULL,ZERO);
X levDelLabel = XtCreateManagedWidget("levelDelimLabel",labelWidgetClass,
X defaultsForm,NULL,ZERO);
X levDelText = XtCreateManagedWidget("levelDelimText",
X asciiTextWidgetClass,defaultsForm,NULL,ZERO);
X}
X
X/*
X * setDefaultsItems() : Sets the values in the defaults editor from the
X * current state of the application resources.
X */
Xstatic void
XsetDefaultsItems()
X{
X char buf[8];
X
X setText(pAppsText,appResources.personalAppoints);
X setText(bakExtText,appResources.backupExtension);
X setText(dateText,appResources.date);
X sprintf(buf,"%d",appResources.numMonths);
X setText(numMonText,buf);
X sprintf(buf,"%d",appResources.checkpointInterval);
X setText(chkIntText,buf);
X setText(reaSilText,appResources.rearrangeSilently ? "True" : "False");
X sprintf(buf,"%d",appResources.defaultLevel);
X setText(defLevText,buf);
X setText(levDelText,appResources.levelDelim);
X}
X
X/*
X * setText() : Set the value of a text item.
X */
Xstatic void
XsetText(item,text)
XWidget item;
Xchar *text;
X{
X Arg args[1];
X
X XtSetArg(args[0],XtNstring,text);
X XtSetValues(item,args,ONE);
X}
X
X/* - - - - - - - - */
X/* Callback procedures */
X/*
X * applyProc() : Callback for apply button - Set the application resources
X * from the items on the defaults editor panel. Some of these require
X * special action when changed, and this routine does that.
X */
X/*ARGSUSED*/
XCALLBACK_PROC(applyProc)
X{
X Arg args[1];
X char *s;
X int n;
X
X XtSetArg(args[0],XtNstring,&(appResources.personalAppoints));
X XtGetValues(pAppsText,args,ONE);
X XtSetArg(args[0],XtNstring,&(appResources.backupExtension));
X XtGetValues(bakExtText,args,ONE);
X XtSetArg(args[0],XtNstring,&s);
X XtGetValues(dateText,args,ONE);
X if (strcmp(s,appResources.date) != 0) {
X appResources.date = XtNewString(s); /* leak! */
X parseDate(appResources.date,¤tDay,¤tMon,¤tYear);
X }
X XtSetArg(args[0],XtNstring,&s);
X XtGetValues(numMonText,args,ONE);
X if (strcmp(s,"1") != 0 && strcmp(s,"2") != 0 &&
X strcmp(s,"3") != 0 && strcmp(s,"12") != 0) {
X#ifdef USE_ALERT
X alert("Error: numMonths must be 1, 2, 3, or 12.");
X#else
X fprintf(stderr,"\007%s: numMonths must be 1, 2, 3, or 12\n",program);
X#endif
X } else if (n != appResources.numMonths) {
X n = ONE;
X setNumMonths((Widget)NULL,(XEvent *)NULL,&s,&n);
X }
X XtSetArg(args[0],XtNstring,&s);
X XtGetValues(chkIntText,args,ONE);
X n = atoi(s);
X if (n != appResources.checkpointInterval) {
X appResources.checkpointInterval = n;
X XtRemoveTimeOut(timeoutId);
X if (n > 0)
X timeoutId = XtAppAddTimeOut(app_con,(unsigned long)(n*60000),
X timeoutProc,NULL);
X }
X XtSetArg(args[0],XtNstring,&s);
X XtGetValues(reaSilText,args,ONE);
X n = (strcasecmp(s,"True") == 0 || strcmp(s,"1") == 0);
X if (n != appResources.rearrangeSilently) {
X appResources.rearrangeSilently = n;
X if (currentDayFormData != NULL) {
X checkpointAppoints(currentDayFormData);
X setDayFormData(currentDayFormData);
X }
X }
X XtSetArg(args[0],XtNstring,&s);
X XtGetValues(defLevText,args,ONE);
X appResources.defaultLevel = atoi(s);
X XtSetArg(args[0],XtNstring,&(appResources.levelDelim));
X XtGetValues(levDelText,args,ONE);
X}
X
X/*
X * revertProc() : Callback for revert button - Reset the text strings to
X * the way they were when editDefaults was called last. Does NOT undo
X * any changed that were made.
X */
X/*ARGSUSED*/
XCALLBACK_PROC(revertProc)
X{
X setDefaultsItems();
X}
X
X/*
X * dismissProc() : Callback for dismiss button - Pop down the editor.
X */
X/*ARGSUSED*/
XCALLBACK_PROC(dismissProc)
X{
X XtPopdown(defaultsShell);
X}
X
X/* - - - - - - - - */
X/* Action procedures */
X/*
X * focusNextDefaultstem() : Move input focus to next defaults editor item,
X * wrapping at bottom.
X */
X/*ARGSUSED*/
XACTION_PROC(focusNextDefaultsItem)
X{
X if (w == pAppsText)
X w = bakExtText;
X else if (w == bakExtText)
X w = dateText;
X else if (w == dateText)
X w = numMonText;
X else if (w == numMonText)
X w = chkIntText;
X else if (w == chkIntText)
X w = reaSilText;
X else if (w == reaSilText)
X w = defLevText;
X else if (w == defLevText)
X w = levDelText;
X else if (w == levDelText)
X w = pAppsText;
X else
X return;
X XSetInputFocus(display,XtWindow(w),RevertToParent,CurrentTime);
X}
X
X/*
X * focusNextDefaultsItem() : Move input focus to previous defaults editor item,
X * wrapping at top.
X */
X/*ARGSUSED*/
XACTION_PROC(focusPrevDefaultsItem)
X{
X if (w == pAppsText)
X w = levDelText;
X else if (w == bakExtText)
X w = pAppsText;
X else if (w == dateText)
X w = bakExtText;
X else if (w == numMonText)
X w = dateText;
X else if (w == chkIntText)
X w = numMonText;
X else if (w == reaSilText)
X w = chkIntText;
X else if (w == defLevText)
X w = reaSilText;
X else if (w == levDelText)
X w = defLevText;
X else
X return;
X XSetInputFocus(display,XtWindow(w),RevertToParent,CurrentTime);
X}
END_OF_FILE
if test 9136 -ne `wc -c <'edit-defaults.c'`; then
echo shar: \"'edit-defaults.c'\" unpacked with wrong size!
fi
# end of 'edit-defaults.c'
fi
if test -f 'edit-defaults.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'edit-defaults.h'\"
else
echo shar: Extracting \"'edit-defaults.h'\" \(359 characters\)
sed "s/^X//" >'edit-defaults.h' <<'END_OF_FILE'
X/*
X * edit.h : External defs for editing global defaults
X *
X * George Ferguson, ferguson at cs.rochester.edu, 27 Feb 1991.
X *
X * $Id: edit-defaults.h,v 2.1 91/02/28 11:21:18 ferguson Exp $
X */
X#ifndef EDIT_DEFAULTS_H
X#define EDIT_DEFAULTS_H
X
Xextern void editDefaults();
Xextern void focusNextDefaultsItem(), focusPrevDefaultsItem();
X
X#endif /* EDIT_DEFAULTS_H */
END_OF_FILE
if test 359 -ne `wc -c <'edit-defaults.h'`; then
echo shar: \"'edit-defaults.h'\" unpacked with wrong size!
fi
# end of 'edit-defaults.h'
fi
if test -f 'edit.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'edit.c'\"
else
echo shar: Extracting \"'edit.c'\" \(11588 characters\)
sed "s/^X//" >'edit.c' <<'END_OF_FILE'
X/*
X * edit.c : Edit an appointment in detail
X *
X * George Ferguson, ferguson at cs.rochester.edu, 27 Feb 1991.
X *
X * $Id: edit.c,v 2.1 91/02/28 11:21:20 ferguson Exp $
X */
X#include <stdio.h>
X#include <X11/Intrinsic.h>
X#include <X11/Shell.h>
X#include <X11/StringDefs.h>
X#include <X11/Xaw/Form.h>
X#include <X11/Xaw/Command.h>
X#include <X11/Xaw/Label.h>
X#include <X11/Xaw/AsciiText.h>
X#include <X11/Xaw/Cardinals.h>
X#include "xkal.h"
X#include "month.h"
X#include "day.h"
X#include "db.h"
X#include "util.h"
X#include "date-strings.h"
X#include "app-resources.h" /* for notesLabel */
X#ifdef USE_ALERT
X#include "alert.h"
X#endif
X
X/*
X * Functions declared in this file
X */
Xvoid editAppoint();
Xvoid focusNextEditItem(),focusPrevEditItem();
X
Xstatic void initEditShell(),setEditItems(),setText();
Xstatic void applyProc(),revertProc(),deleteProc(),dismissProc();
Xstatic Boolean getCurrentEditMsg();
X
X/*
X * Data declared in this file
X */
Xstatic Widget editShell,editForm;
Xstatic Widget applyButton,revertButton,deleteButton,dismissButton;
Xstatic Widget dowLabel,dowText,dayLabel,dayText,monLabel,monText;
Xstatic Widget yearLabel,yearText,timeLabel,timeText;
Xstatic Widget textLabel,textText,levelLabel,levelText;
Xstatic DayFormData *currentEditFormData;
Xstatic Msgrec currentEditMsg;
X
X#define ACTION_PROC(NAME) void NAME(w,event,params,num_params) \
X Widget w; \
X XEvent *event; \
X String *params; \
X Cardinal *num_params;
X
X#define CALLBACK_PROC(NAME) static void NAME(w,client_data,call_data) \
X Widget w; \
X caddr_t client_data,call_data;
X
X/* - - - - - - - - */
X/* External interface (action) procedure */
X/*
X * editAppoint() : Pops up (possibly creating) the appointment editor,
X * and fills it with the information from the appointment corresponding
X * to the text widget taht this action is invoked from.
X */
X/*ARGSUSED*/
XACTION_PROC(editAppoint)
X{
X Arg args[1];
X int i,type;
X
X if (currentDayFormData == NULL)
X return;
X for (i=0; i < numDisplayedAppoints; i++)
X if (w == currentDayFormData->items[i]->time ||
X w == currentDayFormData->items[i]->text)
X break;
X if (i == numDisplayedAppoints)
X return;
X if (w == currentDayFormData->items[i]->time)
X w = currentDayFormData->items[i]->text;
X XtSetArg(args[0],XtNeditType,&type);
X XtGetValues(w,args,ONE);
X if (type != XawtextEdit) {
X XBell(display,0);
X return;
X }
X if (editShell == NULL)
X initEditShell();
X checkpointAppoints(currentDayFormData);
X currentEditFormData = currentDayFormData;
X currentEditFormData->editing = True;
X if (currentEditFormData->msg[i] == NULL) {
X currentEditMsg.dow = 0;
X currentEditMsg.day = currentEditFormData->day;
X currentEditMsg.month = currentEditFormData->month;
X currentEditMsg.year = currentEditFormData->year;
X postotime(i,&(currentEditMsg.hour),&(currentEditMsg.mins));
X currentEditMsg.text = "";
X currentEditMsg.level = appResources.defaultLevel;
X } else {
X currentEditMsg.dow = currentEditFormData->msg[i]->dow;
X currentEditMsg.day = currentEditFormData->msg[i]->day;
X currentEditMsg.month = currentEditFormData->msg[i]->month;
X currentEditMsg.year = currentEditFormData->msg[i]->year;
X currentEditMsg.hour = currentEditFormData->msg[i]->hour;
X currentEditMsg.mins = currentEditFormData->msg[i]->mins;
X currentEditMsg.text = XtNewString(currentEditFormData->msg[i]->text);
X currentEditMsg.level = currentEditFormData->msg[i]->level;
X }
X setEditItems(¤tEditMsg);
X XtPopup(editShell,XtGrabNone);
X}
X
X/* - - - - - - - - */
X/* Initialization procedures */
X
X/*
X * initEditShell() : Create the popup appointment editor.
X */
Xstatic void
XinitEditShell()
X{
X editShell = XtCreatePopupShell("editShell",topLevelShellWidgetClass,
X toplevel,NULL,ZERO);
X editForm = XtCreateManagedWidget("editForm",formWidgetClass,
X editShell,NULL,ZERO);
X applyButton = XtCreateManagedWidget("applyButton",commandWidgetClass,
X editForm,NULL,ZERO);
X XtAddCallback(applyButton,"callback",applyProc,NULL);
X revertButton = XtCreateManagedWidget("revertButton",commandWidgetClass,
X editForm,NULL,ZERO);
X XtAddCallback(revertButton,"callback",revertProc,NULL);
X deleteButton = XtCreateManagedWidget("deleteButton",commandWidgetClass,
X editForm,NULL,ZERO);
X XtAddCallback(deleteButton,"callback",deleteProc,NULL);
X dismissButton = XtCreateManagedWidget("dismissButton",
X commandWidgetClass,editForm,NULL,ZERO);
X XtAddCallback(dismissButton,"callback",dismissProc,NULL);
X dowLabel = XtCreateManagedWidget("dowLabel",labelWidgetClass,
X editForm,NULL,ZERO);
X dowText = XtCreateManagedWidget("dowText",asciiTextWidgetClass,
X editForm,NULL,ZERO);
X dayLabel = XtCreateManagedWidget("dayLabel",labelWidgetClass,
X editForm,NULL,ZERO);
X dayText = XtCreateManagedWidget("dayText",asciiTextWidgetClass,
X editForm,NULL,ZERO);
X monLabel = XtCreateManagedWidget("monLabel",labelWidgetClass,
X editForm,NULL,ZERO);
X monText = XtCreateManagedWidget("monText",asciiTextWidgetClass,
X editForm,NULL,ZERO);
X yearLabel = XtCreateManagedWidget("yearLabel",labelWidgetClass,
X editForm,NULL,ZERO);
X yearText = XtCreateManagedWidget("yearText",asciiTextWidgetClass,
X editForm,NULL,ZERO);
X timeLabel = XtCreateManagedWidget("timeLabel",labelWidgetClass,
X editForm,NULL,ZERO);
X timeText = XtCreateManagedWidget("timeText",asciiTextWidgetClass,
X editForm,NULL,ZERO);
X textLabel = XtCreateManagedWidget("textLabel",labelWidgetClass,
X editForm,NULL,ZERO);
X textText = XtCreateManagedWidget("textText",asciiTextWidgetClass,
X editForm,NULL,ZERO);
X levelLabel = XtCreateManagedWidget("levelLabel",labelWidgetClass,
X editForm,NULL,ZERO);
X levelText = XtCreateManagedWidget("levelText",asciiTextWidgetClass,
X editForm,NULL,ZERO);
X XtRealizeWidget(editShell); /* so we can set titlebar */
X}
X
X/*
X * setEditItems() : Sets the values in the appointment editor text items
X * to values ffrom the given appoint.
X */
Xstatic void
XsetEditItems(msg)
XMsgrec *msg;
X{
X char buf[8];
X
X if (msg->dow == 0)
X setText(dowText,"");
X else
X setText(dowText,shortDowStr[msg->dow-1]);
X if (msg->day == 0)
X setText(dayText,"");
X else {
X sprintf(buf,"%d",msg->day);
X setText(dayText,buf);
X }
X if (msg->month == 0)
X setText(monText,"");
X else
X setText(monText,shortMonthStr[msg->month-1]);
X if (msg->year == 0)
X setText(yearText,"");
X else {
X sprintf(buf,"%d",msg->year);
X setText(yearText,buf);
X }
X if (msg->hour == -1)
X setText(timeText,appResources.notesLabel);
X else
X setText(timeText,timetostr(msg->hour*60+msg->mins));
X setText(textText,msg->text);
X sprintf(buf,"%d",msg->level);
X setText(levelText,buf);
X}
X
X/*
X * setText() : Set the given text item's value to the given string.
X */
Xstatic void
XsetText(item,text)
XWidget item;
Xchar *text;
X{
X Arg args[1];
X
X XtSetArg(args[0],XtNstring,text);
X XtSetValues(item,args,ONE);
X}
X
X/* - - - - - - - - */
X/* Callback procedures */
X
X/*
X * applyProc() : Callback for apply button - Add an entry with the fields
X * given in the editor panel to the DB. Removes any other that matches
X * exactly (including the text). Resets the month display to reflect
X * the change (and the day within the month).
X */
X/*ARGSUSED*/
XCALLBACK_PROC(applyProc)
X{
X Msgrec msg;
X
X if (!getCurrentEditMsg(&msg))
X return;
X deleteEntry(msg.dow,msg.year,msg.month,msg.day,msg.hour,msg.mins,msg.text);
X addEntry(msg.dow,msg.year,msg.month,msg.day,msg.hour,msg.mins,msg.text,
X False,msg.level);
X appointsChanged = True;
X setDayFormData(currentEditFormData,currentEditFormData->day,
X currentEditFormData->month,
X currentEditFormData->year);
X shadeButton(currentEditFormData->buttonData,(GC)NULL,0,0);
X}
X
X/*
X * revertProc() : Callback for revert button - Reset the text strings to
X * the way they were when editAppoint was called last. Does NOT undo
X * any changed that were made.
X */
X/*ARGSUSED*/
XCALLBACK_PROC(revertProc)
X{
X setEditItems(¤tEditMsg);
X}
X
X/*
X * deleteProc() : Callback for delete button - Removes any appoint that
X * exactly matches the items on the editor panel. Updates the month
X * display to reflect the change.
X */
X/*ARGSUSED*/
XCALLBACK_PROC(deleteProc)
X{
X Msgrec msg;
X
X checkpointAppoints(currentEditFormData);
X if (!getCurrentEditMsg(&msg))
X return;
X if (deleteEntry(msg.dow,msg.year,msg.month,msg.day,msg.hour,msg.mins,
X msg.text)) {
X appointsChanged = True;
X setDayFormData(currentEditFormData,currentEditFormData->day,
X currentEditFormData->month,
X currentEditFormData->year);
X shadeButton(currentEditFormData->buttonData,(GC)NULL,0,0);
X }
X}
X
X/*
X * dismissProc() : Callback for dismiss button - Pop down the editor.
X */
X/*ARGSUSED*/
XCALLBACK_PROC(dismissProc)
X{
X currentEditFormData->editing = False;
X XtFree(currentEditMsg.text);
X XtPopdown(editShell);
X}
X
X/* - - - - - - - - */
X/* Action procedures */
X/*
X * focusNextEditItem() : Move input focus to next editor item, wrapping
X * at bottom.
X */
X/*ARGSUSED*/
XACTION_PROC(focusNextEditItem)
X{
X if (w == dowText)
X w = dayText;
X else if (w == dayText)
X w = monText;
X else if (w == monText)
X w = yearText;
X else if (w == yearText)
X w = timeText;
X else if (w == timeText)
X w = textText;
X else if (w == textText)
X w = levelText;
X else if (w == levelText)
X w = dowText;
X else
X return;
X XSetInputFocus(display,XtWindow(w),RevertToParent,CurrentTime);
X}
X
X/*
X * focusPrevEditItem() : Move input focus to previous editor item, wrapping
X * at top.
X */
X/*ARGSUSED*/
XACTION_PROC(focusPrevEditItem)
X{
X if (w == dowText)
X w = levelText;
X else if (w == dayText)
X w = dowText;
X else if (w == monText)
X w = dayText;
X else if (w == yearText)
X w = monText;
X else if (w == timeText)
X w = yearText;
X else if (w == textText)
X w = timeText;
X else if (w == levelText)
X w = textText;
X else
X return;
X XSetInputFocus(display,XtWindow(w),RevertToParent,CurrentTime);
X}
X
X/* - - - - - - - - */
X/*
X * getCurrentEditMsg() : Fills in the given Msgrec with values taken from
X * the editor text items.
X */
Xstatic Boolean
XgetCurrentEditMsg(msg)
XMsgrec *msg;
X{
X Arg args[1];
X char *s;
X int i,t;
X
X XtSetArg(args[0],XtNstring,&s);
X XtGetValues(dowText,args,ONE);
X if (!*s)
X msg->dow = 0;
X else {
X for (i=0; i < 7; i++)
X if (strcasecmp(s,longDowStr[i]) == 0 ||
X strcasecmp(s,shortDowStr[i]) == 0)
X break;
X if (i == 7) {
X#ifdef USE_ALERT
X alert("Error: bad dow string: \"%s\".",s);
X#else
X fprintf(stderr,"\007%s: bad dow string: \"%s\"\n",program,s);
X#endif
X return(False);
X } else
X msg->dow = i+1;
X }
X XtGetValues(dayText,args,ONE);
X msg->day = atoi(s); /* no checking! */
X XtGetValues(monText,args,ONE);
X if (!*s)
X msg->month = 0;
X else {
X for (i=0; i < 7; i++)
X if (strcasecmp(s,longMonthStr[i]) == 0 ||
X strcasecmp(s,shortMonthStr[i]) == 0)
X break;
X if (i == 7) {
X#ifdef USE_ALERT
X alert("Error: bad month string: \"%s\".",s);
X#else
X fprintf(stderr,"\007%s: bad month string: \"%s\"\n",program,s);
X#endif
X return(False);
X } else
X msg->month = i+1;
X }
X XtGetValues(yearText,args,ONE);
X msg->year = atoi(s); /* no checking! */
X XtGetValues(timeText,args,ONE);
X if (!*s || strcasecmp(s,appResources.notesLabel) == 0)
X msg->hour = msg->mins = -1;
X else {
X t = strtotime(s);
X msg->hour = t / 60;
X msg->mins = t % 60;
X }
X XtGetValues(textText,args,ONE);
X msg->text = s;
X XtGetValues(levelText,args,ONE);
X msg->level = atoi(s); /* no checking! */
X return(True);
X}
END_OF_FILE
if test 11588 -ne `wc -c <'edit.c'`; then
echo shar: \"'edit.c'\" unpacked with wrong size!
fi
# end of 'edit.c'
fi
if test -f 'edit.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'edit.h'\"
else
echo shar: Extracting \"'edit.h'\" \(324 characters\)
sed "s/^X//" >'edit.h' <<'END_OF_FILE'
X/*
X * edit.h : External defs for the popup appointment editor panel
X *
X * George Ferguson, ferguson at cs.rochester.edu, 27 Feb 1991.
X *
X * $Id: edit.h,v 2.1 91/02/28 11:21:21 ferguson Exp $
X */
X#ifndef EDIT_H
X#define EDIT_H
X
Xextern void editAppoint();
Xextern void focusNextEditItem(),focusPrevEditItem();
X
X#endif /* EDIT_H */
END_OF_FILE
if test 324 -ne `wc -c <'edit.h'`; then
echo shar: \"'edit.h'\" unpacked with wrong size!
fi
# end of 'edit.h'
fi
if test -f 'month.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'month.c'\"
else
echo shar: Extracting \"'month.c'\" \(6947 characters\)
sed "s/^X//" >'month.c' <<'END_OF_FILE'
X/*
X * month.c : Widget creation and action binding for the month
X * forms, and their sub-widgets.
X *
X * George Ferguson, ferguson at cs.rochester.edu, 27 Oct 1990.
X * Version 1.1 - 27 Feb 1991.
X *
X * $Id: month.c,v 2.1 91/02/28 11:21:22 ferguson Exp $
X */
X#include <X11/Intrinsic.h>
X#include <X11/Shell.h>
X#include <X11/StringDefs.h>
X#include <X11/Xaw/Form.h>
X#include <X11/Xaw/Command.h>
X#include <X11/Xaw/Toggle.h>
X#include <X11/Xaw/Label.h>
X#include <X11/Xaw/AsciiText.h>
X#include <X11/Xaw/Cardinals.h>
X#include "xkal.h"
X#include "month.h"
X#include "day.h"
X#include "db.h"
X#include "app-resources.h"
X#include "date-strings.h"
X
X/*
X * Functions defined in this file
X */
XMonthFormData *createMonthFormData();
Xvoid setMonthFormData();
Xvoid selectDay();
Xvoid shadeButton();
X
Xstatic void dayButtonCallbackProc();
Xstatic void getGCAndXY();
X
X/*
X * Data defined in this file
X */
Xstatic Widget radioGroup;
X
X#define CALLBACK_PROC(NAME) static void NAME(w,client_data,call_data) \
X Widget w; \
X caddr_t client_data,call_data;
X
X
X/* - - - - - - - - */
X/*
X * createMonthFormData() : Returns a monthFormData whose Form is unmanaged.
X */
XMonthFormData *
XcreateMonthFormData(parent,name,num)
XWidget parent;
Xchar *name;
Xint num; /* 1,2,3,12 */
X{
X MonthFormData *m;
X DayButtonData *d;
X Widget widget;
X Arg args[3];
X char text[16];
X int row,col,index;
X int w,h;
X
X m = XtNew(MonthFormData);
X m->form = XtCreateWidget(name,formWidgetClass,parent,NULL,ZERO);
X switch (num) {
X case 1: w = appResources.dateWidth1;
X h = appResources.dateHeight1;
X break;
X case 2: w = appResources.dateWidth2;
X h = appResources.dateHeight2;
X break;
X case 3: w = appResources.dateWidth3;
X h = appResources.dateHeight3;
X break;
X case 12: w = appResources.dateWidth12;
X h = appResources.dateHeight12;
X break;
X }
X sprintf(text,"monthLabel%d",num);
X m->label = XtCreateManagedWidget(text,labelWidgetClass,m->form,NULL,ZERO);
X if (appResources.dowLabels) {
X sprintf(text,"dowLabel%d",num);
X XtSetArg(args[0],XtNfromVert,m->label);
X XtSetArg(args[1],XtNfromHoriz,NULL);
X index = appResources.dowOffset;
X for (col=0; col < 7; col++) {
X XtSetArg(args[2],XtNlabel,shortDowStr[index]);
X widget = XtCreateManagedWidget(text,labelWidgetClass,m->form,
X args,THREE);
X index = (index == 6) ? 0 : index+1;
X XtSetArg(args[1],XtNfromHoriz,widget);
X }
X XtSetArg(args[0],XtNfromVert,widget);
X } else {
X XtSetArg(args[0],XtNfromVert,m->label);
X }
X sprintf(text,"dayButton%d",num);
X for (row=0; row < 6; row++) {
X XtSetArg(args[1],XtNfromHoriz,NULL);
X for (col=0; col < 7; col++) {
X d = m->days[row*7+col] = XtNew(DayButtonData);
X d->button = XtCreateManagedWidget(text,toggleWidgetClass,
X m->form,args,TWO);
X XtAddCallback(d->button,"callback",dayButtonCallbackProc,d);
X XtSetArg(args[2],XtNradioData,d->button);
X XtSetValues(d->button,args+2,ONE);
X if (radioGroup == NULL)
X radioGroup = d->button;
X XawToggleChangeRadioGroup(d->button,radioGroup);
X d->pixmap = XCreatePixmap(display,root,w,h,
X DefaultDepthOfScreen(screen));
X
X XtSetArg(args[1],XtNfromHoriz,d->button);
X }
X XtSetArg(args[0],XtNfromVert,d->button);
X }
X return(m);
X}
X
X/*
X * setMonthFormData() : Draw the individual days in the month, including
X * the date and shading for criticality.
X */
Xvoid
XsetMonthFormData(m,num,month,year)
XMonthFormData *m;
Xint num,month,year;
X{
X DayButtonData *d;
X Arg args[1];
X GC gc;
X char text[16];
X int first,numDays;
X int i,x,y;
X
X getGCAndXY(num,&gc,&x,&y);
X XawFormDoLayout(m->form,False);
X XawToggleUnsetCurrent(radioGroup);
X sprintf(text,"%s %d",longMonthStr[month-1],year);
X XtSetArg(args[0],XtNlabel,text);
X XtSetValues(m->label,args,ONE);
X first = firstDOW(month,year)-1-appResources.dowOffset;
X numDays = lastDay(month,year);
X for (i=0; i < 42; i++) {
X d = m->days[i];
X if (i < first || i >= first+numDays) {
X d->day = 0;
X XFillRectangle(display,d->pixmap,emptyGC,0,0,50,50);
X XtSetArg(args[0],XtNbitmap,d->pixmap);
X XtSetValues(d->button,args,ONE);
X } else {
X d->day = i-first+1;
X d->month = month;
X d->year = year;
X shadeButton(d,gc,x,y);
X }
X }
X XawFormDoLayout(m->form,True);
X m->month = month;
X m->year = year;
X}
X
X/*
X * setGCAndXY() : Depending on num, parses the appropriate geometry
X * string into *xp and *yp, and puts the correct GC* into gcp.
X * This function is here so it can be outside the loop in
X * setMonthFormData(), but really belongs in shadeButton.
X */
Xstatic void
XgetGCAndXY(num,gcp,xp,yp)
XGC *gcp;
Xint *xp,*yp;
X{
X int w,h;
X
X switch (num) {
X case 1: XParseGeometry(appResources.datePosition1,xp,yp,&w,&h);
X *gcp = dateGC1;
X break;
X case 2: XParseGeometry(appResources.datePosition2,xp,yp,&w,&h);
X *gcp = dateGC2;
X break;
X case 3: XParseGeometry(appResources.datePosition3,xp,yp,&w,&h);
X *gcp = dateGC3;
X break;
X case 12: XParseGeometry(appResources.datePosition12,xp,yp,&w,&h);
X *gcp = dateGC12;
X break;
X }
X}
X
X/*
X * shadeButton() : Shades a dayButton. This is global so it can be called
X * after the appointments have changed without redrawing everything.
X */
Xvoid
XshadeButton(d,gc,x,y)
XDayButtonData *d;
XGC gc;
Xint x,y;
X{
X Arg args[1];
X char text[4];
X int n;
X
X if (gc == (GC)NULL)
X getGCAndXY(appResources.numMonths,&gc,&x,&y);
X n = lookupEntry(d->day,d->month,d->year,-1,-1,-1,NULL,True);
X if (n > appResources.maxLevel)
X n = appResources.maxLevel;
X XFillRectangle(display,d->pixmap,shadeGC[n],0,0,
X appResources.dateWidth1,appResources.dateHeight1);
X sprintf(text,"%d",d->day);
X if (appResources.opaqueDates)
X XDrawImageString(display,d->pixmap,gc,x,y,text,strlen(text));
X else
X XDrawString(display,d->pixmap,gc,x,y,text,strlen(text));
X XtSetArg(args[0],XtNbitmap,d->pixmap);
X XtSetValues(d->button,args,ONE);
X}
X
X/*
X * selectDay() : Used to highlight a day (usually on startup or from
X * the "today" action) without the user having clicked on it.
X */
Xvoid
XselectDay(m,day,mon,year)
XMonthFormData *m;
Xint day,mon,year;
X{
X int which;
X
X which = firstDOW(mon,year)-appResources.dowOffset+day-2;
X XawToggleSetCurrent(radioGroup,m->days[which]->button);
X}
X
X/*
X * dayButtonCallbackProc() : The callback when a day is clicked on (or
X * at least when the "notify" action is invoked). Pops up a new
X * dayForm is there isn't currently one, and sets it or the current
X * one to the new day's appoints.
X */
X/*ARGSUSED*/
XCALLBACK_PROC(dayButtonCallbackProc)
X{
X DayButtonData *d = (DayButtonData *)client_data;
X
X if (d->day == 0)
X return;
X if (currentDayFormData == NULL)
X currentDayFormData = createPopupDayFormData();
X else
X checkpointAppoints(currentDayFormData);
X currentDayFormData->buttonData = d;
X if (XawToggleGetCurrent(radioGroup) != NULL)
X setDayFormData(currentDayFormData,d->day,d->month,d->year);
X else
X clearDayFormData(currentDayFormData);
X}
END_OF_FILE
if test 6947 -ne `wc -c <'month.c'`; then
echo shar: \"'month.c'\" unpacked with wrong size!
fi
# end of 'month.c'
fi
if test -f 'month.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'month.h'\"
else
echo shar: Extracting \"'month.h'\" \(637 characters\)
sed "s/^X//" >'month.h' <<'END_OF_FILE'
X/*
X * month.h : Data types and external defs for month stuff
X *
X * George Ferguson, ferguson at cs.rochester.edu, 27 Oct 1990.
X * Version 1.1 - 27 Feb 1991.
X *
X * $Id: month.h,v 2.1 91/02/28 11:21:24 ferguson Exp $
X */
X#ifndef MONTH_H
X#define MONTH_H
X
Xtypedef struct _DayButtonData {
X int day,month,year;
X Pixmap pixmap;
X Widget button; /* Command */
X} DayButtonData;
Xtypedef struct _MonthFormData {
X int month,year;
X DayButtonData *days[42];
X Widget label; /* Label */
X Widget form; /* Form */
X} MonthFormData;
X
Xextern MonthFormData *createMonthFormData();
Xextern void setMonthFormData();
Xextern void selectDay();
X
X#endif /* MONTH_H */
END_OF_FILE
if test 637 -ne `wc -c <'month.h'`; then
echo shar: \"'month.h'\" unpacked with wrong size!
fi
# end of 'month.h'
fi
if test -f 'patchlevel.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'patchlevel.h'\"
else
echo shar: Extracting \"'patchlevel.h'\" \(135 characters\)
sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
X/*
X * patchlevel.h - Version information
X *
X * George Ferguson, ferguson at cs.rochester.edu, 13 Mar 1991.
X */
X
X#define XKAL_VERSION 1.13
END_OF_FILE
if test 135 -ne `wc -c <'patchlevel.h'`; then
echo shar: \"'patchlevel.h'\" unpacked with wrong size!
fi
# end of 'patchlevel.h'
fi
if test -f 'resources.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'resources.h'\"
else
echo shar: Extracting \"'resources.h'\" \(569 characters\)
sed "s/^X//" >'resources.h' <<'END_OF_FILE'
X/*
X * resources.h: Resource loading code and definitions.
X *
X * Most other modules should include app-resources.h for access to
X * the resources after they've been loaded.
X *
X * George Ferguson, ferguson at cs.rochester.edu, 27 Feb 1991.
X *
X * $Id: resources.h,v 2.2 91/03/13 13:31:35 ferguson Exp $
X *
X */
X#ifndef RESOURCES_H
X#define RESOURCES_H
X
Xextern XrmOptionDescRec xkalOptions[15]; /* cmd line options */
Xextern XtResource xkalResources[53]; /* applications resources */
X
Xextern void getResources(); /* load resources without display */
X
X#endif /* RESOURCES_H */
END_OF_FILE
if test 569 -ne `wc -c <'resources.h'`; then
echo shar: \"'resources.h'\" unpacked with wrong size!
fi
# end of 'resources.h'
fi
if test -f 'strcasecmp.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'strcasecmp.c'\"
else
echo shar: Extracting \"'strcasecmp.c'\" \(405 characters\)
sed "s/^X//" >'strcasecmp.c' <<'END_OF_FILE'
X/*
X * strcasecmp(s,t): Just like strcmp(3) but ignores case.
X *
X * Adapted from strcmp() in K&&R, page 102.
X *
X * George Ferguson, ferguson at cs.rochester.edu, 12 Feb 1991.
X */
X
Xint
Xstrcasecmp(s,t)
Xchar *s,*t;
X{
X for ( ; *s == *t ||
X (*s >= 'A' && *s <= 'Z' && *s-'A'+'a' == *t) ||
X (*t >= 'A' && *t <= 'Z' && *t-'A'+'a' == *s) ; s++, t++)
X if (*s == '\0')
X return(0);
X return(*s - *t);
X}
END_OF_FILE
if test 405 -ne `wc -c <'strcasecmp.c'`; then
echo shar: \"'strcasecmp.c'\" unpacked with wrong size!
fi
# end of 'strcasecmp.c'
fi
if test -f 'string-convert.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'string-convert.c'\"
else
echo shar: Extracting \"'string-convert.c'\" \(1158 characters\)
sed "s/^X//" >'string-convert.c' <<'END_OF_FILE'
X/*
X * string-convert.c : A kludgy way to prevent getting a warning
X * message of the form "can't convert NULL to type Widget".
X *
X * George Ferguson, ferguson at cs.rochester.edu, 8 Feb 1991.
X *
X * This code is lifted from lib/Xt/Converters.c in the X11R4 source
X * tree. I would register my own converter for string to widget, but
X * there's no way to get the default converter, so I'd end up copying
X * or rewriting even more code. By the way, this works because the
X * converter returns NULL when it fails, which is what we want.
X *
X * $Id: string-convert.c,v 2.0 91/02/08 15:55:32 ferguson Exp $
X */
X#include <X11/Intrinsic.h>
X#include <X11/StringDefs.h>
X
X/* from IntrinsicI.h */
Xstatic String XtNconversionError = "conversionError";
Xextern String XtCXtToolkitError;
X
Xvoid XtStringConversionWarning(from, toType)
X String from, toType;
X{
X String params[2];
X Cardinal num_params = 2;
X
X if (strcasecmp(from,"NULL") == 0 &&
X strcasecmp(toType,XtRWidget) == 0)
X return;
X
X params[0] = from;
X params[1] = toType;
X XtWarningMsg(XtNconversionError,"string",XtCXtToolkitError,
X "Cannot convert string \"%s\" to type %s",
X params,&num_params);
X}
END_OF_FILE
if test 1158 -ne `wc -c <'string-convert.c'`; then
echo shar: \"'string-convert.c'\" unpacked with wrong size!
fi
# end of 'string-convert.c'
fi
if test -f 'util.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'util.h'\"
else
echo shar: Extracting \"'util.h'\" \(506 characters\)
sed "s/^X//" >'util.h' <<'END_OF_FILE'
X/*
X * util.h : External defs for callers of misc routines.
X *
X * George Ferguson, ferguson at cs.rochester.edu, 27 Oct 1990.
X * Version 1.1 - 27 Feb 1991.
X *
X * $Id: util.h,v 2.1 91/02/28 11:21:39 ferguson Exp $
X *
X */
X#ifndef UTIL_H
X#define UTIL_H
X
Xextern int computeDOW(), firstDOW(), lastDay();
Xextern void nextDay(),prevDay(),getCurrentDate();
Xextern int parseDate();
Xextern void parseLine();
Xextern char *expandFilename();
Xextern int strtotime();
Xextern char *timetostr();
X
X#endif /* UTIL_H */
END_OF_FILE
if test 506 -ne `wc -c <'util.h'`; then
echo shar: \"'util.h'\" unpacked with wrong size!
fi
# end of 'util.h'
fi
if test -f 'xkal-automail' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'xkal-automail'\"
else
echo shar: Extracting \"'xkal-automail'\" \(906 characters\)
sed "s/^X//" >'xkal-automail' <<'END_OF_FILE'
X#!/bin/sh
X#
X# xkal-automail : Schedules an at job for the time given as
X# argument. The job will basically do what xkal-mail
X# does, namely mail the day's appointments if there are
X# any non-zero-level ones. The job reschedules itself
X# for the next day.
X#
X# Note that the first automatic mailing will be "tomorrow" at
X# the given time, not today, even it could be.
X#
X# George Ferguson, ferguson at cs.rochester.edu, 19 Feb 1991.
X#
X
Xxkal=xkal
Xmailer=Mail
Xtmp=/tmp/xkal-automail$USER
X
Xcase $# in
X 1) when=$1 ; rec=${USER:?} ;;
X 2) when=$1 ; rec=$2 ;;
X *) echo 'usage: xkal-automail when [recipient]' 1>&2; exit 1
Xesac
X
Xat -s $when tomorrow >/dev/null 2>&1 <<END_OF_SCRIPT
Xtrap "rm -f $tmp; exit 1" 1 2 3 15
Xif $xkal -listOnly -exitUsesLevels -date +1d >$tmp
Xthen
X :
Xelse
X $mailer -s "Reminders from xkal for \`head -1 $tmp\`" $rec <$tmp
Xfi
Xrm -f $tmp
Xxkal-automail $when $rec
XEND_OF_SCRIPT
END_OF_FILE
if test 906 -ne `wc -c <'xkal-automail'`; then
echo shar: \"'xkal-automail'\" unpacked with wrong size!
fi
chmod +x 'xkal-automail'
# end of 'xkal-automail'
fi
echo shar: End of archive 3 \(of 5\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 5 archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--
George Ferguson ARPA: ferguson at cs.rochester.edu
University of Rochester UUCP: {decvax,rutgers}!rochester!ferguson
Rochester NY 14627-0226 VOX: (716) 275-2527
More information about the Alt.sources
mailing list