[comp.sources.misc] v03i082: faces - a visual mail and print monitor for Suns. Part 1 of 2.

richb@sunaus.oz.AU (Rich Burridge) (07/18/88)

comp.sources.misc: Volume 3, Issue 82
Submitted-by: Rich Burridge <richb@sunaus.oz.AU>
Archive-Name: faces


This is the first general release of a face server for monitoring mail
and print jobs. It is based on the AT&T v8 program vismon, but is not
derived from vismon sources.

Permission is given to distribute these sources, as long as the
copyright messages are not removed, and no monies are exchanged.

See the README and manual page for more details.

Save this message in a new directory, strip off the beginning down to
and including the CUT HERE line, unpack with sh, then type "make".
Create your face directory, hostname sub-directories and username icons,
and you're set.

If you already have your face scanned in and iconised and would like to
add it to the library I'm building up, please feel free to email it to me.

Many thanks to Guy Harris for the basis of the latest manual page and Dave
Lemke for many excellent suggestions. Dan Hellers' watch program was also
consulted in the early days to glean how to do certain things.

There will be a NeWS version in the near future, which will include a lot
more of Daves' suggestions and some very sexy features, but not for a
while; I have a few other projects I wish to finish first.

This code has been tested internally within certain areas of Sun
Microsystems. If you find any bugs please report them to me; also any
suggestions.

    Rich.

------CUT HERE------CUT HERE------
#! /bin/sh
# this is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh to create the files:
#	get.c
#	main.c
#	mon.c
#	rec.c
#	sunview.c
# This archive created: Thu Jul 14 13:58:11 EST 1988
#
#
export PATH; PATH=/bin:$PATH
#
if [ -f get.c ]
then
echo shar: will not over-write existing file get.c
else
echo shar: extracting 'get.c',     4442 characters
cat > get.c <<'Funky_Stuff'
 
/*  get.c
 *
 *  Extraction routines used by faces.
 *
 *  Copyright (c) Rich Burridge - Sun Microsystems Australia.
 *                                All rights reserved.
 *
 *  Permission is given to distribute these sources, as long as the
 *  copyright messages are not removed, and no monies are exchanged. 
 *
 *  Version 1.1 - July 1988.
 *
 *  No responsibility is taken for any errors on inaccuracies inherent
 *  either to the comments or the code of this program, but if reported
 *  to me, then an attempt will be made to fix them.
 */

#include "faces.h"
#include "extern.h"
#include "patchlevel.h"

char *
get_field(ftype,line)      /* Get field option from given line. */
enum field_type ftype ;
char *line ;
{
  char *ptr1, *ptr2 ;
  char str1[5],str2[MAXLINE],str3[4],str4[4],str5[3],str6[9],str7[5] ;

  SSCANF(line,"%s %s %s %s %s %s %s",
               str1,str2,str3,str4,str5,str6,str7) ;
  switch ((int) ftype)
    {
      case HOSTNAME  : if ((ptr2 = rindex(str2,'!')) != NULL)
                         {
                           ptr1 = str2 ;
                           *ptr2 = '\0' ;
                           while (ptr2 != ptr1)
                             {
                               *ptr2-- ;
                               if (*ptr2 == '!') return(ptr2+1) ;
                             }
                           return(ptr2) ;
                         }
                       else if ((ptr2 = index(str2,'@')) != NULL)
                         return(ptr2+1) ;
                       else return(NULL) ;
 
      case TIMESTAMP : str6[5] = '\0' ;
                       return(str6) ;
 
      case USERNAME  : if ((ptr2 = rindex(str2,'!')) != NULL)
                         return(ptr2+1) ;
                       else if ((ptr2 = index(str2,'@')) != NULL)
                         {
                           ptr1 = str2 ;
                           *ptr2 = '\0' ;
                           while (ptr2 != ptr1)
                             {
                               *ptr2-- ;
                               if (*ptr2 == '@') return(ptr2+1) ;
                             }
                           return(ptr2) ;
                         }
                       else return(str2) ;
    }
/*NOTREACHED*/
}


