[comp.sources.misc] v13i071: Faces v1.4.5: a visual list monitor for mail etc..

rburridge@Sun.COM (Rich Burridge) (07/03/90)

Posting-number: Volume 13, Issue 71
Submitted-by: rburridge@Sun.COM (Rich Burridge)
Archive-name: faces-1.4.5/part02

------CUT HERE------faces.part2------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
#	parsefrom.c
#	news.c
#	sunview.c
# This archive created: Fri Jun 29 10:45:08 EST 1990
#
#
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',    17463 characters
cat > get.c <<'Funky_Stuff'

/*  @(#)get.c 1.16 90/06/26
 *
 *  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. 
 *
 *  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 <stdio.h>
#include <strings.h>
#include <pwd.h>
#include <ctype.h>
#include "faces.h"
#include "extern.h"
#include "patchlevel.h"


get_blit_ikon(name, buf)      /* Load blit ikon file. */
char *name ;
unsigned short buf[256] ;
{
  FILE *fin ;
  char *ptr ;
  int i, j, temp ;

  if ((fin = fopen(name, "r")) == NULL) return(-1) ;
  for (i = 0; i < BLITHEIGHT; i++)
    {
      FGETS(nextline, MAXLINE, fin) ;
      ptr = nextline ;
#ifdef REVORDER
      for (j = 2; j >= 0; j--)
#else
      for (j = 0; j < 3; j++)
#endif /*REVORDER*/
        {
          while (*ptr == ' ' || *ptr == '\t') ptr++ ;
          SSCANF(ptr, "0x%X", &temp) ;
          buf[i*4 + j] = (short) temp ;
          ptr = index(ptr, ',') ;
          ptr++ ;         
        }                 
      buf[i*4 + 3] = 0 ;    
    }
  for (i = BLITHEIGHT; i < iconheight; i++)
    for (j = 0; j < 4; j++) buf[i*4 + j] = 0 ;
  FCLOSE(fin) ;
  return(0) ;
}


unsigned short
get_hex(fp)
FILE *fp ;
{
  int c ;
  unsigned short rval = 0 ;

  while ((c = getc(fp)) != EOF)
    {
      if (c != '0') continue ;
      c = getc(fp) ;
      if (c != 'x') continue ;
      while ((c = getc(fp)) != EOF)
        {
               if (c >= '0' && c <= '9') rval = (rval << 4) + (c - '0') ;
          else if (c >= 'a' && c <= 'f') rval = (rval << 4) + (c - 'a' + 10) ;
          else if (c >= 'A' && c <= 'F') rval = (rval << 4) + (c - 'A' + 10) ;
          else break ;
        }
      break ;
    }
  return rval ;
}


get_icon(dirname, buf)            /* Read in icon file. */
char *dirname ;
unsigned short buf[256] ;
{

/*  Attempts to open the correct face file.
 *
 *  If this is an "old" style ikon, then it should be in 48x48x1 format.
 *
 *  If the face file is face.ps, then another record is added to the list
 *  of NeWS .ps files to animate at a later time.
 *  If this is face.xbm, 48x48x1 or sun.icon, and the open is successful,
 *  then the face image is read into buf.
 *  -1 is returned on failure.
 */

  char *ptr ;

  if (old_style)    /* Check for "old" style ikon first. */
    {
      if (get_blit_ikon(dirname, buf) == 0) return BLITTYPE ;
      return -1 ;
    }

  ptr = rindex(dirname, '/') ;     /* Find last slash in iconname. */
  if (EQUAL(ptr+1, "face.ps"))
    if (get_news_icon(dirname)      == 0) return NEWSTYPE ;
  if (EQUAL(ptr+1, "sun.icon"))
    if (get_sun_icon(dirname, buf)  == 0) return SUNTYPE ;
  if (EQUAL(ptr+1, "48x48x1"))
    if (get_blit_ikon(dirname, buf) == 0) return BLITTYPE ;
  if (EQUAL(ptr+1, "face.xbm"))
    if (get_x11_icon(dirname, buf)  == 0) return X11TYPE ;
  return -1 ;
}


get_news_icon(name)    /* Create record for news.ps file. */
char *name ;
{
  FILE *fin ;

  if (gtype != NEWS) return -1 ;
  if ((fin = fopen(name, "r")) == NULL) return -1 ;
  FCLOSE(fin) ;
  add_ps_rec(row, column, name) ;
  return 0 ;
}


