[comp.sources.misc] v05i093: faces v1.3 - visual mail/print monitor, Part 2/3

richb@sunchat.oz.AU (Rich Burridge) (12/24/88)

Posting-number: Volume 5, Issue 93
Submitted-By: Rich Burridge <richb@sunchat.oz.AU>
Archive-name: faces-1.3/part02

------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:
#	mon.c
#	news.c
#	rec.c
#	sunview.c
# This archive created: Sun Dec 11 14:57:25 EST 1988
#
#
export PATH; PATH=/bin:$PATH
#
if [ -f mon.c ]
then
echo shar: will not over-write existing file mon.c
else
echo shar: extracting 'mon.c',     8937 characters
cat > mon.c <<'Funky_Stuff'
/*LINTLIBRARY*/
#ifndef lint
static char sccsid[] = "@(#)mon.c 1.4 88/12/11" ;
#endif

/*  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. 
 * 
 *  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"

adjust()          /* Adjust the row and column position. */
{
  struct psinfo *this ;

  if (mtype != MONNEW)
    {
      if (++column == NO_PER_ROW)
        {
          column = 0 ;
          row++ ;
        }
      return ;
    }
  if (psrecs != NULL)           /* Adjust animation positions for MONNEW */
    {
      this = psrecs ;           /* Point to beginning of chain. */
      while (this != NULL)
        {
          this->column++ ;      /* Adjust column position. */
          if (facetype == NEWSTYPE && this->next == NULL)
            this->column-- ;    /* Reset for brand new animate record. */
          this = this->next ;
        }
    }
}


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 ;
    }
  firsttime = 0 ;
}


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 realname[MAXLINE] ;  /* Real username for this user. */
  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. */

  column = row = 0 ;        /* Start in top left corner of pixrect. */
  newmail = 0 ;             /* Assume no new mail. */
  noicons = 0 ;

  if (mtype == MONNEW) make_pixrect(NO_PER_ROW) ;
  if (stat(spoolfile,&buf) == -1)
    {
      lastsize = 0 ;
      if (mtype == MONNEW) show_display() ;   /* Show new mail. */
      else make_display() ;     /* Output icons and tidyup chain of records. */
      return ;
    }
  if (buf.st_size > lastsize) newmail = 1 ;   /* New mail found. */
  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. */
        show_display() ;
        return ;
      }

  if ((fp = fopen(spoolfile,"r")) == NULL)     /* Open spoolfile. */
    {
      if (mtype == MONNEW) show_display() ;   /* Show new mail. */
      else make_display() ;     /* Output icons and tidyup chain of records. */
      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) ;

        h_to_c(host, community) ;    /* Turn hostname into community name. */
        a_to_u(community, user, realname) ;
        make_iconname(community, realname) ;
        if (mtype == MONNEW)
          {
            add_face(BOTH, ORDINARY, iconname) ;
            if (!dontshowtime) text(ICON, LEFT, ts) ;
            if (!dontshowuser) text(WINDOW, LEFT, realname) ;
            adjust() ;
          }
        else
          {
            if ((crec = rec_exists(community, realname)) != NULL)
              {
                STRCPY(crec->ts, ts) ;
                if (!crec->total) noicons++ ;
                crec->total++ ;
              }
            else add_record(community, realname, ts, 0) ;
          }
      }
  FCLOSE(fp) ;
  if (mtype == MONNEW) show_display() ;   /* Show new mail. */
  else make_display() ;     /* Output icons and tidyup chain of records. */
}


