[comp.sources.misc] v14i067: Mp v2.4.5 - the mail/news pretty printer

rburridge@Sun.COM (Rich Burridge) (08/30/90)

Posting-number: Volume 14, Issue 67
Submitted-by: rburridge@Sun.COM (Rich Burridge)
Archive-name: mp-2.4.5/part01

[Hi Brandon. I think this has undergone enough changes since it
 was last posted to the net to warrant a new posting. When you
 get a moment, could you post to comp.sources.misc please? ]

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

The mp program will pretty print various files for you. It can be used
in conjunction with a mail reading utility for producing a pretty print
of your mail items. It can be used with a news reading tool to pretty
print news articles. Digests can also be printed, and this version can
pretty print ordinary ASCII files as well. Support for personal organiser
printing was added into the last released version.

This version introduces a landscape mode for mp, to allow you to print
two "pages" per page. This should all help us save some trees.

see the README file for more details.

------CUT HERE------mp.shar.part1------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:
#	header.c
#	io.c
#	main.c
#	misc.c
#	print.c
#	extern.h
#	mp.h
#	patchlevel.h
#	README
#	MANIFEST
#	FILES
#	CHANGES
#	TODO
# This archive created: Wed Aug 29 12:25:52 EST 1990
#
#
export PATH; PATH=/bin:$PATH
#
if [ -f header.c ]
then
echo shar: will not over-write existing file header.c
else
echo shar: extracting 'header.c',     5850 characters
cat > header.c <<'Funky_Stuff'

/*  @(#)header.c 1.4 90/08/17
 *
 *  Copyright (c) Steve Holden and Rich Burridge.
 *                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 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 "mp.h"
#include "extern.h"


/*  If input line is header of type 'hdr', get the contents of the header
 *  into 'dest' (dynamically allocated).
 */

void
get_header(hdr, dest)
char *hdr ;
char **dest ;
{
  if (EQUAL(hdr))
    {
      *dest = malloc((unsigned) (strlen(nextline) - strlen(hdr) + 1)) ;
      STRCPY(*dest, nextline + strlen(hdr)) ;
    }
}


/*  If input line is header of type 'hdr', get header into dest. The header
 *  may have multiple lines. This skips input to next line.
 */
 
void
get_mult_hdr(hdr, dest)
char *hdr ;
char *dest[] ;
{ 
  int i = 0 ;
  
  if (EQUAL(hdr))
    {
      get_header(hdr, dest) ;
      i++ ;
      readline() ;
      while (i < MAXCONT && !emptyline(nextline) && isspace(nextline[0]))
        {
          dest[i] = malloc((unsigned) (strlen(nextline) + 1)) ;
          STRCPY(dest[i], nextline) ;
          i++ ;
          readline() ;
        }
      dest[i] = NULL ;
    }
}


/*  Parse_headers is a function which reads and parses the message headers,
 *  extracting the bits which are of interest.
 *
 *  The document is on standard input; the document is read up to the end of
 *  the header; the next line is read ahead into 'nextline'.
 *
 *  Parameter:
 *  digest  indicates if parsing is of digest headers instead of message
 *          headers
 *
 *  Implicit Input:
 *  nextline  contains the next line from standard input
 *
 *  Side-effects:
 *  The function fills in the global header variables with headers found.
 *  The global variable doc_type is set to the document type
 *  The global variable nextline is set
 *  The document is read up to the line following the headers
 */


void
parse_headers(digest)
bool digest ;           /* Parsing digest headers */
{
  char *colon ;         /* Pointer to colon in line */
  char *c ;             /* General character pointer */

/*  If not processing digest headers, determine if this article is an
 *  ordinary text file.
 */

  if (!digest)
    {
      if (!EQUAL(FROM_HDR))         /* UNIX From_ header? */
        {
          colon = index(nextline, ':') ;
          if (colon == NULL)        /* No colon => not a header line */
            {
              doc_type = DO_TEXT ;
              return ;
            }
          c = nextline ;
          while (c < colon && (!isspace(*c))) c++ ;
          if (c != colon)      /* Whitespace in header name => not header */
            {
              doc_type = DO_TEXT ;
              return ;
            }
        }    
    }    

  doc_type = DO_MAIL ;    /* Default to mail document */

/* Parse headers */

  while (TRUE)
    {
      if (emptyline(nextline)) break ;    /* End of headers */

      if (!digest)
        {
          get_header(FROM_HDR,      &from_) ;
          get_header(APP_FROMHDR,   &apparently_from) ;
          get_header(APP_TOHDR,     &apparently_to) ;
          get_header(NEWSGROUPSHDR, &newsgroups) ;
          get_header(REPLYHDR,      &reply_to) ;

          get_mult_hdr(TOHDR,       to) ;
          if (emptyline(nextline)) break ;

          get_mult_hdr(CCHDR,       cc) ;
          if (emptyline(nextline)) break ;

          if (doc_type != DO_NEWS && EQUAL(NEWSGROUPSHDR))
            doc_type = DO_NEWS ;
        }
      get_header(FROMHDR, &from) ;
      get_header(SUBJECTHDR, &subject) ;
      get_header(DATEHDR, &date) ;

      if (!EQUAL(TOHDR) && !EQUAL(CCHDR))
        {
          while (!end_of_file && !end_of_line)
            readline() ;                       /* Skip rest of long lines */
          readline() ;
        }
    }    
}


void
reset_headers()          /* Reset header values for next message. */
{
  int i ;
 
  if (from != NULL) free(from) ;
  if (from_ != NULL) free(from_) ;
  if (apparently_from != NULL) free(apparently_from) ;
  if (apparently_to != NULL) free(apparently_to) ;
  if (date != NULL) free(date) ;
  if (newsgroups != NULL) free(newsgroups) ;
  if (reply_to != NULL) free(reply_to) ;
 
  from = from_ = apparently_from = apparently_to = NULL ;
  date = newsgroups = reply_to = subject = NULL ;
 
  for (i = 0; i < MAXCONT+1; i++)
    {
      if (to[i] != NULL) free(to[i]) ;
      if (cc[i] != NULL) free(cc[i]) ;
      to[i] = cc[i] = NULL ;
    }
}


/*  Show_headers outputs the headers in PostScript. Different headers are
 *  output depending 'digest'.
 */

