home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / x / volume14 / xmalarm / part02 < prev    next >
Text File  |  1991-10-08  |  58KB  |  2,573 lines

  1. Path: uunet!sun-barr!cronkite.Central.Sun.COM!newstop!exodus!mips.com
  2. From: peebles@mips.com (Andrew Peebles)
  3. Newsgroups: comp.sources.x
  4. Subject: v14i081: Motif Alarm program, Part02/02
  5. Message-ID: <21242@exodus.Eng.Sun.COM>
  6. Date: 9 Oct 91 01:27:45 GMT
  7. References: <csx-14i080-xmalarm@uunet.UU.NET>
  8. Sender: news@exodus.Eng.Sun.COM
  9. Lines: 2561
  10. Approved: argv@sun.com
  11.  
  12. Submitted-by: peebles@mips.com (Andrew Peebles)
  13. Posting-number: Volume 14, Issue 81
  14. Archive-name: xmalarm/part02
  15.  
  16.  
  17. Xalarm is a Motif-based personal reminder and clock program.
  18.  
  19. #---------------------------------- cut here ----------------------------------
  20. # This is a shell archive.  Remove anything before this line,
  21. # then unpack it by saving it in a file and typing "sh file".
  22. #
  23. # Wrapped by  peebles@wildcat on Fri Aug 23 14:21:30 PDT 1991
  24. #
  25. # This archive contains:
  26. #    SetArg.c
  27. #    arm.c
  28. #    at.c
  29. #    help.c
  30. #    image.c
  31. #    view.c
  32. #    xalarm.c
  33. #    xalarm_d.c
  34. #
  35. LANG=""; export LANG
  36. echo x - SetArg.c
  37. cat > SetArg.c << '@EOF'
  38. #include "copyright.h"
  39. #ident    "$Header: SetArg.c,v 4.3 90/12/27 13:17:18 mar Exp $"
  40. #include <stdio.h>
  41. #include <ctype.h>
  42. #include <X11/Xlib.h>
  43. #include <X11/Intrinsic.h>
  44. #include <X11/StringDefs.h>
  45. #include <X11/Xos.h>
  46. #include <sys/stat.h>
  47.  
  48. #include <varargs.h>
  49.  
  50. /*
  51.  * Function SetArgs
  52.  *
  53.  * SetArgs fills an ArgList (an array of Args) with a given list of values.
  54.  * The list of values is NULL terminated.
  55.  *
  56.  * SetArgs returns the number of arguments that were set.
  57.  *
  58.  * EXAMPLE USAGE:
  59.  *
  60.  * int n;
  61.  * Arg args[10];
  62.  *
  63.  * n = SetArgs (args,
  64.  *        XmNwidth, 10,
  65.  *        XmNheight, 20,
  66.  *        NULL);
  67.  * XtSetValues (w, args, n);
  68.  */
  69.  
  70. SetArgs(va_alist)
  71. va_dcl
  72. {
  73.   va_list a;
  74.  
  75.   /* The first argument is the array to fill. */
  76.   register ArgList this_arg;
  77.  
  78.   /* Others are name and value pairs. */
  79.   String name;
  80.   
  81.   /* How many Args have we set? */
  82.   int count = 0;
  83.   
  84.   va_start(a);
  85.   this_arg = va_arg(a, ArgList);
  86.   
  87.   while ((name = va_arg(a, String)) != NULL)
  88.     {
  89.       XtSetArg(this_arg[count], name, va_arg(a, XtArgVal));    
  90.       ++count;
  91.     }
  92.   
  93.   va_end(a);
  94.   return count;
  95. }
  96.  
  97.  
  98. /*
  99.  * New shared function between xalarm and xalarm_display.  This function
  100.  * reads xalarm message files and attempts to handle both the new and old 
  101.  * text formats, biased towards the new.  If it encounters an old format
  102.  * file, it will automatically convert it to new.
  103.  */
  104. char *
  105. ReadMessageText (fname)
  106. char *fname;
  107. {
  108.   char    *text;
  109.   int    size, fsize;
  110.   int    fd;
  111.   struct stat buf;
  112.  
  113.   if ((fd = open (fname, O_RDONLY, 0644)) == -1) {
  114.     return(NULL);
  115.   }
  116.  
  117.   if (fstat(fd, &buf) == -1) {
  118.     fclose(fd);
  119.     return(NULL);
  120.   }
  121.  
  122.   size = buf.st_size;
  123.  
  124.   text = (char *) XtMalloc (size+2);
  125.  
  126.   read (fd, text, size);
  127.   close (fd);
  128.  
  129.   /*
  130.    * Does the first character look printable?  If not its probably the
  131.    * old format and we got to read it that way.
  132.    */
  133.   if (!isprint(text[0])) {
  134.     if ((fd = open (fname, O_RDONLY, 0644)) == -1) {
  135.       return(NULL);
  136.     }
  137.     read (fd, &size, sizeof(int));
  138.     text = (char *) XtMalloc (size+2);
  139.     read (fd, text, size);
  140.     close (fd);
  141.  
  142.     /*
  143.      * And write it back out again.  If the write fails, just ignore it!
  144.      */
  145.     if ((fd = open (fname, O_WRONLY)) != -1) {
  146.       write (fd, text, size);
  147.       close (fd);
  148.     }
  149.   }
  150.  
  151.   /*
  152.    * text now contains the message text
  153.    */
  154.   text[size] = '\0';
  155.   return (text);
  156. }
  157. @EOF
  158. echo x - arm.c
  159. cat > arm.c << '@EOF'
  160. #include "copyright.h"
  161. #ident    "$Header: arm.c,v 4.2 90/12/27 13:18:02 mar Exp $"
  162. /***************************************************************************
  163.  *
  164.  * FILE NAME        : arm.c
  165.  *
  166.  * AUTHOR        : Andrew Peebles
  167.  *
  168.  * DESCRIPTION        : The routines for auto-repeat feature on forward
  169.  *              and reverse keys on the main xalarm display
  170.  *
  171.  * VERSIONS        : @(#)arm.c    1.1
  172.  *
  173.  ***************************************************************************/
  174.  
  175. /*
  176.  * standard includes
  177.  */
  178. #include <stdio.h>
  179. #include <Xm/Xm.h>
  180.  
  181. void RepeatTimeOut();
  182. XtIntervalId    repeatId = 0;
  183.  
  184. extern Widget top;
  185. extern int    RepeatDelay;
  186. extern int    InitialDelay;
  187.  
  188. void
  189. arm (w, client, call)
  190. Widget    w;
  191. void    (*client)();    /* fwd or rev callback function pointer */
  192. caddr_t    call;
  193. {
  194.   /*
  195.    * client (w, NULL, NULL)
  196.    * tid = addTimeOut (initialDelay)
  197.    */
  198.   client (w, NULL, NULL);
  199.   XSync (XtDisplay (top), False);
  200.   repeatId = XtAppAddTimeOut (XtWidgetToApplicationContext(top),
  201.                   InitialDelay,
  202.                   RepeatTimeOut,
  203.                   client);
  204. }
  205.  
  206. void
  207. disarm (w, client, call)
  208. Widget    w;
  209. caddr_t    client, call;
  210. {
  211.   /*
  212.    * if (tid)
  213.    *    removeTimeOut (tid)
  214.    */
  215.   if (repeatId != 0)
  216.     XtRemoveTimeOut (repeatId);
  217.   repeatId = 0;
  218. }
  219.  
  220. void
  221. RepeatTimeOut (func, id)
  222. void (*func)();
  223. XtIntervalId id;
  224. {
  225.   func (0, NULL, NULL);
  226.   XSync (XtDisplay (top), False);
  227.   repeatId = XtAppAddTimeOut (XtWidgetToApplicationContext(top),
  228.                   RepeatDelay,
  229.                   RepeatTimeOut,
  230.                   func);
  231. }
  232.  
  233.     
  234.  
  235. @EOF
  236. echo x - at.c
  237. cat > at.c << '@EOF'
  238. #include "copyright.h"
  239. /*
  240.  * standard includes
  241.  */
  242. #include <stdio.h>
  243. #include <X11/Xos.h>
  244. #include <pwd.h>
  245. #include "at.h"
  246.  
  247. #ifdef USE_SYSV_AT
  248. #define ATSYS    "sysv"
  249. #else
  250. #define ATSYS    "bsd"
  251. #endif 
  252.  
  253. static char    *user = NULL;
  254.  
  255. int
  256. at_command (hour, minute, month, day, file, idfile, id, cmd)
  257. int    hour, minute;
  258. char    *month;
  259. int    day;
  260. char    *file, *idfile;
  261. char    *id;
  262. int    cmd;
  263. {
  264.   char    com[1024];
  265.   int    status;
  266.  
  267.   if (!user) {
  268.     struct passwd *p = (struct passwd *) getpwuid(getuid());
  269.     user = p->pw_name;
  270.   }
  271.  
  272.   switch (cmd) {
  273.   case AT_SUBMIT:
  274.     sprintf (com, "xat %s %s submit xxx %02d%02d %s %d %s > %s 2> %s",
  275.          ATSYS, user,
  276.          hour, minute,
  277.          month, day,
  278.          file, idfile, idfile);
  279.     status = system(com);
  280.     break;
  281.   case AT_LIST:
  282.     sprintf (com, "xat %s %s list xxx xxx xxx xxx xxx",
  283.          ATSYS, user);
  284.     status = system(com);
  285.     break;
  286.   case AT_REMOVE:
  287.     sprintf (com, "xat %s %s remove %s xxx xxx xxx xxx",
  288.          ATSYS, user, id);
  289.     status = system(com);
  290.     break;
  291.   }
  292.  
  293.   return (status);
  294. }
  295.  
  296.   
  297.  
  298. @EOF
  299. echo x - help.c
  300. cat > help.c << '@EOF'
  301. #include "copyright.h"
  302. #ident    "$Header: help.c,v 4.2 90/12/27 13:20:50 mar Exp $"
  303. /***************************************************************************
  304.  *
  305.  * FILE NAME        : help.c
  306.  *
  307.  * AUTHOR        : Andrew Peebles
  308.  *
  309.  * DESCRIPTION        : Contains the initial help screen code
  310.  *
  311.  * VERSIONS        : @(#)help.c    1.5
  312.  *
  313.  ***************************************************************************/
  314.  
  315. /*
  316.  * standard includes
  317.  */
  318. #include <stdio.h>
  319. #include <Xm/Text.h>
  320. #include <Xm/PushB.h>
  321. #include <Xm/Form.h>
  322. #include <X11/Xos.h>
  323. #include <sys/stat.h>
  324.  
  325. Widget    dialog, text, quit;
  326. Widget  REF;
  327.  
  328. /*
  329.  * Function:
  330.  */
  331. Help (ref, help_file)
  332. Widget    ref;
  333. char    *help_file;
  334. /*
  335.  * Creates and brings up the tutorial screen when xalarm is invoked for
  336.  * the first time.
  337.  */
  338. {
  339.   Arg     args[20];
  340.   int    n;
  341.   void    QuitCB();
  342.   int    status;
  343.  
  344.   REF = ref;
  345.  
  346.   dialog = XmCreateFormDialog (ref,
  347.                    "help",
  348.                    NULL,0);
  349.  
  350.   XtManageChild (dialog);
  351.  
  352.   n = SetArgs (args,
  353.                XmNtopAttachment, XmATTACH_FORM,
  354.                XmNleftAttachment, XmATTACH_FORM,
  355.                NULL);
  356.  
  357.   quit = XmCreatePushButton (dialog,
  358.                  "quit",
  359.                  args, n);
  360.  
  361.   XtManageChild (quit);
  362.  
  363.   n = SetArgs (args,
  364.                XmNeditMode, XmMULTI_LINE_EDIT,
  365.                XmNcolumns, 85,
  366.                XmNrows, 24,
  367.                XmNwordWrap, True,
  368.                XmNscrollHorizontal, False,
  369.                XmNautoShowCursorPosition, True,
  370.                XmNcursorPositionVisible, True,
  371.                XmNblinkRate, 0,
  372.                XmNeditable, False,
  373.                NULL);
  374.   text = XmCreateScrolledText (dialog,
  375.                                "text",
  376.                                args,n);
  377.  
  378.   status = GetHelpInfo (text, help_file);
  379.  
  380.   XtManageChild (text);
  381.   
  382.   n = SetArgs (args,
  383.                XmNtopAttachment, XmATTACH_WIDGET,
  384.                XmNtopWidget, quit,
  385.                XmNleftAttachment, XmATTACH_FORM,
  386.                XmNrightAttachment, XmATTACH_FORM,
  387.                XmNeditMode, XmMULTI_LINE_EDIT,
  388.                XmNcolumns, 85,
  389.                XmNrows, 24,
  390.                NULL);
  391.   XtSetValues (XtParent(text), args, n);
  392.  
  393.   XtAddCallback (quit, XmNactivateCallback, QuitCB, NULL);
  394.  
  395.   XtManageChild (dialog);
  396.  
  397.   return (status);
  398. }
  399.  
  400. /*
  401.  * Function:
  402.  */
  403. void 
  404. QuitCB(w, client, call)
  405. Widget    w;
  406. caddr_t    client, call;
  407. /*
  408.  * Callback attached to the quit button on the help window
  409.  */
  410. {
  411.   Widget box = XtParent(w);
  412.   Widget shell = XtParent (box);
  413.   
  414.   XtUnmanageChild (box);
  415.   XtDestroyWidget (shell);
  416. }
  417.  
  418. /*
  419.  * Function:
  420.  */
  421. GetHelpInfo (w, fname)
  422. Widget    w;
  423. char    *fname;
  424. /*
  425.  * Read in the tutorial file and put it in the text edit widgwet.
  426.  */
  427. {
  428.   Arg    args[5];
  429.   char    *buffer;
  430.   int    fp;
  431.   struct stat stats;
  432.  
  433.   if ((fp = open (fname, O_RDONLY, 0644)) == -1) {
  434.     Warning (REF,"Can't open help file");
  435.     return(False);
  436.   }
  437.  
  438.   fstat (fp, &stats);
  439.  
  440.   buffer = (char *) XtMalloc (stats.st_size);
  441.   read (fp, buffer, stats.st_size);
  442.  
  443.  
  444.   XtSetArg (args[0], XmNvalue, buffer);
  445.   XtSetValues (w, args, 1);
  446.  
  447.   close (fp);
  448.  
  449.   return (True);
  450. }
  451.  
  452.  
  453.  
  454. @EOF
  455. echo x - image.c
  456. cat > image.c << '@EOF'
  457. #include "copyright.h"
  458. #ident    "$Header: image.c,v 4.2 90/12/27 13:21:12 mar Exp $"
  459. /***************************************************************************
  460.  *
  461.  * FILE NAME        : image.c
  462.  *
  463.  * AUTHOR        : Andrew Peebles
  464.  *
  465.  * DESCRIPTION        : Contains Xm routines for pixmap handling
  466.  *
  467.  * VERSIONS        : @(#)image.c    1.4
  468.  *
  469.  ***************************************************************************/
  470.  
  471. /*
  472.  * standard includes
  473.  */
  474. #include <stdio.h>
  475. #include <X11/Intrinsic.h>
  476. #include <X11/IntrinsicP.h>
  477. #include <Xm/Xm.h>
  478. #include "image.h"
  479.  
  480. /*
  481.  * Function:
  482.  */
  483. Boolean
  484. CreateAndInstallPixmap (bits, width, height, name)
  485. char    *bits;
  486. int    width, height;
  487. char    *name;
  488. /*
  489.  * Take parameters from a bitmap(1) include file, create an XImage and
  490.  * install it in the Motif PIXMAP cache where it can be referenced by
  491.  * name.
  492.  */
  493. {
  494.     XImage *image;
  495.  
  496.     image = (XImage *) XtMalloc (sizeof (XImage));
  497.     image->width = width;
  498.     image->height = height;
  499.     image->data = bits;
  500.     image->depth = 1;
  501.     image->xoffset = 0;
  502.     image->format = XYBitmap;
  503.     image->byte_order = LSBFirst;
  504.     image->bitmap_unit = 8;
  505.     image->bitmap_bit_order = LSBFirst;
  506.     image->bitmap_pad = 8;
  507.     image->bytes_per_line = (width+7)/8;
  508.  
  509.     return (XmInstallImage (image, name));
  510. }
  511.  
  512. /*
  513.  * Function:
  514.  */
  515. Pixmap
  516. GetPixmap (w, name)
  517. Widget    w;
  518. char    *name;
  519. /*
  520.  * Return a PIXMAP that is stored in the Motif PIXMAP cache by name
  521.  */
  522. {
  523.   Pixmap    p;
  524.   Arg        args[5];
  525.   Pixel        f,b;
  526.  
  527.   XtSetArg (args[0], XmNforeground, &f);
  528.   XtSetArg (args[1], XmNbackground, &b);
  529.   XtGetValues (w, args, 2);
  530.   p = XmGetPixmap (w->core.screen,
  531.            name,
  532.            f, b);
  533.   return (p);
  534. }
  535.  
  536. /*
  537.  * Function:
  538.  */
  539. void
  540. InstallDefaultPixmaps ()
  541. /*
  542.  * Install the standard dialog pixmaps in the PIXMAP cache.  I stole
  543.  * these from the dialog widgets provided by Motif.  They are nice lookin
  544.  * bitmap images.
  545.  */
  546. {
  547.   XImage    *image;
  548.  
  549.   CreateAndInstallPixmap (errorBits,
  550.               errorWidth,
  551.               errorHeight,
  552.               "xm_error");
  553.  
  554.   CreateAndInstallPixmap (infoBits,
  555.               infoWidth,
  556.               infoHeight,
  557.               "xm_info");
  558.  
  559.   CreateAndInstallPixmap (questionBits,
  560.               questionWidth,
  561.               questionHeight,
  562.               "xm_question");
  563.  
  564.   CreateAndInstallPixmap (warningBits,
  565.               warningWidth,
  566.               warningHeight,
  567.               "xm_warning");
  568.  
  569.   CreateAndInstallPixmap (workingBits,
  570.               workingWidth,
  571.               workingHeight,
  572.               "xm_working");
  573.  
  574. }
  575. @EOF
  576. echo x - view.c
  577. cat > view.c << '@EOF'
  578. #include "copyright.h"
  579. #ident    "$Header: view.c,v 4.4 90/12/27 13:22:16 mar Exp $"
  580. /***************************************************************************
  581.  *
  582.  * FILE NAME        : view.c
  583.  *
  584.  * AUTHOR        : Andrew Peebles
  585.  *
  586.  * DESCRIPTION        : routines to view pending alarms
  587.  *
  588.  * VERSIONS        : @(#)view.c    1.5
  589.  *
  590.  ***************************************************************************/
  591.  
  592. /*
  593.  * standard includes
  594.  */
  595. #include <stdio.h>
  596. #include <ctype.h>
  597. #include <X11/Xos.h>
  598. #ifdef BSD43
  599. #include <sys/dir.h>
  600. #else
  601. #include <dirent.h>
  602. #endif
  603. #include <sys/stat.h>
  604. #include <Xm/SelectioB.h>
  605.  
  606. #include "at.h"
  607.  
  608. extern Widget top;
  609. extern char   *display_name;
  610. Widget REF_WIDGET_SELECT;
  611. extern char *ReadMessageText();
  612.  
  613. extern int at_command();
  614.  
  615. /*
  616.  * This stucture is used as an entry in an array and contains the
  617.  * information pertaining to an alarm.  The alarm file directory is
  618.  * scaned, and for each pending alarm a structure is created and filled
  619.  * out and added to the array of pending alarms.
  620.  */
  621. typedef struct _message_item {
  622.   char    *atID;            /* the ID returned by at */
  623.   char    *date;            /* time this alarm will go off */
  624.   char    *first_10_chars;    /* first 10 chars of alarm message */
  625.   char    *filename;        /* basename of the alarm files */
  626. } message_item;
  627.  
  628. /*
  629.  * this array contains the pending alarms.  note that there can be a MAX
  630.  * of 1K pending at any given time.
  631.  */
  632. message_item    *messages[1024];
  633. int        num_messages = 0;
  634.  
  635. /*
  636.  * Function:
  637.  */
  638. MakeList (dir)
  639. char    *dir;
  640. /*
  641.  * Scan the alarm file directory and fill out the messages[] array
  642.  */
  643. {
  644.   DIR    *dirp;
  645. #ifdef BSD43
  646.   struct direct *item;
  647. #else
  648.   struct dirent *item;
  649. #endif
  650.   char    message[120];
  651.   char    *ext();
  652.   char  *CopyString();
  653.  
  654.   if ((dirp = opendir (dir)) == NULL) {
  655.     sprintf (message,"Can't open %s to read pending alarms",dir);
  656.     Warning (top,message);
  657.     return(0);
  658.   }
  659.  
  660.   num_messages = 0;
  661.  
  662.   for (item = readdir(dirp); item != NULL; item = readdir(dirp)) {
  663.     if (strcmp(ext(item->d_name),".aid") == 0) {
  664.       messages[num_messages++] = (message_item *) XtMalloc (sizeof(message_item));
  665.       messages[num_messages -1]->filename = CopyString (item->d_name);
  666.       GetMessageInfo (messages [num_messages -1], dir, item->d_name);
  667.     }
  668.   }
  669.   closedir(dirp);
  670. }
  671.  
  672. /*
  673.  * Function:
  674.  */
  675. char *
  676. ext (str)
  677. char *str;
  678. /*
  679.  * return the file name extension for the passed in file
  680.  */
  681. {
  682.   char *p = str;
  683.   while ((*p != '.') && (*p != '\0')) ++p;
  684.   if (*p == '\0') return ("..");
  685.   else return (p);
  686. }
  687.  
  688. /*
  689.  * Function:
  690.  */
  691. char *
  692. CopyString (str)
  693. char *str;
  694. /*
  695.  * return a copy of the passed in string
  696.  */
  697. {
  698.   char    *p;
  699.  
  700.   p = (char *) XtMalloc (strlen(str));
  701.   strcpy(p,str);
  702.   return(p);
  703. }
  704.  
  705. /*
  706.  * Function:
  707.  */
  708. GetMessageInfo (item, dir, fname)
  709. message_item *item;
  710. char         *dir;
  711. char         *fname;
  712. /*
  713.  * Fill in the message_item with the alarm info.
  714.  */
  715. {
  716.   char    *basename();
  717.   char    *base = basename (fname);
  718.   char    text_file[512];
  719.   char    aid_file[512];
  720.   FILE    *fp, *fopen();
  721.   char    *tok, *strtok();
  722.   char    warning[120];
  723.   int    size;
  724.   struct stat buf;
  725.  
  726.   sprintf (text_file,"%s/%s.txt",dir,fname);
  727.   sprintf (aid_file, "%s/%s.aid",dir,fname);
  728.  
  729.   if ((fp = fopen (aid_file, "r")) == NULL) {
  730.     sprintf (warning,"Can't open %s to read alarm info",aid_file);
  731.     Warning (top,warning);
  732.     return(0);
  733.   }
  734.  
  735.   item->first_10_chars = ReadMessageText (text_file);
  736.   if (!item->first_10_chars) {
  737.     sprintf (warning,"Can't open %s to read alarm text",text_file);
  738.     Warning (top,warning);
  739.     fclose(fp);
  740.     return(0);
  741.   }
  742.   if (strlen(item->first_10_chars) > 10)
  743.     item->first_10_chars[9] = '\0';
  744.  
  745.   StripCR (item->first_10_chars);
  746.  
  747.   fgets (warning, 120, fp);
  748.   fgets (warning, 120, fp);
  749.   tok = strtok (warning," ");
  750.   item->atID = CopyString (strtok(NULL," "));
  751.   tok = strtok (NULL," ");
  752.   item->date = CopyString (strtok(NULL,"\n"));
  753.   fclose(fp);
  754. }
  755.  
  756. /*
  757.  * Function:
  758.  */
  759. char *
  760. basename (str)
  761. char    *str;
  762. /*
  763.  * chop off the file name extension of the passed in file
  764.  */
  765. {
  766.   char    *p = str;
  767.   while (*p != '.') ++p;
  768.   *p = '\0';
  769.   return(str);
  770. }
  771.  
  772. /*
  773.  * Function:
  774.  */
  775. DumpList()
  776. /*
  777.  * Debug routine that dumps the contents of the messages[] array
  778.  */
  779. {
  780.   int    i;
  781.   for (i=0; i<num_messages; i++) {
  782.     printf ("at id : %s\n",messages[i]->atID);
  783.     printf ("date  : %s\n",messages[i]->date);
  784.     printf ("message : %s\n",messages[i]->first_10_chars);
  785.     printf ("filename: %s\n\n",messages[i]->filename);
  786.   }
  787. }
  788.   
  789. /*
  790.  * Function:
  791.  */
  792. DisplayList()
  793. /*
  794.  * Display the contents of the messages[] array in a selectionBox widget
  795.  * where the user can view an alarm message or remove an alarm from the 
  796.  * system.
  797.  */
  798. {
  799.   Widget    select;
  800.   Widget    button;
  801.   char        line[80];
  802.   XmString    *xmstrings;
  803.   Arg        args[10];
  804.   int        n,i;
  805.   void        ViewAlarm(), RemoveAlarm(), HideViewer();
  806.  
  807.   /*
  808.    * Create an XmStringList containing lines for each pendind alarm.
  809.    * Each line will have the time the alarm will go off and the first
  810.    * 10 charaters of the alarm message.  This list will go into the
  811.    * list portion of the selectionBox widget.
  812.    */
  813.   xmstrings = (XmString *) XtMalloc (sizeof(XmString) * num_messages);
  814.   for (i=0; i<num_messages; i++) {
  815.     sprintf (line,"%d: %s - %s",i,messages[i]->date,messages[i]->first_10_chars);
  816.     xmstrings[i] = XmStringCreateLtoR (line, XmSTRING_DEFAULT_CHARSET);
  817.   }
  818.  
  819.   if (num_messages == 0)
  820.     xmstrings = NULL;
  821.  
  822.   n = SetArgs (args,
  823.            XmNlistItems, xmstrings,
  824.            XmNlistItemCount, num_messages,
  825.            XmNlistLabelString, XmStringCreateLtoR("Pending Alarms",XmSTRING_DEFAULT_CHARSET),
  826.            XmNeditable, False,
  827.            XmNokLabelString, XmStringCreateLtoR("view",XmSTRING_DEFAULT_CHARSET),
  828.            XmNcancelLabelString, XmStringCreateLtoR("remove",XmSTRING_DEFAULT_CHARSET),
  829.            XmNhelpLabelString, XmStringCreateLtoR("done",XmSTRING_DEFAULT_CHARSET),
  830.            XmNmustMatch, True,
  831.            NULL);
  832.   select = XmCreateSelectionDialog (top,
  833.                     "ViewMessages",
  834.                     args,n);
  835.  
  836.   button = XmSelectionBoxGetChild (select,
  837.                    XmDIALOG_APPLY_BUTTON);
  838.   XtUnmanageChild(button);
  839.  
  840.   button = XmSelectionBoxGetChild (select,
  841.                    XmDIALOG_OK_BUTTON);
  842.   XtRemoveAllCallbacks (button, XmNactivateCallback);
  843.   XtAddCallback (button, XmNactivateCallback, ViewAlarm, NULL);
  844.  
  845.   button = XmSelectionBoxGetChild (select,
  846.                    XmDIALOG_CANCEL_BUTTON);
  847.   XtRemoveAllCallbacks (button, XmNactivateCallback);
  848.   XtAddCallback (button, XmNactivateCallback, RemoveAlarm, NULL);
  849.  
  850.   XtAddCallback (select, XmNhelpCallback, HideViewer, select);
  851.  
  852.   REF_WIDGET_SELECT = select;
  853.  
  854.   XtManageChild (select);
  855. }
  856.  
  857. void
  858. HideViewer(w, shell, unused)
  859. Widget    w, shell;
  860. caddr_t unused;
  861. {
  862.   XtUnmanageChild (shell);
  863.   XtDestroyWidget (shell);
  864. }
  865.  
  866. /*
  867.  * Function:
  868.  */
  869. void
  870. ViewAlarm(w, client, call)
  871. Widget    w;
  872. caddr_t    client, call;
  873. /*
  874.  * View a pending alarm message.  The "displayProgram" will be used via
  875.  * a system(3c) call to display the message.
  876.  */
  877. {
  878.   char    *item;
  879.   XmString text_string;
  880.   Arg    args[5];
  881.   int    n;
  882.   Widget    select = XtParent(w);
  883.   Widget    shell  = XtParent(select);
  884.   char    *tok;
  885.   int    index;
  886.   char    com[120];
  887.   extern char *InfoFilePath;
  888.   extern char *DisplayProgram;
  889.   char    text_file[512];
  890.  
  891.   n = SetArgs (args,
  892.            XmNtextString, &text_string,
  893.            NULL);
  894.   XtGetValues (REF_WIDGET_SELECT, args, n);
  895.  
  896.   XmStringGetLtoR (text_string,
  897.            XmSTRING_DEFAULT_CHARSET,
  898.            &item);
  899.  
  900.   if (!item) return;
  901.   if (item[0] == '\0') return;
  902.  
  903.   /*
  904.    * The item in the selection buffer has its index in the messages[]
  905.    * array as its first characters.  Scan this index out so we can index
  906.    * the pending alarm in the messages[] array so we can get file names.
  907.    */
  908.   tok = strtok (item,":");
  909.   sscanf (tok,"%d",&index);
  910.  
  911.   basename(messages[index]->filename);
  912.   sprintf (text_file,"%s/%s.txt",InfoFilePath,messages[index]->filename);
  913.   sprintf (com,"%s -display %s %s &",
  914.        DisplayProgram,display_name,text_file);
  915.   system(com); 
  916. }
  917.  
  918. /*
  919.  * Function:
  920.  */
  921. void
  922. RemoveAlarm(w, client, call)
  923. Widget    w;
  924. caddr_t    client, call;
  925. /*
  926.  * Remove the selected alarm from the system.  We will use a call to
  927.  * "at -l" via a system(3c) call.
  928.  */
  929. {
  930.   char    *item;
  931.   XmString text_string;
  932.   Arg    args[5];
  933.   int    n;
  934.   Widget    select = XtParent(w);
  935.   Widget    shell  = XtParent(select);
  936.   char    *tok;
  937.   int    index;
  938.   char    com[120];
  939.   extern char *InfoFilePath;
  940.   char    fname[512];
  941.  
  942.   n = SetArgs (args,
  943.            XmNtextString, &text_string,
  944.            NULL);
  945.   XtGetValues (REF_WIDGET_SELECT, args, n);
  946.  
  947.   XmStringGetLtoR (text_string,
  948.            XmSTRING_DEFAULT_CHARSET,
  949.            &item);
  950.  
  951.   if (!item) return;
  952.   if (item[0] == '\0') return;
  953.  
  954.   /*
  955.    * The item in the selection buffer has its index in the messages[]
  956.    * array as its first characters.  Scan this index out so we can index
  957.    * the pending alarm in the messages[] array so we can get file names.
  958.    */
  959.   tok = strtok (item,":");
  960.   sscanf (tok,"%d",&index);
  961.  
  962. #if 0
  963.   sprintf (com,"/usr/bin/at -r %s",messages[index]->atID);
  964.   system(com); 
  965. #endif
  966.  
  967.   at_command (0,0,"xx",0,"xx","xx",messages[index]->atID,AT_REMOVE);
  968.  
  969.   basename (messages[index]->filename);
  970.  
  971.   /*
  972.    * and remove the alarm files
  973.    */
  974.   sprintf (fname,"rm -f %s/%s.*",InfoFilePath,messages[index]->filename);
  975.   system(fname); 
  976.  
  977.   /*
  978.    * And now remove it from the list
  979.    */
  980.   XmListDeleteItem (XmSelectionBoxGetChild(REF_WIDGET_SELECT,
  981.                        XmDIALOG_LIST), text_string);
  982.   /*
  983.    * and clear out the select window
  984.    */
  985.   XmTextSetString (XmSelectionBoxGetChild(REF_WIDGET_SELECT,
  986.                       XmDIALOG_TEXT), NULL);
  987. }
  988.  
  989. /*
  990.  * Function:
  991.  */
  992. StripCR (str)
  993. char    *str;
  994. /*
  995.  * convert <cr>s in string to ' ' so selection buffer don't get
  996.  * messed up
  997.  */
  998. {
  999.   char    *p = str;
  1000.   while (*p != '\0') {
  1001.     if (*p == '\n') *p = ' ';
  1002.     ++p;
  1003.   }
  1004. }
  1005. @EOF
  1006. echo x - xalarm.c
  1007. cat > xalarm.c << '@EOF'
  1008. /*
  1009.  * xalarm - a Motif based personal reminder and clock program
  1010.  *
  1011.  * Copyright (c) 1990 MIPS Computer Systems, Inc.
  1012.  *
  1013.  * Permission to use, copy, modify, and distribute this software and its
  1014.  * documentation for any purpose and without fee is hereby granted, provided
  1015.  * that the above copyright notice appear in all copies and that both that
  1016.  * copyright notice and this permission notice appear in supporting
  1017.  * documentation, and that the name of Mips Computer Systems, Inc. not
  1018.  * be used in advertising or publicity pertaining to distribution of
  1019.  * the software without specific, written prior permission.  Mips Computer
  1020.  * Systems, Inc. makes no representations about the suitability of this
  1021.  * software for any purpose.  It is provided "as is" without express or
  1022.  * implied warranty.
  1023.  *
  1024.  * MIPS COMPUTER SYSTEMS, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO
  1025.  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  1026.  * FITNESS, IN NO EVENT SHALL MIPS COMPUTER SYSTEMS,INC. BE LIABLE FOR
  1027.  * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  1028.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
  1029.  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  1030.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  1031.  */
  1032. /*
  1033.  * Author:    Andrew Peebles
  1034.  *        peebles@mips.com
  1035.  */
  1036. #ident    "$Header: xalarm.c,v 4.3 90/12/27 13:22:27 mar Exp $"
  1037. static char version[] = "@(#)xalarm.c    1.7";
  1038. /***************************************************************************
  1039.  *
  1040.  * FILE NAME        : xalarm.c
  1041.  *
  1042.  * AUTHOR        : Andrew Peebles
  1043.  *
  1044.  * DESCRIPTION        : 
  1045.  *
  1046.  *    Xalarm is a Motif application that displays an alarm clock on the
  1047.  *    screen that shows the current time in a segmented display and the
  1048.  *    current day of the week and date.  The user can program alarms
  1049.  *    and enter messages that will be displayed when those alarms go off.
  1050.  *    Pending alarms can be viewed and purged from the system.
  1051.  *
  1052.  *    Xalarm uses the Unix system 5 "at" command to schedule these alarms.
  1053.  *    Another X window program, called xalarm_display is used to display
  1054.  *    an alarm when it goes off.  When an alarm is programmed by the
  1055.  *    user, three files are created.  The three files use the current
  1056.  *    clock time as returned by time(3c) for a base. A message file,
  1057.  *    called <time>.txt, contains the message for that alarm.  A command
  1058.  *    file, called <time>.com, is the file executed by at when the alarm
  1059.  *    will go off.  The third file, called <time>.aid contains the at
  1060.  *    ID of the at command origianlly fired for this alarm.  When an
  1061.  *    alarm is created by the user, this is what happens:
  1062.  *
  1063.  *    1. Two files are created, with the following contents:
  1064.  *        nnnn.com
  1065.  *            xalarm_display nnnn.txt
  1066.  *            rm nnnn.txt nnnn.aid
  1067.  *            exec rm nnnn.com
  1068.  *
  1069.  *        nnnn.txt
  1070.  *            <size in bytes of message>
  1071.  *            Message Text ...
  1072.  *
  1073.  *    2. Then the unix at command is fired via a system(3c) call:
  1074.  *        at 11:00 am < nnnn.com 2> nnnn.aid
  1075.  *
  1076.  *    The <time>.aid file is used by the Pending Alarm screen to remove
  1077.  *    pending alarms from the system via an "at -r <at_id>" command.
  1078.  *
  1079.  * VERSIONS        : @(#)xalarm.c    1.7
  1080.  *
  1081.  ***************************************************************************/
  1082.  
  1083. /*
  1084.  * standard includes
  1085.  */
  1086. #include <stdio.h>
  1087. #include <X11/Xos.h>
  1088. #include <Xm/Xm.h>
  1089. #include <Xm/Form.h>
  1090. #include <Xm/DrawingA.h>
  1091. #include <Xm/Frame.h>
  1092. #include <Xm/PushB.h>
  1093. #include <Xm/ToggleB.h>
  1094. #include <Xm/RowColumn.h>
  1095. #include <Xm/Label.h>
  1096.  
  1097. #include "patchlevel.h"
  1098.  
  1099. /*
  1100.  * digits for the segmented display
  1101.  */
  1102. #include "b0.h"
  1103. #include "b1.h"
  1104. #include "b2.h"
  1105. #include "b3.h"
  1106. #include "b4.h"
  1107. #include "b5.h"
  1108. #include "b6.h"
  1109. #include "b7.h"
  1110. #include "b8.h"
  1111. #include "b9.h"
  1112. /*
  1113.  * blank bitmaps for place holders
  1114.  */
  1115. #include "blank.h"
  1116. #include "blankdots.h"
  1117. /*
  1118.  * the dots between hours and minutes in the
  1119.  * segmented display
  1120.  */
  1121. #include "dots.h"
  1122. /*
  1123.  * button face bitmaps for the main xalarm keys
  1124.  */
  1125. #include "set.h"
  1126. #include "ffwd.h"
  1127. #include "revd.h"
  1128. #include "pwr.h"
  1129.  
  1130. /*
  1131.  * The bitmaps above are converted to XImages for 
  1132.  * writing the screen.  The digits are kept in the
  1133.  * Digits array for ease of access, the dots are
  1134.  * kept seperate.
  1135.  */
  1136. XImage    *Digits[11];
  1137. XImage    *DOTS;
  1138. XImage  *BlankDots;
  1139.  
  1140. /*
  1141.  * This gc is used for drawing the digits
  1142.  */
  1143. GC    gc;
  1144.  
  1145. /*
  1146.  * The main xalarm display widgets
  1147.  */
  1148. Widget    top,        /* top level application widget */
  1149.         bb,        /* a Form, holds every one together */
  1150.         frame,        /* frame surrounding segmented display */
  1151.         rc,        /* rowColumn for the toggles */
  1152.         draw,        /* drawingArea for the segmented display */
  1153.         label,        /* Label for the date */
  1154.         pm_ind;        /* Label for the AM/PM indicator */
  1155.  
  1156. /*
  1157.  * These are the programming keys, ToggleButtons in the rowColumn
  1158.  */
  1159. Widget    day_btn,
  1160.         hour_btn,
  1161.         min_btn;
  1162.  
  1163. /*
  1164.  * These are the other buttons on the main display
  1165.  */
  1166. Widget    set,
  1167.         fwd,
  1168.         rev,
  1169.         pwr;    /* the name is historical, this is the pending view button */
  1170.  
  1171. /*
  1172.  * These two arrays are kept for ease of getting the string for a day from a
  1173.  * number obtained from ctime().  The abrevs. here must be compatible with
  1174.  * the Unix "at" command, as they are used to fire alarms.
  1175.  */
  1176. char    *Days[] = {
  1177.   "Sun",
  1178.   "Mon",
  1179.   "Tue",
  1180.   "Wed",
  1181.   "Thu",
  1182.   "Fri",
  1183.   "Sat"
  1184.   };
  1185.  
  1186. char    *Months[] = {
  1187.   "Jan",
  1188.   "Feb",
  1189.   "Mar",
  1190.   "Apr",
  1191.   "May",
  1192.   "Jun",
  1193.   "Jul",
  1194.   "Aug",
  1195.   "Sep",
  1196.   "Oct",
  1197.   "Nov",
  1198.   "Dec"
  1199.   };
  1200.  
  1201. /*
  1202.  * The Non-Widget Resources
  1203.  */
  1204. typedef struct _resoure_data {
  1205.   char        *FilePath;     /* path to alarm files */
  1206.   Boolean    TickTock;     /* do the dots between hour and minute blink*/
  1207.   char        *DisplayProgram; /* path to alarm display program */
  1208.   char        *HelpFile;     /* path to tutorial file */
  1209.   int        InitialDelay;     /* for begin auto repeat */
  1210.   int        RepeatDelay;     /* for repeating auto repeat */
  1211. } resource_data, *resource_data_ptr;
  1212.  
  1213. static XtResource resources[] = {
  1214.   {"filePath",
  1215.      "FilePath",
  1216.      XmRString,
  1217.      sizeof (char *),
  1218.      XtOffset(resource_data_ptr, FilePath),
  1219.      XmRString,
  1220.      NULL},        /* default will be $HOME */
  1221.   {"displayProgram",
  1222.      "DisplayProgram",
  1223.      XmRString,
  1224.      sizeof (char *),
  1225.      XtOffset(resource_data_ptr, DisplayProgram),
  1226.      XmRString,
  1227.      NULL},        /* no default, MUST BE SPECIFIED BY USER */
  1228.   {"helpFile",
  1229.      "HelpFile",
  1230.      XmRString,
  1231.      sizeof (char *),
  1232.      XtOffset(resource_data_ptr, HelpFile),
  1233.      XmRString,
  1234.      "/usr/lib/X11/app-defaults/xalarm/help.txt"},
  1235.   {"tickTock",
  1236.      "TickTock",
  1237.      XmRBoolean,
  1238.      sizeof (int),
  1239.      XtOffset (resource_data_ptr, TickTock),
  1240.      XmRString,
  1241.      "True"},
  1242.   {"initialDelay",
  1243.      "InitialDelay",
  1244.      XmRInt,
  1245.      sizeof (int),
  1246.      XtOffset (resource_data_ptr, InitialDelay),
  1247.      XmRString,
  1248.      "250"},
  1249.   {"repeatDelay",
  1250.      "RepeatDelay",
  1251.      XmRInt,
  1252.      sizeof (int),
  1253.      XtOffset (resource_data_ptr, RepeatDelay),
  1254.      XmRString,
  1255.      "50"}
  1256. };
  1257.  
  1258. /****************************************************************************
  1259.  * These are the different alarm types, passed as timeout IDs to the
  1260.  * timeout handler.
  1261.  ****************************************************************************/
  1262.  
  1263. #define SYS_TIME    0    /* update the time */
  1264. #define SYS_TICK    1    /* toggle the blinking dots */
  1265.  
  1266. /*
  1267.  * and a couple of commonly used time values
  1268.  */
  1269. #define MS        1000    /* 100 ms / sec */
  1270. #define E_60_SECONDS    60*MS
  1271. #define E_1_SECOND    1*MS
  1272.  
  1273. /*
  1274.  * Am I in Programming Mode ?  I need to know this when I want to
  1275.  * potencially update the time.  If i'm in programming mode, I don't
  1276.  * wnat to change the display on the user!  This variable is set
  1277.  * in the cb.c file routines that control programming of alarms.
  1278.  */
  1279. extern Boolean PROGRAMMING;
  1280.  
  1281. /*
  1282.  * this will contain the path to the information files created for
  1283.  * each alarm and is set in the resource files, obtained with
  1284.  * a call to GetApplicationResources
  1285.  */
  1286. char    *InfoFilePath;
  1287.  
  1288. /*
  1289.  * the name of the program to use to display alarm messages on
  1290.  * the screen, set in the resource files, obtained with a call to
  1291.  * GetApplicationResources.
  1292.  */
  1293. char    *DisplayProgram;
  1294. char    *display_name;
  1295.  
  1296. /*
  1297.  * These are times for the timeout events used for the auto repeat
  1298.  * functions of the << and >> buttons.
  1299.  */
  1300. int    RepeatDelay;
  1301. int    InitialDelay;
  1302.  
  1303. /**************************************************************************
  1304.  *                 M A I N
  1305.  **************************************************************************/
  1306. main (argc, argv)
  1307. int    argc;
  1308. char    **argv;
  1309. {
  1310.   /* various callback function declarations */
  1311.   void    display_expose_event();
  1312.   void    TimeOutEvent();
  1313.   void    OffEvent();
  1314.   void    PlusEvent();
  1315.   void    MinusEvent();
  1316.   void    DayEvent();
  1317.   void    HourEvent();
  1318.   void    MinEvent();
  1319.   void    SetEvent();
  1320.   void    arm();
  1321.   void    disarm();
  1322.   Display *dpy;
  1323.  
  1324.   resource_data    res_data;    /* for GetApplicationResources call */
  1325.  
  1326.   Arg    args[10];        /* for setting XmArg values */
  1327.   int    n;
  1328.  
  1329.   /*
  1330.    * by default, the users HOME will contain the alarm information
  1331.    * files.  This will be reset if specified in the resource files
  1332.    */
  1333.   InfoFilePath = (char *) getenv ("HOME");
  1334.  
  1335.   top = XtInitialize ("main",
  1336.               "XAlarm",        /* APPLICATION CLASS NAME */
  1337.               NULL,NULL,
  1338.               &argc,argv);
  1339.  
  1340.   dpy = XtDisplay(top);
  1341.   display_name = dpy->display_name;
  1342.  
  1343.   /*
  1344.    * we're gonna use fancy PIXMAP buttons.  Install them
  1345.    * in the PIXMAP cache.
  1346.    */
  1347.   CreateAndInstallPixmap (ffwd_bits, ffwd_width, ffwd_height, "fwd_face");
  1348.   CreateAndInstallPixmap (revd_bits, revd_width, revd_height, "rev_face");
  1349.   CreateAndInstallPixmap (set_bits, set_width, set_height, "set_face");
  1350.   CreateAndInstallPixmap (pwr_bits, pwr_width, pwr_height, "pwr_face");
  1351.  
  1352.   /*
  1353.    * Create the widgets for this application
  1354.    */
  1355.   CreateApplicationWidgets();
  1356.  
  1357.   /*
  1358.    * Get the non-widget resources
  1359.    */
  1360.   XtGetApplicationResources (top,
  1361.                  &res_data,
  1362.                  resources,
  1363.                  XtNumber(resources),
  1364.                  NULL,0);
  1365.  
  1366.   /*
  1367.    * set the auto repeat delays
  1368.    */
  1369.   InitialDelay = res_data.InitialDelay;
  1370.   RepeatDelay = res_data.RepeatDelay;
  1371.  
  1372.   /*
  1373.    * Reset InfoFilePath if specified
  1374.    */
  1375.   if (res_data.FilePath)
  1376.     InfoFilePath = res_data.FilePath;
  1377.  
  1378.   /*
  1379.    * If display program is not set, bail.
  1380.    */
  1381.   if (res_data.DisplayProgram)
  1382.     DisplayProgram = res_data.DisplayProgram;
  1383.   else {
  1384.     fprintf (stderr,"You must specify the `displayProgram' resource\n");
  1385.     fprintf (stderr,"in your resource file.  Xalarm will not function\n");
  1386.     fprintf (stderr,"properly without it.\n");
  1387.     exit(1);
  1388.   }
  1389.  
  1390.   /*
  1391.    * The first time xalarm is invoked, a brief tutorial will be displayed
  1392.    * in a read-only text edit widget.  See the function definition for 
  1393.    * how this is done.
  1394.    */
  1395.   NeedsHelp (InfoFilePath,res_data.HelpFile);
  1396.  
  1397.   /*
  1398.    * add an expose routine for the segmented display
  1399.    */
  1400.   XtAddCallback (draw,
  1401.          XmNexposeCallback,
  1402.          display_expose_event,
  1403.          NULL);
  1404.  
  1405.   /*
  1406.    * Add the push button call backs
  1407.    */
  1408.   XtAddCallback (pwr,      XmNactivateCallback, OffEvent);
  1409.   XtAddCallback (rev,      XmNarmCallback, arm, PlusEvent);
  1410.   XtAddCallback (fwd,      XmNarmCallback, arm, MinusEvent);
  1411.   XtAddCallback (rev,      XmNdisarmCallback, disarm);
  1412.   XtAddCallback (fwd,      XmNdisarmCallback, disarm);
  1413.   XtAddCallback (set,      XmNactivateCallback, SetEvent);
  1414.   XtAddCallback (day_btn,  XmNarmCallback,      DayEvent);
  1415.   XtAddCallback (hour_btn, XmNarmCallback,      HourEvent);
  1416.   XtAddCallback (min_btn,  XmNarmCallback,      MinEvent);
  1417.  
  1418.   /*
  1419.    * and go for it
  1420.    */
  1421.   XtRealizeWidget (top);
  1422.  
  1423.   SetupDisplay (draw);        /* create all of the seg. display digits */
  1424.   ComputeDisplaySize ();    /* bogus additional sizing for seg. display */
  1425.  
  1426.   /*
  1427.    * install the periodic time update and ticker update
  1428.    * timeout events
  1429.    */
  1430.   XtAppAddTimeOut (XtWidgetToApplicationContext(top),
  1431.            E_60_SECONDS,
  1432.            TimeOutEvent,
  1433.            (caddr_t) SYS_TIME);
  1434.  
  1435.   if (res_data.TickTock)
  1436.     XtAppAddTimeOut (XtWidgetToApplicationContext(top),
  1437.              E_1_SECOND,
  1438.              TimeOutEvent,
  1439.              (caddr_t) SYS_TICK);
  1440.  
  1441.   XtMainLoop();
  1442. }
  1443.  
  1444. /****************************************************************************
  1445.  *                 M A I N
  1446.  ****************************************************************************/
  1447.  
  1448. /*
  1449.  * Function:
  1450.  */
  1451. void
  1452. display_expose_event (w, closure, call)
  1453. Widget    w;
  1454. caddr_t    closure, call;
  1455. /*
  1456.  * This callback is attached to the DrawingArea widget to redraw the
  1457.  * segmented display containing the time.
  1458.  */ 
  1459. {
  1460.   long    clock, time();
  1461.   struct tm    *theTime, *localtime();
  1462.  
  1463.   clock = time ((long *) 0);
  1464.   theTime    = localtime (&clock);
  1465.   UpdateTime (theTime->tm_hour, 
  1466.           theTime->tm_min,
  1467.           theTime->tm_wday,
  1468.           theTime->tm_mon,
  1469.           theTime->tm_mday,
  1470.           True);
  1471. }
  1472.  
  1473. /*
  1474.  * Function:
  1475.  */
  1476. void
  1477. GetTime (hour, min, wday, mon, mday)
  1478. int    *hour, *min, *wday, *mon, *mday;
  1479. /*
  1480.  * Used by various other routines for obtaining the current time in
  1481.  * the pointers passed in.
  1482.  */
  1483. {
  1484.   long clock, time();
  1485.   struct tm *theTime, *localtime();
  1486.  
  1487.   clock = time ((long *) 0);
  1488.   theTime = localtime (&clock);
  1489.   *hour = theTime->tm_hour; 
  1490.   *min  = theTime->tm_min;
  1491.   *wday = theTime->tm_wday;
  1492.   *mon  = theTime->tm_mon;
  1493.   *mday = theTime->tm_mday;
  1494. }  
  1495.  
  1496. /*
  1497.  * Function:
  1498.  */
  1499. XmString
  1500. GetDate(wday,mon,mday)
  1501. int wday, mon, mday;
  1502. /*
  1503.  * Returns an XmString containg the current day of the week and date
  1504.  */
  1505. {
  1506.   XmString    date;
  1507.   char        dateStr[15];
  1508.  
  1509.   sprintf (dateStr,"%s, %s. %d",Days[wday],Months[mon],mday);
  1510.   date = XmStringCreateLtoR (dateStr,XmSTRING_DEFAULT_CHARSET);
  1511.   return (date);
  1512. }
  1513.  
  1514. /*
  1515.  * Function:
  1516.  */
  1517. XmString
  1518. GetAMPM(h,m)
  1519. int h, m;
  1520. /*
  1521.  * Returns an XmString containing "AM" or "PM" based in the hour and
  1522.  * minute passed in.
  1523.  */
  1524. {
  1525.   XmString    date;
  1526.   char        dateStr[5];
  1527.   Boolean    PM;
  1528.  
  1529.   if (h > 12) {
  1530.     PM = True;
  1531.   }
  1532.   else if ((h == 12) && (m > 0)) {
  1533.     PM = True;
  1534.   }
  1535.   else {
  1536.     PM = False;
  1537.   }
  1538.   date = XmStringCreateLtoR (((PM == True) ? "PM" : "AM"), 
  1539.                  XmSTRING_DEFAULT_CHARSET);
  1540.   return (date);
  1541. }
  1542.  
  1543. /*
  1544.  * Function:
  1545.  */
  1546. UpdateTime (hour, minute, wday, month, mday, SetDate)
  1547. int    hour, minute, wday, month, mday;
  1548. Boolean SetDate;
  1549. /*
  1550.  * This function is used to draw the time and date in the main xalarm
  1551.  * display.  The time and date is passed in as integers (obtained by
  1552.  * calls to ctime(3c) functions).  The boolean "SetDate" tells if we
  1553.  * should update the date string as well as the time.  This boolean
  1554.  * is used to make drawing the display less "jumpy" when only the time
  1555.  * is being updated.
  1556.  */
  1557. {
  1558.   int        PM = False;
  1559.   int        XOFFSET = 0;
  1560.   int        YOFFSET = 0;
  1561.   Window     win;
  1562.   Display    *display;
  1563.   int        i;
  1564.   Arg        args[5];
  1565.   int        n;
  1566.  
  1567.   win       = XtWindow (draw);
  1568.   display = XtDisplay (draw);
  1569.  
  1570.  
  1571.   n=0;
  1572.   XtSetArg (args[n], XmNlabelString, GetAMPM(hour,minute)); n++;
  1573.   XtSetValues (pm_ind, args, n);
  1574.  
  1575.   if (hour == 0)
  1576.     hour = 24;
  1577.  
  1578.   if (hour > 12) {
  1579.     PM = True;
  1580.     hour -= 12;
  1581.   }
  1582.   else if ((hour == 12) && (minute > 0)) {
  1583.     PM = True;
  1584.   }
  1585.   else {
  1586.     PM = False;
  1587.   }
  1588.   XClearWindow (display, win); 
  1589.  
  1590.   /*
  1591.    * place the digits into the segmented display
  1592.    */
  1593.   if ((hour/10) != 0) {
  1594.     XPutImage (display,win,gc,Digits[ (hour / 10) ],0,0,
  1595.                   XOFFSET+0,YOFFSET+0,
  1596.                   16,26);
  1597.   }
  1598.   else {
  1599.     XPutImage (display,win,gc,Digits[ 10 ],0,0,
  1600.                   XOFFSET+0,YOFFSET+0,
  1601.                   16,26);
  1602.   }
  1603.   XPutImage (display,win,gc,Digits[ (hour % 10) ],0,0,
  1604.                   XOFFSET+16,YOFFSET+0,
  1605.                   16,26);
  1606.  
  1607.   XPutImage (display,win,gc,DOTS,0,0,
  1608.                   XOFFSET+32,YOFFSET+0,
  1609.                   5,26);
  1610.  
  1611.   XPutImage (display,win,gc,Digits[ (minute / 10) ],0,0,
  1612.                   XOFFSET+37,YOFFSET+0,
  1613.                   16,26);
  1614.  
  1615.   XPutImage (display,win,gc,Digits[ (minute % 10) ],0,0,
  1616.                   XOFFSET+53,YOFFSET+0,
  1617.                   16,26);
  1618.  
  1619.   if (SetDate) {
  1620.     n=0;
  1621.     XtSetArg (args[n], XmNlabelString, GetDate(wday,month,mday)); n++;
  1622.     XtSetValues (label, args, n);
  1623.   }
  1624.  
  1625.   XFlush (display);    /* should do this whenever you're drawing your own */
  1626.                         /* graphics do the server is synced up */
  1627. }
  1628.  
  1629. /*
  1630.  * Function:
  1631.  */
  1632. static Boolean    TickOn = True;
  1633. Tick()
  1634. /*
  1635.  * This function call will toggle the dots in the segmented display
  1636.  * on and off.  It is a nice and simple effect when scheduled every
  1637.  * second, makes xalarm look like a "real" machine.  It is called from
  1638.  * the time out event handler.
  1639.  */
  1640. {
  1641.   Window    win = XtWindow (draw);
  1642.   Display    *display = XtDisplay (draw);
  1643.   int        XOFFSET = 0;
  1644.   int        YOFFSET = 0;
  1645.  
  1646.   if (TickOn) {
  1647.     TickOn = False;
  1648.     XPutImage (display,win,gc,BlankDots,0,0,
  1649.            XOFFSET+32,YOFFSET+0,
  1650.            5,26);
  1651.   }
  1652.   else {
  1653.     TickOn = True;
  1654.     XPutImage (display,win,gc,DOTS,0,0,
  1655.            XOFFSET+32,YOFFSET+0,
  1656.            5,26);
  1657.   }
  1658.   XFlush (XtDisplay(top));
  1659. }
  1660.  
  1661. /*
  1662.  * Function:
  1663.  */
  1664. SetupDisplay (w)
  1665. Widget    w;
  1666. /*
  1667.  * This function sets up the digit XImage structures for the
  1668.  * segmented display.
  1669.  */
  1670. {  
  1671.   Pixmap        fore;
  1672.   Pixmap        back;
  1673.   Arg        args[5];
  1674.   XImage    *MakeImage();
  1675.   XGCValues     values;
  1676.   int           screen;
  1677.  
  1678.   XtSetArg (args[0], XmNforeground, &fore);
  1679.   XtSetArg (args[1], XmNbackground, &back);
  1680.   XtGetValues (w, args, 2);
  1681.  
  1682.   screen = DefaultScreen (XtDisplay(w));
  1683.   values.foreground = fore;
  1684.   values.background = back;
  1685.  
  1686.   gc = XCreateGC (XtDisplay(w),
  1687.           XtWindow(w),
  1688.           (GCForeground | GCBackground),
  1689.           &values);
  1690.  
  1691.   Digits[0] = MakeImage (b0_width,
  1692.              b0_height,
  1693.              b0_bits);
  1694.  
  1695.   Digits[1] = MakeImage (b1_width,
  1696.              b1_height,
  1697.              b1_bits);
  1698.  
  1699.   Digits[2] = MakeImage (b2_width,
  1700.              b2_height,
  1701.              b2_bits);
  1702.  
  1703.   Digits[3] = MakeImage (b3_width,
  1704.              b3_height,
  1705.              b3_bits);
  1706.  
  1707.   Digits[4] = MakeImage (b4_width,
  1708.              b4_height,
  1709.              b4_bits);
  1710.  
  1711.   Digits[5] = MakeImage (b5_width,
  1712.              b5_height,
  1713.              b5_bits);
  1714.  
  1715.   Digits[6] = MakeImage (b6_width,
  1716.              b6_height,
  1717.              b6_bits);
  1718.  
  1719.   Digits[7] = MakeImage (b7_width,
  1720.              b7_height,
  1721.              b7_bits);
  1722.  
  1723.   Digits[8] = MakeImage (b8_width,
  1724.              b8_height,
  1725.              b8_bits);
  1726.  
  1727.   Digits[9] = MakeImage (b9_width,
  1728.              b9_height,
  1729.              b9_bits);
  1730.  
  1731.   Digits[10] = MakeImage (blank_width,
  1732.               blank_height,
  1733.               blank_bits);
  1734.  
  1735.   DOTS = MakeImage (dots_width,
  1736.             dots_height,
  1737.             dots_bits);
  1738.   
  1739.   BlankDots = MakeImage (blankdots_width,
  1740.              blankdots_height,
  1741.              blankdots_bits);
  1742. }
  1743.  
  1744. /*
  1745.  * Function:
  1746.  */
  1747. XImage *
  1748. MakeImage (width, height, data)
  1749. int    width, height;
  1750. char    *data;
  1751. /*
  1752.  * Return an XImage structure created with the passed in
  1753.  * parameters.  The input parameters are bitmap(1) generated and
  1754.  * are in the include file for a bitmap image.
  1755.  */
  1756. {
  1757.   XImage    *image;
  1758.  
  1759.       image = (XImage *) XtMalloc (sizeof (XImage));
  1760.       image->width = width;
  1761.       image->height = height;
  1762.       image->data = data;
  1763.       image->depth = 1;
  1764.       image->xoffset = 0;
  1765.       image->format = XYBitmap;
  1766.       image->byte_order = LSBFirst;
  1767.       image->bitmap_unit = 8;
  1768.       image->bitmap_bit_order = LSBFirst;
  1769.       image->bitmap_pad = 8;
  1770.       image->bytes_per_line = (width+7)/8;
  1771.  
  1772.   return (image);
  1773. }
  1774.  
  1775. /*
  1776.  * Function:
  1777.  */
  1778. ComputeDisplaySize ()
  1779. /*
  1780.  * After the digits are read in, the drawingArea widget is sized to
  1781.  * to surround them.
  1782.  */
  1783. {
  1784.   Arg    args[5];
  1785.   int    sw,sh;
  1786.  
  1787.   sw = (2 * b0_width) + dots_width + (2 * b0_width);  
  1788.   sh = b0_height;
  1789.   XtSetArg (args[0], XmNwidth, sw);
  1790.   XtSetArg (args[1], XmNheight, sh);
  1791.   XtSetValues (draw, args, 2);
  1792.  
  1793. }
  1794.  
  1795. /*
  1796.  * Function:
  1797.  */
  1798. GetWidgetSize (w, width, height)
  1799. Widget    w;
  1800. int    *width, *height;
  1801. /*
  1802.  * Return the current size of a passed in widget
  1803.  */
  1804. {
  1805.   Arg    args[5];
  1806.  
  1807.   XtSetArg (args[0], XmNwidth, width);
  1808.   XtSetArg (args[1], XmNheight, height);
  1809.   XtGetValues (w, args, 2);
  1810. }
  1811.  
  1812. /* 
  1813.  * Function:
  1814.  */
  1815. SetGlobalSize ()
  1816. /*
  1817.  * This function sends the window manager the size hints for xalarm.
  1818.  * I don't want xalarm to be resized, and I want it to come up a
  1819.  * particular size no matter what the user wants.  Is this bad?  I
  1820.  * don't think so for an application of this type.  Xalarm looks bad
  1821.  * at any other size.
  1822.  *
  1823.  * The hard-coded size is based on and depends on the use of the
  1824.  * "9x15" font.
  1825.  *
  1826.  * ----------------------------------------------------------------------
  1827.  * In this version, the R4/Motif 1.1, the XmForm functions a lot better,
  1828.  * and this function is no longer called.  There is no font dependent
  1829.  * behavior and the application can be resized.
  1830.  */
  1831. {
  1832.   XSizeHints hints;
  1833.   Arg    args[5];
  1834.   int    w,h;
  1835.   int    x,y;
  1836.  
  1837.   XtSetArg (args[0],XmNwidth,&w);
  1838.   XtSetArg (args[1],XmNheight,&h);
  1839.   XtSetArg (args[2],XmNx, &x);
  1840.   XtSetArg (args[3],XmNy, &y);
  1841.   
  1842.   XtGetValues (top,args,4);
  1843.  
  1844.   hints.width = hints.max_width = hints.min_width = 200;
  1845.   hints.height = hints.max_height = hints.min_height = 105;
  1846.   hints.x = x;
  1847.   hints.y = y;
  1848.   hints.flags = (USSize | PSize | PMinSize | PMaxSize | USPosition);  
  1849.   XSetNormalHints (XtDisplay(top),XtWindow(top), &hints); 
  1850. }
  1851.  
  1852. /*
  1853.  * Function:
  1854.  */
  1855. CreateApplicationWidgets()
  1856. /*
  1857.  * This function created the main xalarm dispay widgets
  1858.  */
  1859. {
  1860.   Arg    args[10];
  1861.   int    n;
  1862.   XmString GetDate();
  1863.  
  1864.   /*
  1865.    * the form contains all children
  1866.    */
  1867.   n=0;
  1868.   XtSetArg (args[n], XmNhorizontalSpacing, 3); n++;
  1869.   XtSetArg (args[n], XmNverticalSpacing, 3); n++;
  1870.   XtSetArg (args[n], XmNallowOverlap, False); n++;
  1871.   XtSetArg (args[n], XmNrubberPositioning, True); n++;
  1872.   bb = XmCreateForm (top,
  1873.              "bb",
  1874.              args,n);
  1875.   XtManageChild (bb);
  1876.  
  1877.   /*
  1878.    * The day, hour, and minute programming selections
  1879.    * are radio buttons, to provide a one of many selection
  1880.    * model.
  1881.    */
  1882.   n=0;
  1883.   XtSetArg (args[n],XmNtopAttachment, XmATTACH_FORM); n++;
  1884.   XtSetArg (args[n],XmNrightAttachment,XmATTACH_FORM); n++;
  1885.   XtSetArg (args[n],XmNentryClass,xmToggleButtonWidgetClass); n++;
  1886.   rc = XmCreateRadioBox (bb,
  1887.              "sets",
  1888.              args,n);
  1889.   XtManageChild (rc);
  1890.   XmAddTabGroup (rc);
  1891.  
  1892.   /*
  1893.    * and now the toggles
  1894.    */
  1895.   n=0;
  1896.   XtSetArg (args[n], XmNmarginHeight, 0); n++;
  1897.   day_btn = XmCreateToggleButton (rc,
  1898.                   "day",
  1899.                   args,n);
  1900.   XtManageChild (day_btn);
  1901.   hour_btn = XmCreateToggleButton (rc,
  1902.                   "hour",
  1903.                    args,n);
  1904.   XtManageChild (hour_btn);
  1905.   min_btn = XmCreateToggleButton (rc,
  1906.                   "min",
  1907.                   args,n);
  1908.   XtManageChild (min_btn);
  1909.  
  1910.   /*
  1911.    * There is a set button to finish the programming
  1912.    * sequence.
  1913.    */
  1914.   n=0;
  1915.   XtSetArg (args[n],XmNtopAttachment,XmATTACH_WIDGET); n++;
  1916.   XtSetArg (args[n],XmNtopWidget,rc); n++;
  1917.   XtSetArg (args[n],XmNrightAttachment,XmATTACH_FORM); n++;
  1918.   XtSetArg (args[n],XmNbottomAttachment,XmATTACH_FORM); n++;
  1919.   set = XmCreatePushButton (bb,
  1920.                 "set",
  1921.                 args,n);
  1922.   XtManageChild (set);
  1923.   XmAddTabGroup (set);
  1924.  
  1925.   n=0;
  1926.   XtSetArg (args[n],XmNlabelType,XmPIXMAP); n++;
  1927.   XtSetArg (args[n],XmNlabelPixmap,GetPixmap(set,"set_face")); n++;
  1928.   XtSetValues (set,args,n);
  1929.  
  1930.   /*
  1931.    * there are two buttons for programming the alarm,
  1932.    * a backward and a forward button.  Both will have
  1933.    * pixmaps for button faces.
  1934.    */
  1935.   n=0;
  1936.   XtSetArg (args[n],XmNrightAttachment,XmATTACH_WIDGET); n++;  
  1937.   XtSetArg (args[n],XmNrightWidget,rc); n++;
  1938.   XtSetArg (args[n],XmNtopAttachment,XmATTACH_FORM); n++;
  1939.   rev = XmCreatePushButton (bb,
  1940.                 "fwd",
  1941.                 args,n);
  1942.   XtManageChild (rev);
  1943.   n=0;
  1944.   XtSetArg (args[n],XmNlabelType,XmPIXMAP); n++;
  1945.   XtSetArg (args[n],XmNlabelPixmap,GetPixmap(rev,"rev_face")); n++;
  1946.   XtSetValues (rev,args,n);
  1947.  
  1948.   n=0;
  1949.   XtSetArg (args[n],XmNrightAttachment,XmATTACH_WIDGET); n++;
  1950.   XtSetArg (args[n],XmNrightWidget,rev); n++;
  1951.   XtSetArg (args[n],XmNtopAttachment,XmATTACH_FORM); n++;
  1952.   fwd = XmCreatePushButton (bb,
  1953.                 "rev",
  1954.                 args,n);
  1955.   XtManageChild (fwd);
  1956.   n=0;
  1957.   XtSetArg (args[n],XmNlabelType,XmPIXMAP); n++;
  1958.   XtSetArg (args[n],XmNlabelPixmap,GetPixmap(fwd,"fwd_face")); n++;
  1959.   XtSetValues (fwd,args,n);
  1960.  
  1961.   /*
  1962.    * The segmented display is a frame around a drawing area
  1963.    */
  1964.   n=0;
  1965.   XtSetArg (args[n],XmNmarginWidth, 5); n++;
  1966.   XtSetArg (args[n],XmNmarginHeight, 5); n++;
  1967.   XtSetArg (args[n],XmNrightAttachment,XmATTACH_WIDGET); n++; 
  1968.   XtSetArg (args[n],XmNrightWidget,rc); n++;
  1969.   XtSetArg (args[n],XmNtopAttachment,XmATTACH_WIDGET); n++;
  1970.   XtSetArg (args[n],XmNtopWidget, fwd); n++;
  1971.   XtSetArg (args[n],XmNrightOffset,7); n++;
  1972.   frame = XmCreateFrame (bb,
  1973.              "frame",
  1974.              args,n);
  1975.   XtManageChild (frame);
  1976.  
  1977.   n=0;
  1978.   XtSetArg (args[n],XmNwidth,75); n++;
  1979.   XtSetArg (args[n],XmNheight,25); n++;
  1980.   draw = XmCreateDrawingArea (frame,
  1981.                   "display",
  1982.                   args,n);
  1983.   XtManageChild (draw);
  1984.  
  1985.  
  1986.   /*
  1987.    * and under the segmented display is a date label
  1988.    */
  1989.   n=0;
  1990.   XtSetArg (args[n],XmNleftAttachment,XmATTACH_FORM); n++;
  1991.   XtSetArg (args[n],XmNrightAttachment,XmATTACH_WIDGET); n++;
  1992.   XtSetArg (args[n],XmNrightWidget,set); n++;
  1993.   XtSetArg (args[n],XmNtopAttachment,XmATTACH_WIDGET); n++;
  1994.   XtSetArg (args[n],XmNtopWidget,frame); n++;
  1995.   XtSetArg (args[n],XmNlabelString,GetDate(6,6,6)); n++;
  1996.   label = XmCreateLabel (bb,
  1997.              "date",
  1998.              args,n);
  1999.   XtManageChild (label);
  2000.  
  2001.   /*
  2002.    * over the label is the power button
  2003.    */
  2004.   n=0;
  2005.   XtSetArg (args[n],XmNbottomAttachment,XmATTACH_WIDGET); n++;
  2006.   XtSetArg (args[n],XmNbottomWidget,label); n++;
  2007.   XtSetArg (args[n],XmNleftAttachment,XmATTACH_FORM); n++; 
  2008.   XtSetArg (args[n],XmNrightAttachment,XmATTACH_WIDGET); n++;
  2009.   XtSetArg (args[n],XmNrightOffset, 15); n++;
  2010.   XtSetArg (args[n],XmNrightWidget,frame); n++;
  2011.   pwr = XmCreatePushButton (bb,
  2012.                 "pwr",
  2013.                 args,n);
  2014.   XtManageChild(pwr);
  2015.   XmAddTabGroup(pwr);
  2016.   n=0;
  2017.   XtSetArg (args[n],XmNlabelType, XmPIXMAP); n++;
  2018.   XtSetArg (args[n],XmNlabelPixmap, GetPixmap(pwr,"pwr_face")); n++;
  2019.   XtSetValues (pwr, args, n);
  2020.  
  2021.   /*
  2022.    * and a am/pm indicator
  2023.    */
  2024.   n=0;
  2025.   XtSetArg (args[n],XmNlabelString,GetAMPM(5,5)); n++;
  2026.   XtSetArg (args[n],XmNrightAttachment,XmATTACH_WIDGET); n++;
  2027.   XtSetArg (args[n],XmNrightWidget,frame); n++;
  2028.   XtSetArg (args[n],XmNrightOffset, 15); n++;
  2029.   XtSetArg (args[n],XmNbottomAttachment,XmATTACH_WIDGET); n++;
  2030.   XtSetArg (args[n],XmNbottomWidget,pwr); n++;
  2031.   pm_ind = XmCreateLabel (bb,
  2032.               "pm",
  2033.               args,n);
  2034.   XtManageChild(pm_ind);
  2035. }
  2036.  
  2037. /*
  2038.  * Function:
  2039.  */
  2040. void
  2041. TimeOutEvent (type, id)
  2042. int        type;
  2043. XtIntervalId     *id;
  2044. /*
  2045.  * This function is the timeout event procedure, called when a time
  2046.  * out event occurs.  There are two possible timeout events, one that
  2047.  * is scheduled every 60 seconds to update the time, and one that is
  2048.  * scheduled every second that makes the dots blink.  The two are distinguished
  2049.  * by the "type" parameter.
  2050.  */
  2051. {
  2052.   int    hour,min,wday,mon,mday;
  2053.  
  2054.   switch (type) {
  2055.   case SYS_TIME:
  2056.     if (!PROGRAMMING) {
  2057.       GetTime (&hour, &min, &wday, &mon, &mday);
  2058.       UpdateTime (hour, min, wday, mon, mday, True);
  2059.     }
  2060.     /* reschedule it */
  2061.     XtAppAddTimeOut (XtWidgetToApplicationContext(top),
  2062.              E_60_SECONDS,
  2063.              TimeOutEvent,
  2064.              (caddr_t) SYS_TIME);
  2065.     break;
  2066.   case SYS_TICK:
  2067.     if (!PROGRAMMING) {
  2068.       Tick();
  2069.     }
  2070.     /* reschedule it */
  2071.     XtAppAddTimeOut (XtWidgetToApplicationContext(top),
  2072.              E_1_SECOND,
  2073.              TimeOutEvent,
  2074.              (caddr_t) SYS_TICK);
  2075.     break;
  2076.   default:
  2077.     fprintf (stderr, "xalarm: Unknown alarm type, %d\n",type);
  2078.     break;
  2079.   }
  2080. }
  2081.  
  2082. /*
  2083.  * Function:
  2084.  */
  2085. NeedsHelp (fpath, helpfile)
  2086. char    *fpath;
  2087. char    *helpfile;
  2088. /*
  2089.  * This function checks the existence of a file called ".needshelp"
  2090.  * in the directory where the alarm message files exist.  If its
  2091.  * not there, the help window is poped up and the file is created.
  2092.  * Future invokations of xalarm will see this file and the tutorial
  2093.  * will not come up.
  2094.  */
  2095. {
  2096.   char    com[120];
  2097.   char    *fname;
  2098.   FILE    *fp, *fopen();
  2099.  
  2100.   fname = (char *) XtMalloc (strlen(fpath) + strlen("/.needshelp") + 5);
  2101.   sprintf (fname, "%s/.needshelp", fpath);
  2102.   
  2103.   if ((fp = fopen (fname, "r")) != NULL) {
  2104.     fclose(fp);
  2105.     return (0);
  2106.   }
  2107.  
  2108.   if (!Help (top, helpfile)) {
  2109.     return(0);
  2110.   }
  2111.  
  2112.   if ((fp = fopen(fname,"w")) == NULL) {
  2113.     Warning (top,"Can't open help lock file.");
  2114.     return (0);
  2115.   }
  2116.  
  2117.   fprintf (fp,"\n");
  2118. }
  2119.  
  2120. /*
  2121.  * The End
  2122.  */
  2123.  
  2124.  
  2125.  
  2126. @EOF
  2127. echo x - xalarm_d.c
  2128. cat > xalarm_d.c << '@EOF'
  2129. #include "copyright.h"
  2130. #ident    "$Header: xalarm_d.c,v 4.5 90/12/27 13:22:49 mar Exp $"
  2131. static char version[] = "@(#)xalarm_d.c    1.7";
  2132. /***************************************************************************
  2133.  *
  2134.  * FILE NAME        : xalarm_display.c
  2135.  *
  2136.  * AUTHOR        : Andrew Peebles
  2137.  *
  2138.  * DESCRIPTION        : 
  2139.  *
  2140.  *    This program is used to display an alarm message on the screen.
  2141.  *    It is invoked when an alarm goes off (via a Unix SYSTEMV at call)
  2142.  *    and when a user views a pending alarm.  Because of the displayProgram
  2143.  *    resource for xalarm, any similar program could be written to display
  2144.  *    alarm messages.  Note that by adopting this "two program" appraoch,
  2145.  *    xalarm itself does not have to be running to recieve alarm messages.
  2146.  *
  2147.  * VERSIONS        : @(#)xalarm_d.c    1.7
  2148.  *
  2149.  ***************************************************************************/
  2150.  
  2151. /*
  2152.  * standard includes
  2153.  */
  2154. #include <stdio.h>
  2155.  
  2156. #include <Xm/Xm.h>
  2157. #include <Xm/Text.h>
  2158. #include <Xm/PushB.h>
  2159. #include <Xm/Form.h>
  2160. #include <X11/Shell.h>
  2161. #include <X11/StringDefs.h>
  2162. #include <X11/Xos.h>
  2163. #include <sys/stat.h>
  2164.  
  2165. Widget    top, form, ok, snooze, text;
  2166. extern  char *ReadMessageText();
  2167.  
  2168. /*
  2169.  * Non-widget resource structurs.  These are used so a call to
  2170.  * GetApplicationResources can retrieve this resource from a
  2171.  * number of places.
  2172.  */
  2173. typedef struct _res_data {
  2174.   int    snooze_time;        /* number of seconds to snooze */
  2175.   Boolean beep_on;        /* turn on beeper */
  2176.   int    beep_freq;        /* frequency of beep */
  2177.   int   beep_volume;        /* beep volume (-100 to 100) */
  2178. } res_data, *res_data_ptr;
  2179.  
  2180. res_data myresources;        /* global resource table */
  2181.  
  2182. static XtResource resources[] = {
  2183.   {"snoozeTime",
  2184.      "SnoozeTime",
  2185.      XmRInt,
  2186.      sizeof(int),
  2187.      XtOffset (res_data_ptr, snooze_time),
  2188.      XmRString,
  2189.      "30"},            /* default is 30 seconds */
  2190.   {"beepOn",
  2191.      "BeepOn",
  2192.      XmRBoolean, 
  2193.      sizeof (Boolean),
  2194.      XtOffset (res_data_ptr, beep_on),
  2195.      XmRString,
  2196.      "True"},            /* default is on */
  2197.   {"beepPeriod",
  2198.      "BeepPeriod",
  2199.      XmRInt,
  2200.      sizeof(int),
  2201.      XtOffset (res_data_ptr, beep_freq),
  2202.      XmRString,
  2203.      "1"},            /* every second */
  2204.   {"beepVolume",
  2205.      "BeepVolume",
  2206.      XmRInt,
  2207.      sizeof(int),
  2208.      XtOffset (res_data_ptr, beep_volume),
  2209.      XmRString,
  2210.      "99"}            /* 99; valid range is -100 to 100 */
  2211. };
  2212.  
  2213. #define MS 1000
  2214. int    SysSnoozeTime = 30*MS;    /* 30 second snooze time default */
  2215.  
  2216. /*
  2217.  * Used to keep track of beep timeout
  2218.  */
  2219. XtIntervalId    BeepId = 0;
  2220.  
  2221. /*
  2222.  * Now restrict beeper to beep 5 times, then do not beep again unless
  2223.  * snooze is selected.
  2224.  */
  2225. int BEEPTIMES = 5;
  2226.  
  2227. /***************************************************************************
  2228.  *                 M A I N
  2229.  ***************************************************************************/
  2230. main (argc, argv)
  2231. int    argc;
  2232. char    **argv;
  2233. {
  2234.   Arg    args[10];
  2235.   int    n;
  2236.   Display *display;
  2237.   Screen *scrn;
  2238.   char **saved_argv;
  2239.   int saved_argc = argc;
  2240.   int    i;
  2241.   void    TimeOutEvent();
  2242.   void    OKCallback(), SnoozeCallback(), TimeOut();
  2243.   XtAppContext     context;
  2244.  
  2245.   /*
  2246.    * We'll go through the long hand method of initializing this application
  2247.    * so if the display is not accessable, the message is instead mailed to
  2248.    * the user.
  2249.    */
  2250.   XtToolkitInitialize();
  2251.  
  2252.   saved_argv = (char **) XtCalloc(
  2253.       (unsigned) ((argc) + 1) , (unsigned)sizeof(*saved_argv));
  2254.   
  2255.   for (i = 0 ; i < argc ; i++) saved_argv[i] = argv[i];
  2256.   saved_argv[i] = NULL;
  2257.  
  2258.   context = XtCreateApplicationContext();
  2259.   if ((display = XtOpenDisplay(context,
  2260.                    NULL,
  2261.                    NULL,
  2262.                    "XAlarm_display",
  2263.                    NULL,0,
  2264.                    &argc,argv)) == NULL) {
  2265.     Recover (argc,argv);
  2266.     exit(1);
  2267.   }
  2268.   scrn = DefaultScreenOfDisplay(display);
  2269.   n = SetArgs (args,
  2270.           XtNscreen, scrn,
  2271.           XtNargc, saved_argc,
  2272.           XtNargv, saved_argv,
  2273.           NULL);
  2274.  
  2275.   top = XtAppCreateShell (NULL,
  2276.               "XAlarm_display",
  2277.               applicationShellWidgetClass,
  2278.               display,
  2279.               args,n);
  2280.  
  2281.   /*
  2282.    * Create the main display widgets
  2283.    */
  2284.   CreateApplicationWidgets();
  2285.  
  2286.   /*
  2287.    * Get the non-widget resources
  2288.    */
  2289.   XtGetApplicationResources (top,
  2290.                              &myresources,
  2291.                              resources,
  2292.                              XtNumber(resources),
  2293.                              NULL,0);
  2294.   SysSnoozeTime = MS*myresources.snooze_time;
  2295.  
  2296.   /*
  2297.    * Add the callbacks to the buttons
  2298.    */
  2299.   XtAddCallback (ok, XmNactivateCallback, OKCallback, NULL);
  2300.   XtAddCallback (snooze, XmNactivateCallback, SnoozeCallback, NULL);
  2301.  
  2302.   /*
  2303.    * get the alarm message and put it in text widget
  2304.    */
  2305.   GetAlarmMessage (argv[1]);
  2306.  
  2307.   XtRealizeWidget (top);
  2308.  
  2309.   /*
  2310.    * if beep on then set up beep timeout
  2311.    */
  2312.   if (myresources.beep_on) {
  2313.     XBell (XtDisplay(top), myresources.beep_volume);
  2314.     BeepId = XtAppAddTimeOut (context,
  2315.                   myresources.beep_freq*MS,
  2316.                   TimeOutEvent,
  2317.                   NULL);
  2318.   }
  2319.  
  2320.   XtAppMainLoop(context);
  2321. }
  2322.  
  2323. /*
  2324.  * Function:
  2325.  */
  2326. CreateApplicationWidgets()
  2327. /*
  2328.  * Create the main display widgets
  2329.  */
  2330. {
  2331.   Arg    args[10];
  2332.   int    n;
  2333.  
  2334.   form = XmCreateForm (top,
  2335.                "form",
  2336.                NULL,0);
  2337.   XtManageChild (form);
  2338.  
  2339.   n = SetArgs (args,
  2340.            XmNtopAttachment, XmATTACH_FORM,
  2341.            XmNleftAttachment, XmATTACH_FORM,
  2342.            NULL);
  2343.   ok = XmCreatePushButton (form,
  2344.                "OK",
  2345.                args,n);
  2346.   XtManageChild (ok);
  2347.  
  2348.   n = SetArgs (args,
  2349.            XmNtopAttachment, XmATTACH_FORM,
  2350.            XmNrightAttachment, XmATTACH_FORM,
  2351.            NULL);
  2352.   snooze = XmCreatePushButton (form,
  2353.                    "Snooze",
  2354.                    args,n);
  2355.   XtManageChild (snooze);
  2356.  
  2357.   n = SetArgs (args,
  2358.            XmNeditMode, XmMULTI_LINE_EDIT,
  2359.                XmNcolumns, 40,
  2360.                XmNrows, 12,
  2361.                XmNwordWrap, True,
  2362.                XmNscrollHorizontal, False,
  2363.                XmNautoShowCursorPosition, True,
  2364.                XmNcursorPositionVisible, True,
  2365.                XmNblinkRate, 0,
  2366.            XmNeditable, False,
  2367.            NULL);
  2368.   text = XmCreateScrolledText (form,
  2369.                    "text",
  2370.                    args,n);
  2371.   XtManageChild (text);
  2372.   n = SetArgs (args,
  2373.                XmNtopAttachment, XmATTACH_WIDGET,
  2374.                XmNtopWidget, ok,
  2375.                XmNleftAttachment, XmATTACH_FORM,
  2376.            XmNeditMode, XmMULTI_LINE_EDIT,
  2377.                NULL);
  2378.   XtSetValues (XtParent(text), args, n);
  2379. }
  2380.  
  2381. /*
  2382.  * Function:
  2383.  */
  2384. GetAlarmMessage (fname)
  2385. char    *fname;
  2386. /*
  2387.  * The the alarm message text and put it in the text widget
  2388.  */
  2389. {
  2390.   char    *buffer;
  2391.   Arg    args[2];
  2392.  
  2393.   if ((buffer = ReadMessageText(fname)) == NULL) {
  2394.     fprintf (stderr,"Can't open %s.\n",fname);
  2395.     exit(1);
  2396.   }
  2397.   
  2398.   XtSetArg (args[0], XmNvalue, buffer);
  2399.   XtSetValues (text, args, 1);
  2400. }
  2401.  
  2402. /*
  2403.  * Function:
  2404.  */
  2405. void
  2406. OKCallback (w, client, call)
  2407. Widget    w;
  2408. caddr_t    client, call;
  2409. /*
  2410.  * Callback attached to the "OK" button.  Just exit the application.
  2411.  */
  2412. {
  2413.   exit(0);
  2414. }
  2415.  
  2416. /*
  2417.  * Function:
  2418.  */
  2419. void
  2420. SnoozeCallback (w, client, call)
  2421. Widget    w;
  2422. caddr_t    client, call;
  2423. /*
  2424.  * Callback attached to the "Snooze" button.  Set up a timeout event
  2425.  * to occur in the number of seconds the user specified for the snooze
  2426.  * time and then unmap the application (so it disappears).  The timeout
  2427.  * event will remap the application.
  2428.  */
  2429. {
  2430.   void    TimeOut();
  2431.  
  2432.   XtAppAddTimeOut (XtWidgetToApplicationContext(top),
  2433.            SysSnoozeTime,
  2434.            TimeOut,
  2435.            NULL);
  2436.  
  2437.   XtUnmapWidget (top);
  2438.  
  2439.   /*
  2440.    * Remove the beeper timeout if present
  2441.    */
  2442.   if (BeepId != 0)
  2443.     XtRemoveTimeOut (BeepId);
  2444.  
  2445. }
  2446.  
  2447. /*
  2448.  * Function:
  2449.  */
  2450. void 
  2451. TimeOut (w, client, call)
  2452. Widget    w;
  2453. caddr_t    client, call;
  2454. /*
  2455.  * remap the application after the snooze time has expired
  2456.  */
  2457. {
  2458.   XtMapWidget (top);
  2459.  
  2460.   /*
  2461.    * re-establish beep timeout if specified
  2462.    */
  2463.   if (myresources.beep_on) {
  2464.     XBell (XtDisplay(top), myresources.beep_volume);
  2465.     BEEPTIMES = 5;
  2466.     BeepId = XtAppAddTimeOut (XtWidgetToApplicationContext(top),
  2467.                   myresources.beep_freq*MS,
  2468.                   TimeOutEvent,
  2469.                   NULL);
  2470.   }
  2471. }
  2472.  
  2473. /*
  2474.  * These arrays are kept to display nice text for the alarm time
  2475.  */
  2476. char    *Days[] = {
  2477.   "Sun",
  2478.   "Mon",
  2479.   "Tue",
  2480.   "Wed",
  2481.   "Thu",
  2482.   "Fri",
  2483.   "Sat"
  2484.   };
  2485.  
  2486. char    *Months[] = {
  2487.   "Jan",
  2488.   "Feb",
  2489.   "Mar",
  2490.   "Apr",
  2491.   "May",
  2492.   "Jun",
  2493.   "Jul",
  2494.   "Aug",
  2495.   "Sep",
  2496.   "Oct",
  2497.   "Nov",
  2498.   "Dec"
  2499.   };
  2500.  
  2501. /*
  2502.  * Function:
  2503.  */
  2504. Recover (num_args, args)
  2505. int    num_args;
  2506. char    **args;
  2507. /*
  2508.  * Can't open the display.  We'll just write the message to stdout and
  2509.  * at will mail it to the user.
  2510.  */
  2511. {
  2512.   char    *fname = args[num_args-1];
  2513.   int    fp;
  2514.   struct tm *theTime, *localtime();
  2515.   long    clock;
  2516.   char    line[120];
  2517.   char    *buffer;
  2518.   int    buf_size;
  2519.  
  2520.   clock = time ((long *)0);
  2521.   theTime = localtime(&clock);
  2522.  
  2523.   printf ("xalarm message sent at %d:%02d on %s, %s %d :\n", theTime->tm_hour,
  2524.       theTime->tm_min, 
  2525.       Days[theTime->tm_wday],
  2526.       Months[theTime->tm_mon],
  2527.       theTime->tm_mday);
  2528.  
  2529.   if ((fp = open (fname, O_RDONLY, 0644)) == -1) {
  2530.     printf ("Can't open %s to display.\n",fname);
  2531.     exit(1);
  2532.   }
  2533.  
  2534.   read (fp, &buf_size, sizeof(int));
  2535.   buffer = (char *) XtMalloc (buf_size+5);
  2536.   read (fp, buffer, buf_size);
  2537.   buffer[buf_size] = '\0';
  2538.  
  2539.   printf ("%s\n",buffer);
  2540.  
  2541.   close(fp);
  2542.   return(0);
  2543. }
  2544.  
  2545. void
  2546. TimeOutEvent (client, id)
  2547. caddr_t        client;
  2548. XtIntervalId    id;
  2549. /*
  2550.  * when beep timeout occurs
  2551.  */
  2552. {
  2553.   XBell (XtDisplay(top), myresources.beep_volume);
  2554.  
  2555.   if ( (--BEEPTIMES) ) {
  2556.     BeepId = XtAppAddTimeOut (XtWidgetToApplicationContext(top),
  2557.                   myresources.beep_freq*MS,
  2558.                   TimeOutEvent,
  2559.                   NULL);
  2560.   }
  2561.   else {
  2562.     BeepId = 0;
  2563.   }
  2564. }
  2565. @EOF
  2566. exit 0
  2567.  
  2568. --
  2569. Dan Heller
  2570. Z-Code Software    O'Reilly && Associates       Comp-sources-x:
  2571. President          Senior Writer                comp-sources-x@uunet.uu.net
  2572. argv@z-code.com    argv@ora.com                 [^^^  this address only!]
  2573.