get_options(argc,argv)             /* Read and process command line options. */
int argc ;
char *argv[] ;
{
  INC ;
  while (argc > 0)
    {
      if (argv[0][0] == '-')
        switch (argv[0][1])
          {
            case 'P' : INC ;         /* Monitor printer queue. */
                       mtype = MONPRINTER ;
                       if (*argv != NULL && argv[0][0] != '-')
                         STRCPY(printer,*argv) ;
                       else DEC ;
                       break ;
            case 'a' : mtype = MONALL ;    /* Monitor the whole of the spoolfile. */
                       break ;
            case 'f' : INC ;         /* Different directory for face icons. */
                       STRCPY(facedir,*argv) ;
                       break ;
            case 'h' : INC ;         /* Default hostname for mail with no hostname. */
                       STRCPY(defhost,*argv) ;
                       break ;
            case 'i' : INC ;         /* Set interval for checking (in seconds). */
                       interval = atoi(*argv) ;
                       break ;
            case 'n' : dontshowno = 1 ;  /* Do not show number of messages. */
                       break ;
            case 's' : INC ;         /* Alternative spoolfile to monitor. */
                       STRCPY(spoolfile,*argv) ;
                       break ;
            case 't' : dontshowtime = 1 ;  /* Do not show timestamps. */
                       break ;
            case 'v' : FPRINTF(stderr,"%s version 1.0.%1d\n",progname,PATCHLEVEL) ;
                       exit(1) ;
            case '?' : FPRINTF(stderr,"Usage: %s [-P printer] [-f facedir] [-h defhost] ") ;
                       FPRINTF(stderr,"[-i] [-n] [-s spoolfile] [-t] [-v] [-?]\n",progname) ;
                       exit(1) ;
          }
      INC ;
    }
}


char *
getname()       /* Get users name from passwd entry. */
{
  char *getlogin(), *username ;
  struct passwd *getpwuid(), *pwent ;

  if (!(username = getlogin()))
    {
      pwent = getpwuid(getuid()) ;
      username = pwent->pw_name ;
      endpwent() ;                   /* Close the passwd file */
    }
  return username ;
}
Funky_Stuff
len=`wc -c < get.c`
if [ $len !=     4442 ] ; then
echo error: get.c was $len bytes long, should have been     4442
fi
fi # end of overwriting check
if [ -f main.c ]
then
echo shar: will not over-write existing file main.c
else
echo shar: extracting 'main.c',     5336 characters
cat > main.c <<'Funky_Stuff'

/*  main.c
 *
 *  Icon face server for monitoring mail and print jobs.
 *  This program is based on the AT&T v8 mail face server,
 *  vismon, but is not derived from vismon source.
 * 
 *  Copyright (c) Rich Burridge - Sun Microsystems Australia.
 *                                All rights reserved.
 *
 *  Permission is given to distribute these sources, as long as the
 *  copyright messages are not removed, and no monies are exchanged. 
 * 
 *  Version 1.1 - July 1988.
 *
 *  No responsibility is taken for any errors on inaccuracies inherent
 *  either to the comments or the code of this program, but if reported
 *  to me, then an attempt will be made to fix them.
 */

#include "faces.h"

char *get_field(), *getname() ;
int do_check() ;
struct recinfo *rec_exists() ;

struct recinfo *recs = NULL ;   /* Mail messages being monitored. */
struct recinfo *last = NULL ;   /* End of the chain of mail records. */
struct stat buf ;               /* Buffer for stat call for file existence. */
long lastsize ;                 /* Last known size of the mail folder. */

enum mon_type mtype ;           /* Type of monitoring operation to do. */

char bounced_ts[6] ;            /* Time stamp for bounced messages. */
char defhost[MAXLINE] ;         /* Default host for mail with no hostname. */
char facedir[MAXLINE] ;         /* Directory containing face images. */
char iconname[MAXLINE] ;        /* Name of the icon file for this person. */
char nextline[MAXLINE] ;        /* Next line from users mail spool file. */
char printer[MAXLINE] ;         /* Printer name to monitor. */
char progname[MAXLINE] ;        /* Name of this program. */
char spoolfile[MAXLINE] ;       /* Full pathname of users current mail. */
char unknown_ts[6] ;            /* Time stamp for "no face" messages. */
char *username ;                /* This users name. */

int bounced ;       /* Number of bounced MAILER-DAEMONS. */
int column ;        /* Column number for next icon. */
int dontshowno ;    /* Set if number of messages should not be displayed. */
int dontshowtime ;  /* Set if timestamp for new mail should be displayed. */
int height ;        /* Height in pixels of faces display. */
int interval ;      /* Interval in seconds for new mail check. */
int noicons ;       /* Number of faces this time around. */
int row ;           /* Row number for next icon. */
int total ;         /* Total number of new messages. */
int unknown ;       /* Count of number of mail messages with no face. */
int width ;         /* Width in pixels of faces display. */