void
show_headers(digest)
bool digest ;
{
  if (digest)
    {
      if (from)       mixedshow(FROMHDR,    from) ;
      if (subject)    mixedshow(SUBJECTHDR, subject) ;
      if (date)       mixedshow(DATEHDR,    date) ;
    }
  else
    {
      if (from_)           boldshow(FROM_HDR,       from_) ;
      if (from)            mixedshow(FROMHDR,       from) ;
      if (apparently_from) mixedshow(APP_FROMHDR,   apparently_from) ;
      if (to[0])           show_mult_hdr(TOHDR,     to) ;
      if (apparently_to)   mixedshow(APP_TOHDR,     apparently_to) ;
      if (cc[0])           show_mult_hdr(CCHDR,     cc) ;
      if (reply_to)        mixedshow(REPLYHDR,      reply_to) ;
      if (newsgroups)      mixedshow(NEWSGROUPSHDR, newsgroups) ;
      if (subject[0])      mixedshow(SUBJECTHDR,    subject) ;
      if (date)            mixedshow(DATEHDR,       date) ;
    }
}


void
show_mult_hdr(hdr, val)
char *hdr ;              /* Name of header */
char *val[] ;            /* Value of header */
{
  mixedshow(hdr, *val) ;
  val++ ;
  while (*val) romanshow(*val++) ;
}

Funky_Stuff
len=`wc -c < header.c`
if [ $len !=     5850 ] ; then
echo error: header.c was $len bytes long, should have been     5850
fi
fi # end of overwriting check
if [ -f io.c ]
then
echo shar: will not over-write existing file io.c
else
echo shar: extracting 'io.c',     2329 characters
cat > io.c <<'Funky_Stuff'

/*  @(#)io.c 1.3 89/10/18
 *
 *  Copyright (c) Steve Holden and Rich Burridge.
 *                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 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 "mp.h"
#include "extern.h"


/* Emptyline returns true if its argument is empty or whitespace only */
         
bool
emptyline(str)
char *str ;
{
  while (*str)
    {
      if (!isspace(*str)) return(FALSE) ;
      str++ ;
    }
  return(TRUE) ;
}


/*  Read an input line into nextline, setting end_of_file, end_of_page
 *  and end_of_line appropriately.
 */

void
readline()
{
  int c ;
  int i = 0 ;      /* Index into current line being read. */
  int len = 0 ;    /* Length of the current line. */

  if (end_of_file) return ;
  end_of_page = end_of_line = FALSE ;

  while (len < llen && (c = getc(fp)) != EOF && c != '\n' && c != '\f')
    {
      if (c == '\t')
        {
          do
            {
              nextline[i++] = ' ' ;
              len++ ;
            }
          while (len % 8 != 0 && len <= llen) ;
        }
      else
        { 
          nextline[i++] = c ;
          len++ ;
        }
      if (c == '\b') len -= 2 ;
    }
  nextline[i] = '\0' ;

  if (len == llen && c != EOF && c != '\n' && c != '\f')
    {
      c = getc(fp) ;
      if (c != EOF && c != '\n' && c != '\f') UNGETC(c, fp) ;
    }

  switch (c)
    {
      case EOF  : if (i == 0) end_of_file = TRUE ;
                  else
                    { 
                      UNGETC(c, fp) ;
                      end_of_line = TRUE ;
                    }
                  break ;
      case '\n' : end_of_line = TRUE ;
                  break ;

/*  /usr/ucb/mail for some unknown reason, appends a bogus formfeed at
 *  the end of piped output. The next character is checked; if it's an
 *  EOF, then end_of_file is set, else the character is put back.
 */

      case '\f' : if ((c = getc(fp)) == EOF) end_of_file = TRUE ;
                  else UNGETC(c, fp) ;

                  end_of_line = TRUE ;
                  end_of_page = TRUE ;
                  break ;
    }
}
Funky_Stuff
len=`wc -c < io.c`
if [ $len !=     2329 ] ; then
echo error: io.c was $len bytes long, should have been     2329
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',     7418 characters
cat > main.c <<'Funky_Stuff'

/*  @(#)main.c 1.6 90/08/17
 *
 *  Takes a mail file, a news article or an ordinary file
 *  and pretty prints it on a Postscript printer.
 *
 *-----------------------------------------------------------------------
 *
 *  Credits:
 *
 *  Original written in the Icon language by Steve Holden.
 *
 *  Converted to C, modified and maintained
 *  by Rich Burridge - Sun Microsystems Australia.
 *
 *  Further modifications to handle news articles and MH mail,
 *  by Bruno Pillard  - Chorus Systemes, St Quentin en Yvelines, France
 *
 *  Addition of digest printing by Dave Glowacki of Public
 *  Works Computer Services, St Paul, MN.
 *
 *  Ordinary text file pretty printing by Rich Burridge.
 *
 *  Substantial modifications to header parsing and command options
 *  by Jeremy Webber, Computer Science Dept, University of Adelaide,
 *  Australia.
 *
 *  Support for printing multiple files and subject line filename print
 *  for ordinary files added by S. Manoharan, Edinburgh University.
 *
 *  Landscape mode added by Michael Tuciarone.
 *
 *----------------------------------------------------------------------
 *
 *  Copyright (c) Steve Holden and Rich Burridge.
 *                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 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 "mp.h"

/* Command line option flags */
 
bool article  = FALSE ;       /* Set for news in "Article from " format. */
bool digest   = FALSE ;       /* Are we are printing a mail digest (-d) */
bool filofax  = FALSE ;       /* Set if we are printing a filofax file. */
bool folder   = FALSE ;       /* Set if we are printing a mail folder. */
bool text_doc = FALSE ;       /* Printing normal text (-o) */
bool timeman  = FALSE ;       /* Set if we are printing a Time Manager file. */
 
/* Header definitions. */
 
char *FROMHDR       = "From:" ;
char *FROM_HDR      = "From " ;            /* UNIX From header */
char *APP_FROMHDR   = "Apparently_from:" ;
char *TOHDR         = "To:" ;
char *APP_TOHDR     = "Apparently_to:" ;
char *CCHDR         = "Cc:" ;
char *SUBJECTHDR    = "Subject:" ;
char *DATEHDR       = "Date:" ;
char *NEWSGROUPSHDR = "Newsgroups:" ;
char *REPLYHDR      = "Reply_to:" ;

/* Header lines. */

