home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / x / volume13 / xmail / part06 / Mailwatch.c < prev   
C/C++ Source or Header  |  1991-06-15  |  21KB  |  711 lines

  1. /*
  2.  * @(#)Mailwatch.c - MODIFIED for use as an active icon in the xmail program.
  3.  *
  4.  * Author:  Dan Heller <island!argv@sun.com>
  5.  * This code was stolen from Mailbox.c --the widget which supports "xbiff"
  6.  * written by Jim Fulton which was apparently stolen from Clock.c, the widget
  7.  * which supports "xclock."  Note, you are witnessing the big bang theory of
  8.  * software development (everything is a subclass of universeWidgetClass).
  9.  *
  10.  * Major changes:
  11.  * XtRemoveTimeOut() is called before calling XtAddTimeOut().  The original
  12.  * xbiff would eventually timeout all the time rather than every 30 seconds
  13.  * because the old timer was never removed.
  14.  *
  15.  * User can specify any icon he chooses for either the up flag or the down
  16.  * flag.  Icons don't need to be the same size (defaults to flagup/flagdown).
  17.  *
  18.  * When new mail comes in, a user supplied callback function is invoked.
  19.  *
  20.  * The mailbox flag goes up when there is new mail _and_ the user hasn't
  21.  * read it yet.  As soon as the user updates the access time on the mailbox,
  22.  * the flag goes down.  This removes the incredibly annoying habit xbiff
  23.  * had where you read some mail but not delete it from the mailbox and the
  24.  * flag would remain up.
  25.  *
  26.  * Destroy() will now destroy the flagup and flagdown pixmaps.
  27.  *
  28. ** November 1990 - Michael C. Wagnitz - National Semiconductor Corporation
  29. ** The following modifications were made for use in xmail.
  30. **
  31. ** Added options to display username or mail server host name in icon window.
  32. **
  33. ** November 1989 - Michael C. Wagnitz - National Semiconductor Corporation
  34. **
  35. ** Removed button handler, custom cursor, and 'from()' reader functions.
  36. ** Added reset_mailbox() function, my own icons (56x56 bits), and also
  37. ** added timer initialization to Initialize() routine (we might not ever be
  38. ** Realized, if the user never iconifies my parent).  This also fixes a Sun4
  39. ** bug for trying to remove an initial interval_id with a garbage address.
  40. ** Also changed check_mailbox() to test access time vs. modified and zero size
  41. ** of file, rather than trying to track our last access or increase in size.
  42. **
  43. ** Copyright 1990 by National Semiconductor Corporation
  44. **
  45. ** Permission to use, copy, modify, and distribute this software and its
  46. ** documentation for any purpose is hereby granted without fee, provided that
  47. ** the above copyright notice appear in all copies and that both that
  48. ** copyright notice and this permission notice appear in supporting
  49. ** documentation, and that the name of National Semiconductor Corporation not
  50. ** be used in advertising or publicity pertaining to distribution of the
  51. ** software without specific, written prior permission.
  52. **
  53. ** NATIONAL SEMICONDUCTOR CORPORATION MAKES NO REPRESENTATIONS ABOUT THE
  54. ** SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS"
  55. ** WITHOUT EXPRESS OR IMPLIED WARRANTY.  NATIONAL SEMICONDUCTOR CORPORATION
  56. ** DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
  57. ** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO
  58. ** EVENT SHALL NATIONAL SEMICONDUCTOR CORPORATION BE LIABLE FOR ANY SPECIAL,
  59. ** INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  60. ** LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  61. ** OR OTHER TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  62. ** PERFORMANCE OF THIS SOFTWARE.
  63. **
  64. ** The following software modules were created and are Copyrighted by National
  65. ** Semiconductor Corporation:
  66. **
  67. ** 1. reset_mailbox,
  68. ** 2. set_host,
  69. ** 3. set_user,
  70. ** 4. set_none, and
  71. ** 5. GetMailHostName.
  72. **
  73. ** Author:  Michael C. Wagnitz - National Semiconductor Corporation
  74. **
  75. */
  76.  
  77.  
  78. #include <X11/Xos.h>
  79. #include <X11/IntrinsicP.h>        /* for toolkit stuff */
  80. #include <X11/cursorfont.h>        /* for cursor constants */
  81. #include <X11/StringDefs.h>        /* for useful atom names */
  82. #include "MailwatchP.h"            /* for implementation mailbox stuff */
  83. #include <stdio.h>            /* for printing error messages */
  84. #include <sys/stat.h>            /* for stat() */
  85. #include <sys/param.h>            /* for MAXHOSTNAMELEN */
  86. #include <pwd.h>            /* for getting username */
  87. #include <errno.h>
  88. #include "icon.mail"            /* for flag up (mail present) bits */
  89. #include "icon.nomail"            /* for flag down (mail not here) */
  90.  
  91. #include <X11/Xaw/XawInit.h>
  92. #include <X11/Xmu/Converters.h>        /* for XmuCvtStringToBitmap */
  93.  
  94. #define between(x, i, y)   ((i) < (x) ? (x) : (i) > (y) ? (y) : (i))
  95.  
  96. #define REMOVE_TIMEOUT(id) if (!id) ; else XtRemoveTimeOut(id)
  97.  
  98. static struct stat    stbuf;
  99. static Boolean        SetValues();
  100. static Pixmap        make_pixmap();
  101. static GC        GetNormalGC(), GetInvertGC();
  102. static void        GetMailFile(), GetUserName(), GetMailHostName(),
  103.             CloseDown(), check_mailbox(), redraw_mailbox(),
  104.             ClassInitialize(), Initialize(), Destroy(),
  105.             Realize(), Redisplay(), clock_tic(), set_title();
  106. extern void        reset_mailbox(), set_host(), set_user(), set_none();
  107. extern Widget        toplevel;
  108.  
  109. #define min(a,b) ((a) < (b) ? (a) : (b))
  110. #define max(a,b) ((a) > (b) ? (a) : (b))
  111.  
  112. static char defaultTranslations[] =
  113.     "<Key>h:        set-host()    \n\
  114.      <Key>u:        set-user()    \n\
  115.      <Key>space:    set-none()";
  116.  
  117. static XtActionsRec actionsList[] = {
  118.     { "set-host",    set_host    },
  119.     { "set-user",    set_user    },
  120.     { "set-none",    set_none    },
  121. };
  122.  
  123. /* Initialization of defaults */
  124. #define offset(field) XtOffset(MailwatchWidget,mailbox.field)
  125. #define goffset(field) XtOffset(Widget,core.field)
  126.  
  127.  
  128. static XtResource resources[] = {
  129.     {XtNupdate, XtCInterval, XtRInt, sizeof(int),
  130.     offset(update), XtRImmediate, (caddr_t) 30 },
  131.     {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
  132.     offset(foreground_pixel), XtRString, XtDefaultForeground },
  133.     {XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
  134.     goffset(background_pixel), XtRString, XtDefaultBackground },
  135.     {XtNreverseVideo, XtCBoolean, XtRBoolean, sizeof(Boolean),
  136.     offset(reverseVideo), XtRImmediate, (caddr_t) False },
  137.     {XtNbell, XtCBoolean, XtRBoolean, sizeof(Boolean),
  138.     offset(bell), XtRImmediate, (caddr_t) True },
  139.     {XtNfile, XtCFile, XtRString, sizeof(String),
  140.     offset(filename), XtRString, NULL},
  141.     {XtNnoMailFlag, XtCPixmap, XtRBitmap, sizeof(Pixmap),
  142.     offset(nomail.bitmap), XtRString, NULL},
  143.     {XtNmailFlag, XtCPixmap, XtRBitmap, sizeof(Pixmap),
  144.     offset(mail.bitmap), XtRString, NULL},
  145.     {XtNcallback, XtCCallback, XtRCallback, sizeof(caddr_t),
  146.     offset(callback), XtRCallback, NULL},
  147.     {"useName", XtCBoolean, XtRBoolean, sizeof(Boolean),
  148.     offset(useName), XtRString, "FALSE" },
  149.     {"useHost", XtCBoolean, XtRBoolean, sizeof(Boolean),
  150.     offset(useHost), XtRString, "FALSE" },
  151.     { XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
  152.     offset(font), XtRString, "fixed"},
  153. };
  154.  
  155. #undef offset
  156. #undef goffset
  157.  
  158. MailwatchClassRec mailwatchClassRec = {
  159.     {    /* core fields */
  160.     /* superclass        */ &widgetClassRec,
  161.     /* class_name        */ "Mailwatch",
  162.     /* widget_size        */ sizeof(MailwatchRec),
  163.     /* class_initialize    */ ClassInitialize,
  164.     /* class_part_initialize*/ NULL,
  165.     /* class_inited     */ FALSE,
  166.     /* initialize        */ Initialize,
  167.     /* initialize_hook    */ NULL,
  168.     /* realize        */ Realize,
  169.     /* actions        */ actionsList,
  170.     /* num_actions        */ XtNumber(actionsList),
  171.     /* resources        */ resources,
  172.     /* resource_count    */ XtNumber(resources),
  173.     /* xrm_class        */ NULL,
  174.     /* compress_motion    */ TRUE,
  175.     /* compress_exposure    */ TRUE,
  176.     /* compress_enterleave    */ TRUE,
  177.     /* visible_interest    */ FALSE,
  178.     /* destroy        */ Destroy,
  179.     /* resize        */ NULL,
  180.     /* expose        */ Redisplay,
  181.     /* set_values        */ SetValues,
  182.     /* set_values_hook    */ NULL,
  183.     /* set_values_almost    */ XtInheritSetValuesAlmost,
  184.     /* get_values_hook    */ NULL,
  185.     /* accept_focus        */ NULL,
  186.     /* version        */ XtVersion,
  187.     /* callback_private    */ NULL,
  188.     /* tm_table        */ defaultTranslations,
  189.     /* query_geometry    */ NULL,
  190.     }
  191. };
  192.  
  193. WidgetClass mailwatchWidgetClass = (WidgetClass) & mailwatchClassRec;
  194.  
  195. /*
  196.  * private procedures
  197.  */
  198. static Pixmap
  199. make_pixmap (dpy, w, bitmap, depth, widthp, heightp)
  200. Display        *dpy;
  201. MailwatchWidget    w;
  202. Pixmap        bitmap;
  203. int        depth;
  204. int        *widthp, *heightp;
  205. {
  206.  Window root;
  207.  int x, y;
  208.  unsigned int width, height, bw, dep;
  209.  unsigned long fore, back;
  210.  
  211.  
  212.  if (bitmap == 0 ||
  213.      ! XGetGeometry(dpy, bitmap, &root, &x, &y, &width, &height, &bw, &dep))
  214.     return None;
  215.  
  216.  *widthp = (int) width;
  217.  *heightp = (int) height;
  218.  fore = w->mailbox.foreground_pixel;
  219.  back = w->core.background_pixel;
  220.  return XmuCreatePixmapFromBitmap(dpy, w->core.window, bitmap, 
  221.                       width, height, depth, fore, back);
  222. }
  223.  
  224.  
  225. static void
  226. ClassInitialize()
  227. {
  228.  static XtConvertArgRec screenConvertArg[] = {
  229.     { XtWidgetBaseOffset, (caddr_t) XtOffset(Widget, core.screen), sizeof(Screen *) }
  230.     };
  231.  
  232.  XawInitializeWidgetSet();
  233.  XtAddConverter (XtRString, XtRBitmap, XmuCvtStringToBitmap,
  234.             screenConvertArg, XtNumber(screenConvertArg));
  235.  return;
  236. } /* ClassInitialize */
  237.  
  238.  
  239. static void
  240. Initialize(request, new)
  241. Widget request, new;
  242. {
  243.     MailwatchWidget w = (MailwatchWidget) new;
  244.  
  245.     GetUserName(w);
  246.  
  247.     GetMailHostName(w);
  248.  
  249.     if (!w->mailbox.filename)
  250.     GetMailFile(w);
  251.  
  252.     if (w->mailbox.reverseVideo) {
  253.     Pixel tmp;
  254.  
  255.     tmp = w->mailbox.foreground_pixel;
  256.     w->mailbox.foreground_pixel = w->core.background_pixel;
  257.     w->core.background_pixel = tmp;
  258.     }
  259.  
  260.     GetNormalGC(w);
  261.  
  262.     GetInvertGC(w);
  263.  
  264.     w->mailbox.flag_up = FALSE;        /* because it hasn't been shown yet */
  265.     w->mailbox.mail.pixmap = None;
  266.     w->mailbox.nomail.pixmap = None;
  267.  
  268.     w->mailbox.last_access = (stat(w->mailbox.filename, &stbuf) == 0) ?
  269.                              stbuf.st_atime : 0 ;    /* last accessed */
  270.     return;
  271. }
  272.  
  273.  
  274. static void
  275. clock_tic(client_data, id)
  276. caddr_t client_data;
  277. XtIntervalId *id;
  278. {
  279.     MailwatchWidget w = (MailwatchWidget) client_data;
  280.  
  281.     check_mailbox(w, FALSE);
  282. }
  283.  
  284.  
  285. static void
  286. set_title(str)
  287. String    str;
  288. {
  289.  Display    *dpy = XtDisplay(toplevel);
  290.  Window        win  = XtWindow(toplevel);
  291.  String        c, name, title;
  292.  
  293.  
  294.  XFetchName(dpy, win, &name);
  295.  if (! name)
  296.     name = XtNewString("xmail");
  297.  else
  298.     if ((c = (char *)strrchr(name, '_')) != NULL)
  299.         *c = '\0';
  300.  
  301.  if (! *str)
  302.     title = XtMalloc(strlen(name) + 1);
  303.  else
  304.     title = XtMalloc(strlen(name) + strlen(str) + 2);
  305.  
  306.  if (! title)
  307.     XtError("xmail: Insufficient memory to allocate title space");
  308.  
  309.  if (! *str)
  310.     sprintf(title, "%s", name);
  311.  else
  312.     sprintf(title, "%s_%s", name, str);
  313.  
  314.  XStoreName(dpy, win, title);
  315.  
  316.  XtFree(name);
  317.  XtFree(title);
  318. } /* end - set_title */
  319.  
  320.  
  321. void
  322. set_host(m)
  323. MailwatchWidget        m;
  324. {
  325.  register Display    *dpy = XtDisplay(m);
  326.  register Window    win = XtWindow(m);
  327.  register int        x, y, h, w;
  328.  
  329.  
  330.  set_title(m->mailbox.mailhost);
  331.  
  332.  m->mailbox.useHost = True;
  333.  m->mailbox.useName = False;
  334.  h = m->mailbox.font->max_bounds.width - m->mailbox.font->max_bounds.lbearing;
  335.  w = strlen(m->mailbox.mailhost);
  336.  h = (h * w) - 2;
  337.  x = max(m->core.width - h, 2);            /* if (x < 2) x = 2; */
  338.  x /= 2;
  339.  y = m->core.height - m->mailbox.font->descent;
  340.  
  341.  XFillRectangle(dpy, win, m->mailbox.invert_GC,
  342.                       0, y - m->mailbox.font->ascent, m->core.width,
  343.                       m->mailbox.font->ascent + m->mailbox.font->descent);
  344.  
  345.  XDrawString(dpy, win, m->mailbox.normal_GC, x, y, m->mailbox.mailhost, w);
  346. } /* end - set_host */
  347.  
  348.  
  349. void
  350. set_user(m)
  351. MailwatchWidget        m;
  352. {
  353.  register Display    *dpy = XtDisplay(m);
  354.  register Window    win = XtWindow(m);
  355.  register int        x, y, h, w;
  356.  
  357.  
  358.  set_title(m->mailbox.username);
  359.  
  360.  m->mailbox.useHost = False;
  361.  m->mailbox.useName = True;
  362.  h = m->mailbox.font->max_bounds.width - m->mailbox.font->max_bounds.lbearing;
  363.  w = strlen(m->mailbox.username);
  364.  h = (h * w) - 2;
  365.  x = max(m->core.width - h, 2);            /* if (x < 2) x = 2; */
  366.  x /= 2;
  367.  y = m->core.height - m->mailbox.font->descent;
  368.  
  369.  XFillRectangle(dpy, win, m->mailbox.invert_GC,
  370.                       0, y - m->mailbox.font->ascent, m->core.width,
  371.                       m->mailbox.font->ascent + m->mailbox.font->descent);
  372.  
  373.  XDrawString(dpy, win, m->mailbox.normal_GC, x, y, m->mailbox.username, w);
  374. } /* end - set_user */
  375.  
  376.  
  377. void
  378. set_none(m)
  379. MailwatchWidget        m;
  380. {
  381.  set_title("");
  382.  m->mailbox.useHost = m->mailbox.useName = False;
  383.  redraw_mailbox(m);
  384. } /* end - set_none */
  385.  
  386.  
  387. static GC
  388. GetNormalGC(w)
  389. MailwatchWidget w;
  390. {
  391.     XtGCMask valuemask;
  392.     XGCValues xgcv;
  393.  
  394.     valuemask = GCForeground | GCBackground | GCFunction | GCGraphicsExposures;
  395.     xgcv.foreground = w->mailbox.foreground_pixel;
  396.     xgcv.background = w->core.background_pixel;
  397.     xgcv.function = GXcopy;
  398.     xgcv.graphics_exposures = False;
  399.     w->mailbox.normal_GC = XtGetGC((Widget) w, valuemask, &xgcv);
  400. }
  401.  
  402. static GC
  403. GetInvertGC(w)
  404. MailwatchWidget w;
  405. {
  406.     XtGCMask valuemask;
  407.     XGCValues xgcv;
  408.  
  409.     valuemask = GCForeground | GCBackground | GCFunction | GCGraphicsExposures;
  410.     xgcv.foreground = w->core.background_pixel;
  411.     xgcv.background = w->mailbox.foreground_pixel;
  412.     xgcv.function = GXcopy;
  413.     xgcv.graphics_exposures = False;    /* this is Bool, not Boolean */
  414.     w->mailbox.invert_GC = XtGetGC((Widget) w, valuemask, &xgcv);
  415. }
  416.  
  417.  
  418. static void
  419. Realize(gw, valuemaskp, attr)
  420. Widget gw;
  421. XtValueMask *valuemaskp;
  422. XSetWindowAttributes *attr;
  423. {
  424.  MailwatchWidget w = (MailwatchWidget) gw;
  425.  register Display *dpy = XtDisplay(w);
  426.  int depth = w->core.depth;
  427.  
  428.  
  429.  XtCreateWindow(gw, InputOutput, (Visual *) CopyFromParent, *valuemaskp, attr);
  430. /*
  431. * build up the pixmaps that we'll put into the image
  432. */
  433.  if (w->mailbox.mail.bitmap == None)
  434.      w->mailbox.mail.bitmap = XCreateBitmapFromData(dpy, w->core.window,
  435.                     mail_bits, mail_width, mail_height);
  436.  
  437.  if (w->mailbox.nomail.bitmap == None)
  438.      w->mailbox.nomail.bitmap = XCreateBitmapFromData(dpy, w->core.window,
  439.                 no_mail_bits, no_mail_width, no_mail_height);
  440.  
  441.  w->mailbox.nomail.pixmap = make_pixmap (dpy, w, w->mailbox.nomail.bitmap,
  442.                        depth,
  443.                        &w->mailbox.nomail.width,
  444.                        &w->mailbox.nomail.height);
  445.  
  446.  w->mailbox.mail.pixmap = make_pixmap (dpy, w, w->mailbox.mail.bitmap,
  447.                       depth,
  448.                       &w->mailbox.mail.width,
  449.                       &w->mailbox.mail.height);
  450.     /* the size of the icon should be the size of the larger icon. */
  451.  if (w->core.width == 0)
  452.      w->core.width = max(w->mailbox.mail.width, w->mailbox.nomail.width);
  453.  if (w->core.height == 0)
  454.      w->core.width = max(w->mailbox.mail.height, w->mailbox.nomail.height);
  455.  
  456. /* set status check timer */
  457.  w->mailbox.interval_id = XtAddTimeOut(w->mailbox.update * 1000,
  458.                                             clock_tic, (caddr_t) w);
  459. }
  460.  
  461. static void
  462. Destroy(gw)
  463. Widget gw;
  464. {
  465.     MailwatchWidget w = (MailwatchWidget) gw;
  466.     Display    *dpy = XtDisplay(gw);
  467.  
  468.     XtFree(w->mailbox.filename);
  469.     XtFree(w->mailbox.username);
  470.     XtFree(w->mailbox.mailhost);
  471.     REMOVE_TIMEOUT(w->mailbox.interval_id);
  472.     XtReleaseGC(w, w->mailbox.normal_GC);
  473.     XFreePixmap(dpy, w->mailbox.mail.bitmap);
  474.     XFreePixmap(dpy, w->mailbox.mail.pixmap);
  475.     XFreePixmap(dpy, w->mailbox.mail.mask);
  476.     XFreePixmap(dpy, w->mailbox.nomail.bitmap);
  477.     XFreePixmap(dpy, w->mailbox.nomail.pixmap);
  478.     XFreePixmap(dpy, w->mailbox.nomail.mask);
  479. }
  480.  
  481. static void
  482. Redisplay(gw)
  483. Widget gw;
  484. {
  485.     MailwatchWidget w = (MailwatchWidget) gw;
  486.  
  487.     REMOVE_TIMEOUT(w->mailbox.interval_id);
  488.     check_mailbox(w, TRUE);
  489. }
  490.  
  491.  
  492. /*
  493. ** Modified to NOT update the mail file timestamp via utimes(), and to
  494. ** ignore state change where mail adds a status record to the message.
  495. ** The first eliminates collisions with mail during delivery, and the
  496. ** second eliminates false triggers for new mail.  The number of times
  497. ** the terminal bell is rung is controlled by the same .mailrc resource
  498. ** (bell) used by Sunview's mailtool.
  499. */
  500. static void
  501. check_mailbox(w, force_redraw)
  502. MailwatchWidget w;
  503. Boolean force_redraw;
  504. {
  505.  int        i, redraw = 0;
  506.  char        *p = NULL;
  507.  
  508.  
  509.  if (stat(w->mailbox.filename, &stbuf) < 0) {        /* no mail file */
  510.     if (w->mailbox.flag_up == TRUE) {
  511.        force_redraw = 0;
  512.        UnsetNewmail(w, NULL, NULL);
  513.       }
  514.    } else {
  515.     if (stbuf.st_atime > stbuf.st_mtime &&
  516.         stbuf.st_atime >= w->mailbox.last_access) {    /* mail was seen */
  517.        w->mailbox.last_access = stbuf.st_atime;
  518.        if (w->mailbox.flag_up == TRUE) {
  519.           force_redraw = 0;
  520.           UnsetNewmail(w, NULL, NULL);
  521.          }
  522.       } else {
  523.        if (stbuf.st_size != 0 && 
  524.            stbuf.st_mtime > w->mailbox.last_access) {    /* got new mail */
  525.           w->mailbox.last_access = stbuf.st_mtime;
  526.           if (w->mailbox.flag_up == FALSE) {
  527.              if (w->mailbox.bell) {
  528.                 i = 1;
  529.                 if (p = (char *)GetMailrc("bell"))
  530.                    sscanf(p, "%d", &i);
  531.                 i = between(1, i, 5);
  532.                 for (; i > 0; i--)
  533.                     XBell(XtDisplay(w), MAILBOX_VOLUME);
  534.                }
  535.              w->mailbox.flag_up = TRUE;
  536.              redraw = TRUE;
  537.              XtCallCallbacks(w, XtNcallback, NULL);
  538.             }
  539.          }
  540.       }
  541.    }
  542.  
  543.  if (redraw || force_redraw)
  544.     redraw_mailbox(w);
  545.  
  546.  /* reset timer */
  547.  w->mailbox.interval_id = XtAddTimeOut(w->mailbox.update * 1000,
  548.     clock_tic, (caddr_t) w);
  549. } /* check_mailbox */
  550.  
  551. /*
  552. ** Retrieve the user's mailbox filename - use MAIL environment value, if set
  553. */
  554. static void
  555. GetMailFile(w)
  556. MailwatchWidget w;
  557. {
  558.  if (! (w->mailbox.filename = (char *) GetMailEnv("MAIL"))) {
  559.     if (! (w->mailbox.filename = (String) XtMalloc(strlen(MAILBOX_DIRECTORY) + 1
  560.       + strlen(w->mailbox.username) + 1))) {
  561.        fprintf(stderr, "Mailbox widget: can't allocate enough memory.\n");
  562.        CloseDown(w, 1);
  563.       }
  564.     sprintf(w->mailbox.filename,"%s/%s\0",MAILBOX_DIRECTORY,w->mailbox.username);
  565.    }
  566. } /* GetMailFile */
  567.  
  568.  
  569. /*
  570. ** Retrieve the mailbox user's name
  571. */
  572. static void
  573. GetUserName(w)
  574. MailwatchWidget w;
  575. {
  576.  char *username = (char *)getlogin();
  577.  
  578.  if (! username) {
  579.     struct passwd *pw = getpwuid(getuid());
  580.  
  581.     if (! pw) {
  582.        fprintf(stderr, "Mailbox widget: can't find your username.\n");
  583.        CloseDown(w, 1);
  584.       }
  585.     username = pw->pw_name;
  586.    }
  587.  
  588.  if (! (w->mailbox.username = XtNewString(username))) {
  589.     XtWarning("Mailbox widget: can't allocate space for username.\n");
  590.     CloseDown(w, 1);
  591.    }
  592. } /* GetUserName */
  593.  
  594.  
  595. /*
  596. ** Retrieve the mail server's host name
  597. */
  598. static void
  599. GetMailHostName(w)
  600. MailwatchWidget w;
  601. {
  602.  FILE    *stream, *popen();
  603.  char    buf[BUFSIZ], hostname[MAXHOSTNAMELEN], *mailhost = NULL;
  604.  int    n;
  605.  
  606.  
  607.  sprintf(buf, "/usr/lib/sendmail -bv %s < /dev/null", w->mailbox.username);
  608.  if (stream = popen(buf, "r")) {
  609.     if (fgets(buf, BUFSIZ, stream)) {
  610.        for (n = 0; buf[n] && buf[n] != '@'; n++);
  611.        if (! buf[n])
  612.           n = strlen(w->mailbox.username);
  613.        mailhost = &buf[++n];            /* starting beyond username */
  614.        for (; buf[n] && buf[n] != '.'; n++);    /* until we find ellipsis */
  615.        buf[n] = '\0';
  616.       }
  617.     pclose(stream);
  618.    }
  619.  
  620.  if (*mailhost == NULL) {
  621.     gethostname(hostname, MAXHOSTNAMELEN);
  622.     mailhost = hostname;
  623.    }
  624.  
  625.  if (! (w->mailbox.mailhost = XtNewString(mailhost))) {
  626.     XtWarning("Mailbox widget: can't allocate space for mailhost.\n");
  627.     CloseDown(w, 1);
  628.    }
  629. } /* GetMailHostName */
  630.  
  631.  
  632. static void
  633. CloseDown(w, status)
  634. MailwatchWidget w;
  635. int status;
  636. {
  637.     Display *dpy = XtDisplay(w);
  638.  
  639.     XtDestroyWidget(w);
  640.     XCloseDisplay(dpy);
  641.     _exit(status);
  642. }
  643.  
  644. static Boolean
  645. SetValues(gcurrent, grequest, gnew)
  646. Widget gcurrent, grequest, gnew;
  647. {
  648.     MailwatchWidget current = (MailwatchWidget) gcurrent;
  649.     MailwatchWidget new = (MailwatchWidget) gnew;
  650.     Boolean redisplay = FALSE;
  651.  
  652.     if (current->mailbox.update != new->mailbox.update) {
  653.     REMOVE_TIMEOUT(current->mailbox.interval_id);
  654.     new->mailbox.interval_id = XtAddTimeOut(new->mailbox.update * 1000,
  655.         clock_tic,
  656.         (caddr_t) gnew);
  657.     }
  658.     if (current->mailbox.foreground_pixel != new->mailbox.foreground_pixel ||
  659.     current->core.background_pixel != new->core.background_pixel) {
  660.     XtReleaseGC(current, current->mailbox.normal_GC);
  661.     GetNormalGC(new);
  662.     redisplay = TRUE;
  663.     }
  664.     return (redisplay);
  665. }
  666.  
  667. /*
  668.  * drawing code
  669.  */
  670. static void
  671. redraw_mailbox(m)
  672. MailwatchWidget m;
  673. {
  674.     register Display    *dpy = XtDisplay(m);
  675.     register Window    win = XtWindow(m);
  676.     register int    x, y;
  677.     Pixel        back = m->core.background_pixel;
  678.     GC            gc = m->mailbox.normal_GC;
  679.     struct _mbimage    *im;
  680.  
  681.  
  682.     if (m->mailbox.flag_up)            /* paint the "up" position */
  683.     im = &m->mailbox.mail;
  684.     else                    /* paint the "down" position */
  685.     im = &m->mailbox.nomail;
  686.  
  687.     /* center the picture in the window */
  688.     x = ((int)m->core.width - im->width) / 2;
  689.     y = ((int)m->core.height - im->height) / 2;
  690.  
  691.     XSetWindowBackground(dpy, win, back);
  692.     XClearWindow(dpy, win);
  693.     XCopyArea(dpy, im->pixmap, win, gc, 0, 0, im->width, im->height, x, y);
  694.  
  695.     if (m->mailbox.useHost || m->mailbox.useName) {
  696.        if (m->mailbox.useHost) set_host(m);
  697.        else set_user(m);
  698.       }
  699. }
  700.  
  701.  
  702. void
  703. reset_mailbox(gw)
  704. Widget    gw;
  705. {
  706.  MailwatchWidget w = (MailwatchWidget) gw;
  707.  
  708.  w->mailbox.flag_up = FALSE;
  709.  redraw_mailbox(w);
  710. } /* reset_mailbox */
  711.