get_options(argc, argv)    /* Read and process command line options. */
int argc ;
char *argv[] ;
{
  char next[MAXLINE] ;    /* The next command line parameter. */

  INC ;
  while (argc > 0)
    {
      if (argv[0][0] == '-')
        switch (argv[0][1])
          {
            case 'H' : mtype = MONUSERS ;  /* Monitor users on a machine. */
                       INC ;
                       getparam(hostname, argv, "-H needs hostname") ;
                       break ;
            case 'M' : if (argv[0][2] == 'H') mhflag++ ;
                       else goto error ;
                       break ;
            case 'P' : mtype = MONPRINTER ;  /* Monitor printer queue. */
                       INC ;
                       getparam(printer, argv, "-P needs printer name") ;
                       break ;
            case 'U' : update++ ;          /* Update faces database. */
                       break ;
            case 'a' : mtype = MONALL ;    /* Monitor all of the spoolfile. */
                       break ;
            case 'b' : INC ;               /* Alternate background pattern. */
                       getparam(bgicon, argv, "-b needs background icon") ;
                       break ;
            case 'c' : INC ;               /* Number of columns. */
                       getparam(next, argv,
                                      "-c needs number of columns value") ;
                       maxcols = atoi(next) ;
                       if (maxcols <= 0 || maxcols > (1152 / ICONWIDTH))
                         maxcols = NO_PER_ROW ;
                       break ;
            case 'd' : INC ;               /* X11 display information. */
                       getparam(display, argv,
                                         "-d needs display information") ;
                       break ;
            case 'e' : mtype = MONPROG ;   /* User specified program. */
                       INC ;
                       getparam(userprog, argv, "-e needs user program") ;
                       break ;
            case 'f' : INC ;               /* New directory for face icons. */
                       getparam(facedir, argv, "-f needs face directory") ;
                       break ;
            case 'g' : INC ;               /* X11 geometry information. */
                       getparam(geometry, argv,
                                          "-g needs geometry information") ;
                       posspec = 1 ;
                       break ;
            case 'h' : INC ;               /* Face image height. */
                       getparam(next, argv, "-h needs height value") ;
                       imageheight = atoi(next) ;
                       if (imageheight < ICONHEIGHT || imageheight > 250)
                         {
                           FPRINTF(stderr, "Illegal -h value; resetting.\n") ;
                           imageheight = ICONHEIGHT ;
                         }
                       break ;
            case 'i' : invert = 1 ;        /* Reverse video. */
                       break ;
            case 'n' : dontshowno = 1 ;    /* Don't show number of messages. */
                       break ;
            case 'p' : INC ;               /* No. of seconds between checks. */
                       getparam(next, argv, "-p needs period time") ;
                       period = atoi(next) ;
                       break ;
            case 's' : INC ;               /* Alternative spoolfile. */
                       getparam(spoolfile, argv, "-s needs spool directory") ;
                       break ;
            case 't' : dontshowtime = 1 ;  /* Do not show timestamps. */
                       break ;
            case 'u' : dontshowuser = 1 ;  /* Do not show usernames. */
                       break ;
            case 'v' : FPRINTF(stderr, "%s version 1.4.%1d\n",
                                       progname, PATCHLEVEL) ;
                       exit(1) ;
            case 'w' : INC ;               /* Face image width. */
                       getparam(next, argv, "-w needs width value") ;
                       imagewidth = atoi(next) ;
                       if (imagewidth < ICONWIDTH || imagewidth > 250)
                         {
                           FPRINTF(stderr, "Illegal -w value; resetting.\n") ;
                           imagewidth = ICONWIDTH ;
                         }
                       break ; 

/*  SunView windowing arguments. -Wp, -WP and -Wi are used in the NeWS
 *  implementation to initially position the window and icon.
 */

            case 'W' : switch (argv[0][2])
                         {
                           case 'H' : break ;   /* -WH, no sub-args follow */
                           case 'i' : iconic = 1 ;
                                      break ;   /* -Wi, start as an icon. */
                           case 'g' :           /* -Wg, set default color. */
                           case 'n' : break ;   /* -Wn, no label at all */
                           case 'h' :           /* -Wh, height */
                           case 'I' :           /* -WI "icon filename" */
                           case 'l' :           /* -Wl "some window label" */
                           case 'L' :           /* -Wl "some icon label" */
                           case 't' :           /* Font filename */
                           case 'T' :           /* Icon font filename */
                           case 'w' : INC ;     /* Width, in columns. */
                                      break ;
                           case 'p' : INC ;     /* -Wp xnum ynum */
                                      getparam(next, argv,
                                               "-Wp needs x coordinate") ;
                                      wx = atoi(next) ;
                                      INC ;
                                      getparam(next, argv,
                                               "-Wp needs y coordinate") ;
                                      wy = atoi(next) ;
                                      posspec = 1 ;
                                      break ;
                           case 'P' : INC ;      /* -WP xnum ynum */
                                      getparam(next, argv,
                                               "-WP needs x coordinate") ;
                                      ix = atoi(next) ;
                                      INC ;
                                      getparam(next, argv,
                                               "-WP needs y coordinate") ;
                                      iy = atoi(next) ;
                                      break ;
                           case 's' : INC ; INC ;  /* -Ws xnum ynum */
                                      break ;
                           case 'b' :              /* -Wb r g b (bg color spec) */
                           case 'f' : INC ; INC ; INC ;  /* Same, fg color */
                                      break ;
                           default :  FPRINTF(stderr,"%s: -W%c unknown argument\n",
                                                      progname, argv[0][2]) ;
                                      break ;
                         }
                       break ;
            error    :
            default  : usage() ;
                       exit(1) ;
          }
      INC ;
    }
}