char *from            = NULL ;    /* From: */
char *from_           = NULL ;    /* From_ (UNIX from) */
char *apparently_from = NULL ;    /* Apparently_from: */
char *to[MAXCONT+1] ;             /* To: (can have multiple lines) */
char *apparently_to   = NULL ;    /* Apparently_to: */
char *cc[MAXCONT+1]   = NULL ;    /* Cc: (can have multiple lines) */
char *subject         = NULL ;    /* Subject: (can be set from command line) */
char *gsubject        = NULL ;    /* Global subject set from command line. */
char *date            = NULL ;    /* Date: */
char *newsgroups      = NULL ;    /* Newsgroups: (news articles only) */
char *reply_to        = NULL ;    /* Reply-to: */

/* Strings used in page processing. */

char curfname[MAXPATHLEN] ;       /* Current file being printed. */
char *message_for = "" ;          /* "[Mail,News,Listing] for " line */
char *nameptr ;                   /* Used to getenv the NAME variable. */
char *optarg ;                    /* Optional command line argument. */
char *owner       = NULL ;        /* Name of owner (usually equal to 'to') */
char *progname    = NULL ;        /* Name of this program. */
char *prologue    = PROLOGUE ;    /* Name of PostScript prologue file. */
char proname[MAXPATHLEN] ;        /* Full pathname of the prologue file. */

/* Other globals. */

document_type doc_type = DO_MAIL ;  /* Printing type - default mail */

int colct = 0;              /* Column count on current page. */
int cmdfiles = 0 ;          /* Set if file to print given on command line. */
int landscape = 0;          /* Set if in landscape (wide) mode. */
int linect = 0 ;            /* Line count on current page. */
int llen = LINELENGTH ;     /* Number of characters per line. */
int optind ;                /* Optional command line argument indicator. */
int pageno = 1 ;            /* Page number within message. */
int plen = PAGELENGTH ;     /* Number of lines per page. */
int tpn    = 0 ;            /* Total number of pages printed. */

/* Read-ahead variables. */

char nextline[MAXLINE] ;  /* Read-ahead of the mail message, minus nl */

bool end_of_file = FALSE ;     /* EOF indicator */
bool end_of_line ;             /* Is a newline removed from this line */
bool end_of_page = FALSE ;     /* end-of-page indicator - ^L on input */

FILE *fp ;                     /* File pointer for current file. */


main(argc, argv)
int argc ;
char **argv ;
{
  to[0] = cc[0] = NULL ;

  progname = argv[0] ;        /* Save this program name. */

/*  Try to get location of the mp prologue file from an environment variable.
 *  If it's not found, then use the default value.
 */

  if ((prologue = getenv("MP_PROLOGUE")) == NULL)
    prologue = PROLOGUE ;
  SPRINTF(proname, "%s/mp.pro.ps", prologue) ;

  get_options(argc, argv) ;   /* Read and process command line options. */

  show_prologue(proname) ;    /* Send prologue file to output. */

  if (landscape) PRINTF("\nLandscape\n") ;

  FPUTS("%%EndProlog\n", stdout) ;

  if (argc - optind != 0) cmdfiles = 1 ;
  if (!cmdfiles)
    {
      fp = stdin ;                 /* Get input from standard input. */
      STRCPY(curfname, "stdin") ;
      printfile() ;                /* Pretty print *just* standard input. */
    }
  else
    for (; optind < argc; ++optind)
      {
        STRCPY(curfname, argv[optind]) ;    /* Current file to print. */
        if ((fp = fopen(curfname, "r")) == NULL)
          {
            FPRINTF(stderr, "%s: cannot open %s\n", progname, curfname) ;
            continue ;
          }
        pageno = 1 ;       /* Initialise current page number. */
        end_of_file = 0 ;  /* Reset in case there's another file to print. */
        printfile() ;      /* Pretty print current file. */
      }

  show_trailer() ;         /* Send trailer file to output. */

  exit(0) ;
/*NOTREACHED*/
}


printfile()    /* Create PostScript to pretty print the current file. */
{
  readline() ;
  if (end_of_file)
    {
      FPRINTF(stderr, "mp: empty input file, nothing printed\n") ;
      exit(1) ;
    }
 
  if (!text_doc)
    parse_headers(FALSE) ;    /* Parse headers of mail or news article */
  init_setup() ;              /* Set values for remaining globals. */
 
/* Print the document */
 
  startpage() ;               /* Output initial definitions. */

  if (doc_type != DO_TEXT) show_headers(FALSE) ;
  while (!end_of_file)
    {
      if (folder && EQUAL(FROM_HDR))
        {
          linect = plen ;
          reset_headers() ;
          parse_headers(FALSE) ;
          show_headers(FALSE) ;
        }
      if (digest && (EQUAL(FROMHDR) || EQUAL(DATEHDR) || EQUAL(SUBJECTHDR)))
        {
          linect = plen ;
          parse_headers(TRUE) ;
          show_headers(TRUE) ;
        }
      textshow(nextline) ;
      readline() ;
    }    
  if (filofax || timeman) endfile() ;
  else endpage() ;
  FCLOSE(fp) ;
}


show_trailer()
{
  FPUTS("%%Trailer\n", stdout) ;
  PRINTF("%%%%Pages: %1d\n", tpn) ;
}
Funky_Stuff
len=`wc -c < main.c`
if [ $len !=     7418 ] ; then
echo error: main.c was $len bytes long, should have been     7418
fi
fi # end of overwriting check
if [ -f misc.c ]
then
echo shar: will not over-write existing file misc.c
else
echo shar: extracting 'misc.c',     6170 characters
cat > misc.c <<'Funky_Stuff'

/*  @(#)misc.c 1.5 90/08/16
 *
 *  Copyright (c) Steve Holden and Rich Burridge.
 *                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 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 "mp.h"
#include "patchlevel.h"
#include "extern.h"


void
do_date()        /* Output Postscript definition for the date and time. */
{
  long clock ;           /* Used by the localtime function call. */
  struct tm *tm ;        /* Used by the localtime and asctime calls. */

  if (date == NULL)
    {
      clock = time((time_t *) 0) ;
      tm = localtime(&clock) ;
      psdef("TimeNow", asctime(tm)) ;
    }
  else psdef("TimeNow", date) ;
}