do_printer()                 /* Monitor printer queue. */
{
  struct recinfo *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) ;
      return ;
    }
  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. */
    }
  else if (EQUAL(nextline,"Printer Error: may need attention!"))
    {
      make_pixrect(1) ;               /* Just the "no paper" icon. */
      add_face(BOTH, NOPAPER, "") ;   /* Set to "no paper" icon. */
      text(BOTH, LEFT, 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) ;
          h_to_c("", community) ;
          make_iconname(community, owner) ;
          add_record("",owner,"",size) ;
        }
      make_pixrect(noicons) ;
      this = recs ;
      while (this != NULL)
        {
          next = this->next ;
          add_face(WINDOW, ORDINARY, this->iconname) ;
          SPRINTF(nextline, "%1d", this->size) ;
          if (!dontshowuser)
            text(WINDOW, LEFT, this->username) ;  /* Owner. */
          text(WINDOW, RIGHT, nextline) ;         /* Size. */
          if (this == recs)
            {
              add_face(ICON, ORDINARY, this->iconname) ;
              SPRINTF(nextline, "%1d %s", noicons, (noicons == 1 ? "job" : "jobs")) ;
              text(ICON, RIGHT, nextline) ;   /* Number of jobs. */
            }
          adjust() ;    /* Adjust column and row. */
          remove_record(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-1) / NO_PER_ROW) + 1 ;   /* Number of rows of faces. */
  c = NO_PER_ROW ;                     /* Full width display. */
  if (count <= 10)
    {
      r = 1 ;         /* One row. */
      c = count ;     /* Of 'count' columns. */
    }

  height = r * ICONHEIGHT ;    /* Height of the icon display. */
  width = c * ICONWIDTH ;      /* Width of the icon display. */
  create_pixrects(width, height) ;
}


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

  count = noicons ;         /* Number of faces to display. */
  if (!count) count = 1 ;   /* Always one "no mail" icon. */
  make_pixrect(count) ;

  if (!noicons) add_face(BOTH, NOMAIL, "") ;
  else
    {
      this = recs ;
      while (this != NULL)
        {
          next = this->next ;
          add_face(BOTH, ORDINARY, this->iconname) ;
          if (!dontshowno)
            {
              SPRINTF(nextline, "%1d", this->total) ;
              text(ICON, RIGHT, nextline) ;
            }
          if (!dontshowtime) text(ICON, LEFT, this->ts) ;
          if (!dontshowuser) text(WINDOW, LEFT, this->username) ;
          adjust() ;
          remove_record(this) ;
          this = next ;
        }
      recs = last = NULL ;
    }
  show_display() ;         /* Display the latest set of faces. */
}
Funky_Stuff
len=`wc -c < mon.c`
if [ $len !=     8937 ] ; then
echo error: mon.c was $len bytes long, should have been     8937
fi
fi # end of overwriting check
if [ -f news.c ]
then
echo shar: will not over-write existing file news.c
else
echo shar: extracting 'news.c',    10648 characters
cat > news.c <<'Funky_Stuff'
/*LINTLIBRARY*/
#ifndef lint
static char sccsid[] = "@(#)news.c 1.3 88/12/11" ;
#endif

/*  NeWS 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. 
 * 
 *  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 <sundev/kbd.h>
#include <sundev/kbio.h>

#ifdef SUNOS3.x
int fullmask ;               /* Full mask of file descriptors to check on. */
int readmask ;               /* Readmask used in select call. */
#else
fd_set fullmask ;            /* Full mask of file descriptors to check on. */
fd_set readmask ;            /* Readmask used in select call. */
#endif SUNOS3.x

int kbdfd ;                  /* File descriptor for the keyboard. */
int psfd ;                   /* NeWS connection file descriptor. */
unsigned short ibuf[256] ;   /* Ikon/icon image buffer. */

extern FILE *PostScript ;
extern FILE *PostScriptInput ;


add_face(display, itype, name)     /* Add this icon to the display. */
enum disp_type display ;
enum icon_type itype ;
char *name ;
{
  char face[MAXLINE] ;        /* Canvas containing face (Source). */

  switch ((int) itype)
    {
      case NOMAIL   : STRCPY(face, "NomailIcon") ;
                      break ;
      case NOPAPER  : STRCPY(face, "NopaperIcon") ;
                      break ;
      case NOPRINT  : STRCPY(face, "NoprintIcon") ;
                      break ;
      case ORDINARY : if ((facetype = get_icon(name, ibuf)) != -1) 
                        switch (facetype)
                          {
                            case BLITTYPE :
                            case SUNTYPE  : load_icon("Curface") ;
                                            STRCPY(face, "CurfaceIcon") ;
                            case NEWSTYPE : break ;
                          }
                      else STRCPY(face, "NofaceIcon") ;
                      break ;
    }

  if (display == ICON)
    if (mtype == MONPRINTER) adjust_image("MPR", face, 0, 0) ;
    else adjust_image("MPR", face, row, column) ;
  else if (display == WINDOW) adjust_image("PR", face, row, column) ;
  else
    {
      adjust_image("MPR", face, row, column) ;
      adjust_image("PR", face, row, column) ;
    }
  FFLUSH(PostScript) ;
}


