home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume14 / mp-2.4.5 / part01 next >
Text File  |  1990-08-29  |  53KB  |  1,676 lines

  1. Newsgroups: comp.sources.misc
  2. subject: v14i067: Mp v2.4.5 - the mail/news pretty printer (Part 1 of 2).
  3. from: rburridge@Sun.COM (Rich Burridge)
  4. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5.  
  6. Posting-number: Volume 14, Issue 67
  7. Submitted-by: rburridge@Sun.COM (Rich Burridge)
  8. Archive-name: mp-2.4.5/part01
  9.  
  10. [Hi Brandon. I think this has undergone enough changes since it
  11.  was last posted to the net to warrant a new posting. When you
  12.  get a moment, could you post to comp.sources.misc please? ]
  13.  
  14. ----------------------------------------------------------------
  15.  
  16. The mp program will pretty print various files for you. It can be used
  17. in conjunction with a mail reading utility for producing a pretty print
  18. of your mail items. It can be used with a news reading tool to pretty
  19. print news articles. Digests can also be printed, and this version can
  20. pretty print ordinary ASCII files as well. Support for personal organiser
  21. printing was added into the last released version.
  22.  
  23. This version introduces a landscape mode for mp, to allow you to print
  24. two "pages" per page. This should all help us save some trees.
  25.  
  26. see the README file for more details.
  27.  
  28. ------CUT HERE------mp.shar.part1------CUT HERE------
  29. #! /bin/sh
  30. # this is a shell archive, meaning:
  31. # 1. Remove everything above the #! /bin/sh line
  32. # 2. Save the resulting text in a file.
  33. # 3. Execute the file with /bin/sh to create the files:
  34. #    header.c
  35. #    io.c
  36. #    main.c
  37. #    misc.c
  38. #    print.c
  39. #    extern.h
  40. #    mp.h
  41. #    patchlevel.h
  42. #    README
  43. #    MANIFEST
  44. #    FILES
  45. #    CHANGES
  46. #    TODO
  47. # This archive created: Wed Aug 29 12:25:52 EST 1990
  48. #
  49. #
  50. export PATH; PATH=/bin:$PATH
  51. #
  52. if [ -f header.c ]
  53. then
  54. echo shar: will not over-write existing file header.c
  55. else
  56. echo shar: extracting 'header.c',     5850 characters
  57. cat > header.c <<'Funky_Stuff'
  58.  
  59. /*  @(#)header.c 1.4 90/08/17
  60.  *
  61.  *  Copyright (c) Steve Holden and Rich Burridge.
  62.  *                All rights reserved.
  63.  *
  64.  *  Permission is given to distribute these sources, as long as the
  65.  *  copyright messages are not removed, and no monies are exchanged.
  66.  *
  67.  *  No responsibility is taken for any errors inherent either
  68.  *  to the comments or the code of this program, but if reported
  69.  *  to me then an attempt will be made to fix them.
  70.  */
  71.  
  72. #include "mp.h"
  73. #include "extern.h"
  74.  
  75.  
  76. /*  If input line is header of type 'hdr', get the contents of the header
  77.  *  into 'dest' (dynamically allocated).
  78.  */
  79.  
  80. void
  81. get_header(hdr, dest)
  82. char *hdr ;
  83. char **dest ;
  84. {
  85.   if (EQUAL(hdr))
  86.     {
  87.       *dest = malloc((unsigned) (strlen(nextline) - strlen(hdr) + 1)) ;
  88.       STRCPY(*dest, nextline + strlen(hdr)) ;
  89.     }
  90. }
  91.  
  92.  
  93. /*  If input line is header of type 'hdr', get header into dest. The header
  94.  *  may have multiple lines. This skips input to next line.
  95.  */
  96.  
  97. void
  98. get_mult_hdr(hdr, dest)
  99. char *hdr ;
  100. char *dest[] ;
  101.   int i = 0 ;
  102.   
  103.   if (EQUAL(hdr))
  104.     {
  105.       get_header(hdr, dest) ;
  106.       i++ ;
  107.       readline() ;
  108.       while (i < MAXCONT && !emptyline(nextline) && isspace(nextline[0]))
  109.         {
  110.           dest[i] = malloc((unsigned) (strlen(nextline) + 1)) ;
  111.           STRCPY(dest[i], nextline) ;
  112.           i++ ;
  113.           readline() ;
  114.         }
  115.       dest[i] = NULL ;
  116.     }
  117. }
  118.  
  119.  
  120. /*  Parse_headers is a function which reads and parses the message headers,
  121.  *  extracting the bits which are of interest.
  122.  *
  123.  *  The document is on standard input; the document is read up to the end of
  124.  *  the header; the next line is read ahead into 'nextline'.
  125.  *
  126.  *  Parameter:
  127.  *  digest  indicates if parsing is of digest headers instead of message
  128.  *          headers
  129.  *
  130.  *  Implicit Input:
  131.  *  nextline  contains the next line from standard input
  132.  *
  133.  *  Side-effects:
  134.  *  The function fills in the global header variables with headers found.
  135.  *  The global variable doc_type is set to the document type
  136.  *  The global variable nextline is set
  137.  *  The document is read up to the line following the headers
  138.  */
  139.  
  140.  
  141. void
  142. parse_headers(digest)
  143. bool digest ;           /* Parsing digest headers */
  144. {
  145.   char *colon ;         /* Pointer to colon in line */
  146.   char *c ;             /* General character pointer */
  147.  
  148. /*  If not processing digest headers, determine if this article is an
  149.  *  ordinary text file.
  150.  */
  151.  
  152.   if (!digest)
  153.     {
  154.       if (!EQUAL(FROM_HDR))         /* UNIX From_ header? */
  155.         {
  156.           colon = index(nextline, ':') ;
  157.           if (colon == NULL)        /* No colon => not a header line */
  158.             {
  159.               doc_type = DO_TEXT ;
  160.               return ;
  161.             }
  162.           c = nextline ;
  163.           while (c < colon && (!isspace(*c))) c++ ;
  164.           if (c != colon)      /* Whitespace in header name => not header */
  165.             {
  166.               doc_type = DO_TEXT ;
  167.               return ;
  168.             }
  169.         }    
  170.     }    
  171.  
  172.   doc_type = DO_MAIL ;    /* Default to mail document */
  173.  
  174. /* Parse headers */
  175.  
  176.   while (TRUE)
  177.     {
  178.       if (emptyline(nextline)) break ;    /* End of headers */
  179.  
  180.       if (!digest)
  181.         {
  182.           get_header(FROM_HDR,      &from_) ;
  183.           get_header(APP_FROMHDR,   &apparently_from) ;
  184.           get_header(APP_TOHDR,     &apparently_to) ;
  185.           get_header(NEWSGROUPSHDR, &newsgroups) ;
  186.           get_header(REPLYHDR,      &reply_to) ;
  187.  
  188.           get_mult_hdr(TOHDR,       to) ;
  189.           if (emptyline(nextline)) break ;
  190.  
  191.           get_mult_hdr(CCHDR,       cc) ;
  192.           if (emptyline(nextline)) break ;
  193.  
  194.           if (doc_type != DO_NEWS && EQUAL(NEWSGROUPSHDR))
  195.             doc_type = DO_NEWS ;
  196.         }
  197.       get_header(FROMHDR, &from) ;
  198.       get_header(SUBJECTHDR, &subject) ;
  199.       get_header(DATEHDR, &date) ;
  200.  
  201.       if (!EQUAL(TOHDR) && !EQUAL(CCHDR))
  202.         {
  203.           while (!end_of_file && !end_of_line)
  204.             readline() ;                       /* Skip rest of long lines */
  205.           readline() ;
  206.         }
  207.     }    
  208. }
  209.  
  210.  
  211. void
  212. reset_headers()          /* Reset header values for next message. */
  213. {
  214.   int i ;
  215.  
  216.   if (from != NULL) free(from) ;
  217.   if (from_ != NULL) free(from_) ;
  218.   if (apparently_from != NULL) free(apparently_from) ;
  219.   if (apparently_to != NULL) free(apparently_to) ;
  220.   if (date != NULL) free(date) ;
  221.   if (newsgroups != NULL) free(newsgroups) ;
  222.   if (reply_to != NULL) free(reply_to) ;
  223.  
  224.   from = from_ = apparently_from = apparently_to = NULL ;
  225.   date = newsgroups = reply_to = subject = NULL ;
  226.  
  227.   for (i = 0; i < MAXCONT+1; i++)
  228.     {
  229.       if (to[i] != NULL) free(to[i]) ;
  230.       if (cc[i] != NULL) free(cc[i]) ;
  231.       to[i] = cc[i] = NULL ;
  232.     }
  233. }
  234.  
  235.  
  236. /*  Show_headers outputs the headers in PostScript. Different headers are
  237.  *  output depending 'digest'.
  238.  */
  239.  
  240. void
  241. show_headers(digest)
  242. bool digest ;
  243. {
  244.   if (digest)
  245.     {
  246.       if (from)       mixedshow(FROMHDR,    from) ;
  247.       if (subject)    mixedshow(SUBJECTHDR, subject) ;
  248.       if (date)       mixedshow(DATEHDR,    date) ;
  249.     }
  250.   else
  251.     {
  252.       if (from_)           boldshow(FROM_HDR,       from_) ;
  253.       if (from)            mixedshow(FROMHDR,       from) ;
  254.       if (apparently_from) mixedshow(APP_FROMHDR,   apparently_from) ;
  255.       if (to[0])           show_mult_hdr(TOHDR,     to) ;
  256.       if (apparently_to)   mixedshow(APP_TOHDR,     apparently_to) ;
  257.       if (cc[0])           show_mult_hdr(CCHDR,     cc) ;
  258.       if (reply_to)        mixedshow(REPLYHDR,      reply_to) ;
  259.       if (newsgroups)      mixedshow(NEWSGROUPSHDR, newsgroups) ;
  260.       if (subject[0])      mixedshow(SUBJECTHDR,    subject) ;
  261.       if (date)            mixedshow(DATEHDR,       date) ;
  262.     }
  263. }
  264.  
  265.  
  266. void
  267. show_mult_hdr(hdr, val)
  268. char *hdr ;              /* Name of header */
  269. char *val[] ;            /* Value of header */
  270. {
  271.   mixedshow(hdr, *val) ;
  272.   val++ ;
  273.   while (*val) romanshow(*val++) ;
  274. }
  275.  
  276. Funky_Stuff
  277. len=`wc -c < header.c`
  278. if [ $len !=     5850 ] ; then
  279. echo error: header.c was $len bytes long, should have been     5850
  280. fi
  281. fi # end of overwriting check
  282. if [ -f io.c ]
  283. then
  284. echo shar: will not over-write existing file io.c
  285. else
  286. echo shar: extracting 'io.c',     2329 characters
  287. cat > io.c <<'Funky_Stuff'
  288.  
  289. /*  @(#)io.c 1.3 89/10/18
  290.  *
  291.  *  Copyright (c) Steve Holden and Rich Burridge.
  292.  *                All rights reserved.
  293.  *
  294.  *  Permission is given to distribute these sources, as long as the
  295.  *  copyright messages are not removed, and no monies are exchanged.
  296.  *
  297.  *  No responsibility is taken for any errors inherent either
  298.  *  to the comments or the code of this program, but if reported
  299.  *  to me then an attempt will be made to fix them.
  300.  */
  301.  
  302. #include "mp.h"
  303. #include "extern.h"
  304.  
  305.  
  306. /* Emptyline returns true if its argument is empty or whitespace only */
  307.          
  308. bool
  309. emptyline(str)
  310. char *str ;
  311. {
  312.   while (*str)
  313.     {
  314.       if (!isspace(*str)) return(FALSE) ;
  315.       str++ ;
  316.     }
  317.   return(TRUE) ;
  318. }
  319.  
  320.  
  321. /*  Read an input line into nextline, setting end_of_file, end_of_page
  322.  *  and end_of_line appropriately.
  323.  */
  324.  
  325. void
  326. readline()
  327. {
  328.   int c ;
  329.   int i = 0 ;      /* Index into current line being read. */
  330.   int len = 0 ;    /* Length of the current line. */
  331.  
  332.   if (end_of_file) return ;
  333.   end_of_page = end_of_line = FALSE ;
  334.  
  335.   while (len < llen && (c = getc(fp)) != EOF && c != '\n' && c != '\f')
  336.     {
  337.       if (c == '\t')
  338.         {
  339.           do
  340.             {
  341.               nextline[i++] = ' ' ;
  342.               len++ ;
  343.             }
  344.           while (len % 8 != 0 && len <= llen) ;
  345.         }
  346.       else
  347.         { 
  348.           nextline[i++] = c ;
  349.           len++ ;
  350.         }
  351.       if (c == '\b') len -= 2 ;
  352.     }
  353.   nextline[i] = '\0' ;
  354.  
  355.   if (len == llen && c != EOF && c != '\n' && c != '\f')
  356.     {
  357.       c = getc(fp) ;
  358.       if (c != EOF && c != '\n' && c != '\f') UNGETC(c, fp) ;
  359.     }
  360.  
  361.   switch (c)
  362.     {
  363.       case EOF  : if (i == 0) end_of_file = TRUE ;
  364.                   else
  365.                     { 
  366.                       UNGETC(c, fp) ;
  367.                       end_of_line = TRUE ;
  368.                     }
  369.                   break ;
  370.       case '\n' : end_of_line = TRUE ;
  371.                   break ;
  372.  
  373. /*  /usr/ucb/mail for some unknown reason, appends a bogus formfeed at
  374.  *  the end of piped output. The next character is checked; if it's an
  375.  *  EOF, then end_of_file is set, else the character is put back.
  376.  */
  377.  
  378.       case '\f' : if ((c = getc(fp)) == EOF) end_of_file = TRUE ;
  379.                   else UNGETC(c, fp) ;
  380.  
  381.                   end_of_line = TRUE ;
  382.                   end_of_page = TRUE ;
  383.                   break ;
  384.     }
  385. }
  386. Funky_Stuff
  387. len=`wc -c < io.c`
  388. if [ $len !=     2329 ] ; then
  389. echo error: io.c was $len bytes long, should have been     2329
  390. fi
  391. fi # end of overwriting check
  392. if [ -f main.c ]
  393. then
  394. echo shar: will not over-write existing file main.c
  395. else
  396. echo shar: extracting 'main.c',     7418 characters
  397. cat > main.c <<'Funky_Stuff'
  398.  
  399. /*  @(#)main.c 1.6 90/08/17
  400.  *
  401.  *  Takes a mail file, a news article or an ordinary file
  402.  *  and pretty prints it on a Postscript printer.
  403.  *
  404.  *-----------------------------------------------------------------------
  405.  *
  406.  *  Credits:
  407.  *
  408.  *  Original written in the Icon language by Steve Holden.
  409.  *
  410.  *  Converted to C, modified and maintained
  411.  *  by Rich Burridge - Sun Microsystems Australia.
  412.  *
  413.  *  Further modifications to handle news articles and MH mail,
  414.  *  by Bruno Pillard  - Chorus Systemes, St Quentin en Yvelines, France
  415.  *
  416.  *  Addition of digest printing by Dave Glowacki of Public
  417.  *  Works Computer Services, St Paul, MN.
  418.  *
  419.  *  Ordinary text file pretty printing by Rich Burridge.
  420.  *
  421.  *  Substantial modifications to header parsing and command options
  422.  *  by Jeremy Webber, Computer Science Dept, University of Adelaide,
  423.  *  Australia.
  424.  *
  425.  *  Support for printing multiple files and subject line filename print
  426.  *  for ordinary files added by S. Manoharan, Edinburgh University.
  427.  *
  428.  *  Landscape mode added by Michael Tuciarone.
  429.  *
  430.  *----------------------------------------------------------------------
  431.  *
  432.  *  Copyright (c) Steve Holden and Rich Burridge.
  433.  *                All rights reserved.
  434.  *
  435.  *  Permission is given to distribute these sources, as long as the
  436.  *  copyright messages are not removed, and no monies are exchanged.
  437.  *
  438.  *  No responsibility is taken for any errors inherent either
  439.  *  to the comments or the code of this program, but if reported
  440.  *  to me then an attempt will be made to fix them.
  441.  */
  442.  
  443. #include "mp.h"
  444.  
  445. /* Command line option flags */
  446.  
  447. bool article  = FALSE ;       /* Set for news in "Article from " format. */
  448. bool digest   = FALSE ;       /* Are we are printing a mail digest (-d) */
  449. bool filofax  = FALSE ;       /* Set if we are printing a filofax file. */
  450. bool folder   = FALSE ;       /* Set if we are printing a mail folder. */
  451. bool text_doc = FALSE ;       /* Printing normal text (-o) */
  452. bool timeman  = FALSE ;       /* Set if we are printing a Time Manager file. */
  453.  
  454. /* Header definitions. */
  455.  
  456. char *FROMHDR       = "From:" ;
  457. char *FROM_HDR      = "From " ;            /* UNIX From header */
  458. char *APP_FROMHDR   = "Apparently_from:" ;
  459. char *TOHDR         = "To:" ;
  460. char *APP_TOHDR     = "Apparently_to:" ;
  461. char *CCHDR         = "Cc:" ;
  462. char *SUBJECTHDR    = "Subject:" ;
  463. char *DATEHDR       = "Date:" ;
  464. char *NEWSGROUPSHDR = "Newsgroups:" ;
  465. char *REPLYHDR      = "Reply_to:" ;
  466.  
  467. /* Header lines. */
  468.  
  469. char *from            = NULL ;    /* From: */
  470. char *from_           = NULL ;    /* From_ (UNIX from) */
  471. char *apparently_from = NULL ;    /* Apparently_from: */
  472. char *to[MAXCONT+1] ;             /* To: (can have multiple lines) */
  473. char *apparently_to   = NULL ;    /* Apparently_to: */
  474. char *cc[MAXCONT+1]   = NULL ;    /* Cc: (can have multiple lines) */
  475. char *subject         = NULL ;    /* Subject: (can be set from command line) */
  476. char *gsubject        = NULL ;    /* Global subject set from command line. */
  477. char *date            = NULL ;    /* Date: */
  478. char *newsgroups      = NULL ;    /* Newsgroups: (news articles only) */
  479. char *reply_to        = NULL ;    /* Reply-to: */
  480.  
  481. /* Strings used in page processing. */
  482.  
  483. char curfname[MAXPATHLEN] ;       /* Current file being printed. */
  484. char *message_for = "" ;          /* "[Mail,News,Listing] for " line */
  485. char *nameptr ;                   /* Used to getenv the NAME variable. */
  486. char *optarg ;                    /* Optional command line argument. */
  487. char *owner       = NULL ;        /* Name of owner (usually equal to 'to') */
  488. char *progname    = NULL ;        /* Name of this program. */
  489. char *prologue    = PROLOGUE ;    /* Name of PostScript prologue file. */
  490. char proname[MAXPATHLEN] ;        /* Full pathname of the prologue file. */
  491.  
  492. /* Other globals. */
  493.  
  494. document_type doc_type = DO_MAIL ;  /* Printing type - default mail */
  495.  
  496. int colct = 0;              /* Column count on current page. */
  497. int cmdfiles = 0 ;          /* Set if file to print given on command line. */
  498. int landscape = 0;          /* Set if in landscape (wide) mode. */
  499. int linect = 0 ;            /* Line count on current page. */
  500. int llen = LINELENGTH ;     /* Number of characters per line. */
  501. int optind ;                /* Optional command line argument indicator. */
  502. int pageno = 1 ;            /* Page number within message. */
  503. int plen = PAGELENGTH ;     /* Number of lines per page. */
  504. int tpn    = 0 ;            /* Total number of pages printed. */
  505.  
  506. /* Read-ahead variables. */
  507.  
  508. char nextline[MAXLINE] ;  /* Read-ahead of the mail message, minus nl */
  509.  
  510. bool end_of_file = FALSE ;     /* EOF indicator */
  511. bool end_of_line ;             /* Is a newline removed from this line */
  512. bool end_of_page = FALSE ;     /* end-of-page indicator - ^L on input */
  513.  
  514. FILE *fp ;                     /* File pointer for current file. */
  515.  
  516.  
  517. main(argc, argv)
  518. int argc ;
  519. char **argv ;
  520. {
  521.   to[0] = cc[0] = NULL ;
  522.  
  523.   progname = argv[0] ;        /* Save this program name. */
  524.  
  525. /*  Try to get location of the mp prologue file from an environment variable.
  526.  *  If it's not found, then use the default value.
  527.  */
  528.  
  529.   if ((prologue = getenv("MP_PROLOGUE")) == NULL)
  530.     prologue = PROLOGUE ;
  531.   SPRINTF(proname, "%s/mp.pro.ps", prologue) ;
  532.  
  533.   get_options(argc, argv) ;   /* Read and process command line options. */
  534.  
  535.   show_prologue(proname) ;    /* Send prologue file to output. */
  536.  
  537.   if (landscape) PRINTF("\nLandscape\n") ;
  538.  
  539.   FPUTS("%%EndProlog\n", stdout) ;
  540.  
  541.   if (argc - optind != 0) cmdfiles = 1 ;
  542.   if (!cmdfiles)
  543.     {
  544.       fp = stdin ;                 /* Get input from standard input. */
  545.       STRCPY(curfname, "stdin") ;
  546.       printfile() ;                /* Pretty print *just* standard input. */
  547.     }
  548.   else
  549.     for (; optind < argc; ++optind)
  550.       {
  551.         STRCPY(curfname, argv[optind]) ;    /* Current file to print. */
  552.         if ((fp = fopen(curfname, "r")) == NULL)
  553.           {
  554.             FPRINTF(stderr, "%s: cannot open %s\n", progname, curfname) ;
  555.             continue ;
  556.           }
  557.         pageno = 1 ;       /* Initialise current page number. */
  558.         end_of_file = 0 ;  /* Reset in case there's another file to print. */
  559.         printfile() ;      /* Pretty print current file. */
  560.       }
  561.  
  562.   show_trailer() ;         /* Send trailer file to output. */
  563.  
  564.   exit(0) ;
  565. /*NOTREACHED*/
  566. }
  567.  
  568.  
  569. printfile()    /* Create PostScript to pretty print the current file. */
  570. {
  571.   readline() ;
  572.   if (end_of_file)
  573.     {
  574.       FPRINTF(stderr, "mp: empty input file, nothing printed\n") ;
  575.       exit(1) ;
  576.     }
  577.  
  578.   if (!text_doc)
  579.     parse_headers(FALSE) ;    /* Parse headers of mail or news article */
  580.   init_setup() ;              /* Set values for remaining globals. */
  581.  
  582. /* Print the document */
  583.  
  584.   startpage() ;               /* Output initial definitions. */
  585.  
  586.   if (doc_type != DO_TEXT) show_headers(FALSE) ;
  587.   while (!end_of_file)
  588.     {
  589.       if (folder && EQUAL(FROM_HDR))
  590.         {
  591.           linect = plen ;
  592.           reset_headers() ;
  593.           parse_headers(FALSE) ;
  594.           show_headers(FALSE) ;
  595.         }
  596.       if (digest && (EQUAL(FROMHDR) || EQUAL(DATEHDR) || EQUAL(SUBJECTHDR)))
  597.         {
  598.           linect = plen ;
  599.           parse_headers(TRUE) ;
  600.           show_headers(TRUE) ;
  601.         }
  602.       textshow(nextline) ;
  603.       readline() ;
  604.     }    
  605.   if (filofax || timeman) endfile() ;
  606.   else endpage() ;
  607.   FCLOSE(fp) ;
  608. }
  609.  
  610.  
  611. show_trailer()
  612. {
  613.   FPUTS("%%Trailer\n", stdout) ;
  614.   PRINTF("%%%%Pages: %1d\n", tpn) ;
  615. }
  616. Funky_Stuff
  617. len=`wc -c < main.c`
  618. if [ $len !=     7418 ] ; then
  619. echo error: main.c was $len bytes long, should have been     7418
  620. fi
  621. fi # end of overwriting check
  622. if [ -f misc.c ]
  623. then
  624. echo shar: will not over-write existing file misc.c
  625. else
  626. echo shar: extracting 'misc.c',     6170 characters
  627. cat > misc.c <<'Funky_Stuff'
  628.  
  629. /*  @(#)misc.c 1.5 90/08/16
  630.  *
  631.  *  Copyright (c) Steve Holden and Rich Burridge.
  632.  *                All rights reserved.
  633.  *
  634.  *  Permission is given to distribute these sources, as long as the
  635.  *  copyright messages are not removed, and no monies are exchanged.
  636.  *
  637.  *  No responsibility is taken for any errors inherent either
  638.  *  to the comments or the code of this program, but if reported
  639.  *  to me then an attempt will be made to fix them.
  640.  */
  641.  
  642. #include "mp.h"
  643. #include "patchlevel.h"
  644. #include "extern.h"
  645.  
  646.  
  647. void
  648. do_date()        /* Output Postscript definition for the date and time. */
  649. {
  650.   long clock ;           /* Used by the localtime function call. */
  651.   struct tm *tm ;        /* Used by the localtime and asctime calls. */
  652.  
  653.   if (date == NULL)
  654.     {
  655.       clock = time((time_t *) 0) ;
  656.       tm = localtime(&clock) ;
  657.       psdef("TimeNow", asctime(tm)) ;
  658.     }
  659.   else psdef("TimeNow", date) ;
  660. }
  661.  
  662.  
  663. get_opt(argc, argv, options)
  664. int argc ;
  665. char **argv, *options ;
  666. {
  667.   char opch, *str, *ptr ;
  668.   static int flag = 0 ;
  669.   static int cur_argc ;
  670.   static char **cur_argv ;
  671.  
  672.   if (flag == 0)
  673.     {
  674.       cur_argc = argc ;
  675.       cur_argv = argv ;
  676.       flag = 1 ;
  677.       optind = 1 ;
  678.     }
  679.  
  680.   if (cur_argc <= 1) return -1 ;
  681.  
  682.   if (--cur_argc >= 1)
  683.     {
  684.       str = *++cur_argv ;
  685.       if (*str != '-') return -1 ;    /* Argument is not an option   */
  686.       else
  687.         {                             /* Argument is an option */
  688.           if ((ptr = index(options, opch = *++str)) != (char *) 0)
  689.             {
  690.               ++optind ;
  691.               optarg = ++str ;        /* Point to rest of argument if any  */
  692.               if ((*++ptr == ':') && (*optarg == '\0'))
  693.                 {
  694.                   if (--cur_argc <= 0) return '?' ;
  695.                   optarg = *++cur_argv ;
  696.                   ++optind ;
  697.                 }
  698.               return opch ;
  699.             }
  700.           else if (opch == '-')
  701.             {                         /* End of options */
  702.               ++optind ;
  703.               return -1 ;
  704.             }
  705.           else return '?' ;
  706.         }
  707.     } 
  708.   return 0 ;                          /* Should never be reached. */
  709. }
  710.  
  711.  
  712. get_options(argc, argv)      /* Read and process command line options. */
  713. int argc ;
  714. char *argv[] ;
  715. {
  716.   int opch ;
  717.  
  718.   while ((opch = get_opt(argc, argv, "adflmop:s:tv")) != -1)
  719.     switch (opch)
  720.       {
  721.         case 'a' : article = TRUE ;      /* "Article from" format. */
  722.                    break ;
  723.         case 'd' : digest = TRUE ;       /* Print digest. */
  724.                    break ;
  725.         case 'f' : filofax = TRUE ;      /* Print filofax file. */
  726.                    SPRINTF(proname, "%s/mp.pro.filofax.ps", prologue) ;
  727.                    break ;
  728.         case 'l' : landscape = TRUE ;    /* Print in landscape mode. */
  729.                    break ;
  730.         case 'm' : folder = TRUE ;       /* Print mail folder. */
  731.                    break ;
  732.         case 'o' : text_doc = TRUE ;     /* Print ordinary text file */
  733.                    break ;
  734.         case 'p' : if (strlen(optarg))
  735.                      STRCPY(proname, optarg) ;  /* New prologue file. */
  736.                    break ;
  737.         case 's' : if (strlen(optarg))
  738.                      gsubject = optarg ;        /* New subject line. */
  739.                    break ;
  740.         case 't' : timeman = TRUE ;     /* Print Time Manager file. */
  741.                    SPRINTF(proname, "%s/mp.pro.timeman.ps", prologue) ;
  742.                    break ;
  743.         case 'v' : FPRINTF(stderr,
  744.                            "%s version 2.4.%1d\n", progname, PATCHLEVEL) ;                         exit(1) ;
  745.         case '?' : usage() ;
  746.       }
  747. }
  748.  
  749.  
  750. void
  751. init_setup()            /* Set default values for various options. */
  752. {
  753.   char *c, *ptr ;
  754.   int amp_cnt = 0 ;     /* Number of ampersands in gecos field. */
  755.   int i, j, n, spaces ;
  756.   struct passwd *pp ;
  757.  
  758.   c = getlogin() ;      /* Pointer to users login name. */
  759.   if (c == NULL)        /* Get username from password file */
  760.     {
  761.       pp = getpwuid(geteuid()) ;
  762.       if (pp == NULL) c = "printing" ;
  763.       else c = pp->pw_name ;
  764.     }
  765.   owner = malloc((unsigned) (strlen(c) + 1)) ;
  766.   STRCPY(owner, c) ;
  767.  
  768. /*  Have a look for the users gecos (normally real name), so that its a bit
  769.  *  more recognisable. If this field is too long, then we need to truncate
  770.  *  sensibly. We also need to check a few things. If we've extracted
  771.  *  two "words" or have found a comma, then exit. If an ampersand is
  772.  *  found, this is expanded to the users name in capitals.
  773.  */    
  774.      
  775.   pp = getpwnam(owner) ;
  776.   if (pp != NULL && pp->pw_gecos && pp->pw_gecos[0] != '\0')
  777.     {  
  778.       for (i = 0; i < strlen(pp->pw_gecos); i++)
  779.         if (pp->pw_gecos[i] == '&') amp_cnt++ ;
  780.  
  781.       owner = malloc((unsigned) (strlen(pp->pw_gecos) +
  782.                                  amp_cnt * strlen(c) + 1)) ;
  783.  
  784.       n = spaces = 0 ;
  785.       ptr = pp->pw_gecos ;
  786.       for (i = 0; i < strlen(pp->pw_gecos); i++)
  787.         {
  788.                if (*ptr == ',') break ;
  789.           else if (*ptr == '&')
  790.             {
  791.               for (j = 0; j < strlen(c); j++)
  792.                 if (islower(c[j])) owner[n++] = toupper(c[j]) ;
  793.                 else owner[n++] = c[j] ;
  794.               *ptr++ ;
  795.             }
  796.           else if (*ptr == ' ')
  797.             {
  798.               if (++spaces == 2) break ;
  799.               else owner[n++] = *ptr++ ;
  800.             }
  801.           else owner[n++] = *ptr++ ;
  802.           if (n >= NAMELENGTH) break ;
  803.         }
  804.       if (n > NAMELENGTH) n = NAMELENGTH ;
  805.       owner[n] = '\0' ;
  806.     }
  807.   if ((nameptr = getenv("NAME")) != NULL)
  808.     STRCPY(owner, nameptr) ;
  809.  
  810.   if (text_doc) doc_type = DO_TEXT ;
  811.   switch (doc_type)
  812.     {
  813.       case DO_TEXT : message_for = "Listing for ";
  814.                      digest = FALSE ;
  815.                      break ;
  816.       case DO_MAIL : message_for = digest ? "Mail digest for " : "Mail for " ;
  817.                      break ;
  818.       case DO_NEWS : message_for = digest ? "News digest for " : "News for " ;
  819.                      break ;
  820.     }
  821. }
  822.  
  823.  
  824. usage()     /* Print usage message and exit. */
  825. {
  826.   FPRINTF(stderr,"Usage: %s [-a] [-d] [-f] [-l] [-m] ", progname) ;
  827.   FPRINTF(stderr, "[-o] [-p prologue] [-s subject] [-t] [-v] [-?]\n") ;
  828.   exit(1) ;
  829. }
  830.  
  831. Funky_Stuff
  832. len=`wc -c < misc.c`
  833. if [ $len !=     6170 ] ; then
  834. echo error: misc.c was $len bytes long, should have been     6170
  835. fi
  836. fi # end of overwriting check
  837. if [ -f print.c ]
  838. then
  839. echo shar: will not over-write existing file print.c
  840. else
  841. echo shar: extracting 'print.c',     4128 characters
  842. cat > print.c <<'Funky_Stuff'
  843.  
  844. /*  @(#)print.c 1.8 90/08/29
  845.  *
  846.  *  Copyright (c) Steve Holden and Rich Burridge.
  847.  *                All rights reserved.
  848.  *
  849.  *  Permission is given to distribute these sources, as long as the
  850.  *  copyright messages are not removed, and no monies are exchanged.
  851.  *
  852.  *  No responsibility is taken for any errors inherent either
  853.  *  to the comments or the code of this program, but if reported
  854.  *  to me then an attempt will be made to fix them.
  855.  */
  856.  
  857. #include "mp.h"
  858. #include "extern.h"
  859.  
  860.  
  861. boldshow(hdr, str)      /* Display a header all in bold. */
  862. char *hdr, *str ;
  863. {
  864.   useline() ;
  865.   FPUTS("BoldFont ", stdout) ;
  866.   startline() ;
  867.   expand(hdr) ;
  868.   expand(str) ;
  869.   endline() ;
  870. }
  871.  
  872.  
  873. endcol()
  874. {
  875.   linect = 0 ;
  876.   PRINTF("endcol\n") ;
  877. }
  878.  
  879.  
  880. endfile()
  881. {
  882.   linect = 0 ;
  883.   PRINTF("(%1d) endfile\n", pageno) ;
  884. }
  885.  
  886.  
  887. endline()
  888. {
  889.   PRINTF(") showline\n") ;
  890. }
  891.  
  892.  
  893. endpage()
  894. {
  895.   linect = 0 ;
  896.   PRINTF("(%1d) endpage\n", pageno++) ;
  897. }
  898.  
  899.  
  900. expand(s)   /* Display a string with PostScript-sensitive characters escaped */
  901. char *s ;
  902. {
  903.   for (; s && *s; s++)
  904.     {
  905.       switch (*s)
  906.         {
  907.           case '\\' : FPUTS("\\\\", stdout) ;
  908.                       break ;
  909.           case '('  : FPUTS("\\(", stdout) ;
  910.                       break ;
  911.           case ')'  : FPUTS("\\)", stdout) ;
  912.                       break ;
  913.           case '\b' : PUTC(*s, stdout) ;
  914.                       break ;
  915.           default   : if (isprint(*s)) PUTC(*s, stdout) ;
  916.         }
  917.     }
  918. }
  919.  
  920.  
  921. mixedshow(hdr, str)     /* Display a header in mixed bold/Roman. */
  922. char *hdr, *str ;
  923. {
  924.   useline() ;
  925.   FPUTS("BoldFont ", stdout) ;
  926.   startline() ;
  927.   expand(hdr) ;
  928.   FPUTS(") show pf (", stdout) ;
  929.   expand(str) ;
  930.   endline() ;
  931. }
  932.  
  933.  
  934. psdef(name, def)        /* Do a PostScript define. */
  935. char *name, *def ;
  936. {
  937.   PRINTF("/%s (", name) ;
  938.   expand(def) ;
  939.   PRINTF(") def\n") ;
  940. }
  941.  
  942.  
  943. romanshow(str)          /* Display a header all in Roman. */
  944. char *str ;
  945. {
  946.   useline() ;
  947.   FPUTS("pf ", stdout) ;
  948.   startline() ;
  949.   expand(str) ;
  950.   endline() ;
  951. }
  952.  
  953.  
  954. void
  955. set_defs()               /* Setup PostScript definitions. */
  956. {
  957.   int i ;
  958.  
  959.   if (article == TRUE)
  960.     STRCPY(message_for, "Article from") ;             /* MailFor. */
  961.   psdef("MailFor", message_for) ;
  962.  
  963.   if (article == TRUE && newsgroups != NULL)          /* User. */
  964.     {
  965.       for (i = 0; i < strlen(newsgroups); i++)
  966.         if (newsgroups[i] == ',' ||
  967.             newsgroups[i] == '\0') break ;
  968.       owner = (char *) realloc(owner, (unsigned int) i) ;
  969.       STRNCPY(owner, newsgroups, i) ;
  970.       owner[i] = '\0' ;
  971.     }
  972.   psdef("User", owner) ;
  973.  
  974.   do_date() ;                                         /* TimeNow. */
  975.  
  976.   if (text_doc && cmdfiles) subject = curfname ;
  977.   psdef("Subject",
  978.         (gsubject != NULL) ? gsubject : subject) ;    /* Subject. */
  979. }
  980.  
  981.  
  982. /* Display the PostScript prologue file for mp */
  983.                    
  984. show_prologue(pro)
  985. char *pro ;              /* Prologue file name */
  986. {
  987.   FILE *pf ;
  988.   char buf[MAXLINE], tmpstr[MAXLINE] ;
  989.   int t2 ;               /* Possible extract page or line length. */
  990.  
  991.   if ((pf = fopen(pro, "r")) == NULL)                                
  992.     {
  993.       FPRINTF(stderr,"%s: Prologue file %s not found.\n",progname, pro) ;
  994.       exit(1) ;
  995.     }
  996.   while (fgets(buf, MAXLINE, pf) != NULL)
  997.     {
  998.       FPUTS(buf, stdout) ;
  999.  
  1000. /* Check for new line or page length. */
  1001.  
  1002.       SSCANF(buf, "%s %d", tmpstr, &t2) ;
  1003.       if (strcmp(tmpstr, "%%PageLength") == 0)
  1004.         plen = t2 ;               /* Change the page length. */
  1005.       else if (strcmp(tmpstr, "%%LineLength") == 0)
  1006.         llen = t2 ;               /* Change the line length. */
  1007.     }
  1008.   FCLOSE(pf) ;
  1009. }
  1010.  
  1011.  
  1012. startline()
  1013. {
  1014.   PRINTF("(") ;
  1015. }
  1016.  
  1017.  
  1018. startpage()
  1019. {
  1020.   PRINTF("%%%%Page: ? %1d\n", ++tpn) ;
  1021.   set_defs() ;
  1022. }
  1023.  
  1024.  
  1025. textshow(s)
  1026. char *s ;
  1027. {
  1028.   useline() ;
  1029.   FPUTS("sf ", stdout) ;
  1030.   startline() ;
  1031.   expand(s) ;
  1032.   endline() ;
  1033. }
  1034.  
  1035.  
  1036. useline()   /* Called in order to ready a line for printing. */
  1037. {
  1038.   if (++linect > plen || end_of_page == TRUE)
  1039.     {
  1040.       if (landscape && colct == 0)
  1041.         {
  1042.           colct++ ;
  1043.           endcol() ;
  1044.           return ;
  1045.         }
  1046.       colct = 0 ;
  1047.       endpage() ;
  1048.       linect = 0 ;
  1049.       startpage() ;
  1050.     }
  1051. }
  1052. Funky_Stuff
  1053. len=`wc -c < print.c`
  1054. if [ $len !=     4128 ] ; then
  1055. echo error: print.c was $len bytes long, should have been     4128
  1056. fi
  1057. fi # end of overwriting check
  1058. if [ -f extern.h ]
  1059. then
  1060. echo shar: will not over-write existing file extern.h
  1061. else
  1062. echo shar: extracting 'extern.h',     3458 characters
  1063. cat > extern.h <<'Funky_Stuff'
  1064.  
  1065. /*  @(#)extern.h 1.3 90/08/16
  1066.  *
  1067.  *  Contains all the external definitions used by mp.
  1068.  *
  1069.  *  Copyright (c) Steve Holden and Rich Burridge.
  1070.  *                All rights reserved.
  1071.  *
  1072.  *  Permission is given to distribute these sources, as long as the
  1073.  *  copyright messages are not removed, and no monies are exchanged.
  1074.  *
  1075.  *  No responsibility is taken for any errors or inaccuracies inherent
  1076.  *  either to the comments or the code of this program, but if
  1077.  *  reported to me then an attempt will be made to fix them.
  1078.  */
  1079.  
  1080. extern char *APP_FROMHDR ;
  1081. extern char *APP_TOHDR ;
  1082. extern char *CCHDR ;
  1083. extern char *DATEHDR ;
  1084. extern char *FROMHDR ;
  1085. extern char *FROM_HDR ;          /* UNIX From header */
  1086. extern char *NEWSGROUPSHDR ;
  1087. extern char *REPLYHDR ;
  1088. extern char *SUBJECTHDR ;
  1089. extern char *TOHDR ;
  1090.  
  1091. extern char *apparently_from ;   /* Apparently_from: */
  1092. extern char *apparently_to ;     /* Apparently_to: */
  1093. extern char *cc[] ;              /* Cc: (can have multiple lines) */
  1094. extern char *date ;              /* Date: */
  1095. extern char *from ;              /* From: */
  1096. extern char *from_ ;             /* From_ (UNIX from) */
  1097. extern char *gsubject ;          /* Global Subject set from command line. */
  1098. extern char *newsgroups ;        /* Newsgroups: (news articles only) */
  1099. extern char *reply_to ;          /* Reply-to: */
  1100. extern char *subject ;           /* Subject: (can be set from command line) */
  1101. extern char *to[] ;              /* To: (can have multiple lines) */
  1102.  
  1103. extern char curfname[] ;     /* Current file being printed. */
  1104. extern char *message_for ;   /* "[Mail,News,Listing] for " line */
  1105. extern char *nameptr ;       /* Used to getenv the NAME variable. */
  1106. extern char nextline[] ;     /* Read-ahead of the mail message, minus nl */
  1107. extern char *optarg ;        /* Optional command line argument. */
  1108. extern char *owner ;         /* Name of owner (usually equal to 'to') */
  1109. extern char *progname ;      /* Name of this program. */
  1110. extern char *prologue ;      /* Name of PostScript prologue file. */
  1111. extern char proname[] ;      /* Full pathname of the prologue file. */
  1112.  
  1113. extern int colct ;           /* Column count on current page. */
  1114. extern int cmdfiles ;        /* Set if file to print given on command line. */
  1115. extern int landscape ;       /* Set if in landscape (wide) mode. */
  1116. extern int linect ;          /* Line count on current page. */
  1117. extern int llen ;            /* Number of characters per line. */
  1118. extern int optind ;          /* Optional command line argument indicator. */
  1119. extern int pageno ;          /* Page number within message. */
  1120. extern int plen ;            /* Number of lines per page. */
  1121. extern int tpn ;             /* Total number of pages printed. */
  1122.  
  1123. extern bool article ;        /* Set for news in "Article from " format. */
  1124. extern bool digest ;         /* Are we are printing a mail digest (-d) */
  1125. extern bool filofax ;        /* Set if we are printing a filofax file. */
  1126. extern bool folder ;         /* Set if we are printing a mail folder. */
  1127. extern bool text_doc ;       /* Printing normal text (-o) */
  1128. extern bool timeman ;        /* Set if we are printing a Time Manager file. */
  1129.  
  1130. extern bool end_of_file ;    /* EOF indicator */
  1131. extern bool end_of_line ;    /* Is a newline removed from this line */
  1132. extern bool end_of_page ;    /* end-of-page indicator - ^L on input */
  1133.  
  1134. extern document_type doc_type ;  /* Printing type - default mail */
  1135.  
  1136. extern FILE *fp ;            /* File pointer for current file. */
  1137. Funky_Stuff
  1138. len=`wc -c < extern.h`
  1139. if [ $len !=     3458 ] ; then
  1140. echo error: extern.h was $len bytes long, should have been     3458
  1141. fi
  1142. fi # end of overwriting check
  1143. if [ -f mp.h ]
  1144. then
  1145. echo shar: will not over-write existing file mp.h
  1146. else
  1147. echo shar: extracting 'mp.h',     2437 characters
  1148. cat > mp.h <<'Funky_Stuff'
  1149.  
  1150. /*  @(#)mp.h 1.6 90/08/17
  1151.  *
  1152.  *  Contains all the global definitions used by mp.
  1153.  *
  1154.  *  Copyright (c) Steve Holden and Rich Burridge.
  1155.  *                All rights reserved.
  1156.  *
  1157.  *  Permission is given to distribute these sources, as long as the
  1158.  *  copyright messages are not removed, and no monies are exchanged.
  1159.  *
  1160.  *  No responsibility is taken for any errors or inaccuracies inherent
  1161.  *  either to the comments or the code of this program, but if
  1162.  *  reported to me then an attempt will be made to fix them.
  1163.  */
  1164.  
  1165. #include <stdio.h>
  1166. #include <sys/types.h>
  1167. #include <sys/file.h>
  1168. #include <sys/param.h>
  1169. #include <ctype.h>
  1170. #include <time.h>
  1171. #include <pwd.h>
  1172.  
  1173. #ifdef   SYSV
  1174. #include <sys/pathname.h>
  1175. #include <string.h>
  1176. #endif /*SYSV*/
  1177.  
  1178. #define  FCLOSE       (void) fclose
  1179. #define  FPRINTF      (void) fprintf
  1180. #define  FPUTS        (void) fputs
  1181. #define  PRINTF       (void) printf
  1182. #define  PUTC         (void) putc
  1183. #define  SPRINTF      (void) sprintf
  1184. #define  SSCANF       (void) sscanf
  1185. #define  STRCPY       (void) strcpy
  1186. #define  STRNCPY      (void) strncpy
  1187. #define  UNGETC       (void) ungetc
  1188.  
  1189. /* Configuration constants */
  1190.  
  1191. #ifndef  PROLOGUE            /* PostScript prologue file */
  1192. #define  PROLOGUE     "/usr/local/lib"
  1193. #endif /*PROLOGUE*/
  1194.  
  1195. #define  EQUAL(val)   (!strncmp(val, nextline, strlen(val)))
  1196. #define  INC          argc-- ; argv++ ;
  1197.  
  1198. #ifdef  NOINDEX
  1199. #define  index        strchr
  1200. #endif /*NOINDEX*/
  1201.  
  1202. #define  LINELENGTH   80     /* Number of characters per line. */
  1203.  
  1204. #ifndef  MAXPATHLEN
  1205. #define  MAXPATHLEN   1024
  1206. #endif /*MAXPATHLEN*/
  1207.  
  1208. #define  MAXSIZES     4      /* Maximum number of different sizes. */
  1209.  
  1210. #define  NAMELENGTH   18     /* Maximum allowable real user name. */
  1211. #define  PAGELENGTH   60     /* Number of lines per page. */
  1212. #define  MAXCONT      10     /* Maximum no of continuation header lines */
  1213. #define  MAXLINE      256    /* Maximum string length. */
  1214.  
  1215. #ifndef TRUE
  1216. #define TRUE          1
  1217. #define FALSE         0
  1218. #endif  /*TRUE*/
  1219.  
  1220. typedef enum {DO_MAIL, DO_NEWS, DO_TEXT} document_type ;
  1221. typedef char bool ;
  1222.  
  1223. time_t time() ;
  1224. struct tm *localtime() ;
  1225. bool emptyline() ;
  1226. FILE *fopen() ;
  1227. void exit() ;
  1228. char *asctime(), *getenv(), *getlogin(), *gets(), *index(), *malloc() ;
  1229. char *realloc(), *sprintf(), *strchr(), *strcpy(), *strncpy() ;
  1230.  
  1231. void do_date(), get_header(), get_mult_hdr(), init_setup() ;
  1232. void parse_headers(), readline(), reset_headers(), set_defs() ;
  1233. void show_headers(), show_mult_hdr() ;
  1234. Funky_Stuff
  1235. len=`wc -c < mp.h`
  1236. if [ $len !=     2437 ] ; then
  1237. echo error: mp.h was $len bytes long, should have been     2437
  1238. fi
  1239. fi # end of overwriting check
  1240. if [ -f patchlevel.h ]
  1241. then
  1242. echo shar: will not over-write existing file patchlevel.h
  1243. else
  1244. echo shar: extracting 'patchlevel.h',      558 characters
  1245. cat > patchlevel.h <<'Funky_Stuff'
  1246.  
  1247. /*  @(#)patchlevel.h 1.12 90/08/29
  1248.  *
  1249.  *  This is the current patch level for this version of mp.
  1250.  *
  1251.  *  Copyright (c) Steve Holden and Rich Burridge.
  1252.  *                All rights reserved.
  1253.  *
  1254.  *  Permission is given to distribute these sources, as long as the
  1255.  *  copyright messages are not removed, and no monies are exchanged.
  1256.  *
  1257.  *  No responsibility is taken for any errors or inaccuracies inherent
  1258.  *  either to the comments or the code of this program, but if
  1259.  *  reported to me then an attempt will be made to fix them.
  1260.  */
  1261.  
  1262. #define  PATCHLEVEL  5
  1263. Funky_Stuff
  1264. len=`wc -c < patchlevel.h`
  1265. if [ $len !=      558 ] ; then
  1266. echo error: patchlevel.h was $len bytes long, should have been      558
  1267. fi
  1268. fi # end of overwriting check
  1269. if [ -f README ]
  1270. then
  1271. echo shar: will not over-write existing file README
  1272. else
  1273. echo shar: extracting 'README',     4181 characters
  1274. cat > README <<'Funky_Stuff'
  1275.  
  1276. README for mp, the PostScript pretty printer.
  1277.  
  1278. Version 2.4 April 1990.
  1279.  
  1280. Permission is given to distribute these sources, as long as the
  1281. copyright messages are not removed, and no monies are exchanged.
  1282.  
  1283. --------------------------------------------------------------------------
  1284. CONTENTS:
  1285.  
  1286. 1. What is mp?
  1287. 2. Getting started.
  1288. 3. Acknowledgements.
  1289. --------------------------------------------------------------------------
  1290.  
  1291.  
  1292. 1. What is mp?
  1293. --------------
  1294.  
  1295. The mp program will pretty print various files for you. It can be used
  1296. in conjunction with a mail reading utility for producing a pretty print
  1297. of your mail items. It can be used with a news reading tool to pretty
  1298. print news articles. Digests can also be printed, and this version can
  1299. pretty print ordinary ASCII files as well. Support for personal organiser
  1300. printing was added into the last released version.
  1301.  
  1302. This version introduces a landscape mode for mp, to allow you to print
  1303. two "pages" per page. This should all help us save some trees.
  1304.  
  1305. It uses a PostScript prologue file which normally resides in
  1306. /usr/local/lib, but this can be overwritten by use of the -p option.
  1307.  
  1308. See the manual pages for more details on these various options.
  1309.  
  1310.  
  1311. 2. Getting started.
  1312. -------------------
  1313.  
  1314. Initially there is no Makefile file present in the mp source directory.
  1315. You will need to copy Makefile.dist to Makefile, then adjust accordingly.
  1316.  
  1317. The Makefile compilation details are setup to default to compiling on a Sun4
  1318. running SunOS v4.1. Note that there are various compilation definitions that
  1319. might need uncommenting if you are trying to compile and run it on other
  1320. machines or operating systems.
  1321.  
  1322. These are:
  1323.  
  1324. PROLOGUE - Location of the mp prologue file (default: /usr/local/lib)
  1325. NOINDEX  - uncomment if you don't have the index() function.
  1326.  
  1327. See the Makefile for a detailed description of each of these definitions.
  1328.  
  1329. Once you are happy with these settings, then you should do a "make" followed
  1330. by a "make install" which will compile the mp program and put the files in
  1331. their default locations. You will probably have to be super-user when you do
  1332. the "make install"
  1333.  
  1334.  
  1335. 3. Acknowledgements.
  1336. --------------------
  1337.  
  1338. The original version of mp was written by Steve Holden in the ICON language,
  1339. when Steve worked for Sun Microsystems UK. I converted it to the C language
  1340. and added a few features. Bruno Pillard of Chorus Systemes, France added
  1341. support for MH mail and news article printing, plus a shell script (mailp)
  1342. which tidies up the user interface to mp. Dave Glowacki of Public Works
  1343. Computer Services, St Paul, MN. added the ability to print digests and
  1344. tidied up some of the other options. Rick Rodgers, UCSF School of Pharmacy,
  1345. San Francicso revised the initial version of the mp manual page. Doug
  1346. Buchanan added support for printing in filofax and Time Manager format.
  1347. Many thanks go to Jerermy Webber, Computer Science Department of the
  1348. University of Adelaide who rewrote the message parsing and option code and
  1349. made substantial improvements to the programs user friendliness and
  1350. robustness. Sam Manogharan added support for printing multiple files
  1351. specified on the command line, and subject line filename print for ordinary
  1352. files. The landscape mode was written by Michael Tuchiarone.
  1353.  
  1354. Thanks go also to Bill Shannon, Roger De Salis, L. Jill Debord, Frederick
  1355. Avolio, Mark Prior, Stephen Frede, Craig Bishop, Jimmy Aitken, Hugues Leroy,
  1356. Bertrand Decouty, David Fiedler, Scott A. Jordahl, David Boone, Steve Cliffe,
  1357. Maureen Chew, Brian Kohn, Walter Underwood, Mike Khaw, Rick Gunderson, Johan
  1358. Vromans, Brachet, Pierre Mareschal, Roger Riggs, Larry Tsui and Mike
  1359. Bundschuh for bug reports and/or bug fixes plus enhancements.
  1360.  
  1361. My thanks also goes to Glenn Reid from Adobe Systems for the backspacefont.ps
  1362. code used in the prologue files. I'm grateful to all these people, plus
  1363. everybody who has suggested enhancements, and fixed bugs in the previous
  1364. versions.
  1365.  
  1366. ----------------------------------------------------------------------------
  1367.  
  1368. Suggestions for further improvement would be most welcome, plus bug reports
  1369. and comments.
  1370.  
  1371. Rich Burridge,          DOMAIN: richb@Aus.Sun.COM
  1372. PHONE: +61 2 413 2666   ACSnet: richb@sunaus.sun.oz.au
  1373. Funky_Stuff
  1374. len=`wc -c < README`
  1375. if [ $len !=     4181 ] ; then
  1376. echo error: README was $len bytes long, should have been     4181
  1377. fi
  1378. fi # end of overwriting check
  1379. if [ -f MANIFEST ]
  1380. then
  1381. echo shar: will not over-write existing file MANIFEST
  1382. else
  1383. echo shar: extracting 'MANIFEST',     1374 characters
  1384. cat > MANIFEST <<'Funky_Stuff'
  1385. This file tells you in which part of the mp distribution each
  1386. file appeared.
  1387.  
  1388. Filename.                              |  Part #
  1389. --------------------------------------------------
  1390. header.c                               |    1
  1391. io.c                                   |    1
  1392. main.c                                 |    1
  1393. misc.c                                 |    1
  1394. print.c                                |    1
  1395. extern.h                               |    1
  1396. mp.h                                   |    1
  1397. patchlevel.h                           |    1
  1398. README                                 |    1
  1399. Makefile.dist                          |    2
  1400. mailp                                  |    2
  1401. mp.1                                   |    2
  1402. MANIFEST                               |    1
  1403. FILES                                  |    1
  1404. CHANGES                                |    1
  1405. TODO                                   |    1
  1406. mp.el                                  |    2
  1407. mp.pro.ps                              |    2
  1408. mp.pro.alt.ps                          |    2
  1409. mp.pro.filofax.ps                      |    2
  1410. mp.pro.timeman.ps                      |    2
  1411. Data/Mail                              |    2
  1412. Data/MailFolder                        |    2
  1413. Data/NewsArticle1                      |    2
  1414. Data/NewsArticle2                      |    2
  1415. Data/NewsDigest                        |    2
  1416. Funky_Stuff
  1417. len=`wc -c < MANIFEST`
  1418. if [ $len !=     1374 ] ; then
  1419. echo error: MANIFEST was $len bytes long, should have been     1374
  1420. fi
  1421. fi # end of overwriting check
  1422. if [ -f FILES ]
  1423. then
  1424. echo shar: will not over-write existing file FILES
  1425. else
  1426. echo shar: extracting 'FILES',     1795 characters
  1427. cat > FILES <<'Funky_Stuff'
  1428. This file describes all the files that make up the mp distribution.
  1429.  
  1430. Directory mp: the pretty printer for mail, news articles and text files.
  1431. ------------------------------------------------------------------------
  1432.  
  1433. header.c            - mail and news header manipulation routines.
  1434. io.c                - input/output routines for mp.
  1435. main.c              - includes variable declarations and main().
  1436. misc.c              - miscelaneous routines used by mp.
  1437. print.c             - PostScript printing routines.
  1438.  
  1439. extern.h            - External declaractions.
  1440. mp.h                - Macro and constant definitions.
  1441. patchlevel.h        - Current patchlevel for this release of mp.
  1442.  
  1443. README              - describes what mp is, and how to get started.
  1444. Makefile.dist       - Master Makefile used to build mp on Unix systems.
  1445. mailp               - a shell script frontend for running mp.
  1446. mp.1                - the mp manual page (troff/nroff -man format).
  1447. MANIFEST            - tells you what archive part each file was posted in.
  1448. FILES               - what you're reading now.
  1449. CHANGES             - change history. Will be updated with each new patch.
  1450. TODO                - bugs and suggested enhancements. Volunteers?
  1451. mp.el               - emacs code to print with mp.
  1452. mp.pro.ps           - standard mp prologue file.
  1453. mp.pro.alt.ps       - alternative mp prologue file.
  1454. mp.pro.filofax.ps   - mp Filofax prologue file.
  1455. mp.pro.timeman.ps   - mp Time Manager prologue file.
  1456.  
  1457. Sub-directory Data: test data files for new versions of mp.
  1458. -----------------------------------------------------------
  1459. Data/Mail           - a mail article.
  1460. Data/MailFolder     - a simple mail folder.
  1461. Data/NewsArticle1   - a news article.
  1462. Data/NewsArticle2   - another news article.
  1463. Data/NewsDigest     - a digest of news articles.
  1464. Funky_Stuff
  1465. len=`wc -c < FILES`
  1466. if [ $len !=     1795 ] ; then
  1467. echo error: FILES was $len bytes long, should have been     1795
  1468. fi
  1469. fi # end of overwriting check
  1470. if [ -f CHANGES ]
  1471. then
  1472. echo shar: will not over-write existing file CHANGES
  1473. else
  1474. echo shar: extracting 'CHANGES',     5174 characters
  1475. cat > CHANGES <<'Funky_Stuff'
  1476.  
  1477. Mp change history.
  1478. ------------------
  1479.  
  1480. v2.3 - patchlevel 1. - Released to comp.sources.misc (January 1990).
  1481.  
  1482. v2.3 - patchlevel 2. - Posted to comp.sources.bugs (January 1990).
  1483.  
  1484.   Changes:
  1485.  
  1486.     *  From Steve Cliffe <steve@wolfen.cc.uow.oz> 
  1487.        The Makefile used a technique for generating the object files, 
  1488.        from the source files, that not every make has. 
  1489.   
  1490.     *  From Steve Cliffe <steve@wolfen.cc.uow.oz> 
  1491.        Mp used both the index and strchr library calls. It now uses 
  1492.        index by default, and if you don't have this, then you need 
  1493.        to uncomment a macro definition NOINDEX in the Makefile (which 
  1494.        has just been added). 
  1495.  
  1496.     *  From Brian Kohn <bicker@hoqax.att.com> 
  1497.        The variable MAXPATHLEN is not declared on all machines. An 
  1498.        appropriate definition has been added to the mp.h file. 
  1499.  
  1500. New files:
  1501.  
  1502.     *   CHANGES - documented history of the changes made with each new
  1503.                   mp patch.
  1504.  
  1505. v2.3 - patchlevel 3. - Posted to comp.sources.bugs (January 1990).
  1506.  
  1507.     *  The Makefile did not include the CHANGES file in the OTHERS
  1508.        macro definition.
  1509.  
  1510.     *  From Steve Cliffe <steve@wolfen.cc.uow.oz>
  1511.        The new Makefile definition NOINDEX, needs to be included in
  1512.        the CFLAGS definition.
  1513.  
  1514.     *  From Walter Underwood <wunder@hp-ses.sde.hp.com>
  1515.        Several tweaks to the mp man page to correct print on Sys V
  1516.        machines.
  1517.  
  1518. v2.3 - patchlevel 4. - Posted to comp.sources.bugs (January 1990).
  1519.  
  1520.     *  From Mike Khaw <khaw@parcplace.com>
  1521.        The definition for NOINDEX in mp.h should be embedded in an
  1522.        #ifdef not an #ifndef. Arrgghh!!
  1523.  
  1524.     *  The CHANGES file is now upto date.
  1525.  
  1526.     *  From Johan Vromans <jv@mh.nl> 
  1527.        An attempt to initialise the cc array in main.c when the variable
  1528.        is declared doesn't work with the GNU C compiler. This has been
  1529.        removed.
  1530.  
  1531. v2.3 - patchlevel 5. - Posted to comp.sources.bugs (February 1990).
  1532.  
  1533.     *  From Johan Vromans <jv@mh.nl>
  1534.        From Rick Gunderson <rickg@toshiba.tic.oz.au>
  1535.        Storage allocation for string constants is different with cc and
  1536.        the GNU C compiler (gcc). Two adjustments in print.c are needed.
  1537.  
  1538.  
  1539. v2.4 - patchlevel 0. - Started (april 1990).
  1540.  
  1541.     *  From Michael J. Tuciarone <tooch@plan9.Sun.COM>
  1542.        Support for landscape mode. This allows two pages printed per
  1543.        sheet of paper.
  1544.  
  1545.  
  1546. v2.4 - patchlevel 1. - 1st June 1990.
  1547.  
  1548.     *  From Brachet <brachet@imag.fr>
  1549.        Fix for segmentation violation core dump on a System V machine
  1550.        when trying to print multiple news articles.
  1551.  
  1552.     *  From Brachet <brachet@imag.fr>
  1553.        mp took only the first subject of a group of news articles
  1554.        because it didn't parse the subject line properly.
  1555.  
  1556. v2.4 - patchlevel 2. - 14th August 1990. 
  1557.  
  1558.     *  From Pierre Mareschal <pmaresch@hawk.ulowell.edu> 
  1559.  
  1560.        - Fix for multiple mail printing:
  1561.              % mp [-a] file1 file2 file3 ... > mp.out 
  1562.              * Outputs the Prolog only once at the beginning of the file. 
  1563.              * Gives a correct page count at the end of the PostScript file 
  1564.                in the Trailer 
  1565.              * Shorten PostScript output (by more than 10%): 
  1566.                       PrimaryFont -> pf 
  1567.                       SecondaryFont -> sf 
  1568.              * Correct global subject line with -s "Subject" flag. 
  1569.              * Correct current subject line when multiple articles. 
  1570.  
  1571.        - Added another style for mp.pro.ps with the page number in lower
  1572.          right corner. This file has been called mp.pro.alt.ps.
  1573.  
  1574.        - Added Example directory (called Data) with the mp distribution. This
  1575.          contains examples for Mail, Mail Folders, News Articles, News Digests
  1576.          and a plain listing.
  1577.  
  1578.     *  Added a TODO file, with a list of the outstanding problems and
  1579.        suggested enhancements.
  1580.  
  1581.     *  Added MANIFEST and FILES files, to provide a manifest of the
  1582.        distributed files, plus a description of what each file does.
  1583.  
  1584.     *  From Roger Riggs <riggs@suneast.East.Sun.COM>
  1585.        Created emacs functions for printing with mp. A new file (mp.el) has
  1586.        been created.
  1587.  
  1588. v2.4 - patchlevel 3. - 17th August 1990.
  1589.  
  1590.     *  From Larry Tsui <larryt@Canada.Sun.COM>
  1591.        With mp -o filename | lpr, the filename printed on the bottom bar
  1592.        is missing the first character. The subject string setup at the end
  1593.        of set_defs was incorrect.
  1594.  
  1595.     *  Gave mp a though linting (Sun 4/65 - SunOS v4.1).
  1596.  
  1597. v2.4 - patchlevel 4. - 27th August 1990.
  1598.  
  1599.     *  From Mike Bundschuh <mjb@Eng.Sun.COM>
  1600.        Added quick fix to expand() in print.c to check if pointer == NULL
  1601.  
  1602. v2.4 - patchlevel 5. - 29th August 1990.
  1603.  
  1604.     *  From Larry W. Virden <lwv27%cas.BITNET@CUNYVM.CUNY.Edu>
  1605.        Include a Makefile.dist with the mp distribution. This file will
  1606.        need to be copied to Makefile and adjusted accordingly, but it does
  1607.        mean that future changes via patches don't clash with custom user
  1608.        changes. The README file has been updated to mention this.
  1609.  
  1610.     *  From Lupe Christoph <lupe@alanya.Germany.Sun.COM>
  1611.        mp.pro.filofax.ps and mp.pro.timeman.ps still contained definitions
  1612.        for PrimaryFont and SecondaryFont.
  1613. Funky_Stuff
  1614. len=`wc -c < CHANGES`
  1615. if [ $len !=     5174 ] ; then
  1616. echo error: CHANGES was $len bytes long, should have been     5174
  1617. fi
  1618. fi # end of overwriting check
  1619. if [ -f TODO ]
  1620. then
  1621. echo shar: will not over-write existing file TODO
  1622. else
  1623. echo shar: extracting 'TODO',     2508 characters
  1624. cat > TODO <<'Funky_Stuff'
  1625. 1/ From Larry W. Virden <lwv27%cas.BITNET@CUNYVM.CUNY.Edu>
  1626.    Is there any thought of adding support within mp's newsp program to
  1627.    print more of the news article header?  My dream would be to be able
  1628.    to tell newsp (via a .newsprc perhaps?) a set of headers to print using
  1629.    the same syntax as rn - or even having newsp USE my .rnrc file .
  1630.  
  1631. 2/ From Michael J. Tuciarone <tooch@plan9.Sun.COM>
  1632.    The ability to better handle different page sizes depending perhaps on a
  1633.    command line options, or an environment variable, or a LOCALE setting or ...
  1634.  
  1635. 3/ From Michael J. Tuciarone <tooch@plan9.Sun.COM>
  1636.    NeWS/OpenWindows does not implement the CharStrings dictionary.
  1637.    Therefore /backspacefont doesn't work correctly. Need to generate a
  1638.    NeWS/OW compatible version of CourierBack.
  1639.  
  1640. 4/ From Andy Hall <andyh@ncduk.com>
  1641.    Running on a Sparcstation 1+ and with a Canon LBP8 mark 3 printer with
  1642.    PS-1 Scriptcard. This is a true version 51.4 Adobe Interpreter. If I print
  1643.    Unix manual pages using standard Nroff output and the mp.pro.ps v1.2
  1644.    prologue the job gets aborted after a few pages with a stackoverflow
  1645.    message on the serial output (I am using serial interface).  After a bit
  1646.    of investigation using a small C program to produce lines consisting only
  1647.    of a printed line number, a printable character, a backspace, an underscore
  1648.    and a newline, it appears that the job gets aborted on the page where the
  1649.    500th backspace is. I am not a PostScript expert but I am wondering whether
  1650.    the problem lies with the embedded piece of code backspacefont.ps or the way
  1651.    it is used. It is rather too convoluted for me to understand fully but my
  1652.    suspicions are aroused in that the default operand stack size mentioned by
  1653.    Adobe in their red book is 500.
  1654.  
  1655. 5/ From Larry W. Virden <lwv27%cas.BITNET@CUNYVM.CUNY.Edu>
  1656.    Instead of having the lpr going to -Plw in the shell script, have it
  1657.    go to -P$(PRINTER:lw} ... so folks who use the PRINTER variable get it.
  1658.  
  1659. 6/ From Lupe Christoph <lupe@alanya.Germany.Sun.COM>
  1660.    There are so many personal organisers all over the world that you need a
  1661.    more general scheme. What about a flag that takes the name of the personal
  1662.    organisers and sticks it in the mp.pro.%s.ps string ?
  1663.  
  1664.    Of course you need at least a short writeup on how to create these.
  1665.    Better, a short program that takes a general mp.pro.organiser.ps and
  1666.    substitutes a few variables. Or you can use short PostScript fragments,
  1667.    one for each personal organisers.
  1668. Funky_Stuff
  1669. len=`wc -c < TODO`
  1670. if [ $len !=     2508 ] ; then
  1671. echo error: TODO was $len bytes long, should have been     2508
  1672. fi
  1673. fi # end of overwriting check
  1674.  
  1675.