get_opt(argc, argv, options)
int argc ;
char **argv, *options ;
{
  char opch, *str, *ptr ;
  static int flag = 0 ;
  static int cur_argc ;
  static char **cur_argv ;

  if (flag == 0)
    {
      cur_argc = argc ;
      cur_argv = argv ;
      flag = 1 ;
      optind = 1 ;
    }

  if (cur_argc <= 1) return -1 ;

  if (--cur_argc >= 1)
    {
      str = *++cur_argv ;
      if (*str != '-') return -1 ;    /* Argument is not an option   */
      else
        {                             /* Argument is an option */
          if ((ptr = index(options, opch = *++str)) != (char *) 0)
            {
              ++optind ;
              optarg = ++str ;        /* Point to rest of argument if any  */
              if ((*++ptr == ':') && (*optarg == '\0'))
                {
                  if (--cur_argc <= 0) return '?' ;
                  optarg = *++cur_argv ;
                  ++optind ;
                }
              return opch ;
            }
          else if (opch == '-')
            {                         /* End of options */
              ++optind ;
              return -1 ;
            }
          else return '?' ;
        }
    } 
  return 0 ;                          /* Should never be reached. */
}


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

  while ((opch = get_opt(argc, argv, "adflmop:s:tv")) != -1)
    switch (opch)
      {
        case 'a' : article = TRUE ;      /* "Article from" format. */
                   break ;
        case 'd' : digest = TRUE ;       /* Print digest. */
                   break ;
        case 'f' : filofax = TRUE ;      /* Print filofax file. */
                   SPRINTF(proname, "%s/mp.pro.filofax.ps", prologue) ;
                   break ;
        case 'l' : landscape = TRUE ;    /* Print in landscape mode. */
                   break ;
        case 'm' : folder = TRUE ;       /* Print mail folder. */
                   break ;
        case 'o' : text_doc = TRUE ;     /* Print ordinary text file */
                   break ;
        case 'p' : if (strlen(optarg))
                     STRCPY(proname, optarg) ;  /* New prologue file. */
                   break ;
        case 's' : if (strlen(optarg))
                     gsubject = optarg ;        /* New subject line. */
                   break ;
        case 't' : timeman = TRUE ;     /* Print Time Manager file. */
                   SPRINTF(proname, "%s/mp.pro.timeman.ps", prologue) ;
                   break ;
        case 'v' : FPRINTF(stderr,
                           "%s version 2.4.%1d\n", progname, PATCHLEVEL) ;                         exit(1) ;
        case '?' : usage() ;
      }
}


void
init_setup()            /* Set default values for various options. */
{
  char *c, *ptr ;
  int amp_cnt = 0 ;     /* Number of ampersands in gecos field. */
  int i, j, n, spaces ;
  struct passwd *pp ;

  c = getlogin() ;      /* Pointer to users login name. */
  if (c == NULL)        /* Get username from password file */
    {
      pp = getpwuid(geteuid()) ;
      if (pp == NULL) c = "printing" ;
      else c = pp->pw_name ;
    }
  owner = malloc((unsigned) (strlen(c) + 1)) ;
  STRCPY(owner, c) ;
 
/*  Have a look for the users gecos (normally real name), so that its a bit
 *  more recognisable. If this field is too long, then we need to truncate
 *  sensibly. We also need to check a few things. If we've extracted
 *  two "words" or have found a comma, then exit. If an ampersand is
 *  found, this is expanded to the users name in capitals.
 */    
     
  pp = getpwnam(owner) ;
  if (pp != NULL && pp->pw_gecos && pp->pw_gecos[0] != '\0')
    {  
      for (i = 0; i < strlen(pp->pw_gecos); i++)
        if (pp->pw_gecos[i] == '&') amp_cnt++ ;
 
      owner = malloc((unsigned) (strlen(pp->pw_gecos) +
                                 amp_cnt * strlen(c) + 1)) ;

      n = spaces = 0 ;
      ptr = pp->pw_gecos ;
      for (i = 0; i < strlen(pp->pw_gecos); i++)
        {
               if (*ptr == ',') break ;
          else if (*ptr == '&')
            {
              for (j = 0; j < strlen(c); j++)
                if (islower(c[j])) owner[n++] = toupper(c[j]) ;
                else owner[n++] = c[j] ;
              *ptr++ ;
            }
          else if (*ptr == ' ')
            {
              if (++spaces == 2) break ;
              else owner[n++] = *ptr++ ;
            }
          else owner[n++] = *ptr++ ;
          if (n >= NAMELENGTH) break ;
        }
      if (n > NAMELENGTH) n = NAMELENGTH ;
      owner[n] = '\0' ;
    }
  if ((nameptr = getenv("NAME")) != NULL)
    STRCPY(owner, nameptr) ;

  if (text_doc) doc_type = DO_TEXT ;
  switch (doc_type)
    {
      case DO_TEXT : message_for = "Listing for ";
                     digest = FALSE ;
                     break ;
      case DO_MAIL : message_for = digest ? "Mail digest for " : "Mail for " ;
                     break ;
      case DO_NEWS : message_for = digest ? "News digest for " : "News for " ;
                     break ;
    }
}


usage()     /* Print usage message and exit. */
{
  FPRINTF(stderr,"Usage: %s [-a] [-d] [-f] [-l] [-m] ", progname) ;
  FPRINTF(stderr, "[-o] [-p prologue] [-s subject] [-t] [-v] [-?]\n") ;
  exit(1) ;
}

Funky_Stuff
len=`wc -c < misc.c`
if [ $len !=     6170 ] ; then
echo error: misc.c was $len bytes long, should have been     6170
fi
fi # end of overwriting check
if [ -f print.c ]
then
echo shar: will not over-write existing file print.c
else
echo shar: extracting 'print.c',     4128 characters
cat > print.c <<'Funky_Stuff'

/*  @(#)print.c 1.8 90/08/29
 *
 *  Copyright (c) Steve Holden and Rich Burridge.
 *                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 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 "mp.h"
#include "extern.h"


boldshow(hdr, str)      /* Display a header all in bold. */
char *hdr, *str ;
{
  useline() ;
  FPUTS("BoldFont ", stdout) ;
  startline() ;
  expand(hdr) ;
  expand(str) ;
  endline() ;
}


endcol()
{
  linect = 0 ;
  PRINTF("endcol\n") ;
}


endfile()
{
  linect = 0 ;
  PRINTF("(%1d) endfile\n", pageno) ;
}


endline()
{
  PRINTF(") showline\n") ;
}


endpage()
{
  linect = 0 ;
  PRINTF("(%1d) endpage\n", pageno++) ;
}


expand(s)   /* Display a string with PostScript-sensitive characters escaped */
char *s ;
{
  for (; s && *s; s++)
    {
      switch (*s)
        {
          case '\\' : FPUTS("\\\\", stdout) ;
                      break ;
          case '('  : FPUTS("\\(", stdout) ;
                      break ;
          case ')'  : FPUTS("\\)", stdout) ;
                      break ;
          case '\b' : PUTC(*s, stdout) ;
                      break ;
          default   : if (isprint(*s)) PUTC(*s, stdout) ;
        }
    }
}