adjust_image(dest, face, row, column)
char *dest, *face ;
int row, column ;
{
  switch ((int) mtype)
    {
      case MONNEW     : FPRINTF(PostScript, "%d 0 %d %d %s ShiftImage\n",
                                ICONWIDTH, (NO_PER_ROW-1)*ICONWIDTH, ICONHEIGHT,
                                dest) ;
                        if (facetype == NEWSTYPE)
                          {
                            FPRINTF(PostScript, "%d %d %d %d %s ClearBox\n",
                                    column*ICONWIDTH, row*ICONHEIGHT,
                                    ICONWIDTH, ICONHEIGHT, dest) ;
                            return ;
                          }
      case MONALL     :
      case MONPRINTER : FPRINTF(PostScript,"%s %d %d %d %d %s MoveImage\n",
                                face, ICONWIDTH, ICONHEIGHT,
                                column*ICONWIDTH, row*ICONHEIGHT, dest) ;
    }
}


beep_flash(beeps, flashes)    /* Perform visual feedback. */
int beeps, flashes ;
{
  int i, x ;

  if (beeps)
    for (i = 0; i < beeps; i++)
      {
        x = KBD_CMD_BELL ;
        IOCTL(kbdfd, KIOCCMD, &x) ;
        usleep(250000) ;
        x = KBD_CMD_NOBELL ;
        IOCTL(kbdfd, KIOCCMD, &x) ;
        usleep(250000) ;
      }
}


create_pixrects(width, height)        /* Create pixrects for the face images. */
{
  int h, i, j, w ;

  if (mtype == MONNEW && !firsttime) return ;
  FPRINTF(PostScript,"%d %d PR DoPixrects\n", width, height) ;
  h = height ;
  w = width ;
  if (mtype == MONPRINTER)
    {
      h = ICONHEIGHT ;
      w = ICONWIDTH ;
    }
  FPRINTF(PostScript,"%d %d MPR DoPixrects\n", w, h) ;
  if (strlen(bgicon))
    {
      for (i = 0; i < (height / 64); i++)
        for (j = 0; j < (width / 64); j++)
          {
            FPRINTF(PostScript,"BackgroundIcon %d %d %d %d PR MoveImage\n",
                                  ICONWIDTH, ICONHEIGHT, j, i) ;
            FPRINTF(PostScript,"BackgroundIcon %d %d %d %d MPR MoveImage\n",
                                  ICONWIDTH, ICONHEIGHT, j, i) ;
          }
    }
  else FPRINTF(PostScript,"SetBackground\n") ;
}


do_news_ps(psrecs)     /* Display chain of NeWS animations. */
struct psinfo *psrecs ;
{
  struct psinfo *next, *this ;

  this = psrecs ;      /* Point to beginning of NeWS records. */
  while (this != NULL)
    {
      next = this->next ;
      if ((mtype != MONNEW) || (this->column < NO_PER_ROW))
        {
          FPRINTF(PostScript, "(%s) %d %d %d %d ExecFile\n",
                  this->name, ICONWIDTH, ICONHEIGHT,
                  this->column*ICONWIDTH, this->row*ICONHEIGHT) ;
          FFLUSH(PostScript) ;
        }
      this = next ;
    }
}


init_ws_type()
{
  if (ps_open_PostScript() < 0) return -1 ;
  if (send_ps_file(NEWSFILE) == -1)
    {
      FPRINTF(stderr,"%s: cannot open %s\n", progname, NEWSFILE) ;
      FCLOSE(PostScript) ;
      return(-1) ;
    }
  FFLUSH(PostScript) ;
  if (ferror(PostScript))
    {
      FCLOSE(PostScript) ;
      return(-1) ;
    }
  if (invert) FPRINTF(PostScript, "/Invert false def\n") ;
  else FPRINTF(PostScript, "/Invert true def\n") ;
  gtype = NEWS ;
  return(0) ;
}