get_x11_icon(name, buf)     /* Load X11 icon file. */
char *name ;
unsigned short buf[256] ;
{
  FILE *fin ;
  int hgt, i, j, wid ;
  char c, *cptr ;
  unsigned char vbuf[512] ;
  unsigned int tmp ;

  if ((fin = fopen(name, "r")) == NULL) return -1 ;
  if (fgets(nextline, MAXLINE, fin) == NULL) goto err_end ;
  if (sscanf(nextline, "#define %s %d", vbuf, &wid) != 2) goto err_end ;
  if ((cptr = rindex((char *) vbuf, '_')) == NULL || strcmp(cptr, "_width"))
    goto err_end ;
  wid = (wid + 7) / 8 ;

  if (fgets(nextline, MAXLINE, fin) == NULL) goto err_end ;
  if (sscanf(nextline, "#define %s %d", vbuf, &hgt) != 2) goto err_end ;
  if ((cptr = rindex((char *) vbuf, '_')) == NULL || strcmp(cptr, "_height"))
    goto err_end ;
  if (hgt > iconheight) hgt = iconheight ;

  while(nextline[0] == '#')
    if (fgets(nextline, MAXLINE, fin) == NULL) goto err_end ;
  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++)
          {
            tmp = get_hex(fin) & 0xFF ;
            if (j < (iconwidth / 8))
              vbuf[i*8+j] = (unsigned char) tmp ;
          }
      for (i = 0; i < 256; i++)
        buf[i] = (revtable[vbuf[(i*2)+1]] & 0xFF) +
                 ((revtable[vbuf[i*2]] & 0xFF) << 8) ;
      FCLOSE(fin) ;
      return(0) ;
    }
  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++)
          {
            tmp = get_hex(fin) ;
            if (j < (iconwidth / 16))
              buf[i*4+j] = (revtable[tmp >> 8] & 0xFF) +
                           ((revtable[tmp & 0xFF] & 0xFF) << 8) ;
          }
      FCLOSE(fin) ;
      return(0) ;
    }
err_end:

  FCLOSE(fin) ;
  return -1 ;
}


get_xface(ibuf, obuf)              /* Extract "raw" X-Face data. */
char *ibuf ;
unsigned short obuf[] ;
{
  char *ptr ;
  int i, j, temp ;

  ptr = ibuf ;
  for (i = 0; i < BLITHEIGHT; i++)
    {
#ifdef REVORDER
      for (j = 2; j >= 0; j--)
#else
      for (j = 0; j < 3; j++)
#endif /*REVORDER*/
        {
          while (*ptr == ' ' || *ptr == '\t' || *ptr == '\n') ptr++ ;
          SSCANF(ptr, "0x%X", &temp) ;
          obuf[i*4 + j] = (short) temp ;
          ptr = index(ptr, ',') ;
          ptr++ ;
        }
      obuf[i*4 + 3] = 0 ;
    }
  for (i = BLITHEIGHT; i < iconheight; i++)
    for (j = 0; j < 4; j++) obuf[i*4 + j] = 0 ;
}


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 ;
}


getparam(s, argv, errmes)
char *s, *argv[], *errmes ;
{
  if (*argv != NULL) STRCPY(s, *argv) ;
  else
    {
      FPRINTF(stderr,"%s: %s as next argument.\n", progname, errmes) ;
      exit(1) ;
    }
}


get_sun_icon(name, buf)     /* Load Sun icon file. */
char *name ;
unsigned short buf[256] ;
{
  FILE *fin ;
  char htype[MAXLINE] ;     /* Current header comment parameter. */
  int c ;                   /* Count of items found from fscanf call. */
  int comment ;             /* Set if more initial comment to read. */
  int count ;               /* Number of items to read from icon file. */
  int idepth ;              /* Depth of this icon. */
  int iheight ;             /* Height of this icon. */
  int iwidth ;              /* Width of this icon. */
  int ivbpi ;               /* Number of valid bits per item. */
  int temp ;                /* Temporary location for latest 16 bits. */

  if ((fin = fopen(name, "r")) == NULL) return -1 ;
  comment = 1 ;
  while (comment)
    {
      if (fscanf(fin, "%*[^WHDV*]%s", htype) == EOF) break ;
      switch (htype[0])
        {
          case 'W' : SSCANF(htype, "Width=%d", &iwidth) ;
                     if (iwidth != 64)
                       {
                         FPRINTF(stderr, "%s: %s has width %d\n",
                                          progname, name, iwidth) ;
                         FPRINTF(stderr, "This is currently not supported.\n") ;                         return -1 ;
                       }
                     break ;
          case 'H' : SSCANF(htype, "Height=%d", &iheight) ;
                     if (iheight != 64)
                       {
                         FPRINTF(stderr, "%s: %s has height %d\n",
                                          progname, name, iheight) ;
                         FPRINTF(stderr, "This is currently not supported.\n") ;                         return -1 ;
                       }
                     break ;
          case 'D' : SSCANF(htype, "Depth=%d", &idepth) ;
                     if (idepth != 1)
                       {
                         FPRINTF(stderr, "%s: %s has depth %d\n",
                                          progname, name, idepth) ;
                         FPRINTF(stderr, "This is currently not supported.\n") ;
                         return -1 ;
                       }
                     break ;
          case 'V' : SSCANF(htype, "Valid_bits_per_item=%d", &ivbpi) ;
                     if (ivbpi != 16)
                       {
                         FPRINTF(stderr, "%s: %s has %d bits per item\n",
                                          progname, name, ivbpi) ;
                         FPRINTF(stderr, "This is currently not supported.\n") ;
                         return -1 ;
                       }
                     break ;
          case '*' : if (htype[1] == '/') comment = 0 ;
        }
    }

  count = 0 ;
  while (count < ((iheight * iwidth) / 16))
    {
      c = fscanf(fin, " 0x%X,", &temp) ;
      if (c == 0 || c == EOF) break ;
#ifdef REVORDER
      buf[count++] = (short) ((revtable[temp & 0xFF] << 8) +
                             ((revtable[(temp >> 8) & 0xFF]) & 0xFF)) ;
#else
      buf[count++] = (short) temp ;
#endif /*REVORDER*/
    }    
  FCLOSE(fin) ;
  return(0) ;
}


