Xkal - X appointment calendar, Part04/04
George Ferguson
ferguson at cs.rochester.edu
Thu Nov 15 08:30:13 AEST 1990
#! /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 at 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 at 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 at 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 at 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 at cs.rochester.edu
University of Rochester UUCP: {decvax,rutgers}!rochester!ferguson
Rochester NY 14627 VOX: (716) 275-2527
More information about the Alt.sources
mailing list