main(argc,argv)
int argc ;
char *argv[] ;
{
  STRCPY(progname,argv[0]) ;    /* Save this programs name. */
  initialise() ;                /* Set default values for various options. */
  get_options(argc,argv) ;      /* Read and process command line options. */
  make_icon() ;                 /* Create default faces icon. */
  make_frame(argc,argv) ;       /* Create faces window/icon. */
  do_check() ;                  /* Generate initial faces display. */
  start_tool() ;                /* Start up and display the faces icon. */
}


initialise()
{
#ifdef FMONTYPE
  mtype = FMONTYPE ;          /* Type of monitoring to do. */
#else
  mtype = MONNEW ;            /* Just monitor new mail by default. */
#endif FMONTYPE

#ifdef PRINTMON
  STRCPY(printer,PRINTMON) ;  /* Name of printer queue to monitor. */
#else
  STRCPY(printer,"lp") ;      /* Default printer. */
#endif PRINTMON

#ifdef FACEDIR
  STRCPY(facedir,FACEDIR) ;  /* Different directory for face icons. */
#else
  STRCPY(facedir,"/usr/local/faces") ;  /* Directory for face icons. */
#endif FACEDIR

#ifdef DEFHOST
  STRCPY(defhost,DEFHOST) ;  /* Default hostname for mail with no hostname. */
#else
  STRCPY(defhost,"LOCAL") ;
#endif DEFHOST

#ifdef INTERVAL
  interval = INTERVAL ;      /* Interval for new mail/print check. */
#else
  interval = 60 ;            /* Default time in seconds for new check. */
#endif INTERVAL

#ifdef DONTSHOWNO
  dontshowno = DONTSHOWNO ;  /* If nonzero, do not show number of messages. */
#else
  dontshowno = 0 ;           /* Show number of messages for this face. */
#endif DONTSHOWNO

#ifdef SPOOLFILE
  STRCPY(spoolfile,SPOOLFILE) ;   /* Alternative spoolfile to monitor. */
#else
  username = getname() ;     /* Get users name from passwd entry. */
  SPRINTF(spoolfile,"/usr/spool/mail/%s",username) ;
#endif SPOOLFILE

#ifdef DONTSHOWTIME
  dontshowtime = DONTSHOWTIME ;    /* If nonzero, do not show timestamp. */
#else
  dontshowtime = 0 ;         /* Show time stamp for new mail for this face. */
#endif DONTSHOWTIME
}


make_iconname(facedir,host,user)        /* Construct the icon name. */
char *facedir, *host, *user ;
{
  char domain[MAXLINE] ;       /* Hostname reconstructed into domains. */
  char thost[MAXLINE] ;        /* Temporary location for comparison. */
  char *ptr ;                  /* Pointer to the next domain portion. */

  STRCPY(thost,host) ;
  STRCPY(domain,"") ;          /* Nullify the domain name initially. */
  while ((ptr = rindex(thost,'.')) != NULL)
    {
      STRCAT(domain,ptr+1) ;   /* Extract next domain portion. */
      STRNCAT(domain,"/",1) ;
      *ptr = '\0' ;            /* Adjust original host string. */
    }
  STRCAT(domain,thost) ;       /* Extract final portion. */
  SPRINTF(iconname,"%s/%s/%s",facedir,domain,user) ;
}
Funky_Stuff
len=`wc -c < main.c`
if [ $len !=     5336 ] ; then
echo error: main.c was $len bytes long, should have been     5336
fi
fi # end of overwriting check
if [ -f mon.c ]
then
echo shar: will not over-write existing file mon.c
else
echo shar: extracting 'mon.c',     9080 characters
cat > mon.c <<'Funky_Stuff'

/*  mon.c
 *
 *  Monitoring routines used by the faces program.
 * 
 *  Copyright (c) Rich Burridge - Sun Microsystems Australia.
 *                                All rights reserved.
 *
 *  Permission is given to distribute these sources, as long as the
 *  copyright messages are not removed, and no monies are exchanged. 
 * 
 *  Version 1.1 - July 1988.
 *
 *  No responsibility is taken for any errors on inaccuracies inherent
 *  either to the comments or the code of this program, but if reported
 *  to me, then an attempt will be made to fix them.
 */

#include "faces.h"
#include "extern.h"