char *
strlower(str)
char *str ;
{
  char *c ;

  for (c = str; *c != '\0'; c++) 
    if (isupper(*c)) *c = tolower(*c) ;
  return(str) ;
}


usage()      /* Print faces usage message. */
{
  FPRINTF(stderr, "Usage: %s [-MH] [-P printer] [-Wi] [-Wp x y] ", progname) ;
  FPRINTF(stderr, "[-WP x y] [-b background] [-d display] [-f facedir] ") ;
  FPRINTF(stderr, "[-g geometry] [-i] [-n] [-p period] [-s spoolfile] [-u] ") ;
  FPRINTF(stderr, "[-t] [-v]\n") ;
}
Funky_Stuff
len=`wc -c < get.c`
if [ $len !=    17463 ] ; then
echo error: get.c was $len bytes long, should have been    17463
fi
fi # end of overwriting check
if [ -f parsefrom.c ]
then
echo shar: will not over-write existing file parsefrom.c
else
echo shar: extracting 'parsefrom.c',     2094 characters
cat > parsefrom.c <<'Funky_Stuff'

/*  @(#)parsefrom.c 1.2 90/06/20
 *
 *  Returns pointers to the user and host components of an address
 *  described in either a Unix "From " line or an RFC 822 "From:" line.
 *
 *  Copyright (c) Chris Maltby - Softway Ptd Ltd - June 1990.
 *
 *  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 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 <stdio.h>
#include <strings.h>
#include "faces.h"


int
parsefrom(line, userp, hostp)
char *line;
char **userp;
char **hostp;
{
	register char	*p;
	register char	*user;
	register char	*host;

	if (strncmp((user = line), "From ", 5) != 0) {
		if (strncmp(user, "From:", 5) == 0) {
			user += 5;

			while (*user == ' ' || *user == '\t')
				++user;

			/* RFC822 - two formats
			 * From: comment <address>
			 * From: address (comment)
			 */
			if ((p = index(user, '<')) != NULL) {
				user = ++p;
				if ((p = index(user, '>')) != NULL)
					*p = '\0';
				else
					return 0;
			}
			else if ((p = rindex(user, '(')) != NULL) {
				do
					*p = '\0';
				while (*--p == ' ' || *p == '\t');
			}
		}
		else
			return 0;
	} else {
		user += 5;
		while (*user == ' ' || *user == '\t')
			++user;
		if ((p = index(user, ' ')) != NULL)
			*p = '\0';	/* discard date */
	}

	host = NULL;

	/* look for route addresses: @host,addr */
	while (*user == '@') {
		host = ++user;
		if ((p = index(user, ',')) != NULL) {
			*p++ = '\0';
			user = p;
		}
	}
	/* look for '@' */
	while ((p = rindex(user, '@')) != NULL) {
		*p++ = '\0';
		host = p;
	}
	/* now for '%' */
	while ((p = rindex(user, '%')) != NULL) {
		*p++ = '\0';
		host = p;
	}
	/* now for '!' */
	while ((p = index(user, '!')) != NULL) {
		*p++ = '\0';
		host = user;
		user = p;
	}
	if (host == NULL)
		host = "LOCAL";
#ifdef	NODOMAINS
	else if ((p = index(host, '.')) != NULL)
		*p = '\0';
#endif	/* NODOMAINS */
	*hostp = host;
	*userp = user;
	return 1;
}
Funky_Stuff
len=`wc -c < parsefrom.c`
if [ $len !=     2094 ] ; then
echo error: parsefrom.c was $len bytes long, should have been     2094
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',     9777 characters
cat > news.c <<'Funky_Stuff'

/*  @(#)news.c 1.13 90/06/26
 *
 *  NeWS dependent graphics routines used by faces,
 *  the visual mail and print job monitor.
 * 
 *  Copyright (c) Rich Burridge - Sun Microsystems Australia.
 *                                All rights reserved.
 *
 *  Rewritten to use NeWS cps routines by Pat Lashley - Sun Microsystems Inc.
 *
 *  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 <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sundev/kbd.h>
#include <sundev/kbio.h>
#include <NeWS/psmacros.h>
#include "faces.h"
#include "extern.h"
#include "faces_cps.h"

#define  F_ICON    0                  /* Icon index to frame array. */
#define  F_WINDOW  1                  /* Window index to frame array. */