mixedshow(hdr, str)     /* Display a header in mixed bold/Roman. */
char *hdr, *str ;
{
  useline() ;
  FPUTS("BoldFont ", stdout) ;
  startline() ;
  expand(hdr) ;
  FPUTS(") show pf (", stdout) ;
  expand(str) ;
  endline() ;
}


psdef(name, def)        /* Do a PostScript define. */
char *name, *def ;
{
  PRINTF("/%s (", name) ;
  expand(def) ;
  PRINTF(") def\n") ;
}


romanshow(str)          /* Display a header all in Roman. */
char *str ;
{
  useline() ;
  FPUTS("pf ", stdout) ;
  startline() ;
  expand(str) ;
  endline() ;
}


void
set_defs()               /* Setup PostScript definitions. */
{
  int i ;

  if (article == TRUE)
    STRCPY(message_for, "Article from") ;             /* MailFor. */
  psdef("MailFor", message_for) ;

  if (article == TRUE && newsgroups != NULL)          /* User. */
    {
      for (i = 0; i < strlen(newsgroups); i++)
        if (newsgroups[i] == ',' ||
            newsgroups[i] == '\0') break ;
      owner = (char *) realloc(owner, (unsigned int) i) ;
      STRNCPY(owner, newsgroups, i) ;
      owner[i] = '\0' ;
    }
  psdef("User", owner) ;
 
  do_date() ;                                         /* TimeNow. */
 
  if (text_doc && cmdfiles) subject = curfname ;
  psdef("Subject",
        (gsubject != NULL) ? gsubject : subject) ;    /* Subject. */
}


/* Display the PostScript prologue file for mp */
                   
show_prologue(pro)
char *pro ;              /* Prologue file name */
{
  FILE *pf ;
  char buf[MAXLINE], tmpstr[MAXLINE] ;
  int t2 ;               /* Possible extract page or line length. */

  if ((pf = fopen(pro, "r")) == NULL)                                
    {
      FPRINTF(stderr,"%s: Prologue file %s not found.\n",progname, pro) ;
      exit(1) ;
    }
  while (fgets(buf, MAXLINE, pf) != NULL)
    {
      FPUTS(buf, stdout) ;
 
/* Check for new line or page length. */
 
      SSCANF(buf, "%s %d", tmpstr, &t2) ;
      if (strcmp(tmpstr, "%%PageLength") == 0)
        plen = t2 ;               /* Change the page length. */
      else if (strcmp(tmpstr, "%%LineLength") == 0)
        llen = t2 ;               /* Change the line length. */
    }
  FCLOSE(pf) ;
}


startline()
{
  PRINTF("(") ;
}


startpage()
{
  PRINTF("%%%%Page: ? %1d\n", ++tpn) ;
  set_defs() ;
}


textshow(s)
char *s ;
{
  useline() ;
  FPUTS("sf ", stdout) ;
  startline() ;
  expand(s) ;
  endline() ;
}


useline()   /* Called in order to ready a line for printing. */
{
  if (++linect > plen || end_of_page == TRUE)
    {
      if (landscape && colct == 0)
        {
          colct++ ;
          endcol() ;
          return ;
        }
      colct = 0 ;
      endpage() ;
      linect = 0 ;
      startpage() ;
    }
}
Funky_Stuff
len=`wc -c < print.c`
if [ $len !=     4128 ] ; then
echo error: print.c was $len bytes long, should have been     4128
fi
fi # end of overwriting check
if [ -f extern.h ]
then
echo shar: will not over-write existing file extern.h
else
echo shar: extracting 'extern.h',     3458 characters
cat > extern.h <<'Funky_Stuff'

/*  @(#)extern.h 1.3 90/08/16
 *
 *  Contains all the external definitions used by mp.
 *
 *  Copyright (c) Steve Holden and Rich Burridge.
 *                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.
 */

extern char *APP_FROMHDR ;
extern char *APP_TOHDR ;
extern char *CCHDR ;
extern char *DATEHDR ;
extern char *FROMHDR ;
extern char *FROM_HDR ;          /* UNIX From header */
extern char *NEWSGROUPSHDR ;
extern char *REPLYHDR ;
extern char *SUBJECTHDR ;
extern char *TOHDR ;

extern char *apparently_from ;   /* Apparently_from: */
extern char *apparently_to ;     /* Apparently_to: */
extern char *cc[] ;              /* Cc: (can have multiple lines) */
extern char *date ;              /* Date: */
extern char *from ;              /* From: */
extern char *from_ ;             /* From_ (UNIX from) */
extern char *gsubject ;          /* Global Subject set from command line. */
extern char *newsgroups ;        /* Newsgroups: (news articles only) */
extern char *reply_to ;          /* Reply-to: */
extern char *subject ;           /* Subject: (can be set from command line) */
extern char *to[] ;              /* To: (can have multiple lines) */

extern char curfname[] ;     /* Current file being printed. */
extern char *message_for ;   /* "[Mail,News,Listing] for " line */
extern char *nameptr ;       /* Used to getenv the NAME variable. */
extern char nextline[] ;     /* Read-ahead of the mail message, minus nl */
extern char *optarg ;        /* Optional command line argument. */
extern char *owner ;         /* Name of owner (usually equal to 'to') */
extern char *progname ;      /* Name of this program. */
extern char *prologue ;      /* Name of PostScript prologue file. */
extern char proname[] ;      /* Full pathname of the prologue file. */

extern int colct ;           /* Column count on current page. */
extern int cmdfiles ;        /* Set if file to print given on command line. */
extern int landscape ;       /* Set if in landscape (wide) mode. */
extern int linect ;          /* Line count on current page. */
extern int llen ;            /* Number of characters per line. */
extern int optind ;          /* Optional command line argument indicator. */
extern int pageno ;          /* Page number within message. */
extern int plen ;            /* Number of lines per page. */
extern int tpn ;             /* Total number of pages printed. */

extern bool article ;        /* Set for news in "Article from " format. */
extern bool digest ;         /* Are we are printing a mail digest (-d) */
extern bool filofax ;        /* Set if we are printing a filofax file. */
extern bool folder ;         /* Set if we are printing a mail folder. */
extern bool text_doc ;       /* Printing normal text (-o) */
extern bool timeman ;        /* Set if we are printing a Time Manager file. */