load_icon(name)
char *name ;
{
  int i, j ;

  FPRINTF(PostScript,"/%sIcon 64 64 1 { } { <\n", name) ;
  for (i = 0; i < 32; i++)
    {
      for (j = 0; j < 8; j++) FPRINTF(PostScript,"%.4X ", ibuf[i*8+j]) ;
      FPRINTF(PostScript,"\n") ;
    }
  FPRINTF(PostScript,"> } buildimage def\n") ;
}


/*ARGSUSED*/
make_frame(argc,argv)
int argc ;
char *argv[] ;
{
  if ((kbdfd = open("/dev/kbd", 0)) == -1)
    {
      FPRINTF(stderr,"%s: can't open keyboard.\n", progname) ;
      exit(1) ;
    }

  psfd = fileno(PostScriptInput) ;

#ifdef SUNOS3.x
  fullmask = 1 << psfd ;
#else
  FD_ZERO(&fullmask) ;
  FD_SET(psfd, &fullmask) ;
#endif SUNOS3.x

  if (strlen(bgicon))
    if (get_sun_icon(bgicon, ibuf) == 0) load_icon("Background") ;

  FPRINTF(PostScript,"%d %d %d %d %d %d %d MakeFrame\n",
          wx, wy, NO_PER_ROW*ICONWIDTH+10, ICONHEIGHT*10+10,
          ix, iy, iconic) ;
  FPRINTF(PostScript,"InitFont\n") ;
  width = NO_PER_ROW * ICONWIDTH ;
  height = ICONHEIGHT ;
}


make_icon()
{
  if (get_sun_icon("noface.icon", ibuf) == 0) load_icon("Noface") ;
  if (get_sun_icon("nomail.icon", ibuf) == 0) load_icon("Nomail") ;
  if (get_sun_icon("nopaper.icon", ibuf) == 0) load_icon("Nopaper") ;
  if (get_sun_icon("noprint.icon", ibuf) == 0) load_icon("Noprint") ;
}


send_ps_file(fname)
char *fname ;
{
  FILE *stream ;
  int c ;

  if ((stream = fopen(fname,"r")) == NULL) return -1 ;
  while ((c = getc(stream)) != EOF) PUTC(c,PostScript) ;
  FCLOSE(stream) ;
  return 0 ;
}


show_display()        /* Show the latest set of mail icon faces. */
{
  if (mtype != MONPRINTER)
    FPRINTF(PostScript,"%d %d %d %d ShowDisplay\n",
                        width, height, width, height) ;
  else FPRINTF(PostScript,"%d %d %d %d ShowDisplay\n",
                        width, height, ICONWIDTH, ICONHEIGHT) ;

  if (newmail) beep_flash(beeps, flashes) ;
  if (psrecs != NULL) do_news_ps(psrecs) ;
  FFLUSH(PostScript) ;
}


start_tool()
{
  int type ;                     /* Value from NeWS server. */
  struct psinfo *next, *this ;   /* For removing current chain of records. */
  struct timeval tval ;

  tval.tv_usec = 0 ;
  tval.tv_sec = period ;

  for (;;)
    {
      readmask = fullmask ;
#ifdef SUNOS3.x
      SELECT(32, &readmask, 0, 0, &tval) ;
      if (readmask && (1 << psfd))
#else
      SELECT(FD_SETSIZE, &readmask, (fd_set *) 0, (fd_set *) 0, &tval) ;
      if (FD_ISSET(psfd, &readmask))
#endif SUNOS3.x
        {
          if (pscanf(PostScriptInput, "%d", &type) == EOF) exit(1) ;
          switch (type)
            {
              case DIED     : exit(0) ;
              case PAINTED  : if (psrecs != NULL) do_news_ps(psrecs) ;
            }
        }
      else
        {
          this = psrecs ;     /* Point to beginning of NeWS records. */
          if (mtype != MONNEW)
            {
              while (this != NULL)
                {
                  next = this->next ;
                  if (this->name != NULL) free(this->name) ;
                  free((char *) this) ;   /* Remove this record. */
                  this = next ;
                }
              psrecs = plast = NULL ;
            }
          do_check() ;        /* Check the mail/printer again. */
        }
    }
}


