[comp.sources.bugs] Official patch #11 for faces v1.4.

richb@sunaus.oz (Rich Burridge) (01/14/91)

This is official patch #11 for faces v1.4.

CONTENTS:

1. What is faces?
2/ Changes made in this patch.
3/ How to install this patch.
4/ How to get previous patches.

---------------

1/ What is faces?

Faces is a program for monitoring a list visually. Typically this is a list
of incoming mail messages, jobs in the print queue or users on a system.
Faces has the ability to read compressed faces images embedded in your
mail headers, uncompressing them and displaying them on-the-fly. There are
graphical interfaces for X11, XView, SunView and NeWS.

----------------

2/ Changes made in this patch.

         - Removed the mailing list hack from Gregory Dudek. It doesn't seem
           to work quite right, and it cause the incorrect handling of From:
           lines on other mail items.

         - The check to see if the spool file has changed, needed to call
           show_display() if there was no change, otherwise the old offscreen
           memory pixrects, would not be freed.

         - Added a property sheet to the XView version. This allows you to
           toggle the monitoring option (mail/users/printer/custom) on the fly.

         - Ran faces through Saber-C, and fixed up inconsistencies.

----------------

3/ How to install this patch.

This patch consists of just the one part. You should use Larry Wall's patch
program to apply these changes. Assuming you've saved this article in a file
called patch11, then you should do the following:

cd faces_src        # directory where your faces source files are.
patch <patch11
make xview                   # Or Sunview, X11 or NeWS.
make install                 # You might have to be super-user.

----------------

4/ How to get previous patches.

If you need to get patches 5-10, then they can be obtained from the automatic
mail archive server, by sending a message to rb-archive-server@Aus.Sun.COM
containing the line:
 
send faces patchn
 
where n is the patch number you require.
 
If the mail is likely to go back through any sites that impose a size limit,
then I suggest you divide the above request up into two separate mail
messages.
 
You can also include a path line in these requests to indicate the mail
path that the archive server should use to send the files to you. Such a
path line could be:

path uunet.uu.net!hostname!user

Note that this is uunet.uu.net and not just uunet. Sun.COM doesn't recognise
just uunet.

[NOTE: When unpacking the shars generated by the automatic mail service,
       it is possible you will get error messages for incorrect length.
       Please ignore; hopefully the files should still unpack correctly].

Rich Burridge,          DOMAIN: richb@Aus.Sun.COM
Sun Microsystems.       ACSNET: richb@sunaus.sun.oz
PHONE: +61 2 413 2666   UUCP:   {uunet,mcvax,ukc}!munnari!sunaus.oz!richb

------CUT HERE------patch.11------CUT HERE------

------- patchlevel.h -------
Prereq: 10
*** /tmp/da02124        Sun Jan 13 18:50:35 1991
--- patchlevel.h        Thu Jan 10 15:30:15 1991
***************
*** 14,17 ****
   *  reported to me then an attempt will be made to fix them.
   */

! #define  PATCHLEVEL  10
--- 14,17 ----
   *  reported to me then an attempt will be made to fix them.
   */