extern bool end_of_file ;    /* EOF indicator */
extern bool end_of_line ;    /* Is a newline removed from this line */
extern bool end_of_page ;    /* end-of-page indicator - ^L on input */

extern document_type doc_type ;  /* Printing type - default mail */

extern FILE *fp ;            /* File pointer for current file. */
Funky_Stuff
len=`wc -c < extern.h`
if [ $len !=     3458 ] ; then
echo error: extern.h was $len bytes long, should have been     3458
fi
fi # end of overwriting check
if [ -f mp.h ]
then
echo shar: will not over-write existing file mp.h
else
echo shar: extracting 'mp.h',     2437 characters
cat > mp.h <<'Funky_Stuff'

/*  @(#)mp.h 1.6 90/08/17
 *
 *  Contains all the global definitions used by mp.
 *
 *  Copyright (c) Steve Holden and Rich Burridge.
 *                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 <sys/types.h>
#include <sys/file.h>
#include <sys/param.h>
#include <ctype.h>
#include <time.h>
#include <pwd.h>

#ifdef   SYSV
#include <sys/pathname.h>
#include <string.h>
#endif /*SYSV*/

#define  FCLOSE       (void) fclose
#define  FPRINTF      (void) fprintf
#define  FPUTS        (void) fputs
#define  PRINTF       (void) printf
#define  PUTC         (void) putc
#define  SPRINTF      (void) sprintf
#define  SSCANF       (void) sscanf
#define  STRCPY       (void) strcpy
#define  STRNCPY      (void) strncpy
#define  UNGETC       (void) ungetc

/* Configuration constants */

#ifndef  PROLOGUE            /* PostScript prologue file */
#define  PROLOGUE     "/usr/local/lib"
#endif /*PROLOGUE*/

#define  EQUAL(val)   (!strncmp(val, nextline, strlen(val)))
#define  INC          argc-- ; argv++ ;

#ifdef  NOINDEX
#define  index        strchr
#endif /*NOINDEX*/

#define  LINELENGTH   80     /* Number of characters per line. */

#ifndef  MAXPATHLEN
#define  MAXPATHLEN   1024
#endif /*MAXPATHLEN*/

#define  MAXSIZES     4      /* Maximum number of different sizes. */

#define  NAMELENGTH   18     /* Maximum allowable real user name. */
#define  PAGELENGTH   60     /* Number of lines per page. */
#define  MAXCONT      10     /* Maximum no of continuation header lines */
#define  MAXLINE      256    /* Maximum string length. */
 
#ifndef TRUE
#define TRUE          1
#define FALSE         0
#endif  /*TRUE*/
 
typedef enum {DO_MAIL, DO_NEWS, DO_TEXT} document_type ;
typedef char bool ;

time_t time() ;
struct tm *localtime() ;
bool emptyline() ;
FILE *fopen() ;
void exit() ;
char *asctime(), *getenv(), *getlogin(), *gets(), *index(), *malloc() ;
char *realloc(), *sprintf(), *strchr(), *strcpy(), *strncpy() ;

void do_date(), get_header(), get_mult_hdr(), init_setup() ;
void parse_headers(), readline(), reset_headers(), set_defs() ;
void show_headers(), show_mult_hdr() ;
Funky_Stuff
len=`wc -c < mp.h`
if [ $len !=     2437 ] ; then
echo error: mp.h was $len bytes long, should have been     2437
fi
fi # end of overwriting check
if [ -f patchlevel.h ]
then
echo shar: will not over-write existing file patchlevel.h
else
echo shar: extracting 'patchlevel.h',      558 characters
cat > patchlevel.h <<'Funky_Stuff'
 
/*  @(#)patchlevel.h 1.12 90/08/29
 *
 *  This is the current patch level for this version of mp.
 *
 *  Copyright (c) Steve Holden and Rich Burridge.
 *                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.
 */

#define  PATCHLEVEL  5
Funky_Stuff
len=`wc -c < patchlevel.h`
if [ $len !=      558 ] ; then
echo error: patchlevel.h was $len bytes long, should have been      558
fi
fi # end of overwriting check
if [ -f README ]
then
echo shar: will not over-write existing file README
else
echo shar: extracting 'README',     4181 characters
cat > README <<'Funky_Stuff'

README for mp, the PostScript pretty printer.

Version 2.4 April 1990.

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

--------------------------------------------------------------------------
CONTENTS:

1. What is mp?
2. Getting started.
3. Acknowledgements.
--------------------------------------------------------------------------


1. What is mp?
--------------

The mp program will pretty print various files for you. It can be used
in conjunction with a mail reading utility for producing a pretty print
of your mail items. It can be used with a news reading tool to pretty
print news articles. Digests can also be printed, and this version can
pretty print ordinary ASCII files as well. Support for personal organiser
printing was added into the last released version.

This version introduces a landscape mode for mp, to allow you to print
two "pages" per page. This should all help us save some trees.

It uses a PostScript prologue file which normally resides in
/usr/local/lib, but this can be overwritten by use of the -p option.

See the manual pages for more details on these various options.


2. Getting started.
-------------------

Initially there is no Makefile file present in the mp source directory.
You will need to copy Makefile.dist to Makefile, then adjust accordingly.

The Makefile compilation details are setup to default to compiling on a Sun4
running SunOS v4.1. Note that there are various compilation definitions that
might need uncommenting if you are trying to compile and run it on other
machines or operating systems.

These are:

PROLOGUE - Location of the mp prologue file (default: /usr/local/lib)
NOINDEX  - uncomment if you don't have the index() function.

See the Makefile for a detailed description of each of these definitions.

Once you are happy with these settings, then you should do a "make" followed
by a "make install" which will compile the mp program and put the files in
their default locations. You will probably have to be super-user when you do
the "make install"


3. Acknowledgements.
--------------------

The original version of mp was written by Steve Holden in the ICON language,
when Steve worked for Sun Microsystems UK. I converted it to the C language
and added a few features. Bruno Pillard of Chorus Systemes, France added
support for MH mail and news article printing, plus a shell script (mailp)
which tidies up the user interface to mp. Dave Glowacki of Public Works
Computer Services, St Paul, MN. added the ability to print digests and
tidied up some of the other options. Rick Rodgers, UCSF School of Pharmacy,
San Francicso revised the initial version of the mp manual page. Doug
Buchanan added support for printing in filofax and Time Manager format.
Many thanks go to Jerermy Webber, Computer Science Department of the
University of Adelaide who rewrote the message parsing and option code and
made substantial improvements to the programs user friendliness and
robustness. Sam Manogharan added support for printing multiple files
specified on the command line, and subject line filename print for ordinary
files. The landscape mode was written by Michael Tuchiarone.