char *dnames[] = { "PR", "MPR" } ;

char *inames[] = {
    "BackgroundIcon",	"NofaceIcon",	"NomailIcon",	"NopaperIcon",
    "NoprintIcon",	"NousersIcon",	"CurfaceIcon"
  } ;

#ifdef NO_43SELECT
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 /*NO_43SELECT*/

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

extern PSFILE *PostScript ;
extern PSFILE *PostScriptInput ;


adjust_image(dtype, itype, row, column)
    enum disp_type dtype ;
    enum icon_type itype ;
    int row, column ;
{
    switch ((int) mtype)
    {
      case MONNEW:
	ps_shiftimage (imagewidth, (maxcols-1)*imagewidth,
		       imageheight, dnames[(int) dtype]) ;
	
	if  (facetype == NEWSTYPE) {
	    ps_clearbox (column*imagewidth, row*imageheight,
			 imagewidth, imageheight, dnames[(int) dtype]) ;
	    
	    return ;
	} /* else fall into default */
	
      default:
	ps_moveimage (inames[(int) itype], imagewidth, imageheight,
		      column*imagewidth, row*imageheight,
		      dnames[(int) dtype]) ;
    }
}   /* adjust_image() */


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

    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) ;
    }
}   /* beep_flash() */


clear_animates()      /* Remove chain of animate records. */
{
    struct psinfo *next, *this ;   /* For removing current chain of records. */

    for  (this = psrecs  ;  this != NULL  ;  this = next)
    {
	next = this->next ;
	if (this->name != NULL) free(this->name) ;
	free((char *) this) ;   /* Remove this record. */
	this = next ;
    }
    
    psrecs = plast = NULL ;
}   /* clear_animates() */


create_pixrects(width, height)     /* Create pixrects for the face images. */
{
    int h, w ;
    
    if  ((mtype == MONNEW) && !firsttime)	return ;
    ps_dopixrects (width, height, "PR") ;
    h = height ;
    w = width ;
    if (mtype == MONPRINTER)
    {
	h = imageheight ;
	w = imagewidth ;
    }
    ps_dopixrects (w, h, "MPR") ;
    do_background () ;          /* Setup background pattern. */
} /* create_pixrects() */


destroy_image()    /* Null routine. */
{}


do_background()     /* Set up background pattern. */
{
    int i, j ;
    
    
    for  (i = 0; i < (height / imageheight); i++)
    {
	for (j = 0; j < (width / imagewidth); j++)
	{
	    ps_moveimage (inames[BACKGROUND],
			  imagewidth,	imageheight,
			  j,		i,
			  dnames[(int) F_WINDOW]) ;
	    ps_moveimage (inames[BACKGROUND],
			  imagewidth,	imageheight,
			  j,		i,
			  dnames[(int) F_ICON]) ;
	}
    }
}   /* do_background() */


do_news_ps(psrecs)     /* Display chain of NeWS animations. */
    struct psinfo *psrecs ;
{
    struct psinfo	*this ;
    
    
    for  (this = psrecs  ;  this != NULL  ;  this = this->next)
    {
	if ((mtype != MONNEW) || (this->column < maxcols))
        {
	    ps_execfile (this->name, imagewidth, imageheight,
			 this->column*imagewidth, this->row*imageheight) ;
	    ps_flush_PostScript() ;
        }
    }
}   /* do_news_ps() */


handle_mouse()     /* Clear canvas to background and recheck for new mail. */
{
    do_background() ;    /* Setup background pattern. */
    clear_animates() ;   /* Remove chain of animate records. */
    do_check() ;
}


/*ARGSUSED*/
init_ws_type(argc, argv)
    int argc ;
    char *argv[] ;
{
    int i, j ;
    unsigned short buf[256] ;
    
    if (ps_open_PostScript() < 0) return -1 ;
    ps_flush_PostScript() ;
    if (ferror(PostScript))
    {
	ps_close_PostScript() ;
	return(-1) ;
    }
    
    for (i = 0; i < 16; i++)    /* Load default gray background. */
    {
	for (j = 0; j < 4; j++) buf[i * 16      + j] = 0x8888 ;
	for (j = 0; j < 4; j++) buf[i * 16 +  4 + j] = 0x2222 ;
	for (j = 0; j < 4; j++) buf[i * 16 +  8 + j] = 0x8888 ;
	for (j = 0; j < 4; j++) buf[i * 16 + 12 + j] = 0x2222 ;
    }
    
    if (strlen(bgicon)) GET_SUN_ICON(bgicon, buf) ;
    load_icon(BACKGROUND, buf) ;
    
    if (invert) pprintf(PostScript, "%p ", 3, "/Invert false def") ;
    else pprintf(PostScript, "%p ", 3, "/Invert true def") ;
    STRCPY(fname[0], "face.ps") ;
    STRCPY(fname[1], "sun.icon") ;
    STRCPY(fname[2], "48x48x1") ;
    STRCPY(fname[3], "face.xbm") ;
    maxtypes = 4 ;
    gtype = NEWS ;
    return(0) ;
}


