home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3066 / xkal.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-03-15  |  22.1 KB  |  855 lines

  1. /*
  2.  *    xkal.c : graphical appointment tool
  3.  *
  4.  *    George Ferguson, ferguson@cs.rochester.edu,  27 Oct 1990.
  5.  *    Version 1.1 - 27 Feb 1991.
  6.  *
  7.  *    $Id: xkal.c,v 2.2 91/02/28 11:23:24 ferguson Exp $
  8.  *
  9.  */
  10. #ifndef lint
  11. static char ident[] = "@(#) xkal version 1.1 - ferguson@cs.rochester.edu";
  12. #endif
  13. #include <stdio.h>
  14. #include <ctype.h>
  15. #include <X11/Intrinsic.h>
  16. #include <X11/StringDefs.h>
  17. #include <X11/Xmu/Drawing.h>
  18. #include <X11/Xaw/Form.h>
  19. #include <X11/Xaw/MenuButton.h>
  20. #include <X11/Xaw/Cardinals.h>    
  21. #include "EzMenu.h"
  22. #include "app-resources.h"
  23. #include "resources.h"
  24. #include "month.h"
  25. #include "day.h"
  26. #include "edit.h"
  27. #include "edit-defaults.h"
  28. #include "db.h"
  29. #include "util.h"
  30. #include "date-strings.h"
  31. #include "patchlevel.h"
  32. #ifdef USE_ALERT
  33. #include "alert.h"
  34. #endif
  35.  
  36. /*    -    -    -    -    -    -    -    -    */
  37. /*
  38.  * Functions defined in this file:
  39.  */
  40. int main();
  41. void quit(),quit_nosave(),save(),next(),prev(),today(),setNumMonths();
  42. void focusThisItem(), focusNoItem(), focusNextItem(), focusPrevItem();
  43. void escapeToSystem();
  44. void timeoutProc();
  45.  
  46. static void initGraphics(), initGCs(), initWidgets(), createMonthFormDatas();
  47. static void setMonths(), selectCurrentDay();
  48. static void listAppoints(), checkAndSaveAppoints();
  49. static int countAppoints();
  50. static void cvtStringToPixels(), cvtStringToPixmaps(), syntax();
  51. static Pixmap readBitmap();
  52.  
  53. /*
  54.  * Global graphics data
  55.  */
  56. Display *display;
  57. Screen *screen;
  58. Window root;
  59. GC dateGC1,dateGC2,dateGC3,dateGC12,emptyGC,*shadeGC;
  60.  
  61. /*
  62.  * Global widget data
  63.  */
  64. XtAppContext app_con;
  65. Widget toplevel;
  66. Widget bothForm,allForm;
  67. AppResources appResources;
  68. MonthFormData *monthFormData1,*monthFormData2[2];
  69. MonthFormData *monthFormData3[3],*monthFormData12[12];
  70.  
  71. /*
  72.  * Other global data
  73.  */
  74. char *program;
  75. int currentDay,currentMon,currentYear;        /* today */
  76. int mainDay,mainMon,mainYear;            /* display */
  77. int appointsChanged = False;            /* need to save? */
  78. XtIntervalId timeoutId;                /* auto update */
  79.  
  80. /*
  81.  * Action binding table
  82.  */
  83. static XtActionsRec cmdActionsTable[] = {
  84.     { "xkal-quit", quit },
  85.     { "xkal-exit", quit_nosave },
  86.     { "xkal-save", save },
  87.     { "xkal-next", next },
  88.     { "xkal-prev", prev },
  89.     { "xkal-today", today },
  90.     { "xkal-numMonths", setNumMonths },
  91.     { "xkal-system", escapeToSystem },
  92.     { "xkal-focus-this-item", focusThisItem },
  93.     { "xkal-focus-no-item", focusNoItem },
  94.     { "xkal-focus-next-item", focusNextItem },
  95.     { "xkal-focus-prev-item", focusPrevItem },
  96.     { "xkal-edit-appoint", editAppoint },
  97.     { "xkal-focus-next-edit-item", focusNextEditItem },
  98.     { "xkal-focus-prev-edit-item", focusPrevEditItem },
  99.     { "xkal-edit-defaults", editDefaults },
  100.     { "xkal-focus-next-defaults-item", focusNextDefaultsItem },
  101.     { "xkal-focus-prev-defaults-item", focusPrevDefaultsItem },
  102. };
  103.  
  104. /*
  105.  *    Widget and non-widget resources if the application defaults
  106.  *    file can't be found.
  107.  *    [ Generated automatically from Xkal.ad. ]
  108.  */
  109. static String fallbackResources[] = {
  110. #include "Xkal.ad.h"
  111.     NULL
  112. };
  113.  
  114. #define ACTION_PROC(NAME)    void NAME(w,event,params,num_params) \
  115.                     Widget w; \
  116.                     XEvent *event; \
  117.                     String *params; \
  118.                     Cardinal *num_params;
  119.  
  120. /*    -    -    -    -    -    -    -    -    */
  121.  
  122. int
  123. main(argc,argv)
  124. int argc;
  125. char **argv;
  126. {
  127.     int i;
  128.  
  129.     program = *argv;
  130.     for (i=1; i < argc; i++)        /* quick check for non-interactive */
  131.     if (strncmp(argv[i],"-l",2) == 0 || strncmp(argv[i],"-s",2) == 0 ||
  132.                         strncmp(argv[i],"-v",2) == 0)
  133.         break;
  134.     if (i != argc)
  135.     getResources(&argc,argv);    /* found, so don't need display */
  136.     else
  137.     initGraphics(&argc,argv);    /* not found, so interactive mode */
  138.     if (argc > 1) {
  139.     syntax(argc,argv);
  140.     XtDestroyApplicationContext(app_con);
  141.     exit(-1);
  142.     }
  143.     initDb();
  144.     initDateStrings();
  145.     getCurrentDate(¤tDay,¤tMon,¤tYear);
  146.     if (appResources.systemAppoints && *appResources.systemAppoints)
  147.     readDb(appResources.systemAppoints,True);
  148.     if (appResources.personalAppoints && *appResources.personalAppoints)
  149.     readDb(appResources.personalAppoints,False);
  150.     if (appResources.date != NULL && *(appResources.date) != '\0') {
  151.     parseDate(appResources.date,¤tDay,¤tMon,¤tYear);
  152.     if (currentYear < 1901) {
  153.         fprintf(stderr,"%s: invalid year (too early): %d\n",program,
  154.                                 currentYear);
  155.         XtDestroyApplicationContext(app_con);
  156.         exit(-1);
  157.     }
  158.     }
  159.     if (appResources.version) {
  160.     printf("xkal %.2f - George Ferguson (ferguson@cs.rochester.edu)\n",
  161.                                 XKAL_VERSION);
  162.     exit(0);
  163.     }
  164.     if (appResources.listOnly) {
  165.     listAppoints(currentDay,currentMon,currentYear);
  166.     }
  167.     if (appResources.listOnly || appResources.silent) {
  168.     exit(countAppoints(currentDay,currentMon,currentYear,
  169.                          appResources.exitUsesLevels));
  170.     }
  171.     mainDay = currentDay;
  172.     mainMon = currentMon;
  173.     mainYear = currentYear;
  174.     initGCs();
  175.     initWidgets();
  176.     XtRealizeWidget(toplevel);
  177.     if (currentDayFormData != NULL)
  178.     selectCurrentDay();
  179.     if (appResources.checkpointInterval > 0)
  180.     timeoutId = XtAppAddTimeOut(app_con,
  181.             (unsigned long)(appResources.checkpointInterval*60000),
  182.             timeoutProc,NULL);
  183.     XtAppMainLoop(app_con);
  184. }
  185.  
  186. /*    -    -    -    -    -    -    -    -    */
  187. /* Initialization routines */
  188.  
  189. /*
  190.  * initGraphics() : Initialze X connection and toplevel widget.
  191.  */
  192. static void
  193. initGraphics(argcp,argv)
  194. int *argcp;
  195. char **argv;
  196. {
  197.     char *rev,*strchr();
  198.  
  199.     toplevel = XtAppInitialize(&app_con, "Xkal",
  200.                    xkalOptions, XtNumber(xkalOptions),
  201.                    argcp,argv,fallbackResources,NULL,ZERO);
  202.     XtGetApplicationResources(toplevel,(XtPointer)&appResources,
  203.                               xkalResources,XtNumber(xkalResources),NULL,ZERO);
  204.     rev = strchr(fallbackResources[0],'$');
  205.     if (rev && strcmp(appResources.revision,rev) != 0) {
  206.     fprintf(stderr,"%s: app-defaults release not %s\n",program,rev);
  207.     fprintf(stderr,"%s: you may have an outdated app-defaults file\n",
  208.                                 program);
  209.     }
  210.     XtAppAddActions(app_con,cmdActionsTable,XtNumber(cmdActionsTable));
  211.     display = XtDisplay(toplevel);
  212.     screen = XtScreen(toplevel);
  213.     root = RootWindowOfScreen(screen);
  214. }
  215.  
  216. /*
  217.  * initGCs() : Initialize GC's for drawing operations.
  218.  */
  219. static void
  220. initGCs()
  221. {
  222.     XGCValues values;
  223.     XtGCMask mask;
  224.     Pixel *pixels;
  225.     Pixmap *pixmaps;
  226.     int i;
  227.  
  228.     /*
  229.      * initialize date GC's
  230.      */
  231.     values.foreground = (unsigned long)1;
  232.     values.background = (unsigned long)0;
  233.     values.function = GXset;
  234.     mask = GCForeground | GCBackground | GCFunction | GCFont;
  235.     values.font = appResources.dateFont1;
  236.     dateGC1 = XCreateGC(display,root,mask,&values);
  237.     values.font = appResources.dateFont2;
  238.     dateGC2 = XCreateGC(display,root,mask,&values);
  239.     values.font = appResources.dateFont3;
  240.     dateGC3 = XCreateGC(display,root,mask,&values);
  241.     values.font = appResources.dateFont12;
  242.     dateGC12 = XCreateGC(display,root,mask,&values);
  243.     /*
  244.      * initialize empty GC
  245.      */
  246.     values.function = GXcopy;
  247.     values.fill_style = FillTiled;
  248.     values.tile = readBitmap(appResources.noDayShade);
  249.     mask = GCForeground | GCBackground | GCFunction | GCFillStyle | GCTile;
  250.     emptyGC = XCreateGC(display,root,mask,&values);
  251.     /*
  252.      * initialize shading GC's
  253.      */
  254.     values.function = GXcopy;
  255.     mask = GCFunction;
  256.     shadeGC = (GC *)XtCalloc(appResources.maxLevel+1,sizeof(GC));
  257.     shadeGC[0] = XCreateGC(display,root,mask,&values);
  258.     if (DefaultDepthOfScreen(screen) > 1) {    /* COLOR */
  259.     pixels = (Pixel *)XtCalloc(appResources.maxLevel,sizeof(Pixel));
  260.     cvtStringToPixels(appResources.colors,appResources.maxLevel,pixels);
  261.     for (i=1; i <= appResources.maxLevel; i++) {
  262.         values.foreground = pixels[i-1];
  263.         values.fill_style = FillSolid;
  264.         values.function = GXcopy;
  265.         mask = GCForeground | GCBackground | GCFunction;
  266.         shadeGC[i] = XCreateGC(display,root,mask,&values);
  267.     }
  268.     XtFree(pixels);
  269.     } else {                    /* B&W */
  270.     pixmaps = (Pixmap *)XtCalloc(appResources.maxLevel,sizeof(Pixmap));
  271.     cvtStringToPixmaps(appResources.shades,appResources.maxLevel,pixmaps);
  272.     for (i=1; i <= appResources.maxLevel; i++) {
  273.         values.background = (unsigned long)0;
  274.         values.tile = pixmaps[i-1];
  275.         values.fill_style = FillTiled;
  276.         values.function = GXcopy;
  277.         mask = GCForeground | GCBackground | GCTile | GCFillStyle |
  278.                                 GCFunction;
  279.         shadeGC[i] = XCreateGC(display,root,mask,&values);
  280.     }
  281.     XtFree(pixmaps);
  282.     }
  283. }
  284.  
  285. /*
  286.  * initWidgets() : Create necessary widgets and menus (ie. those that
  287.  *    aren't created on the fly).
  288.  */
  289. static void
  290. initWidgets()
  291. {
  292.     bothForm = XtCreateManagedWidget("bothForm",formWidgetClass,toplevel,
  293.                                 NULL,ZERO);
  294.     XtCreateManagedWidget("fileButton",menuButtonWidgetClass,bothForm,
  295.                                 NULL,ZERO);
  296.     XtCreatePopupShell("fileMenu",ezMenuWidgetClass,bothForm,NULL,ZERO);
  297.     XtCreateManagedWidget("viewButton",menuButtonWidgetClass,bothForm,
  298.                                 NULL,ZERO);
  299.     XtCreatePopupShell("viewMenu",ezMenuWidgetClass,bothForm,NULL,ZERO);
  300.     XtCreateManagedWidget("otherButton",menuButtonWidgetClass,bothForm,
  301.                                 NULL,ZERO);
  302.     XtCreatePopupShell("otherMenu",ezMenuWidgetClass,bothForm,NULL,ZERO);
  303.     allForm = XtCreateManagedWidget("allMonthsForm",formWidgetClass,bothForm,
  304.                                 NULL,ZERO);
  305.     createMonthFormDatas(appResources.numMonths);
  306.     if (appResources.bothShown)
  307.     currentDayFormData = createDayFormData(bothForm);
  308.     setMonths();
  309. }
  310.  
  311. /*
  312.  * createMonthFormDatas(n) : Create n monthForms as children of the
  313.  *    allForm widget.
  314.  */
  315. static void
  316. createMonthFormDatas(n)
  317. int n;
  318. {
  319.     char *name = "monthFormXX_XX";
  320.     int i;
  321.  
  322.     switch (n) {
  323.     case 1: monthFormData1 = createMonthFormData(allForm,"monthForm1",1);
  324.         XtManageChild(monthFormData1->form);
  325.         break;
  326.     case 2: for (i=0; i < 2; i++) {
  327.             sprintf(name,"monthForm2_%d",i+1);
  328.             monthFormData2[i] = createMonthFormData(allForm,name,2);
  329.             XtManageChild(monthFormData2[i]->form);
  330.         }
  331.         break;
  332.     case 3: for (i=0; i < 3; i++) {
  333.             sprintf(name,"monthForm3_%d",i+1);
  334.             monthFormData3[i] = createMonthFormData(allForm,name,3);
  335.             XtManageChild(monthFormData3[i]->form);
  336.         }
  337.         break;
  338.     case 12: for (i=0; i < 12; i++) {
  339.             sprintf(name,"monthForm12_%d",i+1);
  340.             monthFormData12[i] = createMonthFormData(allForm,name,12);
  341.             XtManageChild(monthFormData12[i]->form);
  342.         }
  343.         break;
  344.     }
  345. }
  346.  
  347. /*
  348.  * setMonths() : Redraw the months.
  349.  */
  350. static void
  351. setMonths()
  352. {
  353.     int i,prevMon,prevYear,nextMon,nextYear;
  354.  
  355.     XawFormDoLayout(allForm,False);
  356.     switch (appResources.numMonths) {
  357.     case 1:  setMonthFormData(monthFormData1,1,mainMon,mainYear);
  358.          break;
  359.     case 2:     if (mainMon == 12) {
  360.              nextMon = 1;
  361.              nextYear = mainYear+1;
  362.          } else {
  363.              nextMon = mainMon+1;
  364.              nextYear = mainYear;
  365.          }
  366.          setMonthFormData(monthFormData2[0],2,mainMon,mainYear);
  367.          setMonthFormData(monthFormData2[1],2,nextMon,nextYear);
  368.          break;
  369.     case 3:  prevMon = mainMon - 1;
  370.          nextMon = mainMon + 1;
  371.          prevYear = nextYear = mainYear;
  372.          if (mainMon == 1) {
  373.              prevMon = 12;
  374.              prevYear = mainYear - 1;
  375.          } else if (mainMon == 12) {
  376.              nextMon = 1;
  377.              nextYear = mainYear + 1;
  378.          }
  379.          setMonthFormData(monthFormData3[0],3,prevMon,prevYear);
  380.          setMonthFormData(monthFormData3[1],3,mainMon,mainYear);
  381.          setMonthFormData(monthFormData3[2],3,nextMon,nextYear);
  382.          break;
  383.     case 12: for (i=0; i < 12; i++)
  384.              setMonthFormData(monthFormData12[i],12,i+1,mainYear);
  385.          break;
  386.     }
  387.     XawFormDoLayout(allForm,True);
  388. }
  389.  
  390. /*
  391.  * selectCurrentDay() : Higlight current day after figuring out which
  392.  *    form its in.
  393.  */
  394. static void
  395. selectCurrentDay()
  396. {
  397.     switch (appResources.numMonths) {
  398.     case 1: selectDay(monthFormData1,mainDay,mainMon,mainYear);
  399.         break;
  400.     case 2: selectDay(monthFormData2[0],mainDay,mainMon,mainYear);
  401.         break;
  402.     case 3: selectDay(monthFormData3[1],mainDay,mainMon,mainYear);
  403.         break;
  404.     case 12: selectDay(monthFormData12[mainMon-1],mainDay,mainMon,mainYear);
  405.          break;
  406.     }
  407. }
  408.  
  409. /*    -    -    -    -    -    -    -    -    */
  410.  
  411. /*
  412.  * quit() : Save appoints if changed, then quit.
  413.  */
  414. /*ARGSUSED*/
  415. ACTION_PROC(quit)
  416. {
  417.     checkAndSaveAppoints(False);
  418.     XtDestroyApplicationContext(app_con);
  419.     exit(0);
  420. }
  421.  
  422. /*
  423.  * quit_nosave() : Quit without saving.
  424.  */
  425. /*ARGSUSED*/
  426. ACTION_PROC(quit_nosave)
  427. {
  428.     XtDestroyApplicationContext(app_con);
  429.     exit(0);
  430. }
  431.  
  432. /*
  433.  * next() : Display next month.
  434.  */
  435. /*ARGSUSED*/
  436. ACTION_PROC(next)
  437. {
  438.     if (appResources.numMonths < 12) {
  439.     if (mainMon == 12) {
  440.         mainMon = 1;
  441.         mainYear += 1;
  442.     } else {
  443.         mainMon += 1;
  444.     }
  445.     } else {
  446.     mainYear += 1;
  447.     }
  448.     setMonths();
  449. }
  450.  
  451. /*
  452.  * prev() : Display previous month.
  453.  */
  454. /*ARGSUSED*/
  455. ACTION_PROC(prev)
  456. {
  457.     if (appResources.numMonths < 12) {
  458.     if (mainMon == 1) {
  459.         mainMon = 12;
  460.         mainYear -= 1;
  461.     } else {
  462.         mainMon -= 1;
  463.     }
  464.     } else {
  465.     mainYear -= 1;
  466.     }
  467.     setMonths();
  468. }
  469.  
  470. /*
  471.  * today() : Highlight today, possibly resetting months. Also, if date
  472.  *    was not given as resource, then get it again in case we've been
  473.  *    runnign for a while.
  474.  */
  475. /*ARGSUSED*/
  476. ACTION_PROC(today)
  477. {
  478.     /* Reset the current date in case we've been running for a long time. */
  479.     if (appResources.date == NULL || *(appResources.date) == '\0')
  480.     getCurrentDate(¤tDay,¤tMon,¤tYear);
  481.     mainDay = currentDay;
  482.     if (mainMon != currentMon || mainYear != currentYear) {
  483.     mainMon = currentMon;
  484.     mainYear = currentYear;
  485.     setMonths();
  486.     }
  487.     selectCurrentDay();
  488. }
  489.  
  490. /*
  491.  * setNumMonths(n) : Change the number of months being displayed, possibly
  492.  *    creating new monthForms. n should be 1, 2, 3, or 12.
  493.  */
  494. /*ARGSUSED*/
  495. ACTION_PROC(setNumMonths)
  496. {
  497.     int n,i;
  498.  
  499.     if (*num_params != ONE) {
  500.     fprintf(stderr,"%s: bad parms to xkal-numMonths()\n",program);
  501.     return;
  502.     }
  503.     n = atoi(params[0]);
  504.     if (n != 1 && n != 2 && n != 3 && n != 12) {
  505.     fprintf(stderr,"%s: bad num for xkal-numMonths(): %d\n",program,n);
  506.     return;
  507.     }
  508.     if (n == appResources.numMonths)
  509.     return;
  510.     XawFormDoLayout(bothForm,False);
  511.     switch (appResources.numMonths) {
  512.     case 1: XtUnmanageChild(monthFormData1->form);
  513.         break;
  514.     case 2: for (i=0; i < 2; i++)
  515.             XtUnmanageChild(monthFormData2[i]->form);
  516.         break;
  517.     case 3: for (i=0; i < 3; i++)
  518.             XtUnmanageChild(monthFormData3[i]->form);
  519.         break;
  520.     case 12: for (i=0; i < 12; i++)
  521.             XtUnmanageChild(monthFormData12[i]->form);
  522.         break;
  523.     }
  524.     appResources.numMonths = n;
  525.     switch (appResources.numMonths) {
  526.     case 1: if (monthFormData1 == NULL)
  527.             createMonthFormDatas(1);
  528.         setMonths();
  529.         XtManageChild(monthFormData1->form);
  530.         break;
  531.     case 2: if (monthFormData2[0] == NULL)
  532.             createMonthFormDatas(2);
  533.         setMonths();
  534.         for (i=0; i < 2; i++)
  535.             XtManageChild(monthFormData2[i]->form);
  536.         break;
  537.     case 3: if (monthFormData3[0] == NULL)
  538.             createMonthFormDatas(3);
  539.         setMonths();
  540.         for (i=0; i < 3; i++)
  541.             XtManageChild(monthFormData3[i]->form);
  542.         break;
  543.     case 12: if (monthFormData12[0] == NULL)
  544.              createMonthFormDatas(12);
  545.          setMonths();
  546.          for (i=0; i < 12; i++)
  547.              XtManageChild(monthFormData12[i]->form);
  548.          break;
  549.     }
  550.     XawFormDoLayout(bothForm,True);
  551. }
  552.  
  553. /*
  554.  * save() : Save appoints regardless of whether they've changed or not.
  555.  */
  556. /*ARGSUSED*/
  557. ACTION_PROC(save)
  558. {
  559.     checkAndSaveAppoints(True);
  560. }
  561.  
  562. /*
  563.  * escapeToSystem(str) : execute "str" by the shell.
  564.  */
  565. /*ARGSUSED*/
  566. ACTION_PROC(escapeToSystem)
  567. {
  568.     if (*num_params != 1) {
  569. #ifdef USE_ALERT
  570.     alert("Error: too many arguments to xkal-system().");
  571. #else
  572.     fprintf(stderr,"\007%s: too many arguments to xkal-system()\n",program);
  573. #endif
  574.     return;
  575.     }
  576.     system(params[0]);
  577. }
  578.  
  579. /*
  580.  * focusThisItem() : Force input focus to this widget.
  581.  */
  582. /*ARGSUSED*/
  583. ACTION_PROC(focusThisItem)
  584. {
  585.     XWindowAttributes attrs;
  586.  
  587.     XGetWindowAttributes(display,XtWindow(w),&attrs);
  588.     if (attrs.map_state != IsViewable)
  589.     return;
  590.     XSetInputFocus(display,XtWindow(w),RevertToParent,CurrentTime);
  591. }
  592.  
  593. /*
  594.  * focusNoItem() : Unset the input focus.
  595.  */
  596. /*ARGSUSED*/
  597. ACTION_PROC(focusNoItem)
  598. {
  599.     XSetInputFocus(display,PointerRoot,RevertToParent,CurrentTime);
  600. }
  601.  
  602. /*
  603.  * focusNextItem() : Switch input focus to next appointment slot, wrapping
  604.  *    at bottom.
  605.  */
  606. /*ARGSUSED*/
  607. ACTION_PROC(focusNextItem)
  608. {
  609.     int i;
  610.  
  611.     for (i=0; i < numDisplayedAppoints; i++)
  612.     if (w == currentDayFormData->items[i]->text)
  613.         break;
  614.     if (i == numDisplayedAppoints)
  615.     return;
  616.     else if (i == numDisplayedAppoints-1)
  617.     i = 0;
  618.     else
  619.     i += 1;
  620.     XSetInputFocus(display,XtWindow(currentDayFormData->items[i]->text),
  621.                         RevertToParent,CurrentTime);
  622. }
  623.  
  624. /*
  625.  * focusPrevItem() : Switch input focus to previous appointment slot, wrapping
  626.  *    at top.
  627.  */
  628. /*ARGSUSED*/
  629. ACTION_PROC(focusPrevItem)
  630. {
  631.     int i;
  632.  
  633.     for (i=0; i < numDisplayedAppoints; i++)
  634.     if (w == currentDayFormData->items[i]->text)
  635.         break;
  636.     if (i == numDisplayedAppoints)
  637.     return;
  638.     else if (i == 0)
  639.     i = numDisplayedAppoints-1;
  640.     else
  641.     i -= 1;
  642.     XSetInputFocus(display,XtWindow(currentDayFormData->items[i]->text),
  643.                         RevertToParent,CurrentTime);
  644. }
  645.  
  646. /*
  647.  * timeoutProc() : Timer callback - saves appoints if they've changed and
  648.  *    resets timer.
  649.  */
  650. /*ARGSUSED*/
  651. void
  652. timeoutProc(data,id)
  653. XtPointer data;
  654. XtIntervalId *id;
  655. {
  656.     checkAndSaveAppoints(False);
  657.     if (appResources.checkpointInterval > 0)
  658.     timeoutId = XtAppAddTimeOut(app_con,
  659.             (unsigned long)(appResources.checkpointInterval*60000),
  660.             timeoutProc,NULL);
  661. }
  662.  
  663. /*    -    -    -    -    -    -    -    -    */
  664. /* Miscellaneous routines */
  665.  
  666. /*
  667.  * listAppoints() : Print all appoints for day to stdout.
  668.  */
  669. static void
  670. listAppoints(day,mon,year)
  671. int day,mon,year;
  672. {
  673.     Msgrec **apps;
  674.     int dow,n,i;
  675.  
  676.     dow = computeDOW(day,mon,year);
  677.     printf("%s %d %s %d\n",shortDowStr[dow-1],day,shortMonthStr[mon-1],year);
  678.     n = lookupEntry(day,mon,year,-1,-1,-1,NULL,False);
  679.     if (n == 0)
  680.     return;
  681.     apps = (Msgrec **)XtCalloc(n,sizeof(Msgrec *));
  682.     (void)lookupEntry(day,mon,year,-1,-1,n,apps,False);
  683.     for (i=0; i < n; i++)
  684.     if (apps[i]->hour == -1)
  685.         printf("\t%s %s\n",appResources.notesLabel,apps[i]->text);
  686.     else if (apps[i]->mins == -1)
  687.         if (apps[i]->hour >= 12)
  688.         printf("\t%2dpm %s\n",apps[i]->hour-12,apps[i]->text);
  689.         else
  690.         printf("\t%2dam %s\n",apps[i]->hour,apps[i]->text);
  691.     else
  692.         printf("\t%2d:%02d %s\n",apps[i]->hour,apps[i]->mins,apps[i]->text);
  693.     XtFree(apps);
  694. }
  695.  
  696. /*
  697.  * countAppoints() : Return number of appoints (flag = False) or criticality
  698.  *    total (flag = True) for day.
  699.  */
  700. static int
  701. countAppoints(day,mon,year,flag)
  702. int day,mon,year;
  703. Boolean flag;
  704. {
  705.     
  706.     return(lookupEntry(day,mon,year,-1,-1,-1,NULL,flag));
  707. }
  708.  
  709. /*
  710.  * checkAndSaveAppoints() : Transfer data from dayForm to DB, then save
  711.  *    appoints if they've changed.
  712.  */
  713. static void
  714. checkAndSaveAppoints(force)
  715. Boolean force;
  716. {
  717.     if (currentDayFormData != NULL)
  718.     checkpointAppoints(currentDayFormData);
  719.     if (force || appointsChanged)
  720.     writeDb(appResources.personalAppoints,False);
  721.     appointsChanged = False;
  722. }
  723.  
  724. /*    -    -    -    -    -    -    -    -    */
  725. /* Miscellaneous conversion routines */
  726.  
  727. /*
  728.  * cvtStringToPixels() : Converts a string that is a whitespace-separated
  729.  *    list of pixel names, to an array of Pixels.
  730.  */
  731. static void
  732. cvtStringToPixels(str,max,pixels)
  733. char *str;
  734. int max;
  735. Pixel *pixels;
  736. {
  737.     XColor screen_in_out,exact;
  738.     char buf[64];
  739.     int i,j;
  740.  
  741.     strcpy(buf,XtDefaultBackground);
  742.     for (i=0; i < max; i++) {
  743.     if (*str) {
  744.         while (isspace(*str))
  745.         str += 1;
  746.         if (!*str)
  747.         break;
  748.         j = 0;
  749.         while (*str && j < 63 && !isspace(*str))
  750.         buf[j++] = *str++;
  751.         buf[j] = '\0';
  752.         if (*str && !isspace(*str)) {
  753.         fprintf(stderr,"%s: color name too long: %s\n",program,buf);
  754.         while (*str && !isspace(*str))
  755.             str += 1;
  756.         }
  757.     }
  758.     XAllocNamedColor(display,DefaultColormapOfScreen(screen),buf,
  759.                             &screen_in_out,&exact);
  760.     pixels[i] = screen_in_out.pixel;
  761.     }
  762. }
  763.  
  764. /*
  765.  * cvtStringToPixmaps() : Converts a string that is a whitespace-separated
  766.  *    list of bitmap names, to an array of Pixmaps.
  767.  */
  768. static void
  769. cvtStringToPixmaps(str,max,pixmaps)
  770. char *str;
  771. int max;
  772. Pixmap *pixmaps;
  773. {
  774.     char buf[64];
  775.     int i,j;
  776.  
  777.     strcpy(buf,"gray");
  778.     for (i=0; i < max; i++) {
  779.     if (*str) {
  780.         while (isspace(*str))
  781.         str += 1;
  782.         if (!*str)
  783.         break;
  784.         j = 0;
  785.         while (*str && j < 63 && !isspace(*str))
  786.         buf[j++] = *str++;
  787.         buf[j] = '\0';
  788.         if (*str && !isspace(*str)) {
  789.         fprintf(stderr,"%s: shade name too long: %s\n",program,buf);
  790.         while (*str && !isspace(*str))
  791.             str += 1;
  792.         }
  793.     }
  794.     pixmaps[i] = readBitmap(buf);
  795.     }
  796. }
  797.  
  798. /*
  799.  * readBitmap() : Reads the given file using XmuLocateBitmapFile protocol,
  800.  *    then converts to Pixmap and returns it. If not found, prints error
  801.  *    message and returns a default Pixmap.
  802.  */
  803. static Pixmap
  804. readBitmap(name)
  805. char *name;
  806. {
  807.     Pixmap b;
  808.     int w,h,xhot,yhot;
  809.  
  810.     b = XmuLocateBitmapFile(screen,name,NULL,ZERO,&w,&h,&xhot,&yhot);
  811.     if (b == NULL) {
  812.     fprintf(stderr,"%s: couldn't find bitmap \"%s\"\n",program,name);
  813.     return(XCreatePixmap(display,screen,2,2,DefaultDepthOfScreen(screen)));
  814.     } else
  815.     return(XmuCreatePixmapFromBitmap(display,root,b,w,h,
  816.                     DefaultDepthOfScreen(screen),1,0));
  817. }
  818.  
  819. /*    -    -    -    -    -    -    -    -    */
  820. /*
  821.  * syntax() : Print whatever caused the error and the usage message.
  822.  */
  823. static void
  824. syntax(argc,argv)
  825. int argc;
  826. char **argv;
  827. {
  828.     argv += 1;
  829.     if (argc > 2 || (strcmp(*argv,"-help") != 0 && strcmp(*argv,"-?") != 0)) {
  830.     fprintf(stderr,"%s: bad argument(s): ",program);
  831.     while (--argc)
  832.         fprintf(stderr,"%s ",*argv++);
  833.     fprintf(stderr,"\n");
  834.     }
  835.     fprintf(stderr,"usage: %s",program);
  836.     fprintf(stderr,"\t-appoints file\tuse file for personal appointments\n");
  837.     fprintf(stderr,"\t\t-date date\tuse given date for `today'\n");
  838.     fprintf(stderr,"\t\t-numMonths 1|2|3|12\tstart displaying 1, 2, 3 or 12 months\n");
  839.     fprintf(stderr,"\t\t-bothShown\tput day display next to month(s)\n");
  840.     fprintf(stderr,"\t\t-nobothShown\tpopup days as needed\n");
  841.     fprintf(stderr,"\t\t-version\tprint version info to stdout\n");
  842.     fprintf(stderr,"\t\t-listOnly\tprint appoints to stdout\n");
  843.     fprintf(stderr,"\t\t-silent\t\texit with status == number of appoints\n");
  844.     fprintf(stderr,"\t\t-exitUsesLevels\texit status is criticality total\n");
  845.     fprintf(stderr,"\t\t-noexitUsesLevels\texit status is number of appoints\n");
  846.     fprintf(stderr,"\t\t-opaqueDates\tprint day numbers opaquely\n");
  847.     fprintf(stderr,"\t\t-noopaqueDates\tprint day numbers transparently\n");
  848.     fprintf(stderr,"\t\t-dowLabels\tprint day of week at top of columns\n");
  849.     fprintf(stderr,"\t\t-nodowLabels\tdon't print dow at top of columns\n");
  850.     fprintf(stderr,"\t\t-titlebar\tuse titlebars to display dates\n");
  851.     fprintf(stderr,"\t\t-notitlebar\tdon't use titlebars to display dates\n");
  852.     fprintf(stderr,"\t\t-checkpointInterval mins\tmins between autosaves\n");
  853.     fprintf(stderr,"\t\t-xrm 'resource: value'\tpass arbitrary resources\n");
  854. }
  855.