Thanks go also to Bill Shannon, Roger De Salis, L. Jill Debord, Frederick
Avolio, Mark Prior, Stephen Frede, Craig Bishop, Jimmy Aitken, Hugues Leroy,
Bertrand Decouty, David Fiedler, Scott A. Jordahl, David Boone, Steve Cliffe,
Maureen Chew, Brian Kohn, Walter Underwood, Mike Khaw, Rick Gunderson, Johan
Vromans, Brachet, Pierre Mareschal, Roger Riggs, Larry Tsui and Mike
Bundschuh for bug reports and/or bug fixes plus enhancements.

My thanks also goes to Glenn Reid from Adobe Systems for the backspacefont.ps
code used in the prologue files. I'm grateful to all these people, plus
everybody who has suggested enhancements, and fixed bugs in the previous
versions.

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

Suggestions for further improvement would be most welcome, plus bug reports
and comments.

Rich Burridge,          DOMAIN: richb@Aus.Sun.COM
PHONE: +61 2 413 2666   ACSnet: richb@sunaus.sun.oz.au
Funky_Stuff
len=`wc -c < README`
if [ $len !=     4181 ] ; then
echo error: README was $len bytes long, should have been     4181
fi
fi # end of overwriting check
if [ -f MANIFEST ]
then
echo shar: will not over-write existing file MANIFEST
else
echo shar: extracting 'MANIFEST',     1374 characters
cat > MANIFEST <<'Funky_Stuff'
This file tells you in which part of the mp distribution each
file appeared.

Filename.                              |  Part #
--------------------------------------------------
header.c                               |    1
io.c                                   |    1
main.c                                 |    1
misc.c                                 |    1
print.c                                |    1
extern.h                               |    1
mp.h                                   |    1
patchlevel.h                           |    1
README                                 |    1
Makefile.dist                          |    2
mailp                                  |    2
mp.1                                   |    2
MANIFEST                               |    1
FILES                                  |    1
CHANGES                                |    1
TODO                                   |    1
mp.el                                  |    2
mp.pro.ps                              |    2
mp.pro.alt.ps                          |    2
mp.pro.filofax.ps                      |    2
mp.pro.timeman.ps                      |    2
Data/Mail                              |    2
Data/MailFolder                        |    2
Data/NewsArticle1                      |    2
Data/NewsArticle2                      |    2
Data/NewsDigest                        |    2
Funky_Stuff
len=`wc -c < MANIFEST`
if [ $len !=     1374 ] ; then
echo error: MANIFEST was $len bytes long, should have been     1374
fi
fi # end of overwriting check
if [ -f FILES ]
then
echo shar: will not over-write existing file FILES
else
echo shar: extracting 'FILES',     1795 characters
cat > FILES <<'Funky_Stuff'
This file describes all the files that make up the mp distribution.

Directory mp: the pretty printer for mail, news articles and text files.
------------------------------------------------------------------------

header.c            - mail and news header manipulation routines.
io.c                - input/output routines for mp.
main.c              - includes variable declarations and main().
misc.c              - miscelaneous routines used by mp.
print.c             - PostScript printing routines.

extern.h            - External declaractions.
mp.h                - Macro and constant definitions.
patchlevel.h        - Current patchlevel for this release of mp.

README              - describes what mp is, and how to get started.
Makefile.dist       - Master Makefile used to build mp on Unix systems.
mailp               - a shell script frontend for running mp.
mp.1                - the mp manual page (troff/nroff -man format).
MANIFEST            - tells you what archive part each file was posted in.
FILES               - what you're reading now.
CHANGES             - change history. Will be updated with each new patch.
TODO                - bugs and suggested enhancements. Volunteers?
mp.el               - emacs code to print with mp.
mp.pro.ps           - standard mp prologue file.
mp.pro.alt.ps       - alternative mp prologue file.
mp.pro.filofax.ps   - mp Filofax prologue file.
mp.pro.timeman.ps   - mp Time Manager prologue file.

Sub-directory Data: test data files for new versions of mp.
-----------------------------------------------------------
Data/Mail           - a mail article.
Data/MailFolder     - a simple mail folder.
Data/NewsArticle1   - a news article.
Data/NewsArticle2   - another news article.
Data/NewsDigest     - a digest of news articles.
Funky_Stuff
len=`wc -c < FILES`
if [ $len !=     1795 ] ; then
echo error: FILES was $len bytes long, should have been     1795
fi
fi # end of overwriting check
if [ -f CHANGES ]
then
echo shar: will not over-write existing file CHANGES
else
echo shar: extracting 'CHANGES',     5174 characters
cat > CHANGES <<'Funky_Stuff'

Mp change history.
------------------

v2.3 - patchlevel 1. - Released to comp.sources.misc (January 1990).

v2.3 - patchlevel 2. - Posted to comp.sources.bugs (January 1990).

  Changes:

    *  From Steve Cliffe <steve@wolfen.cc.uow.oz> 
       The Makefile used a technique for generating the object files, 
       from the source files, that not every make has. 
  
    *  From Steve Cliffe <steve@wolfen.cc.uow.oz> 
       Mp used both the index and strchr library calls. It now uses 
       index by default, and if you don't have this, then you need 
       to uncomment a macro definition NOINDEX in the Makefile (which 
       has just been added). 
 
    *  From Brian Kohn <bicker@hoqax.att.com> 
       The variable MAXPATHLEN is not declared on all machines. An 
       appropriate definition has been added to the mp.h file. 

New files:

    *   CHANGES - documented history of the changes made with each new
                  mp patch.

v2.3 - patchlevel 3. - Posted to comp.sources.bugs (January 1990).

    *  The Makefile did not include the CHANGES file in the OTHERS
       macro definition.

    *  From Steve Cliffe <steve@wolfen.cc.uow.oz>
       The new Makefile definition NOINDEX, needs to be included in
       the CFLAGS definition.

    *  From Walter Underwood <wunder@hp-ses.sde.hp.com>
       Several tweaks to the mp man page to correct print on Sys V
       machines.

v2.3 - patchlevel 4. - Posted to comp.sources.bugs (January 1990).

    *  From Mike Khaw <khaw@parcplace.com>
       The definition for NOINDEX in mp.h should be embedded in an
       #ifdef not an #ifndef. Arrgghh!!
 
    *  The CHANGES file is now upto date.
 
    *  From Johan Vromans <jv@mh.nl> 
       An attempt to initialise the cc array in main.c when the variable
       is declared doesn't work with the GNU C compiler. This has been
       removed.