add_params(count, ts)     /* Output count and timestamp if applicable. */
int count ;
char *ts ;
{
  if (!dontshowno && mtype == MONALL)
    {
      SPRINTF(nextline, "%1d", count) ;
      text(BOTH, BOTTOMRIGHT, nextline) ;
    }
  if (!dontshowtime) text(ICON, BOTTOMLEFT, ts) ;
}


do_check()                  /* Perform another check of the appropriate type. */
{
  switch ((int) mtype)
    {
      case MONALL     : do_mail(MONALL) ;  /* Monitor all of the mail file. */
                        break ;
      case MONNEW     : do_mail(MONNEW) ;  /* Monitor new mail only. */
                        break ;
      case MONPRINTER : do_printer() ;     /* Monitor the print queue. */
                        break ;
    }
}


do_mail(mtype)              /* Monitor a mail file for new or all mail. */
enum mon_type mtype ;
{        
  char host[MAXLINE] ;      /* Pointer to host name from the "From" line. */
  char *ptr ;               /* Pointer to extract field. */
  char ts[MAXLINE] ;        /* Pointer to time stamp from the "From" line. */
  char user[MAXLINE] ;      /* Pointer to user name from the "From" line. */
  FILE *fp ;                /* File descriptor for users mail spool file. */
  struct recinfo *crec ;    /* Pointer to current mail record for updating. */

  noicons = 0 ;             /* Zeroise counts before getting new totals. */
  unknown = 0 ;
  bounced = 0 ;
  total = 0 ;

  if (stat(spoolfile,&buf) == -1)
    {
      make_display() ;             /* Display the "no mail" icon. */
      return ;
    }
  if (mtype == MONNEW)
    if (buf.st_size <= lastsize)   /* Is the size of mail folder bigger? */
      {
        lastsize = buf.st_size ;   /* No: save new size and exit. */
        return ;
      }

  while (recs != NULL)
    {
      recs->total = 0 ;       /* Zeroise this records total message count. */
      recs = recs->next ;     /* Point to next record. */
    }

  if ((fp = fopen(spoolfile,"r")) == NULL)     /* Open spoolfile. */
    {
      make_display() ;        /* Display the "no mail" icon. */
      return ;
    }
  if (mtype == MONNEW) FSEEK(fp, lastsize, 0) ;
  lastsize = buf.st_size ;
  while (fgets(nextline,MAXLINE,fp) != NULL)
    if (EQUAL(nextline,"From "))
      {
        host[0] = user[0] = ts[0] = '\0' ;

        if ((ptr = get_field(HOSTNAME,nextline)) != NULL)
          STRCPY(host, ptr) ;
        if ((ptr = get_field(USERNAME,nextline)) != NULL)
          STRCPY(user, ptr) ;
        if ((ptr = get_field(TIMESTAMP,nextline)) != NULL)
          STRCPY(ts, ptr) ;

        if (mtype == MONNEW) total++ ;       /* This is a new message. */
        if (EQUAL(user,"MAILER-DAEMON") ||   /* Is this a bounced message? */
            EQUAL(user,"Mailer-Daemon"))
          {
            bounced++ ;
            STRCPY(bounced_ts, ts) ;      /* Save latest timestamp. */
          }
        else if ((crec = rec_exists(host,user)) != NULL)
          {
            STRCPY(crec->ts, ts) ;
            crec->total++ ;
          }
        else
          {
            if (!strlen(host)) STRCPY(host,defhost) ;
            make_iconname(facedir,host,user) ;
            if (!stat(iconname,&buf)) add_record(host,user,ts,0) ;
            else
              {
                unknown++ ;
                STRCPY(unknown_ts, ts) ;   /* Save latest timestamp. */
              }
          }
      }
  FCLOSE(fp) ;
  make_display() ;        /* Output icons and tidyup chain of records. */
}