text(display,just,str)
enum disp_type display ;
enum just_type just ;
char *str ;
{
  int i, len ;
  int c, r ;             /* Column and row position for this face. */
  int x, y ;             /* Position of start of this text string. */
  char line[MAXLINE] ;   /* PostScript text string to be builtup. */
  char tpr ;             /* Indicator for destination offscreen canvas. */

  c = column ;
  r = row ;
  switch ((int) display)
    {
      case BOTH   : text(ICON, just, str) ;
                    text(WINDOW, just, str) ;
                    return ;
      case ICON   : tpr = 'M' ;       /* MPR canvas. */
                    if (mtype != MONALL) c = r = 0 ;
                    break ;
      case WINDOW : tpr = ' ' ;       /*  PR canvas. */
    }

  len = strlen(str) ;         /* Character length of text. */
  if (len > 10)
    {
      len = 10 ;
      str[10] = '\0' ;   /* Maximum of 10 characters. */
    }

  line[0] = '\0' ;
  for (i = 0; i < len; i++)
    switch (str[i])
      {
        case '\\' : STRCAT(line,"\\\\") ;
                    break ;
        case '('  : STRCAT(line,"\\(") ;
                    break ;
        case ')'  : STRCAT(line,"\\)") ;
                    break ;
        default   : STRNCAT(line,&str[i],1) ;
      }

  switch ((int) just)
    {
      case LEFT  : x = c*ICONWIDTH+2 ;
                   y = r*ICONHEIGHT+2 ;
                   break ;
      case RIGHT : x = (c+1)*ICONWIDTH-(len*6)-2 ;
                   y = r*ICONHEIGHT+2 ;
    }
  FPRINTF(PostScript,"%d %d %d %d %cPR ClearBox\n", x, y, len*6+2, 10, tpr) ;
  FPRINTF(PostScript,"(%s) %d %d %cPR MakeText\n", line, x, y, tpr) ;
}
Funky_Stuff
len=`wc -c < news.c`
if [ $len !=    10648 ] ; then
echo error: news.c was $len bytes long, should have been    10648
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',     6808 characters
cat > rec.c <<'Funky_Stuff'
/*LINTLIBRARY*/
#ifndef lint
static char sccsid[] = "@(#)rec.c 1.2 88/12/09" ;
#endif

/*  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. 
 * 
 *  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_alias(crec, username, alias)  /* Add new alias to hostnames' list. */
struct comminfo *crec ;
char *username, *alias ;
{
  struct peopinfo *cptemp, *ptemp ;

  ptemp = (struct peopinfo *) Malloc(sizeof(struct peopinfo)) ;
  ptemp->alias = (char *) Malloc(strlen(alias)) ;
  STRCPY(ptemp->alias, alias) ;
  ptemp->username = (char *) Malloc(strlen(username)) ;
  STRCPY(ptemp->username, username) ;
  ptemp->next = NULL ;

  if (crec->people == NULL) crec->people = ptemp ;
  else
    {
      cptemp = crec->people ;
      while (cptemp != NULL)
        if (cptemp->next == NULL)
          {
            cptemp->next = ptemp ;
            return ;
          }
        else cptemp = cptemp->next ;
    }
}


add_machine(machine, community)    /* Add new machine to list. */
char *machine, *community ;
{
  struct machinfo *temp ;

  temp = (struct machinfo *) Malloc(sizeof(struct machinfo)) ;
  temp->machine = (char *) Malloc(strlen(machine)) ;
  STRCPY(temp->machine, machine) ;
  temp->community = (char *) Malloc(strlen(community)) ;
  STRCPY(temp->community, community) ;
  temp->next = NULL ;

  if (machines == NULL) machines = mlast = temp ;   /* Start chain. */
  else if (mlast != NULL)
    {
      mlast->next = temp ;     /* Add record to existing chain. */
      mlast = temp ;           /* Point to end of chain. */
    }
}


add_ps_rec(row, column, name)  /* Add record for later animation. */
int row, column ;
char *name ;
{
  struct psinfo *temp ;

  temp = (struct psinfo *) Malloc(sizeof(struct psinfo)) ;
  temp->name = (char *) Malloc(strlen(name)) ;
  STRCPY(temp->name, name) ;
  temp->row = row ;
  temp->column = column ;
  temp->next = NULL ;

  if (psrecs == NULL) psrecs = plast = temp ;    /* Start chain. */
  else if (plast != NULL)
    {
      plast->next = temp ;     /* Add record to existing chain. */
      plast = temp ;
    }
}