/*ARGSUSED*/
load_icon(itype, sbuf, not_flipped)
    enum icon_type itype ;
    unsigned short sbuf[256] ;
    int not_flipped ;
{
    ps_buildicon (inames[(int) itype], iconwidth, iconheight, sbuf, 256) ;
}   /* load_icon() */


make_area(dtype, width, height)
    enum disp_type dtype ;
    int width, height ;
{
}   /* make_area() */


/*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 NO_43SELECT
    fullmask = 1 << psfd ;
#else
    FD_ZERO(&fullmask) ;
    FD_SET(psfd, &fullmask) ;
#endif /*NO_43SELECT*/
    
    ps_makeframe (wx, wy, maxcols*imagewidth+10, imageheight*10+10,
		  ix, iy, iconic) ;
    ps_initfont() ;
    width = maxcols * imagewidth ;
    height = imageheight ;
}   /* make_frame() */


make_icon()   /* Null routine. */
{}


repl_image(dtype, dest, width, height)
    enum disp_type dtype ;
    enum image_type dest ;
    int width, height ;
{
    int i, j ;
    
    if (dest != CUROFF) return ;
    for (i = 0; i < (height / imageheight); i++)
    {
	for (j = 0; j < (width / imagewidth); j++)
	{
	    ps_moveimage (inames[BACKGROUND],
			  imagewidth, imageheight, j, i, dnames[(int) dtype]) ;
	}
    }
}   /* repl_image() */


show_display()        /* Show the latest set of mail icon faces. */
{
    if (mtype != MONPRINTER)
    {
	ps_showdisplay (width, height, width, height) ;
    } else {
	ps_showdisplay (width, height, imagewidth, imageheight) ;
    }
    
    if  (newmail)		beep_flash (beeps, flashes) ;
    if  (psrecs != NULL)	do_news_ps (psrecs) ;
    
    ps_flush_PostScript() ;
}   /* show_display() */



start_tool()
{
    int type ;                     /* Value from NeWS server. */
    struct timeval tval ;

    
    tval.tv_usec = 0 ;
    tval.tv_sec = period ;
    
    for (;;)
    {
	readmask = fullmask ;
#ifdef NO_43SELECT
	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 /*NO_43SELECT*/
	{
	    if (pscanf(PostScriptInput, "d", &type) == EOF) exit(1) ;
	    switch (type)
	    {
	      case DIED     : exit(0) ;
	      case LEFTDOWN : if (mtype == MONNEW)
	      {
		  do_background() ;
		  clear_animates() ;
		  do_check() ;
	      }
		break ;
	      case PAINTED  : if (psrecs != NULL) do_news_ps(psrecs) ;
	    }
	}
	else
	{
	    if (mtype != MONNEW) clear_animates() ;
	    do_check() ;        /* Check the mail/printer again. */
	}
    }
}


text(dtype, jtype, str)
    enum disp_type dtype ;
    enum just_type jtype ;
    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. */
    
    c = column ;
    r = row ;
    switch (dtype)
    {
      case DISP_ALL:
	text(DISP_ICON,  jtype, str) ;
	/* Fall into DISP_BOTH */
      case DISP_BOTH:
	text(DISP_NAME,  jtype, str) ;
	text(DISP_OTHER, jtype, str) ;
	return ;
	
      case DISP_ICON:
	c = r = 0 ;
    }
    
    if ((len = strlen(str)) > 10)         /* Character length of text. */
    {
	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 (jtype)
    {
      case LEFT:
	x = c * imagewidth + 2 ;
	y = r * imageheight + 2 ;
	break ;
	
      case RIGHT:
	x = (c + 1) * imagewidth - (len * 6) - 2 ;
	y = r * imageheight + 2 ;
    }

    ps_clearbox (x, y, len*6+2, 10, dnames[(int) dtype]) ;
    ps_maketext (line, x, y, dnames[(int) dtype]) ;
}   /* text() */
Funky_Stuff
len=`wc -c < news.c`
if [ $len !=     9777 ] ; then
echo error: news.c was $len bytes long, should have been     9777
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',    11119 characters
cat > sunview.c <<'Funky_Stuff'

/*  @(#)sunview.c 1.12 90/06/26
 *
 *  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 <stdio.h>
#include "faces.h"
#include "extern.h"
#include <suntool/sunview.h>
#include <suntool/canvas.h>

#define  FONT                    "/usr/lib/fonts/fixedwidthfonts/screen.r.7"

#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 NO_PR_TTEXT
#define  PR_TTEXT                (void) pf_ttext
#else
#define  PR_TTEXT                (void) pr_ttext
#endif /*NO_PR_TTEXT*/

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

#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 *pr[3] ;              /* Pointers to current pixrects. */
Pixrect *old_pr[2] ;          /* Pointers to previous pixrects. */

/* Array of the different icon images. */
Pixrect *images[MAXICONS] = {
  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
} ;

Pixwin *fpw, *pw ;
int toclear ;                 /* Set if faces icon needs clearing. */
int ffd ;                     /* File descriptor of faces frame. */