do_printer()                 /* Monitor printer queue. */
{
  struct recinfo *last, *this, *next ;
  FILE *fp ;                 /* File descriptor for users mail spool file. */
  char command[MAXLINE] ;    /* Lpq system call for this printer. */
  char owner[MAXLINE] ;      /* Owner of job in the print queue. */
  char tempname[MAXLINE] ;   /* Temporary unique filename. */
  int size ;                 /* Size of this print job in bytes. */

  noicons = 0 ;
  SPRINTF(tempname,"/tmp/faces%04d",getpid()) ;
  SPRINTF(command,"lpq -P %s > %s",printer,tempname) ;
  if (system(command))
    {
      FPRINTF(stderr,"%s: system call for printer %s stats failed.\n",
              progname,printer) ;
      exit(1) ;
    }
  if ((fp = fopen(tempname,"r")) == NULL)     /* Open spoolfile. */
    {
      FPRINTF(stderr,"%s: couldn't open printer stats in %s.\n",
              progname,tempname) ;
      return ;
    }
  column = row = 0 ;          /* Start in top left corner of pixrect. */
  FGETS(nextline,MAXLINE,fp) ;
  if (EQUAL(nextline,"no entries"))
    {
      make_pixrect(1) ;                  /* Just the "no print" icon. */
      add_face(BOTH, NOPRINT, "") ;      /* Set to "no print" icon. */
      text(BOTH, TOPLEFT, printer) ;     /* Output printer name. */
    }
  else
    {
      FGETS(nextline,MAXLINE,fp) ;    /* Skip the next line. */
      while (fgets(nextline,MAXLINE,fp) != NULL)
        {
          SSCANF(&nextline[7],"%s",owner) ;
          SSCANF(&nextline[60],"%d",&size) ;
          make_iconname(facedir,defhost,owner) ;
          add_record("",owner,"",size) ;
        }
      make_pixrect(noicons) ;
      this = last = recs ;
      while (this != NULL)
        {
          next = this->next ;
          if (!stat(this->iconname,&buf))
            add_face(WINDOW, ORDINARY, this->iconname) ;
          else add_face(WINDOW, NOFACE, "") ;
          SPRINTF(nextline, "%1d", this->size) ;
          text(WINDOW, BOTTOMRIGHT, nextline) ;    /* Size of print job. */
          text(WINDOW, TOPLEFT, this->username) ;  /* Owner of print job. */
          if (this == recs)
            {
              if (!stat(this->iconname,&buf))
                add_face(ICON, ORDINARY, this->iconname) ;
              else add_face(ICON, NOFACE, "") ;
              SPRINTF(nextline, "%1d jobs", noicons) ;
              text(ICON, BOTTOMRIGHT, nextline) ;   /* Number of jobs. */
            }
          ADJUST ;    /* Adjust column and row. */
          remove_record(last,this) ;
          last = this ;
          this = next ;
        }
      recs = last = NULL ;
    }
  FCLOSE(fp) ;
  UNLINK(tempname) ;
  show_display() ;
}


make_pixrect(count)         /* Make window pixrect the correct size. */
int count ;
{
  int c, r ;                /* Size in columns and rows of window display. */

  r = count / NO_PER_ROW ;     /* Number of rows of face icons. */
  c = count % NO_PER_ROW ;     /* Number of faces in "last" row. */
  if (!r)
    {
      height = ICONHEIGHT ;      /* Just one row. */
      width = c * ICONWIDTH ;    /* Upto ten icons in width. */
    }
  else
    {
      height = r * ICONHEIGHT ;         /* Height of the icon display. */
      width = NO_PER_ROW * ICONWIDTH ;  /* Yes: full width. */
    }
  create_pixrects() ;          /* Create the new memory pixrects. */
}


make_display()              /* Output icons and tidyup chain of records. */
{
  int count ;               /* Name of faces in icon display. */
  struct recinfo *last, *this, *next ;

  if (mtype == MONNEW && !total) return ;   /* Don't change the display. */
  count = noicons ;         /* Number of faces to display. */
  if (unknown) count++ ;
  if (bounced) count++ ;
  if (!count) count = 1 ;   /* Always one "no mail" icon. */
  if (mtype == MONNEW) make_pixrect(10) ;   /* Always upto ten messages displayed. */
  else make_pixrect(count) ;     /* Make display pixrect the correct size. */
  column = row = 0 ;        /* Start in top left corner of icon display. */

  if (!noicons && !unknown)
    {
      add_face(BOTH, NOMAIL, "") ;
      ADJUST ;              /* Adjust row and column values. */
    }
  else
    {
      if (unknown)
        {
          add_face(BOTH, NOFACE, "") ;
          add_params(unknown, unknown_ts) ;
          ADJUST ;          /* Adjust row and column values. */
        }
      if (bounced)
        {
          add_face(BOTH, MAILERD, "") ;
          add_params(bounced, bounced_ts) ;
          ADJUST ;          /* Adjust row and column values. */
        }
      this = last = recs ;
      while (this != NULL)
        {
          next = this->next ;
          if (!this->total) remove_record(last,this) ;
          else
            {
              add_face(BOTH, ORDINARY, this->iconname) ;
              add_params(this->total, this->ts) ;
              text(WINDOW, TOPLEFT, this->username) ;
              ADJUST ;
            }
          last = this ;
          this = next ;
        }
    }
  show_display() ;         /* Display the latest set of faces. */
}
Funky_Stuff
len=`wc -c < mon.c`
if [ $len !=     9080 ] ; then
echo error: mon.c was $len bytes long, should have been     9080
fi
fi # end of overwriting check
if [ -f rec.c ]
then
echo shar: will not over-write existing file rec.c
else
echo shar: extracting 'rec.c',     2339 characters
cat > rec.c <<'Funky_Stuff'