add_record(community, username, timestamp, size)
char *community, *username, *timestamp ;
int size ;
{
  struct recinfo *temp ;

  temp = (struct recinfo *) Malloc(sizeof(struct recinfo)) ;
  temp->community = (char *) Malloc(strlen(community)) ;
  STRCPY(temp->community, community) ;
  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
    {
      last->next = temp ;  /* Add record to existing chain. */
      last = temp ;        /* Point to the end of the chain. */
    }
}


check_comm(hostname, username, alias)  /* Check community list. */
char *hostname, *username, *alias ;
{
  struct comminfo *ctemp ;
 
  ctemp = communities ;      /* Try and find machine record for hostname. */
  while (ctemp != NULL)
    if (EQUAL(ctemp->community, hostname))
      {  
        add_alias(ctemp, username, alias) ;
        return ;
      }  
    else ctemp = ctemp->next ;
 
  ctemp = (struct comminfo *) Malloc(sizeof(struct comminfo)) ;
  ctemp->community = (char *) Malloc(strlen(hostname)) ;
  STRCPY(ctemp->community, hostname) ; 
  ctemp->people = NULL ; 
  ctemp->next = NULL ; 
 
  if (communities == NULL) communities = clast = ctemp ;  /* Start chain. */ 
  else 
    { 
      clast->next = ctemp ;   /* Add record to existing chain. */
      clast = ctemp ;         /* Point to end of chain. */
    }
  add_alias(ctemp, username, alias) ;
}


read_aliases()     /* Setup the hostname aliases subchains. */
{
  char alias[MAXLINE] ;      /* Alias for this community/username. */
  char hostname[MAXLINE] ;   /* This records' hostname. */
  char username[MAXLINE] ;   /* This records real username. */
  char *ptr1, *ptr2 ;
  FILE *fd ;

  if ((fd = fopen(peopfile, "r")) == NULL)   /* Open people file. */
    {
      FPRINTF(stderr,"%s: cannot open %s\n", progname, peopfile) ;
      return ;
    }
  while (fgets(nextline, MAXLINE, fd) != NULL)
    {
      ptr1 = index(nextline, '/') ;
      STRNCPY(hostname, nextline, (int) (ptr1-nextline)) ;
      hostname[(int) (ptr1-nextline)] = '\0' ;
      ptr2 = index(nextline, '=') ;
      STRNCPY(alias, ptr1+1, (int) (ptr2-ptr1-1)) ;
      alias[(int) (ptr2-ptr1-1)] = '\0' ;
      STRNCPY(username, ptr2+1, strlen(ptr2)-2) ;
      username[strlen(ptr2)-2] = '\0' ;
      check_comm(hostname, username, alias) ;
    }
  FCLOSE(fd) ;
}


read_machines()       /* Setup the chain of machine/community records. */
{
  char community[MAXLINE] ;   /* This records' community. */
  char machine[MAXLINE] ;     /* This records' machine name. */
  char *ptr ;
  FILE *fd ;

  if ((fd = fopen(machfile, "r")) == NULL)   /* Open machine file. */
    {
      FPRINTF(stderr,"%s: cannot open %s\n", progname, machfile) ;
      return ;
    }
  while (fgets(nextline, MAXLINE, fd) != NULL)
    {
      ptr = index(nextline, '=') ;
      STRNCPY(machine, nextline, (int) (ptr-nextline)) ;
      machine[(int) (ptr-nextline)] = '\0' ;
      STRNCPY(community, ptr+1, strlen(ptr)-2) ;
      community[strlen(ptr)-2] = '\0' ;
      add_machine(machine, community) ;
    }
  FCLOSE(fd) ;
}


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

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


remove_record(thisrec)        /* Remove this record from the chain. */
struct recinfo *thisrec ;
{
  if (thisrec->community != NULL) free(thisrec->community) ;
  if (thisrec->username != NULL) free(thisrec->username) ;
  if (thisrec->iconname != NULL) free(thisrec->iconname) ;
  free((char *) thisrec) ;
}
Funky_Stuff
len=`wc -c < rec.c`
if [ $len !=     6808 ] ; then
echo error: rec.c was $len bytes long, should have been     6808
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',     9881 characters
cat > sunview.c <<'Funky_Stuff'
/*LINTLIBRARY*/
#ifndef lint
static char sccsid[] = "@(#)sunview.c 1.1 88/12/04" ;
#endif