adjust_image(dtype, itype, row, column)  /* Put new face in memory pixrect. */
enum disp_type dtype ;
enum icon_type itype ;
int row, column ;
{
  switch ((int) mtype)
    {
      case MONNEW : PR_ROP(pr[(int) dtype], imagewidth, 0,
                           (maxcols-1)*imagewidth, imageheight, PIX_SRC,
                           pr[(int) dtype], 0, 0) ;
      default     : PR_ROP(pr[(int) dtype], column*imagewidth, row*imageheight,
                           imagewidth, imageheight, PIX_SRC,
                           images[(int) itype], 0, 0) ;
    }
}


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) ;
}


/*ARGSUSED*/
void
canvas_proc(canvas, event, arg)
Canvas canvas ;
Event *event ;
caddr_t arg ;
{
  int nextc ;

  nextc = event_id(event) ;
  if (event_is_down(event) && nextc == MS_LEFT)
    {
      wdtype = (wdtype == DISP_NAME) ? DISP_OTHER : DISP_NAME ;
      PW_ROP(pw, 0, 0, width, height, PIX_SRC, pr[(int) wdtype], 0, 0) ;
    }
  if (mtype == MONNEW && event_is_ascii(event) && nextc == DEL)
    {
      repl_image(DISP_NAME,  CUROFF, width, height) ;
      repl_image(DISP_OTHER, CUROFF, width, height) ;
      toclear = 1 ;
      do_check() ;
    }
  else window_default_event_proc(canvas, event, arg) ;
}


Notify_value
check_mail()
{
  do_check() ;
}


create_pixrects(width, height)   /* Create pixrects for the face images. */
int width, height ;
{
  old_pr[(int) DISP_NAME]  = pr[(int) DISP_NAME] ;
  old_pr[(int) DISP_OTHER] = pr[(int) DISP_OTHER] ;

  make_area(DISP_NAME, width, height) ;
  repl_image(DISP_NAME, CUROFF, width, height) ;

  if (toclear && mtype == MONNEW)
    {
      repl_image(DISP_OTHER, OLDOFF, width, height) ;
      toclear = 0 ;
    }

  make_area(DISP_OTHER, width, height) ;
  repl_image(DISP_OTHER, CUROFF, width, height) ;

  if (mtype == MONNEW && old_pr[(int) DISP_NAME] != NULL)
    PR_ROP(    pr[(int) DISP_NAME], 0, 0, width, height, PIX_SRC,
           old_pr[(int) DISP_NAME], 0, 0) ;
  if (mtype == MONNEW && old_pr[(int) DISP_OTHER] != NULL)
    PR_ROP(    pr[(int) DISP_OTHER], 0, 0, width, height, PIX_SRC,
           old_pr[(int) DISP_OTHER], 0, 0) ;
}


destroy_image(itype)
enum icon_type itype ;
{
  if (images[(int) itype] != NULL)
    {
      pr_destroy(images[(int) itype]) ;
      images[(int) itype] = NULL ;
    }
}


init_font()
{
  sfont = pf_open(FONT) ;
}


/*ARGSUSED*/
init_ws_type(argc, argv)
int argc ;
char *argv[] ;
{
  int i, j ;
  unsigned short buf[256] ;

  if (getenv("WINDOW_PARENT") == NULL)
    {
      FPRINTF(stderr,"%s: Not a native SunView window\n", progname) ;
      return -1 ;
    }
  for (i = 0; i < 16; i++)    /* Load default gray background. */
    {
      for (j = 0; j < 4; j++) buf[i * 16      + j] = 0x8888 ;
      for (j = 0; j < 4; j++) buf[i * 16 +  4 + j] = 0x2222 ;
      for (j = 0; j < 4; j++) buf[i * 16 +  8 + j] = 0x8888 ;
      for (j = 0; j < 4; j++) buf[i * 16 + 12 + j] = 0x2222 ;
    }

  if (strlen(bgicon)) GET_SUN_ICON(bgicon, buf) ;
  load_icon(BACKGROUND, buf) ;

  STRCPY(fname[0], "sun.icon") ;
  STRCPY(fname[1], "48x48x1") ;
  STRCPY(fname[2], "face.xbm") ;
  maxtypes = 3 ;
  gtype = SVIEW ;
  pr[(int) DISP_NAME] = pr[(int) DISP_OTHER] = NULL ;
  old_pr[(int) DISP_NAME] = old_pr[(int) DISP_OTHER] = NULL ;
  toclear = 0 ;
  return 0 ;
}


/* Create a memory pixrect from given image data. */

/*ARGSUSED*/
load_icon(itype, buf, not_flipped)
enum icon_type itype ;
unsigned short buf[256] ;
int not_flipped ;
{
  unsigned short *ptr ;
  int i ;

  images[(int) itype] = mem_create(iconwidth, iconheight, 1) ;
  ptr = (unsigned short *)
        ((struct mpr_data *) images[(int) itype]->pr_data)->md_image ;
  for (i = 0; i < 256; i++) ptr[i] = buf[i] ;
#ifdef REVORDER
  if (not_flipped)
    ((struct mpr_data *) images[(int) itype]->pr_data)->md_flags &= ~MP_I386 ;
#endif /*REVORDER*/
}