/*  rec.c
 *
 *  Record handling routines used by the faces program.
 * 
 *  Copyright (c) Rich Burridge - Sun Microsystems Australia.
 *                                All rights reserved.
 *
 *  Permission is given to distribute these sources, as long as the
 *  copyright messages are not removed, and no monies are exchanged. 
 * 
 *  Version 1.1 - July 1988.
 *
 *  No responsibility is taken for any errors on inaccuracies inherent
 *  either to the comments or the code of this program, but if reported
 *  to me, then an attempt will be made to fix them.
 */

#include "faces.h"
#include "extern.h"

char *
Malloc(n)
int n ;
{
  char *val ;

  if ((val = malloc((unsigned) n)) == NULL)
    FPRINTF(stderr,"%s: Out of memory.\n",progname) ;
  return val ;
}


add_record(hostname,username,timestamp,size)  /* Add new record to list. */
char *hostname, *username, *timestamp ;
int size ;
{
  struct recinfo *temp ;

  temp = (struct recinfo *) Malloc(sizeof(struct recinfo)) ;
  temp->hostname = (char *) Malloc(strlen(hostname)) ;
  STRCPY(temp->hostname, hostname) ;
  temp->username = (char *) Malloc(strlen(username)) ;
  STRCPY(temp->username, username) ;
  temp->iconname = (char *) Malloc(strlen(iconname)) ;
  STRCPY(temp->iconname, iconname) ;
  STRCPY(temp->ts, timestamp) ;
  temp->size = size ;
  temp->total = 1 ;
  temp->next = NULL ;
  noicons++ ;
  if (recs == NULL) recs = last = temp ;        /* Start chain. */
  else if (last != NULL)
    {
      last->next = temp ;  /* Add record to existing chain. */
      last = temp ;        /* Point to the end of the chain. */
    }
}


struct recinfo *
rec_exists(hostname,username)    /* Check if record exists for mail item. */
char *hostname, *username ;
{
  struct recinfo *temp ;     /* Pointer to mail records used for chaining. */

  temp = recs ;
  while (temp != NULL)
    {
      if (EQUAL(temp->username, username) &&
          EQUAL(temp->hostname, hostname))
        return(temp) ;       /* Record found. */
      temp = temp->next ;    /* Point to next record. */
    }
  return(NULL) ;
}


remove_record(lastrec, thisrec)        /* Remove this record from the chain. */
struct recinfo *lastrec, *thisrec ;
{
  lastrec->next = thisrec->next ;
  free(thisrec->hostname) ;
  free(thisrec->username) ;
  free(thisrec->iconname) ;
  free((char *) thisrec) ;
}
Funky_Stuff
len=`wc -c < rec.c`
if [ $len !=     2339 ] ; then
echo error: rec.c was $len bytes long, should have been     2339
fi
fi # end of overwriting check
if [ -f sunview.c ]
then
echo shar: will not over-write existing file sunview.c
else
echo shar: extracting 'sunview.c',     7904 characters
cat > sunview.c <<'Funky_Stuff'

/*  sunview.c
 *
 *  SunView dependent graphics routines used by faces,
 *  the visual mail and print job monitor.
 * 
 *  Copyright (c) Rich Burridge - Sun Microsystems Australia.
 *                                All rights reserved.
 *
 *  Permission is given to distribute these sources, as long as the
 *  copyright messages are not removed, and no monies are exchanged. 
 * 
 *  Version 1.1 - July 1988.
 *
 *  No responsibility is taken for any errors on inaccuracies inherent
 *  either to the comments or the code of this program, but if reported
 *  to me, then an attempt will be made to fix them.
 */

#include "faces.h"
#include "extern.h"
#include <stdio.h>
#include <suntool/sunview.h>
#include <suntool/canvas.h>