! #define  PATCHLEVEL  11
------- get.c -------
*** /tmp/da02106	Sun Jan 13 18:50:29 1991
--- get.c	Sun Jan 13 13:43:13 1991
***************
*** 155,160 ****
--- 155,162 ----
        if (argv[0][0] == '-')
          switch (argv[0][1])
            {
+             case 'D' : debug = TRUE ;
+                        break ;
              case 'H' : mtype = MONUSERS ;  /* Monitor users on a machine. */
                         INC ;
                         getparam(hostname, argv, "-H needs hostname") ;
***************
*** 356,362 ****
    if (sscanf(nextline, "static %s %*[^{]%c", vbuf, &c) != 2) goto err_end ;
    if (strcmp((char *) vbuf, "char") == 0)
      {
!       for (i = 0; i < sizeof(vbuf); vbuf[i++] = 0) ;
        for (i = 0; i < hgt; i++)
          for (j = 0; j < wid; j++)
            {
--- 358,364 ----
    if (sscanf(nextline, "static %s %*[^{]%c", vbuf, &c) != 2) goto err_end ;
    if (strcmp((char *) vbuf, "char") == 0)
      {
!       for (i = 0; i < sizeof(vbuf); vbuf[i++] = 0) continue ;
        for (i = 0; i < hgt; i++)
          for (j = 0; j < wid; j++)
            {
***************
*** 373,379 ****
    else if (strcmp((char *) vbuf, "short") == 0)
      {
        wid = (wid + 1) / 2 ;
!       for (i = 0; i < 256; buf[i++] = 0) ;
        for (i = 0; i < hgt; i++)
          for (j = 0; j < wid; j++)
            {
--- 375,381 ----
    else if (strcmp((char *) vbuf, "short") == 0)
      {
        wid = (wid + 1) / 2 ;
!       for (i = 0; i < 256; buf[i++] = 0) continue ;
        for (i = 0; i < hgt; i++)
          for (j = 0; j < wid; j++)
            {

------- main.c -------
*** /tmp/da02109	Sun Jan 13 18:50:31 1991
--- main.c	Sun Jan 13 13:47:23 1991
***************
*** 124,129 ****
--- 124,130 ----
  int beeps ;             /* Number of beeps for arrival of new mail. */
  int button1clear = 0 ;  /* Set if button 1 should clear the window. */
  int column ;            /* Column number for next icon. */
+ int debug = 0 ;         /* Set with the -D command line option. */
  int doing_xface = 0 ;   /* Set if we've started to process an X-Face: */
  int dontshowno = 0 ;    /* Set if number of messages shouldn't be displayed. */
  int dontshowtime = 0 ;  /* Set if timestamp for new mail shouldn't be shown. */
***************
*** 356,362 ****
  #ifdef SPOOLFILE
    STRCPY(spoolfile, SPOOLFILE) ;   /* Alternative spoolfile to monitor. */
  #else
!   if (envmail = getenv("MAIL")) STRCPY(spoolfile, envmail) ;
    else
      {
        username = getname() ;     /* Get users name from passwd entry. */
--- 357,363 ----
  #ifdef SPOOLFILE
    STRCPY(spoolfile, SPOOLFILE) ;   /* Alternative spoolfile to monitor. */
  #else
!   if ((envmail = getenv("MAIL")) != NULL) STRCPY(spoolfile, envmail) ;
    else
      {
        username = getname() ;     /* Get users name from passwd entry. */
***************
*** 387,397 ****
  h_to_c(host, community)        /* Turn hostname into community name. */
  char *host, *community ;
  {
!   struct hostent *hp ;
!   struct machinfo *temp ;      /* Pointer to next machine record. */
    char *hostinfo ;             /* Info returned from yp_match */
    int len ;                    /* Length of returned hostinfo */
    int yp_err ;                 /* Result from yp_match() */
  
    if (host[0] == '\0')
      {
--- 388,400 ----
  h_to_c(host, community)        /* Turn hostname into community name. */
  char *host, *community ;
  {
! #ifdef NISLOOKUP
    char *hostinfo ;             /* Info returned from yp_match */
    int len ;                    /* Length of returned hostinfo */
    int yp_err ;                 /* Result from yp_match() */
+ #endif /*NISLOOKUP*/
+ 
+   struct machinfo *temp ;      /* Pointer to next machine record. */
  
    if (host[0] == '\0')
      {

------- mon.c -------
*** /tmp/da02112	Sun Jan 13 18:50:32 1991
--- mon.c	Sun Jan 13 17:30:33 1991
***************
*** 35,41 ****
--- 35,43 ----
  #include "faces.h"
  #include "extern.h"
  
+ static time_t lastmtime = 0 ; /* Only look at mailfile when it's changed. */
  
+ 
  add_face(dtype, itype, name)
  enum disp_type dtype ;
  enum icon_type itype ;
***************
*** 166,173 ****
    FILE *fp ;                /* File descriptor for users mail spool file. */
    time_t ubuf[2] ;          /* For reseting the access time on spoolfile. */
  
-   static time_t lastmtime ; /* Only look at mailfile when it's changed. */
- 
    column = row = 0 ;        /* Start in top left corner of pixrect. */
    newmail = 0 ;             /* Assume no new mail. */
    noicons = 0 ;
--- 168,173 ----
***************
*** 183,192 ****
      }
  
  /*  See if there is any work to do. If the file hasn't changed, then no need
!  *  to do anythingf but exit.
   */
  
!   if (buf.st_mtime == lastmtime) return ;
    lastmtime = buf.st_mtime ;
  
    if (buf.st_size > lastsize ||
--- 183,196 ----
      }
  
  /*  See if there is any work to do. If the file hasn't changed, then no need
!  *  to do anything but exit.
   */
  
!   if (buf.st_mtime == lastmtime)
!     {
!       show_display() ;
!       return ;
!     }
    lastmtime = buf.st_mtime ;
  
    if (buf.st_size > lastsize ||
***************
*** 319,324 ****
--- 323,329 ----
            return ;
  	}
  #endif /*PLP*/
+       if (noicons == 0) noicons++ ;
        make_pixrect(noicons) ;
        this = recs ;
        while (this != NULL)
***************
*** 418,423 ****
--- 423,446 ----
  }
  
  
+ do_prop_check()
+ {
+   struct recinfo *this, *next ;
+ 
+   lastmtime = (time_t) 0 ;
+   lastsize = 0L ;
+   this = recs ;
+   while (this != NULL)       /* Force chain of records to be removed. */
+     {
+       next = this->next ;
+       this->total = 0 ;
+       this = next ;
+     }
+   garbage_collect() ;
+   do_check() ;
+ }
+ 
+ 
  do_users()                   /* Monitor users on a machine. */
  {
    struct recinfo *this, *next ;
***************
*** 615,621 ****
  {
    char *host, *user ;
    char temp[MAXLINE], ts[9] ;
-   char from_address[MAXLINE] ;
  
    if (EQUAL(line, "From "))
      {
--- 638,643 ----
***************
*** 628,658 ****
      {
        if (fromc_found) return ;    /* Only process first From: line. */
        fromc_found = 1 ;
- 
- /*  An ugly hack: if an alias of a special form (comm/full-address) exists,
-  *  then skip the "From:" lookup. This allows stuff from mailing lists to be
-  *  recognized as such, instead of the individual senders. In people.tab,
-  *  include a line like:
-  *
-  *  someplace/foolist@someplace=mailinglist
-  */
- 
-       STRCPY(from_address, face_user) ;
-       if (*face_host != '\0')
-         {
-           STRCAT(from_address, "@") ;
-           STRCAT(from_address, face_host) ;
-         }
-       h_to_c(face_host, community) ;
-       a_to_u(community, from_address, realcomm, temp) ;
-       if (strcmp(from_address, realname) != 0)
-         {
- 
- /*  Had an entry for the full name, that means don't try to do further
-  *  interpretation of the From:
-  */
-           return ;
-         }
      }
  
    if (parsefrom(line, &user, &host))
--- 650,655 ----

------- rec.c -------
*** /tmp/da02115	Sun Jan 13 18:50:33 1991
--- rec.c	Sun Jan 13 13:50:45 1991
***************
*** 231,237 ****
    char aliascomm[MAXLINE] ;  /* Alias for this community/username. */
    char hostname[MAXLINE] ;   /* This records' hostname. */
    char username[MAXLINE] ;   /* This records real username. */
!   char *ptr1, *ptr2 ;
    int i ;
    FILE *fd ;
  
--- 231,237 ----
    char aliascomm[MAXLINE] ;  /* Alias for this community/username. */
    char hostname[MAXLINE] ;   /* This records' hostname. */
    char username[MAXLINE] ;   /* This records real username. */
!   char *ptr1 ;
    int i ;
    FILE *fd ;
  

------- extern.h -------
*** /tmp/da02118	Sun Jan 13 18:50:33 1991
--- extern.h	Sun Jan 13 09:49:06 1991
***************
*** 66,71 ****
--- 66,72 ----
  extern int beeps ;         /* Number of beeps for arrival of new mail. */
  extern int button1clear ;  /* Set if button 1 should clear the window. */
  extern int column ;        /* Column number for next icon. */
+ extern int debug ;         /* Set with the -D command line option. */
  extern int doing_xface ;   /* Set if we've started to process an X-Face: */
  extern int dontshowno ;    /* Set if no. of messages shouldn't  be shown. */
  extern int dontshowtime ;  /* Set if timestamp shouldn't be shown. */

------- faces.h -------
*** /tmp/da02121	Sun Jan 13 18:50:34 1991
--- faces.h	Sun Jan 13 13:34:06 1991
***************
*** 77,83 ****
  enum just_type { LEFT, RIGHT } ;                 /* Text justification. */
  
  /* Different types of file monitoring performed by this program. */
! enum mon_type { MONALL, MONNEW, MONPRINTER, MONPROG, MONUSERS } ;
  
  /* Different graphics systems. Appropriate one set in gtype. */
  enum gr_type { NEWS, SVIEW, X11, XVIEW } ;
--- 77,83 ----
  enum just_type { LEFT, RIGHT } ;                 /* Text justification. */
  
  /* Different types of file monitoring performed by this program. */
! enum mon_type { MONNEW, MONALL, MONPRINTER, MONPROG, MONUSERS } ;
  
  /* Different graphics systems. Appropriate one set in gtype. */
  enum gr_type { NEWS, SVIEW, X11, XVIEW } ;

------- TODO -------
*** /tmp/da02127	Sun Jan 13 18:50:35 1991
--- TODO	Sun Jan 13 12:49:06 1991
***************
*** 37,45 ****
      (b) The new input functionality (click left/middle mouse, raise window,
          Del, ^L and q) has to be added in.
  
- *  With the XView version, add a Properties pinup window which would
-    allow you to change the various monitoring options on the fly.
- 
  *  Add in audio capabilities.
  
  *  From Pat Lashley <patl@Sun.COM>
--- 37,42 ----
***************
*** 192,196 ****
--- 189,196 ----
      x@y with an X-Face: line then another article arrives from x@y with
      a different X-Face: line, then the second face is not shown; just
      the count of the first face get's incremented.
+ 
+ *   With the printer monitoring option, need to handle the unknown printer
+     more elegantly.
  
  *   Optimise.

------- xview.c -------
*** /tmp/da02130	Sun Jan 13 18:50:36 1991
--- xview.c	Sun Jan 13 18:43:06 1991
***************
*** 19,24 ****
--- 19,25 ----
  #include "faces.h"
  #include "extern.h"
  #include <xview/xview.h>
+ #include <xview/panel.h>
  #include <xview/canvas.h>
  #include <xview/icon.h>
  #include <X11/Xlib.h>
***************
*** 28,47 ****
  #define  F_WINDOW  1                  /* Window index to frame array. */
  #define  FONT      "times-roman-10"
  
  #define  NOTIFY_INTERPOSE_EVENT_FUNC  (void) notify_interpose_event_func
  #define  NOTIFY_SET_ITIMER_FUNC       (void) notify_set_itimer_func
  #define  XV_DESTROY                   (void) xv_destroy
  #define  XV_SET                       (void) xv_set
  
  #define  ITIMER_NULL             ((struct itimerval *) 0)
  
  int repaint_proc() ;
  
  Canvas canvas ;
  Canvas_paint_window pw ;
! Frame frame ;
  Icon faces_icon ;
  
  Display *dpy ;
  Drawable xid[2] ;               /* Xlib pointers to the screen and the icon. */
  Pixmap pr[3] = { NULL, NULL, NULL } ;     /* Current memory pixmaps. */
--- 29,66 ----
  #define  F_WINDOW  1                  /* Window index to frame array. */
  #define  FONT      "times-roman-10"
  
+ #define  FRAME_BORDER_SIZE  7
+ #define  FRAME_LABEL_SIZE   30
+ 
  #define  NOTIFY_INTERPOSE_EVENT_FUNC  (void) notify_interpose_event_func
  #define  NOTIFY_SET_ITIMER_FUNC       (void) notify_set_itimer_func
+ #define  XV_CREATE                    (void) xv_create
  #define  XV_DESTROY                   (void) xv_destroy
  #define  XV_SET                       (void) xv_set
  
  #define  ITIMER_NULL             ((struct itimerval *) 0)
  
+ enum popup_pos { P_BELOW, P_RIGHT } ;  /* Positions relative to main frame. */
+ 
  int repaint_proc() ;
+ static void display_prop_sheet(), make_prop_sheet() ;
+ static void position_popup(), show_props() ;
+ static Notify_value prop_apply_proc(), prop_choice_proc() ;
+ static Notify_value prop_defs_proc(), prop_mail_proc(), prop_reset_proc() ;
  
  Canvas canvas ;
  Canvas_paint_window pw ;
! Frame frame, props_frame ;
  Icon faces_icon ;
+ static Menu props_menu ;
+ static Panel props_panel ;
+ static Panel_item props_ctoggle, props_mtoggle, props_ptoggle, props_utoggle ;
+ static Panel_item props_cmd, props_file, props_host, props_mail, props_name ;
+ static Panel_item props_apply, props_defs, props_reset ;
+ static Panel_item props_no, props_period, props_tstamp, props_uname ;
  
+ static enum mon_type prop_mtype ;         /* Current active monitor type. */
+ 
  Display *dpy ;
  Drawable xid[2] ;               /* Xlib pointers to the screen and the icon. */
  Pixmap pr[3] = { NULL, NULL, NULL } ;     /* Current memory pixmaps. */
***************
*** 102,113 ****
  {
    int nextc ;
  
!   nextc = event_id(event) ;
    if (event_is_down(event))
      {
!       if (button1clear && nextc == MS_LEFT) do_key(KEY_CLEAR) ;
!       else if ((button1clear && nextc == MS_MIDDLE) ||
!               (!button1clear && nextc == MS_LEFT))
          {
            wdtype = (wdtype == DISP_NAME) ? DISP_OTHER : DISP_NAME ;
            draw_screen(wdtype) ;
--- 121,132 ----
  {
    int nextc ;
  
!   nextc = event_action(event) ;
    if (event_is_down(event))
      {
!       if (button1clear && nextc == ACTION_SELECT) do_key(KEY_CLEAR) ;
!       else if ((button1clear && nextc == ACTION_ADJUST) ||
!               (!button1clear && nextc == ACTION_SELECT))
          {
            wdtype = (wdtype == DISP_NAME) ? DISP_OTHER : DISP_NAME ;
            draw_screen(wdtype) ;
***************
*** 114,119 ****
--- 133,143 ----
          }
      }
    else if (event_is_ascii(event)) do_key(nextc) ;
+ 
+   if (nextc == ACTION_MENU && event_is_down(event))
+     menu_show((Menu) xv_get(canvas, WIN_MENU), canvas, event, 0) ;
+   else if (nextc == ACTION_PROPS)
+     display_prop_sheet() ;
  }
  
  
***************
*** 121,126 ****
--- 145,151 ----
  check_mail()
  {
    do_check() ;
+   return(NOTIFY_DONE) ;
  }
  
  
***************
*** 162,167 ****
--- 187,204 ----
  }
  
  
+ static void
+ display_prop_sheet()
+ {
+   if (xv_get(props_frame, XV_SHOW) == FALSE)
+     {
+       XV_SET(props_frame, FRAME_PROPS_PUSHPIN_IN, TRUE, 0) ;
+       position_popup(frame, props_frame, P_RIGHT) ;
+       XV_SET(props_frame, XV_SHOW, TRUE, 0) ;
+     }
+ }
+ 
+ 
  draw_screen(wdtype)
  enum disp_type wdtype ;
  {
***************
*** 223,228 ****
--- 260,266 ----
    backgnd = WhitePixel(dpy, screen) ;
    depth = DefaultDepth(dpy, screen) ;
  
+   if (debug) XSynchronize(dpy, TRUE) ;
    init_font() ;
  
    gc_mask = GCFont | GCForeground | GCBackground | GCGraphicsExposures ;
***************
*** 245,251 ****
      }
  
    if (strlen(bgicon)) GET_SUN_ICON(bgicon, buf) ;
!   load_icon(BACKIMAGE, buf) ;
  
    STRCPY(fname[0], "sun.icon") ;
    STRCPY(fname[1], "48x48x1") ;
--- 283,293 ----
      }
  
    if (strlen(bgicon)) GET_SUN_ICON(bgicon, buf) ;
! #ifdef REVORDER
!   load_icon(BACKIMAGE, buf, 1) ;
! #else
!   load_icon(BACKIMAGE, buf, 0) ;
! #endif /*REVORDER*/
  
    STRCPY(fname[0], "sun.icon") ;
    STRCPY(fname[1], "48x48x1") ;
***************
*** 299,304 ****
--- 341,348 ----
  int argc ;
  char *argv[] ;
  {
+   Menu_item tmp_item ;
+ 
    XV_SET(frame,
           FRAME_ICON,                  faces_icon,
           FRAME_LABEL,                 "faces",
***************
*** 314,320 ****
                       CANVAS_RETAINED,     FALSE,
                       CANVAS_PAINTWINDOW_ATTRS,
                       WIN_CONSUME_EVENTS,
!                        MS_LEFT, WIN_ASCII_EVENTS,
                         WIN_LEFT_KEYS, WIN_TOP_KEYS, WIN_RIGHT_KEYS,
                         0,
                       WIN_IGNORE_EVENTS,
--- 358,364 ----
                       CANVAS_RETAINED,     FALSE,
                       CANVAS_PAINTWINDOW_ATTRS,
                       WIN_CONSUME_EVENTS,
!                        MS_LEFT, MS_RIGHT, WIN_ASCII_EVENTS, WIN_REPAINT,
                         WIN_LEFT_KEYS, WIN_TOP_KEYS, WIN_RIGHT_KEYS,
                         0,
                       WIN_IGNORE_EVENTS,
***************
*** 329,334 ****
--- 373,397 ----
  
    width = maxcols * imagewidth ;
    height = imageheight ;
+ 
+   props_menu = xv_create(XV_NULL,         MENU,
+                          MENU_TITLE_ITEM, "Faces",
+                          0) ;
+ 
+   tmp_item = xv_create(XV_NULL,          MENUITEM,
+                        MENU_STRING,      "Properties",
+                        MENU_ACTION_PROC, show_props,
+                        MENU_CLIENT_DATA, 0,
+                        0) ;
+ 
+   XV_SET(props_menu, MENU_APPEND_ITEM, tmp_item, 0) ;
+   XV_SET(pw,
+          WIN_MENU,        props_menu,
+          WIN_BIT_GRAVITY, ForgetGravity,
+          0) ;
+ 
+   make_prop_sheet() ;
+   set_prop_values() ;
  }
  
  
***************
*** 339,345 ****
--- 402,685 ----
  }
  
  
+ static void
+ make_prop_sheet()
+ {
+   props_frame = (Frame) xv_create(frame,  FRAME_PROPS,
+                                  XV_LABEL,          "Faces properties",
+                                  XV_X,              0,
+                                  XV_Y,              0,
+                                  XV_SHOW,           FALSE,
+                                  FRAME_SHOW_FOOTER, TRUE,
+                                  0) ;
+ 
+   props_panel = (Panel) xv_get(props_frame, FRAME_PROPS_PANEL) ;
+   XV_CREATE(props_panel,        PANEL_MESSAGE,
+             XV_X,               xv_col(props_panel, 0),
+             XV_Y,               xv_row(props_panel, 0),
+             PANEL_LABEL_BOLD,   TRUE,
+             PANEL_LABEL_STRING, "Monitor:",
+             0) ;
+ 
+   props_mtoggle = xv_create(props_panel,          PANEL_TOGGLE,
+                             XV_X,                 xv_col(props_panel, 8),
+                             XV_Y,                 xv_row(props_panel, 0),
+                             PANEL_NOTIFY_PROC,    prop_choice_proc,
+                             PANEL_CHOICE_STRINGS,
+                               "Mail",
+                               0,
+                             0) ;
+   props_utoggle = xv_create(props_panel,          PANEL_TOGGLE,
+                             XV_X,                 xv_col(props_panel, 8),
+                             XV_Y,                 xv_row(props_panel, 1),
+                             PANEL_NOTIFY_PROC,    prop_choice_proc,
+                             PANEL_CHOICE_STRINGS,
+                               "Users",
+                               0,
+                             0) ;
+   props_ptoggle = xv_create(props_panel,          PANEL_TOGGLE,
+                             XV_X,                 xv_col(props_panel, 8),
+                             XV_Y,                 xv_row(props_panel, 2),
+                             PANEL_NOTIFY_PROC,    prop_choice_proc,
+                             PANEL_CHOICE_STRINGS,
+                               "Printer",
+                               0,
+                             0) ;
+   props_ctoggle = xv_create(props_panel,          PANEL_TOGGLE,
+             XV_X,                 xv_col(props_panel, 8),
+             XV_Y,                 xv_row(props_panel, 3),
+             PANEL_NOTIFY_PROC,    prop_choice_proc,
+             PANEL_CHOICE_STRINGS,
+               "Custom",
+               0,
+             0) ;
+ 
+   props_mail  = xv_create(props_panel,          PANEL_CHOICE,
+                           XV_X,                 xv_col(props_panel, 16),
+                           XV_Y,                 xv_row(props_panel, 0),
+                           PANEL_NOTIFY_PROC,    prop_mail_proc,
+                           PANEL_CHOICE_STRINGS,
+                             "New",
+                             "All",
+                             0,
+                           0) ;
+   props_file  = xv_create(props_panel,                PANEL_TEXT,
+                           PANEL_VALUE_X,              xv_col(props_panel, 32),
+                           XV_Y,                       xv_row(props_panel, 0),
+                           PANEL_LABEL_STRING,         "File:",
+                           PANEL_LABEL_BOLD,           TRUE,
+                           PANEL_VALUE_DISPLAY_LENGTH, 15,
+                           PANEL_VALUE_STORED_LENGTH,  MAXLINE,
+                           0) ;
+   props_host  = xv_create(props_panel,                PANEL_TEXT,
+                           PANEL_VALUE_X,              xv_col(props_panel, 32),
+                           XV_Y,                       xv_row(props_panel, 1),
+                           PANEL_LABEL_STRING,         "Host:",
+                           PANEL_LABEL_BOLD,           TRUE,
+                           PANEL_VALUE_DISPLAY_LENGTH, 15,
+                           PANEL_VALUE_STORED_LENGTH,  MAXLINE,
+                           0) ;
+   props_name  = xv_create(props_panel,                PANEL_TEXT,
+                           PANEL_VALUE_X,              xv_col(props_panel, 32),
+                           XV_Y,                       xv_row(props_panel, 2),
+                           PANEL_LABEL_STRING,         "Name:",
+                           PANEL_LABEL_BOLD,           TRUE,
+                           PANEL_VALUE_DISPLAY_LENGTH, 15,
+                           PANEL_VALUE_STORED_LENGTH,  MAXLINE,
+                           0) ;
+   props_cmd   = xv_create(props_panel,                PANEL_TEXT,
+                           PANEL_VALUE_X,              xv_col(props_panel, 32),
+                           XV_Y,                       xv_row(props_panel, 3),
+                           PANEL_LABEL_STRING,         "Command:",
+                           PANEL_LABEL_BOLD,           TRUE,
+                           PANEL_VALUE_DISPLAY_LENGTH, 15,
+                           PANEL_VALUE_STORED_LENGTH,  MAXLINE,
+                           0) ;
+ 
+   props_period = xv_create(props_panel,                PANEL_NUMERIC_TEXT,
+                            PANEL_VALUE_X,              xv_col(props_panel, 32),
+                            XV_Y,                       xv_row(props_panel, 4),
+                            PANEL_VALUE_DISPLAY_LENGTH, 4,
+                            PANEL_VALUE_STORED_LENGTH,  4,
+                            PANEL_LABEL_STRING,         "Monitoring interval",
+                            0) ;
+   XV_CREATE(props_panel,        PANEL_MESSAGE,
+             XV_X,               xv_col(props_panel, 41),
+             XV_Y,               xv_row(props_panel, 4),
+             PANEL_LABEL_STRING, "seconds",
+             0) ;
+   props_no     = xv_create(props_panel,          PANEL_CHECK_BOX,
+                            PANEL_VALUE_X,        xv_col(props_panel, 8),
+                            XV_Y,                 xv_row(props_panel, 5),
+                            PANEL_CHOICE_STRINGS,
+                              "Show number of messages",
+                              0,
+                            0) ;
+   props_tstamp = xv_create(props_panel,          PANEL_CHECK_BOX,
+                            PANEL_VALUE_X,        xv_col(props_panel, 8),
+                            XV_Y,                 xv_row(props_panel, 6),
+                            PANEL_CHOICE_STRINGS,
+                              "Show timestamp",
+                              0,
+                            0) ;
+   props_uname = xv_create(props_panel,          PANEL_CHECK_BOX,
+                           PANEL_VALUE_X,        xv_col(props_panel, 8),
+                           XV_Y,                 xv_row(props_panel, 7),
+                           PANEL_CHOICE_STRINGS,
+                             "Show username",
+                             0,
+                           0) ;
+ 
+   props_apply = xv_create(props_panel,        PANEL_BUTTON,
+                           XV_X,               xv_col(props_panel, 7),
+                           XV_Y,               xv_row(props_panel, 9),
+                           PANEL_LABEL_BOLD,   TRUE,
+                           PANEL_LABEL_STRING, "Apply",
+                           PANEL_NOTIFY_PROC,  prop_apply_proc,
+                           0) ;
+   props_reset = xv_create(props_panel,        PANEL_BUTTON,
+                           XV_X,               xv_col(props_panel, 20),
+                           XV_Y,               xv_row(props_panel, 9),
+                           PANEL_LABEL_BOLD,   TRUE,
+                           PANEL_LABEL_STRING, "Reset",
+                           PANEL_NOTIFY_PROC,  prop_reset_proc,
+                           0) ;
+   props_defs  = xv_create(props_panel,        PANEL_BUTTON,
+                           XV_X,               xv_col(props_panel, 33),
+                           XV_Y,               xv_row(props_panel, 9),
+                           PANEL_LABEL_BOLD,   TRUE,
+                           PANEL_LABEL_STRING, "Defaults",
+                           PANEL_NOTIFY_PROC,  prop_defs_proc,
+                           0) ;
+   window_fit(props_panel) ;
+   window_fit(props_frame) ;
+ }
+ 
+ 
+ static void
+ position_popup(parent, child, position)
+ Frame parent, child ;
+ int position ;
+ {
+   Rect crect, prect ;
+   int height, width ;
+ 
+   if (((int) xv_get(child, XV_SHOW)) && position == P_RIGHT) return ;
+   frame_get_rect(parent, &prect) ;
+   frame_get_rect(child,  &crect) ;
+   height = (int) xv_get(parent, XV_HEIGHT) ;
+   width  = (int) xv_get(parent, XV_WIDTH) ;
+ 
+   switch (position)
+     {
+       case P_BELOW : crect.r_left = prect.r_left + FRAME_BORDER_SIZE ;
+                      crect.r_top  = prect.r_top + height + FRAME_LABEL_SIZE +
+                                     FRAME_BORDER_SIZE ;
+                      break ;
+       case P_RIGHT : crect.r_left = prect.r_left + width +
+                                                    (2 * FRAME_BORDER_SIZE) ;
+                      crect.r_top  = prect.r_top ;
+     }
+   frame_set_rect(child, &crect) ;
+ }
+ 
+ 
  /*ARGSUSED*/
+ static Notify_value
+ prop_apply_proc(item, event)
+ Panel_item item ;
+ Event *event ;
+ {
+   mtype = prop_mtype ;
+   period       =   (int) xv_get(props_period, PANEL_VALUE) ;
+   dontshowno   = !((int) xv_get(props_no,     PANEL_VALUE)) ;
+   dontshowtime = !((int) xv_get(props_tstamp, PANEL_VALUE)) ;
+   dontshowuser = !((int) xv_get(props_uname,  PANEL_VALUE)) ;
+ 
+   STRCPY(spoolfile, (char *) xv_get(props_file, PANEL_VALUE)) ;
+   STRCPY(hostname,  (char *) xv_get(props_host, PANEL_VALUE)) ;
+   STRCPY(printer,   (char *) xv_get(props_name, PANEL_VALUE)) ;
+   STRCPY(userprog,  (char *) xv_get(props_cmd,  PANEL_VALUE)) ;
+   do_prop_check() ;
+   return(NOTIFY_DONE) ;
+ }
+ 
+ 
+ /*ARGSUSED*/
+ static Notify_value
+ prop_choice_proc(item, value, event)
+ Panel_item item ;
+ int value ;
+ Event *event ;
+ {
+        if (item == props_mtoggle)
+     prop_mtype = (enum mon_type) xv_get(props_mail, PANEL_VALUE) ;
+   else if (item == props_ptoggle) prop_mtype = MONPRINTER ;
+   else if (item == props_ctoggle) prop_mtype = MONPROG ;
+   else if (item == props_utoggle) prop_mtype = MONUSERS ;
+  
+ /* Activate or inactive all the panel items appropriately. */
+  
+   XV_SET(props_mtoggle, PANEL_VALUE, (item == props_mtoggle), 0) ;
+   XV_SET(props_utoggle, PANEL_VALUE, (item == props_utoggle), 0) ;
+   XV_SET(props_ptoggle, PANEL_VALUE, (item == props_ptoggle), 0) ;
+   XV_SET(props_ctoggle, PANEL_VALUE, (item == props_ctoggle), 0) ;
+  
+   XV_SET(props_mail, PANEL_INACTIVE, (item != props_mtoggle), 0) ;
+   XV_SET(props_file, PANEL_INACTIVE, (item != props_mtoggle), 0) ;
+   XV_SET(props_host, PANEL_INACTIVE, (item != props_utoggle), 0) ;
+   XV_SET(props_name, PANEL_INACTIVE, (item != props_ptoggle), 0) ;
+   XV_SET(props_cmd,  PANEL_INACTIVE, (item != props_ctoggle), 0) ;
+   return(NOTIFY_DONE) ;
+ }
+ 
+ 
+ /*ARGSUSED*/
+ static Notify_value
+ prop_defs_proc(item, event)
+ Panel_item item ;
+ Event *event ;
+ {
+   mtype        = MONNEW ;
+   period       = 60 ;
+   dontshowno   = 0 ;
+   dontshowtime = 0 ;
+   dontshowuser = 0 ;
+   STRCPY(spoolfile, "") ;
+   STRCPY(hostname,  "") ;
+   STRCPY(printer,   "") ;
+   STRCPY(userprog,  "") ;
+   set_prop_values() ;
+   do_prop_check() ;
+   return(NOTIFY_DONE) ;
+ }
+ 
+ 
+ /*ARGSUSED*/
+ static Notify_value
+ prop_mail_proc(item, value, event)
+ Panel_item item ;
+ int value ;
+ Event *event ;
+ {
+   prop_mtype = (enum mon_type) value ;
+   return(NOTIFY_DONE) ;
+ }
+ 
+ 
+ /*ARGSUSED*/
+ static Notify_value
+ prop_reset_proc(item, event)
+ Panel_item item ;
+ Event *event ;
+ {
+   set_prop_values() ;
+   do_prop_check() ;
+   return(NOTIFY_DONE) ;
+ }
+ 
+ 
+ /*ARGSUSED*/
  repaint_proc(canvas, window, repaint_area)
  Canvas canvas ;
  Xv_Window window ;
***************
*** 364,369 ****
--- 704,747 ----
  }
  
  
+ set_prop_values()
+ {
+   Panel_item item ;
+ 
+        if (mtype == MONALL || mtype == MONNEW) item = props_mtoggle ;
+   else if (mtype == MONPRINTER)                item = props_ptoggle ;
+   else if (mtype == MONPROG)                   item = props_ctoggle ;
+   else if (mtype == MONUSERS)                  item = props_utoggle ;
+   prop_mtype = mtype ;
+ 
+ /* Activate or inactive all the panel items appropriately. */
+ 
+   XV_SET(props_mtoggle, PANEL_VALUE, (item == props_mtoggle), 0) ;
+   XV_SET(props_utoggle, PANEL_VALUE, (item == props_utoggle), 0) ;
+   XV_SET(props_ptoggle, PANEL_VALUE, (item == props_ptoggle), 0) ;
+   XV_SET(props_ctoggle, PANEL_VALUE, (item == props_ctoggle), 0) ;
+ 
+   if (mtype == MONNEW || mtype == MONALL)
+     XV_SET(props_mail, PANEL_VALUE, mtype, 0) ;
+ 
+   XV_SET(props_period, PANEL_VALUE,  period,       0) ;
+   XV_SET(props_no,     PANEL_VALUE, !dontshowno,   0) ;
+   XV_SET(props_tstamp, PANEL_VALUE, !dontshowtime, 0) ;
+   XV_SET(props_uname,  PANEL_VALUE, !dontshowuser, 0) ;
+ 
+   XV_SET(props_file, PANEL_VALUE, spoolfile, 0) ;
+   XV_SET(props_host, PANEL_VALUE, hostname, 0) ;
+   XV_SET(props_name, PANEL_VALUE, printer, 0) ;
+   XV_SET(props_cmd,  PANEL_VALUE, userprog, 0) ;
+ 
+   XV_SET(props_mail, PANEL_INACTIVE, (item != props_mtoggle), 0) ;
+   XV_SET(props_file, PANEL_INACTIVE, (item != props_mtoggle), 0) ;
+   XV_SET(props_host, PANEL_INACTIVE, (item != props_utoggle), 0) ;
+   XV_SET(props_name, PANEL_INACTIVE, (item != props_ptoggle), 0) ;
+   XV_SET(props_cmd,  PANEL_INACTIVE, (item != props_ctoggle), 0) ;
+ }
+ 
+ 
  show_display()    /* Show the latest set of mail icon faces. */
  {
    Rect *temprect ;
***************
*** 394,399 ****
--- 772,787 ----
    old_pr[(int) DISP_NAME] = NULL ;
    old_pr[(int) DISP_OTHER] = NULL ;
    XSync(dpy, 0) ;
+ }
+ 
+ 
+ /*ARGSUSED*/
+ static void
+ show_props(m, mi)
+ Menu m ;
+ Menu_item mi ;
+ {
+   display_prop_sheet() ;
  }
  
  

------- CHANGES -------
*** /tmp/da02133	Sun Jan 13 18:50:37 1991
--- CHANGES	Sun Jan 13 13:43:38 1991
***************
*** 623,625 ****
--- 623,640 ----
             listplace/list@listplace  eg.
  
             ics.UCI.EDU/fa.think-c-outbound-request@ics.UCI.EDU
+ 
+ v1.4 - patchlevel 11 - 14th January 1991.
+ 
+          - Removed the mailing list hack from Gregory Dudek. It doesn't seem
+            to work quite right, and it cause the incorrect handling of From:
+            lines on other mail items.
+ 
+          - The check to see if the spool file has changed, needed to call
+            show_display() if there was no change, otherwise the old offscreen
+            memory pixrects, would not be freed.
+ 
+          - Added a property sheet to the XView version. This allows you to
+            toggle the monitoring option (mail/users/printer/custom) on the fly.
+ 
+          - Ran faces through Saber-C, and fixed up inconsistencies.