v2.3 - patchlevel 5. - Posted to comp.sources.bugs (February 1990).

    *  From Johan Vromans <jv@mh.nl>
       From Rick Gunderson <rickg@toshiba.tic.oz.au>
       Storage allocation for string constants is different with cc and
       the GNU C compiler (gcc). Two adjustments in print.c are needed.


v2.4 - patchlevel 0. - Started (april 1990).

    *  From Michael J. Tuciarone <tooch@plan9.Sun.COM>
       Support for landscape mode. This allows two pages printed per
       sheet of paper.


v2.4 - patchlevel 1. - 1st June 1990.

    *  From Brachet <brachet@imag.fr>
       Fix for segmentation violation core dump on a System V machine
       when trying to print multiple news articles.

    *  From Brachet <brachet@imag.fr>
       mp took only the first subject of a group of news articles
       because it didn't parse the subject line properly.

v2.4 - patchlevel 2. - 14th August 1990. 
 
    *  From Pierre Mareschal <pmaresch@hawk.ulowell.edu> 

       - Fix for multiple mail printing:
             % mp [-a] file1 file2 file3 ... > mp.out 
             * Outputs the Prolog only once at the beginning of the file. 
             * Gives a correct page count at the end of the PostScript file 
               in the Trailer 
             * Shorten PostScript output (by more than 10%): 
                      PrimaryFont -> pf 
                      SecondaryFont -> sf 
             * Correct global subject line with -s "Subject" flag. 
             * Correct current subject line when multiple articles. 
 
       - Added another style for mp.pro.ps with the page number in lower
         right corner. This file has been called mp.pro.alt.ps.
 
       - Added Example directory (called Data) with the mp distribution. This
         contains examples for Mail, Mail Folders, News Articles, News Digests
         and a plain listing.

    *  Added a TODO file, with a list of the outstanding problems and
       suggested enhancements.

    *  Added MANIFEST and FILES files, to provide a manifest of the
       distributed files, plus a description of what each file does.

    *  From Roger Riggs <riggs@suneast.East.Sun.COM>
       Created emacs functions for printing with mp. A new file (mp.el) has
       been created.

v2.4 - patchlevel 3. - 17th August 1990.

    *  From Larry Tsui <larryt@Canada.Sun.COM>
       With mp -o filename | lpr, the filename printed on the bottom bar
       is missing the first character. The subject string setup at the end
       of set_defs was incorrect.

    *  Gave mp a though linting (Sun 4/65 - SunOS v4.1).

v2.4 - patchlevel 4. - 27th August 1990.

    *  From Mike Bundschuh <mjb@Eng.Sun.COM>
       Added quick fix to expand() in print.c to check if pointer == NULL

v2.4 - patchlevel 5. - 29th August 1990.

    *  From Larry W. Virden <lwv27%cas.BITNET@CUNYVM.CUNY.Edu>
       Include a Makefile.dist with the mp distribution. This file will
       need to be copied to Makefile and adjusted accordingly, but it does
       mean that future changes via patches don't clash with custom user
       changes. The README file has been updated to mention this.

    *  From Lupe Christoph <lupe@alanya.Germany.Sun.COM>
       mp.pro.filofax.ps and mp.pro.timeman.ps still contained definitions
       for PrimaryFont and SecondaryFont.
Funky_Stuff
len=`wc -c < CHANGES`
if [ $len !=     5174 ] ; then
echo error: CHANGES was $len bytes long, should have been     5174
fi
fi # end of overwriting check
if [ -f TODO ]
then
echo shar: will not over-write existing file TODO
else
echo shar: extracting 'TODO',     2508 characters
cat > TODO <<'Funky_Stuff'
1/ From Larry W. Virden <lwv27%cas.BITNET@CUNYVM.CUNY.Edu>
   Is there any thought of adding support within mp's newsp program to
   print more of the news article header?  My dream would be to be able
   to tell newsp (via a .newsprc perhaps?) a set of headers to print using
   the same syntax as rn - or even having newsp USE my .rnrc file .

2/ From Michael J. Tuciarone <tooch@plan9.Sun.COM>
   The ability to better handle different page sizes depending perhaps on a
   command line options, or an environment variable, or a LOCALE setting or ...

3/ From Michael J. Tuciarone <tooch@plan9.Sun.COM>
   NeWS/OpenWindows does not implement the CharStrings dictionary.
   Therefore /backspacefont doesn't work correctly. Need to generate a
   NeWS/OW compatible version of CourierBack.

4/ From Andy Hall <andyh@ncduk.com>
   Running on a Sparcstation 1+ and with a Canon LBP8 mark 3 printer with
   PS-1 Scriptcard. This is a true version 51.4 Adobe Interpreter. If I print
   Unix manual pages using standard Nroff output and the mp.pro.ps v1.2
   prologue the job gets aborted after a few pages with a stackoverflow
   message on the serial output (I am using serial interface).  After a bit
   of investigation using a small C program to produce lines consisting only
   of a printed line number, a printable character, a backspace, an underscore
   and a newline, it appears that the job gets aborted on the page where the
   500th backspace is. I am not a PostScript expert but I am wondering whether
   the problem lies with the embedded piece of code backspacefont.ps or the way
   it is used. It is rather too convoluted for me to understand fully but my
   suspicions are aroused in that the default operand stack size mentioned by
   Adobe in their red book is 500.

5/ From Larry W. Virden <lwv27%cas.BITNET@CUNYVM.CUNY.Edu>
   Instead of having the lpr going to -Plw in the shell script, have it
   go to -P$(PRINTER:lw} ... so folks who use the PRINTER variable get it.

6/ From Lupe Christoph <lupe@alanya.Germany.Sun.COM>
   There are so many personal organisers all over the world that you need a
   more general scheme. What about a flag that takes the name of the personal
   organisers and sticks it in the mp.pro.%s.ps string ?

   Of course you need at least a short writeup on how to create these.
   Better, a short program that takes a general mp.pro.organiser.ps and
   substitutes a few variables. Or you can use short PostScript fragments,
   one for each personal organisers.
Funky_Stuff
len=`wc -c < TODO`
if [ $len !=     2508 ] ; then
echo error: TODO was $len bytes long, should have been     2508
fi
fi # end of overwriting check