/*  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. 
 * 
 *  No responsibility is taken for any errors or 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

#ifdef SUNOS3.x
#define  PR_TTEXT                (void) pf_ttext
#else
#define  PR_TTEXT                (void) pr_ttext
#endif SUNOS3.x

#define  PW_ROP                  (void) pw_rop
#define  WIN_BELL                (void) win_bell
#define  WINDOW_SET              (void) window_set

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

int repaint_proc() ;

Canvas canvas ;
Frame frame ;
Icon faces_icon ;
Pixfont *sfont ;              /* Small font for timestamp and count. */
Pixrect *mpr, *pr ;           /* Pointers to current pixrects. */
Pixrect *old_mpr, *old_pr ;   /* Pointers to previous pixrects. */
Pixrect *background ;         /* Pointer to background pattern or gray. */
Pixwin *fpw, *pw ;
Rect *temprect ;
int ffd ;                     /* File descriptor of faces frame. */

short gray_image[] = { 0x8000, 0x8000, 0x2000, 0x2000 } ;
mpr_static(gray_pr, 4, 4, 1, gray_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 nopaper_image[] = {
#include "nopaper.icon"
} ;
mpr_static(nopaper_pr, 64, 64, 1, nopaper_image) ;

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


add_face(display, itype, name)
enum disp_type display ;
enum icon_type itype ;
char *name ;
{
  Pixrect *face_pr ;
  unsigned short buf[256] ;  /* Ikon/icon image. */
  unsigned short *ptr ;
  int freeit ;               /* Set if we should destroy this pixrect. */
  int i ;

  freeit = 0 ;
  switch ((int) itype)
    {
      case NOMAIL   : face_pr = &nomail_pr ;
                      break ;
      case NOPAPER  : face_pr = &nopaper_pr ;
                      break ;
      case NOPRINT  : face_pr = &noprint_pr ;
                      break ;
      case ORDINARY : if (get_icon(name, buf) == -1) face_pr = &noface_pr ;
                      else
                        {
                          face_pr = mem_create(64, 64, 1) ;
                          ptr = (unsigned short *)
                                ((struct mpr_data *) face_pr->pr_data)->md_image ;
                          for (i = 0; i < 256; i++) ptr[i] = buf[i] ;
                          freeit = 1 ;
                        }
                      break ;
    }
  if (display == ICON)
    if (mtype == MONPRINTER) adjust_image(mpr, face_pr, 0, 0) ;
    else adjust_image(mpr, face_pr, row, column) ;
  else if (display == WINDOW) adjust_image(pr, face_pr, row, column) ;
  else
    {
      adjust_image(mpr, face_pr, row, column) ;
      adjust_image(pr, face_pr, row, column) ;
    }
  if (freeit) PR_DESTROY(face_pr) ;
}


adjust_image(fpr, face_pr, row, column)    /* Place new face in memory pixrect. */
Pixrect *fpr, *face_pr ;
int row, column ;
{
  switch ((int) mtype)
    {
      case MONNEW     : PR_ROP(fpr, 64, 0, 640-64, 64, PIX_SRC, fpr, 0, 0) ;
      case MONALL     :
      case MONPRINTER : PR_ROP(fpr, column*ICONWIDTH, row*ICONHEIGHT,
                               ICONWIDTH, ICONHEIGHT, PIX_SRC, face_pr, 0, 0) ;
    }
}


Notify_value
check_mail()
{
  do_check() ;
}


beep_flash(beeps, flashes)    /* Perform visual feedback. */
int beeps, flashes ;
{
  static struct timeval btime = { 0, 250000 } ;   /* Beep timer. */
  int bfd ;        /* File descriptor for faces window, or -1. */
  Pixwin *bpw ;    /* Pixwin pointer for faces window, or 0. */

  if (beeps || flashes)
    do
      {
        bfd = beeps > 0 ? ffd : -1 ;
        bpw = flashes > 0 ? fpw : (Pixwin *) 0 ;
        WIN_BELL(bfd, btime, bpw) ;
        SELECT(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &btime) ;
        beeps-- ;
        flashes-- ;
      } 
    while (beeps > 0) ;
}


create_pixrects(width, height)   /* Create pixrects for the face images. */
int width, height ;
{
  old_pr = pr ;
  pr = mem_create(width, height, 1) ;
  PR_REPLROP(pr, 0, 0, width, height, PIX_SRC, background, 0, 0) ;
  faces_icon = (Icon) window_get(frame, FRAME_ICON) ;
  old_mpr = (Pixrect *) icon_get(faces_icon, ICON_IMAGE) ;
  if (mtype == MONPRINTER) mpr = mem_create(ICONWIDTH, ICONHEIGHT, 1) ;
  else
    {
      mpr = mem_create(width, height, 1) ;
      PR_REPLROP(mpr, 0, 0, width, height, PIX_SRC, background, 0, 0) ;
    }
  if (mtype == MONNEW && old_pr != NULL)
    PR_ROP(pr, 0, 0, width, height, PIX_SRC, old_pr, 0, 0) ;
  if (mtype == MONNEW && old_mpr != NULL)
    PR_ROP(mpr, 0, 0, width, height, PIX_SRC, old_mpr, 0, 0) ;
}


init_ws_type()
{
  gtype = SUNVIEW ;
  return 0 ;
}


make_frame(argc,argv)
int argc ;
char *argv[] ;
{
  unsigned short buf[256] ;  /* For background pattern. */
  unsigned short *ptr ;
  int i ;

  if (strlen(bgicon))
    {
      if (get_sun_icon(bgicon, buf) == 0) background = &gray_pr ;
      background = mem_create(64, 64, 1) ;
      ptr = (unsigned short *)
            ((struct mpr_data *) background->pr_data)->md_image ;
      for (i = 0; i < 256; i++) ptr[i] = buf[i] ;
    }
  else background = &gray_pr ;

  frame = window_create((Window) 0, FRAME,
                        FRAME_ICON, faces_icon,
                        FRAME_SHOW_LABEL, FALSE,
                        FRAME_SUBWINDOWS_ADJUSTABLE, FALSE,
                        FRAME_NO_CONFIRM, TRUE,
                        WIN_WIDTH, NO_PER_ROW * ICONWIDTH + 10,
                        WIN_HEIGHT, ICONHEIGHT * 10 + 10,
                        FRAME_ARGS, argc,argv,
                        0) ;
  fpw = (Pixwin *) window_get(frame, WIN_PIXWIN) ;
  ffd = (int) window_get(frame, WIN_FD) ;

  canvas = window_create(frame, CANVAS,
                         CANVAS_REPAINT_PROC, repaint_proc,
                         CANVAS_RETAINED, TRUE,
                         0) ;
  pw = canvas_pixwin(canvas) ;
  sfont = pf_open(SMALLFONT) ;
  width = NO_PER_ROW * ICONWIDTH ;
  height = ICONHEIGHT ;
}


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


/*ARGSUSED*/
repaint_proc(canvas, pw, repaint_area)
Canvas canvas ;
Pixwin *pw ;
Rectlist *repaint_area ;
{
  PW_ROP(pw, 0, 0, width, height, PIX_SRC, pr, 0, 0) ;
}


show_display()    /* Show the latest set of mail icon faces. */
{
  if (invert)     /* Invert the memory pixrects before displaying. */
    {
      PR_ROP(pr, 0, 0, width, height, PIX_NOT(PIX_DST), pr, 0, 0) ;
      PR_ROP(mpr, 0, 0, width, height, PIX_NOT(PIX_DST), pr, 0, 0) ;
    }

  if (mtype != MONPRINTER)
    {
      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 (newmail) beep_flash(beeps, flashes) ;
  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 = period ;
  tval.it_value.tv_usec = 0 ;
  tval.it_value.tv_sec = period ;
  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. */
  if (len > 10)
    {
      len = 10 ;
      str[10] = '\0' ;   /* Maximum of 10 characters. */
    }
  switch ((int) just)
    {
      case LEFT  : x = c*ICONWIDTH+2 ;
                   y = (r+1)*ICONHEIGHT-2 ;
                   break ;
      case RIGHT : 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 !=     9881 ] ; then
echo error: sunview.c was $len bytes long, should have been     9881
fi
fi # end of overwriting check