#define  ICON_SET                (void) icon_set
#define  NOTIFY_SET_ITIMER_FUNC  (void) notify_set_itimer_func
#define  PR_DESTROY              (void) pr_destroy
#define  PR_REPLROP              (void) pr_replrop
#define  PR_ROP                  (void) pr_rop
#define  PR_TTEXT                (void) pr_ttext
#define  PW_ROP                  (void) pw_rop
#define  WINDOW_SET              (void) window_set

#define  SMALLFONT    "/usr/lib/fonts/fixedwidthfonts/screen.r.7"
#define  ITIMER_NULL  ((struct itimerval *) 0)

Canvas canvas ;
Frame frame ;
Icon faces_icon ;
Pixfont *sfont ;       /* Small character font for timestamp and count. */
Pixrect *mpr, *pr ;           /* Pointers to current pixrects. */
Pixrect *old_mpr, *old_pr ;   /* Pointers to previous pixrects. */
Pixrect *icon_load_mpr() ;
Pixwin *pw ;
Rect *temprect ;

short gray_image[16] = {
  0x8888, 0x8888, 0x2222, 0x2222,
  0x8888, 0x8888, 0x2222, 0x2222,
  0x8888, 0x8888, 0x2222, 0x2222,
  0x8888, 0x8888, 0x2222, 0x2222
} ;
mpr_static(gray_pr,16,16,1,gray_image) ;

short bounced_image[] = {
#include "bounced.icon"
} ;
mpr_static(bounced_pr,64,64,1,bounced_image) ;

short noface_image[] = {
#include "noface.icon"
} ;
mpr_static(noface_pr,64,64,1,noface_image) ;
 
short nomail_image[] = {
#include "nomail.icon"
} ;
mpr_static(nomail_pr,64,64,1,nomail_image) ;

short noprint_image[] = {
#include "noprint.icon"
} ;
mpr_static(noprint_pr,64,64,1,noprint_image) ;


add_face(display, itype, filename)     /* Add this icon to the display. */
enum disp_type display ;
enum icon_type itype ;
char *filename ;
{
  char error_msg[256] ;      /* Possible error message from icon_load_mpr. */
  Pixrect *face_pr ;

  switch ((int) itype)
    {
      case MAILERD  : face_pr = &bounced_pr ;
                      break ;
      case NOFACE   : face_pr = &noface_pr ;
                      break ;
      case NOMAIL   : face_pr = &nomail_pr ;
                      break ;
      case NOPRINT  : face_pr = &noprint_pr ;
                      break ;
      case ORDINARY : if ((face_pr = icon_load_mpr(filename, error_msg)) == NULL)
                        {
                          FPRINTF(stderr,"%s: %s is not a valid icon file.\n",
                                         progname,filename) ;
                          face_pr = &noface_pr ;
                        }
                      break ;
    }
  switch ((int) display)
    {
      case BOTH    : add_face(ICON, itype, filename) ;
                     add_face(WINDOW, itype, filename) ;
                     break ;
      case ICON    : if (mtype != MONALL)
                       PR_ROP(mpr, 0, 0, ICONWIDTH, ICONHEIGHT,
                              PIX_SRC, face_pr, 0, 0) ;
                     else PR_ROP(mpr, column*ICONWIDTH, row*ICONHEIGHT, ICONWIDTH, ICONHEIGHT,
                                 PIX_SRC, face_pr, 0, 0) ;
                     break ;
      case WINDOW  : switch ((int) mtype)
                       {
                         case MONNEW     : PR_ROP(pr, 64, 0, 640-64, 64, PIX_SRC, pr, 0, 0) ;
                         case MONALL     :
                         case MONPRINTER : PR_ROP(pr, column*ICONWIDTH, row*ICONHEIGHT,
                                                  ICONWIDTH, ICONHEIGHT,
                                                  PIX_SRC, face_pr, 0, 0) ;
                       }
    }
}


Notify_value
check_mail()
{
  do_check() ;
}


create_pixrects()        /* Create pixrects for the face images. */
{
  old_pr = pr ;
  pr = mem_create(width, height, 1) ;
  PR_REPLROP(pr, 0, 0, width, height, PIX_SRC, &gray_pr, 0, 0) ;
  mpr = mem_create(width, height, 1) ;
  PR_REPLROP(mpr, 0, 0, width, height, PIX_SRC, &gray_pr, 0, 0) ;

  if (mtype == MONNEW && old_pr != NULL)
    PR_ROP(pr, 0, 0, width, height, PIX_SRC, old_pr, 0, 0) ;
}