make_area(dtype, width, height)
enum disp_type dtype ;
{
  pr[(int) dtype] = mem_create(width, height, 1) ;
}


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,
                        WIN_WIDTH,         maxcols * imagewidth + 10,
                        WIN_HEIGHT,        imageheight * 10 + 10,
                        FRAME_ARGS,        argc, argv,
                        0) ;
  fpw = (Pixwin *) LINT_CAST(window_get(frame, WIN_PIXWIN)) ;
  ffd = (int) window_get(frame, WIN_FD) ;

  canvas = window_create(frame, CANVAS,
                         WIN_EVENT_PROC,      canvas_proc,
                         CANVAS_REPAINT_PROC, repaint_proc,
                         CANVAS_RETAINED,     TRUE,
                         0) ;
  WINDOW_SET(canvas, WIN_CONSUME_KBD_EVENTS, WIN_ASCII_EVENTS,
                     WIN_LEFT_KEYS, WIN_TOP_KEYS, WIN_RIGHT_KEYS,
                     WIN_UP_EVENTS, 0, 0) ;
  WINDOW_SET(canvas, WIN_IGNORE_PICK_EVENT, LOC_MOVE, 0) ;
  pw = canvas_pixwin(canvas) ;
  init_font() ;
  width = maxcols * imagewidth ;
  height = imageheight ;
}


make_icon()
{
  faces_icon = icon_create(WIN_WIDTH,  imagewidth,
                           WIN_HEIGHT, imageheight,
                           0) ;
  if (mtype == MONPRINTER) adjust_image(DISP_ICON, NOPRINT, 0, 0) ;
  else                     adjust_image(DISP_ICON, NOMAIL,  0, 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[(int) wdtype], 0, 0) ;
}


repl_image(dtype, dest, width, height)
enum disp_type dtype ;
enum image_type dest ;
int width, height ;
{
  if (dest == CUROFF)
    {
      if (pr[(int) dtype])
        PR_REPLROP(pr[(int) dtype], 0, 0, width, height, PIX_SRC,
                   images[(int) BACKGROUND], 0, 0) ;
    }
  else
    {
      if (old_pr[(int) dtype])
        PR_REPLROP(old_pr[(int) dtype], 0, 0, width, height, PIX_SRC,
                   images[(int) BACKGROUND], 0, 0) ;
    }
}


show_display()    /* Show the latest set of mail icon faces. */
{
  Rect *temprect ;

  if (invert)     /* Invert the memory pixrects before displaying. */
    {
      PR_ROP(pr[(int) DISP_NAME],  0, 0, width, height, PIX_NOT(PIX_DST),
             pr[(int) DISP_NAME],  0, 0) ;
      PR_ROP(pr[(int) DISP_OTHER], 0, 0, width, height, PIX_NOT(PIX_DST),
             pr[(int) DISP_OTHER], 0, 0) ;
    }

  ICON_SET(faces_icon, ICON_IMAGE, pr[(int) DISP_ICON], 0) ;
  WINDOW_SET(frame, FRAME_ICON, faces_icon, 0) ;

  temprect = (Rect *) LINT_CAST(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[(int) wdtype], 0, 0) ;

  if (newmail) beep_flash(beeps, flashes) ;
  if (old_pr[(int) DISP_NAME])    PR_DESTROY(old_pr[(int) DISP_NAME]) ;
  if (old_pr[(int) DISP_OTHER])   PR_DESTROY(old_pr[(int) DISP_OTHER]) ;
  old_pr[(int) DISP_NAME]  = NULL ;
  old_pr[(int) DISP_OTHER] = NULL ;
}


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(dtype, jtype, str)
enum disp_type dtype ;
enum just_type jtype ;
char *str ;
{
  int len ;
  int c, r ;         /* Column and row position for this face. */
  int x, y ;         /* Position of start of this text string. */

  c = column ;
  r = row ;
  switch (dtype)
    {
      case DISP_ALL    : text(DISP_ICON,  jtype, str) ;
      case DISP_BOTH   : text(DISP_NAME,  jtype, str) ;
                         text(DISP_OTHER, jtype, str) ;
                         return ;
      case DISP_ICON   : c = r = 0 ;;
                         break ;
    }

  if ((len = strlen(str)) > 10)         /* Character length of text. */
    {
      len = 10 ;
      str[10] = '\0' ;   /* Maximum of 10 characters. */
    }
  switch (jtype)
    {
      case LEFT  : x =  c      * imagewidth + 2 ;
                   y = (r + 1) * imageheight - 4 ;
                   break ;
      case RIGHT : x = (c + 1) * imagewidth - (len * 6) - 2 ;
                   y = (r + 1) * imageheight - 4 ;
    }
  PR_ROP(pr[(int) dtype], x, y - 9, len * 6 + 2, 10, PIX_CLR,
         (Pixrect *) NULL, 0, 0) ;
  PR_TTEXT(pr[(int) dtype], x, y, PIX_SRC ^ PIX_NOT(PIX_DST), sfont, str) ;
}
Funky_Stuff
len=`wc -c < sunview.c`
if [ $len !=    11119 ] ; then
echo error: sunview.c was $len bytes long, should have been    11119
fi
fi # end of overwriting check