ferguson@cs.rochester.edu (George Ferguson) (11/15/90)
#! /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 4 (of 4)." # Contents: util.c xkal.c # Wrapped by ferguson@swan.cs.rochester.edu on Mon Nov 12 14:07:08 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'util.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'util.c'\" else echo shar: Extracting \"'util.c'\" \(4574 characters\) sed "s/^X//" >'util.c' <<'END_OF_FILE' X/* X * util.c : Some miscellaneous routines for handling dates. X * X * George Ferguson (ferguson@cs.rochester.edu), 27 Oct 1990. X * X * $Id: util.c,v 1.1 90/10/28 13:05:14 ferguson Exp $ X * X */ X X#include <sys/time.h> X#include <ctype.h> Xextern char *shortMonStr[]; X X/* X * Functions defined here: X */ Xint computeDOW(), firstDOW(), lastDay(); Xvoid getCurrentDate(); Xint parseDate(); X X/* X * Global data X */ Xstatic int mon_max[] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; X X/* - - - - - - - - */ X/* X * computeDOW(day,mon,year) : Returns the day of the week for the X * requested date (0=Sunday, 1=Monday, etc). X * This newer, faster, method is courtesy findeis@alberta. X */ Xint XcomputeDOW(d,m,y) Xint d,m,y; X{ X static int dp [12] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5}; X register int y4, s; X X y = y - 1; /* actually y - 1901 */ X s = (y/4) * 5; X y4 = y % 4; X if ((y4 == 3) && (m>1)) s++; X s = s + y4 + dp[m] + d + 1; X return (s % 7); X} X X/* X * firstDOW(mon,year) : Returns the doy of the week for the first X * day of the given month and year. X */ Xint XfirstDOW(mon,year) Xint mon,year; X{ X return(computeDOW(1,mon,year)); X} X X/* X * lastDay(mon,year) : Returns the last day of the requested X * month (and handles leap years, etc). X */ Xint XlastDay(mon,year) Xint mon,year; X{ X if ((mon == 1)&&(dysize(year+1900) == 366)) X return(29); X else return(mon_max[mon]); X} X X/* X * nextDay(d,m,y) : Increment d,m,y to the next day X */ Xvoid XnextDay(dp,mp,yp) Xint *dp,*mp,*yp; X{ X if (*dp != lastDay(*mp,*yp)) X *dp += 1; X else { X *dp = 1; X if (*mp != 11) X *mp += 1; X else { X *mp = 0; X *yp += 1; X } X } X} X X/* X * prevDay(d,m,y) : Decrement d,m,y to the previous day X */ Xvoid XprevDay(dp,mp,yp) Xint *dp,*mp,*yp; X{ X if (*dp != 1) X *dp -= 1; X else { X if (*mp != 0) X *mp -= 1; X else { X *yp -= 1; X *mp = 0; X } X *dp = lastDay(*mp,*yp); X } X} X X/* - - - - - - - - */ X/* X * getCurrentDate() : What else? X */ Xvoid XgetCurrentDate(dp,mp,yp) Xint *dp,*mp,*yp; X{ X struct timeval t; X struct timezone tz; X struct tm *r; X X gettimeofday(&t,&tz); X r = localtime(&(t.tv_sec)); X *dp = r->tm_mday; X *mp = r->tm_mon; X *yp = r->tm_year; X} X X/* - - - - - - - - */ X/* X * parseDate(text,dp,mp,yp) : Parse the string text into a date which is X * either an absolute or a relative date as follows: X * X * rel date = [+-]{<num>[dmy]}* X * abs date = [<day><mon><year>]* where <day> = <num> less than 32 X * <mon> = <string> X * <year>= <num> greater than 32 X * The variables pointed to by dp,mp,yp are filled in with the new date. X * Whitespace is skipped. X * Returns -1 if the date was garbled, else 0. X */ Xint XparseDate(text,dp,mp,yp) Xchar *text; Xint *dp,*mp,*yp; X{ X int day,mon,year,last,num,sign,i; X X day = mon = year = 0; X last = lastDay(*mp,*yp); X if (*text == '+' || *text == '-') { /* relative date */ X sign = *text++; /* save sign */ X while (*text) { /* parse string... */ X while (isspace(*text)) /* skip white space */ X text += 1; X num = 0; X while (*text >= '0' && *text <= '9') { /* get a number */ X num = num * 10 + *text - '0'; X text += 1; X } X switch(*text) { /* and a specifier */ X case '\0': /* no specifier => days */ X case 'D' : X case 'd' : day = num; X break; X case 'M' : X case 'm' : mon = num; X break; X case 'Y' : X case 'y' : year = num; X break; X default: return(-1); X } X if (*text != '\0') /* continue unless at end */ X text += 1; X } X if (sign == '+') { /* now set the `current' date */ X *dp += day; X if (*dp > last) { X *dp -= last; X *mp += 1; X } X *mp += mon; X if (*mp > 11) { X *mp -= 12; X *yp += 1; X } X *yp += year; X } else { X *yp -= year; X *mp -= mon; X if (*mp < 0) { X *mp += 12; X *yp -= 1; X } X *dp -= day; X if (*dp < 1) { X *mp -= 1; X if (*mp < 0) { X *mp = 11; X *yp -= 1; X } X *dp += last; X } X } X } else { /* absolute date */ X while (*text) { X while (isspace(*text)) /* skip white space */ X text += 1; X num = 0; X while (*text >= '0' && *text <= '9') { /* try a number */ X num = num * 10 + *text - '0'; X text += 1; X } X if (num == 0) { /* no number try a month */ X if (islower(*text)) X *text = toupper(*text); X for (i=0; i < 12 && strcmp(text,shortMonStr[i]) != 0; i++) ; X if (i == 12) { X return(-1); X } else { X *mp = i; X text += 3; X } X } else if (num < 32) /* number was either day or year */ X *dp = num; X else if (num >= 1900) X *yp = num - 1900; X else *yp = num; X } X } X return(0); X} END_OF_FILE if test 4574 -ne `wc -c <'util.c'`; then echo shar: \"'util.c'\" unpacked with wrong size! fi # end of 'util.c' fi if test -f 'xkal.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xkal.c'\" else echo shar: Extracting \"'xkal.c'\" \(12988 characters\) sed "s/^X//" >'xkal.c' <<'END_OF_FILE' X/* X * xkal.c : graphical appoinment tool X * X * George Ferguson, ferguson@cs.rochester.edu, 27 Oct 1990. X * X * $Id: xkal.c,v 1.10 90/11/12 13:14:52 ferguson Exp $ X * X */ Xstatic char *rcsid = "$Id: xkal.c,v 1.10 90/11/12 13:14:52 ferguson Exp $"; X#include <stdio.h> X#include <ctype.h> X#include <X11/Intrinsic.h> X#include <X11/StringDefs.h> X#include <X11/Xmu/Drawing.h> X#include <X11/Xaw/Form.h> X#include <X11/Xaw/MenuButton.h> X#include <X11/Xaw/Cardinals.h> X#include "EzMenu.h" X#include "app-resources.h" X#include "resources.h" X#include "month.h" X#include "day.h" X#include "schedule.h" X#include "db.h" X#include "util.h" X#include "date-strings.h" X X/* - - - - - - - - */ X/* X * Functions defined in this file: X */ Xint main(); Xint countAppoints(); X Xstatic void initGraphics(), initGCs(), initWidgets(); Xstatic void createMonthFormDatas(), setMonths(); Xstatic void quit(), quit_nosave(), next(), prev(), today(), setNumMonths(); Xstatic void save(), editSchedule(); Xstatic void syntax(),listAppoints(); Xstatic Pixmap readBitmap(); X X/* X * Global graphics data X */ XDisplay *display; XScreen *screen; XWindow root; XGC dateGC1,dateGC3,dateGC12,emptyGC,shadeGC[23]; X X/* X * Global widget data X */ XXtAppContext app_con; XWidget toplevel; XWidget bothForm,allForm; XAppResources appResources; XMonthFormData *monthFormData1,*monthFormData3[3],*monthFormData12[12]; X X/* X * Other global data X */ Xchar *program; Xint currentDay,currentMon,currentYear; /* today */ Xint mainDay,mainMon,mainYear; /* display */ Xint appointsChanged = False; Xint numMonths; X X/* X * Action binding table X */ Xstatic XtActionsRec cmdActionsTable[] = { X { "xkal-quit", quit }, X { "xkal-exit", quit_nosave }, X { "xkal-save", save }, X { "xkal-next", next }, X { "xkal-prev", prev }, X { "xkal-today", today }, X { "xkal-numMonths", setNumMonths }, X { "xkal-edit-schedule", editSchedule }, X}; X X/* X * Widget and non-widget resources if the application defaults X * file can't be found. X * [ Generated automatically from Xkal.ad. ] X */ Xstatic String fallbackResources[] = { X#include "Xkal.ad.h" X NULL X}; X X/* - - - - - - - - */ X Xint Xmain(argc, argv) Xint argc; Xchar **argv; X{ X program = *argv; X initGraphics(&argc,argv); X initDb(); X getCurrentDate(¤tDay,¤tMon,¤tYear); X readAppoints(appResources.appoints); X if (appResources.date != NULL && *(appResources.date) != '\0') X parseDate(appResources.date,¤tDay,¤tMon,¤tYear); X if (appResources.silent) { X XtDestroyApplicationContext(app_con); X exit(countAppoints(currentDay,currentMon,currentYear)); X } X if (appResources.listOnly) { X listAppoints(currentDay,currentMon,currentYear); X XtDestroyApplicationContext(app_con); X exit(countAppoints(currentDay,currentMon,currentYear)); X } X mainDay = currentDay; X mainMon = currentMon; X mainYear = currentYear; X numMonths = appResources.numMonths; X initGCs(); X initWidgets(); X XtRealizeWidget(toplevel); X if (currentDayFormData != NULL) { X switch (numMonths) { X case 1: selectDay(monthFormData1,mainDay,mainMon,mainYear); X break; X case 3: selectDay(monthFormData3[1],mainDay,mainMon,mainYear); X break; X case 12: selectDay(monthFormData12[mainMon],mainDay,mainMon, X mainYear); X break; X } X } X XtAppMainLoop(app_con); X} X Xstatic void XinitGraphics(argcp,argv) Xint *argcp; Xchar **argv; X{ X char *rev,*strchr(); X X toplevel = XtAppInitialize(&app_con, "Xkal", X options, XtNumber(options), X argcp,argv,fallbackResources,NULL,ZERO); X if (*argcp > 1) { X syntax(*argcp,argv); X XtDestroyApplicationContext(app_con); X exit(-1); X } X XtGetApplicationResources(toplevel,(XtPointer)&appResources, X resources,XtNumber(resources),NULL,ZERO); X rev = strchr(fallbackResources[0],'$'); X if (strcmp(appResources.revision,rev) != 0) { X fprintf(stderr,"%s: app-defaults release not %s\n",program,rev); X fprintf(stderr,"%s: you may have an outdated app-defaults file\n", X program); X } X XtAppAddActions(app_con,cmdActionsTable,XtNumber(cmdActionsTable)); X display = XtDisplay(toplevel); X screen = XtScreen(toplevel); X root = RootWindowOfScreen(screen); X} X Xstatic void XinitGCs() X{ X XGCValues values; X XtGCMask mask; X int i; X X values.foreground = (unsigned long)1; X values.background = (unsigned long)0; X values.function = GXset; X mask = GCForeground | GCBackground | GCFunction | GCFont; X values.font = appResources.dateFont1; X dateGC1 = XCreateGC(display,root,mask,&values); X values.font = appResources.dateFont3; X dateGC3 = XCreateGC(display,root,mask,&values); X values.font = appResources.dateFont12; X dateGC12 = XCreateGC(display,root,mask,&values); X values.function = GXcopy; X values.fill_style = FillTiled; X values.tile = readBitmap(appResources.noDayShade); X mask = GCForeground | GCBackground | GCFunction | GCFillStyle | GCTile; X emptyGC = XCreateGC(display,root,mask,&values); X values.function = GXcopy; X mask = GCFunction; X shadeGC[0] = XCreateGC(display,root,mask,&values); X for (i=1; i < 23; i++) { X if (DefaultDepthOfScreen(screen) > 1) { /* COLOR */ X values.foreground = appResources.color[i]; X values.fill_style = FillSolid; X values.function = GXcopy; X mask = GCForeground | GCBackground | GCFunction; X } else { /* B&W */ X values.foreground = (unsigned long)1; X values.background = (unsigned long)0; X values.tile = readBitmap(appResources.shade[i]); X values.fill_style = FillTiled; X values.function = GXcopy; X mask = GCForeground | GCBackground | GCTile | GCFillStyle | X GCFunction; X } X shadeGC[i] = XCreateGC(display,root,mask,&values); X } X} X Xstatic void XinitWidgets() X{ X char *s,name[256]; X int i; X X bothForm = XtCreateManagedWidget("bothForm",formWidgetClass,toplevel, X NULL,ZERO); X XtCreateManagedWidget("fileButton",menuButtonWidgetClass,bothForm, X NULL,ZERO); X XtCreatePopupShell("fileMenu",ezMenuWidgetClass,bothForm,NULL,ZERO); X XtCreateManagedWidget("viewButton",menuButtonWidgetClass,bothForm, X NULL,ZERO); X XtCreatePopupShell("viewMenu",ezMenuWidgetClass,bothForm,NULL,ZERO); X XtCreateManagedWidget("otherButton",menuButtonWidgetClass,bothForm, X NULL,ZERO); X XtCreatePopupShell("otherMenu",ezMenuWidgetClass,bothForm,NULL,ZERO); X allForm = XtCreateManagedWidget("allMonthsForm",formWidgetClass,bothForm, X NULL,ZERO); X createMonthFormDatas(numMonths); X if (appResources.bothShown) X currentDayFormData = createDayFormData(bothForm); X setMonths(); X} X Xstatic void XcreateMonthFormDatas(n) Xint n; X{ X char *name = "monthFormXX_XX"; X int i; X X switch (n) { X case 1: monthFormData1 = createMonthFormData(allForm,"monthForm1",1); X XtManageChild(monthFormData1->form); X break; X case 3: for (i=0; i < 3; i++) { X sprintf(name,"monthForm3_%d",i+1); X monthFormData3[i] = createMonthFormData(allForm,name,3); X XtManageChild(monthFormData3[i]->form); X } X break; X case 12: for (i=0; i < 12; i++) { X sprintf(name,"monthForm12_%d",i+1); X monthFormData12[i] = createMonthFormData(allForm,name,12); X XtManageChild(monthFormData12[i]->form); X } X break; X } X} X Xstatic void XsetMonths() X{ X Arg args[2]; X int i,prevMon,prevYear,nextMon,nextYear; X X XawFormDoLayout(allForm,False); X switch (numMonths) { X case 1: setMonthFormData(monthFormData1,1,mainMon,mainYear); X break; X case 3: prevMon = mainMon - 1; X nextMon = mainMon + 1; X prevYear = nextYear = mainYear; X if (mainMon == 0) { X prevMon = 11; X prevYear = mainYear - 1; X } else if (mainMon == 11) { X nextMon = 0; X nextYear = mainYear + 1; X } X setMonthFormData(monthFormData3[0],3,prevMon,prevYear); X setMonthFormData(monthFormData3[1],3,mainMon,mainYear); X setMonthFormData(monthFormData3[2],3,nextMon,nextYear); X break; X case 12: for (i=0; i < 12; i++) X setMonthFormData(monthFormData12[i],12,i,mainYear); X break; X } X XawFormDoLayout(allForm,True); X} X X/* - - - - - - - - */ X X#define ACTION_PROC(NAME) static void NAME(w,event,params,num_params) \ X Widget w; \ X XEvent *event; \ X String *params; \ X Cardinal *num_params; X XACTION_PROC(quit) X{ X if (currentDayFormData != NULL) X checkpointAppoints(currentDayFormData); X if (appointsChanged) X writeAppoints(appResources.appoints); X XtDestroyApplicationContext(app_con); X exit(0); X} X XACTION_PROC(quit_nosave) X{ X XtDestroyApplicationContext(app_con); X exit(0); X} X XACTION_PROC(next) X{ X if (numMonths == 1 || numMonths == 3) { X if (mainMon == 11) { X mainMon = 0; X mainYear += 1; X } else { X mainMon += 1; X } X } else { X mainYear += 1; X } X setMonths(); X} X XACTION_PROC(prev) X{ X if (numMonths == 1 || numMonths == 3) { X if (mainMon == 0) { X mainMon = 11; X mainYear -= 1; X } else { X mainMon -= 1; X } X } else { X mainYear -= 1; X } X setMonths(); X} X XACTION_PROC(today) X{ X mainDay = currentDay; X mainMon = currentMon; X mainYear = currentYear; X setMonths(); X switch (numMonths) { X case 1: selectDay(monthFormData1,mainDay,mainMon,mainYear); X break; X case 3: selectDay(monthFormData3[1],mainDay,mainMon,mainYear); X break; X case 12: selectDay(monthFormData12[mainMon],mainDay,mainMon,mainYear); X break; X } X} X XACTION_PROC(setNumMonths) X{ X int n,i; X X if (*num_params != ONE) { X fprintf(stderr,"%s: bad parms to xkal-numMonths()\n",program); X return; X } X if ((n=atoi(params[0])) == numMonths) X return; X XawFormDoLayout(bothForm,False); X switch (numMonths) { X case 1: XtUnmanageChild(monthFormData1->form); X break; X case 3: for (i=0; i < 3; i++) X XtUnmanageChild(monthFormData3[i]->form); X break; X case 12: for (i=0; i < 12; i++) X XtUnmanageChild(monthFormData12[i]->form); X break; X } X numMonths = n; X switch (numMonths) { X case 1: if (monthFormData1 == NULL) X createMonthFormDatas(1); X setMonths(); X XtManageChild(monthFormData1->form); X break; X case 3: if (monthFormData3[0] == NULL) X createMonthFormDatas(3); X setMonths(); X for (i=0; i < 3; i++) X XtManageChild(monthFormData3[i]->form); X break; X case 12: if (monthFormData12[0] == NULL) X createMonthFormDatas(12); X setMonths(); X for (i=0; i < 12; i++) X XtManageChild(monthFormData12[i]->form); X break; X } X XawFormDoLayout(bothForm,True); X} X XACTION_PROC(save) X{ X if (currentDayFormData != NULL) X checkpointAppoints(currentDayFormData); X if (appointsChanged) X writeAppoints(appResources.appoints); X appointsChanged = False; X} X XACTION_PROC(editSchedule) X{ X createPopupSchedule(); X} X X/* - - - - - - - - */ X Xstatic void XlistAppoints(day,mon,year) Xint day,mon,year; X{ X int i,dow; X char *s; X X dow = computeDOW(day,mon,year); X printf("%s %d %s %d\n",shortDayStr[dow],day,shortMonStr[mon],year+1900); X for (i=0; i < 20; i++) { X if ((s=lookup(i,day,mon,year)) != NULL) X if (i % 2 == 0) X printf("\t%2d:00 %s\n",8+(i / 2),s); X else X printf("\t%2d:30 %s\n",8+((i-1)/2),s); X } X for (i=20; i < 22; i++) { X if ((s=lookup(i,day,mon,year)) != NULL) X printf("\tNOTES %s\n",s); X } X} X Xint XcountAppoints(day,mon,year) Xint day,mon,year; X{ X int i,n; X X n = 0; X for (i=0; i < 22; i++) { X if (lookupAppoint(i,day,mon,year) != NULL) X n += 1; X } X return(n); X} X X/* - - - - - - - - */ X Xstatic Pixmap XreadBitmap(name) Xchar *name; X{ X Pixmap b; X int w,h,xhot,yhot; X X b = XmuLocateBitmapFile(screen,name,NULL,ZERO,&w,&h,&xhot,&yhot); X if (b == NULL) { X fprintf(stderr,"%s: couldn't find bitmap \"%s\"\n",program,name); X return(XCreatePixmap(display,screen,2,2,DefaultDepthOfScreen(screen))); X } else X return(XmuCreatePixmapFromBitmap(display,root,b,w,h, X DefaultDepthOfScreen(screen),1,0)); X} X X/* - - - - - - - - */ X/* X * syntax() : print the usage message X */ Xstatic void Xsyntax(argc,argv) Xint argc; Xchar **argv; X{ X argv += 1; X if (argc > 2 || (strcmp(*argv,"-help") != 0 && strcmp(*argv,"-?") != 0)) { X fprintf(stderr,"%s: bad argument(s): ",program); X while (--argc) X fprintf(stderr,"%s ",*argv++); X fprintf(stderr,"\n"); X } X fprintf(stderr,"usage: %s",program); X fprintf(stderr,"\t-appoints file\tuse file for appointments\n"); X fprintf(stderr,"\t\t-date date\tuse given date for `today'\n"); X fprintf(stderr,"\t\t-numMonths 1|3|12\tstart displaying 1, 3 or 12 months\n"); X fprintf(stderr,"\t\t-bothShown\tput day display next to month(s)\n"); X fprintf(stderr,"\t\t-nobothShown\tpopup days as needed\n"); X fprintf(stderr,"\t\t-listOnly\tprint appoints to stdout\n"); X fprintf(stderr,"\t\t\t-silent\texit with status == number of appoints\n"); X fprintf(stderr,"\t\t-opaqueDates\tprint day numbers opaquely\n"); X fprintf(stderr,"\t\t-noopaqueDates\tprint day numbers transparently\n"); X fprintf(stderr,"\t\t-dowLabels\tprint day of week at top of columns\n"); X fprintf(stderr,"\t\t-nodowLabels\tdon't print dow at top of columns\n"); X} END_OF_FILE if test 12988 -ne `wc -c <'xkal.c'`; then echo shar: \"'xkal.c'\" unpacked with wrong size! fi # end of 'xkal.c' fi echo shar: End of archive 4 \(of 4\). cp /dev/null ark4isdone MISSING="" for I in 1 2 3 4 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 4 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 VOX: (716) 275-2527