ferguson@cs.rochester.edu (George Ferguson) (03/14/91)
#! /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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@cs.rochester.edu University of Rochester UUCP: {decvax,rutgers}!rochester!ferguson Rochester NY 14627-0226 VOX: (716) 275-2527