make_frame(argc,argv)
int argc ;
char *argv[] ;
{
  frame = window_create((Window) 0, FRAME,
                        FRAME_ICON, faces_icon,
                        FRAME_SHOW_LABEL, FALSE,
                        FRAME_SUBWINDOWS_ADJUSTABLE, FALSE,
                        FRAME_NO_CONFIRM, TRUE,
                        FRAME_ARGS, argc,argv,
                        FRAME_CLOSED, TRUE,
                        0) ;
  canvas = window_create(frame, CANVAS, CANVAS_RETAINED, TRUE, 0) ;
  pw = canvas_pixwin(canvas) ;
  sfont = pf_open(SMALLFONT) ;
  old_pr = old_mpr = NULL ;
}


make_icon()
{
  if (mtype == MONPRINTER)
    faces_icon = icon_create(ICON_IMAGE, &noprint_pr, 0) ;
  else faces_icon = icon_create(ICON_IMAGE, &nomail_pr, 0) ;
}


show_display()        /* Show the latest set of mail icon faces. */
{
  faces_icon = (Icon) window_get(frame, FRAME_ICON) ;
  old_mpr = (Pixrect *) icon_get(faces_icon, ICON_IMAGE) ;
  if (mtype == MONALL)
    {
      temprect = (Rect *) icon_get(faces_icon, ICON_IMAGE_RECT) ;
      temprect->r_height = height ;
      temprect->r_width = width ;
      ICON_SET(faces_icon, ICON_HEIGHT, height,
                           ICON_WIDTH, width,
                           ICON_IMAGE_RECT, temprect,
                           ICON_IMAGE, mpr,
                           0) ;
    }
  else ICON_SET(faces_icon, ICON_IMAGE, mpr, 0) ;
  WINDOW_SET(frame, FRAME_ICON, faces_icon, 0) ;

  temprect = (Rect *) window_get(frame, FRAME_OPEN_RECT) ;
  temprect->r_height = height+10 ;
  temprect->r_width = width+10 ;
  WINDOW_SET(frame, FRAME_OPEN_RECT, temprect, 0) ;
  PW_ROP(pw,0,0,width,height,PIX_SRC,pr,0,0) ;

  if (old_pr) PR_DESTROY(old_pr) ;
  if (old_mpr) PR_DESTROY(old_mpr) ;
}


start_tool()
{
  struct itimerval tval ;

  tval.it_interval.tv_usec = 0 ;
  tval.it_interval.tv_sec = interval ;
  tval.it_value.tv_usec = 0 ;
  tval.it_value.tv_sec = interval ;
  NOTIFY_SET_ITIMER_FUNC(frame, check_mail,
                         ITIMER_REAL, &tval, ITIMER_NULL) ;
  window_main_loop(frame) ;
}


text(display,just,str)
enum disp_type display ;
enum just_type just ;
char *str ;
{
  int len ;
  int c, r ;         /* Column and row position for this face. */
  int x, y ;         /* Position of start of this text string. */
  Pixrect *tpr ;

  c = column ;
  r = row ;
  switch ((int) display)
    {
      case BOTH   : text(ICON, just, str) ;
                    text(WINDOW, just, str) ;
                    return ;
      case ICON   : tpr = mpr ;
                    if (mtype != MONALL) c = r = 0 ;
                    break ;
      case WINDOW : tpr = pr ;
    }

  len = strlen(str) ;         /* Character length of text. */
  switch ((int) just)
    {
      case TOPLEFT     : x = c*ICONWIDTH+2 ;
                         y = (r+1)*ICONHEIGHT-17 ;
                         break ;
      case TOPRIGHT    : x = (c+1)*ICONWIDTH-(len*6)-2 ;
                         y = (r+1)*ICONHEIGHT-17 ;
                         break ;
      case BOTTOMLEFT  : x = c*ICONWIDTH+2 ;;
                         y = (r+1)*ICONHEIGHT-2 ;
                         break ;
      case BOTTOMRIGHT : x = (c+1)*ICONWIDTH-(len*6)-2 ;
                         y = (r+1)*ICONHEIGHT-2 ;
    }
  PR_ROP(tpr, x, y-9, len*6+2, 10, PIX_CLR, (Pixrect *) NULL, 0, 0) ;
  PR_TTEXT(tpr, x, y, PIX_SRC ^ PIX_NOT(PIX_DST), sfont, str) ;
}
Funky_Stuff
len=`wc -c < sunview.c`
if [ $len !=     7904 ] ; then
echo error: sunview.c was $len bytes long, should have been     7904
fi
fi # end of overwriting check