home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume15 / mp < prev    next >
Text File  |  1988-05-25  |  15KB  |  574 lines

  1. Path: uunet!munnari!sources-request
  2. From: sources-request@munnari.oz
  3. Newsgroups: comp.sources.unix
  4. Subject: v15i012:  mp - mail pretty printer v1.4 (aka mail->postscript), Part01/01
  5. Keywords: PostScript.
  6. Message-ID: <2148@munnari.oz>
  7. Date: 26 May 88 19:23:41 GMT
  8. Sender: kre@munnari.oz
  9. Lines: 562
  10. Approved: kre@munnari.oz.au
  11.  
  12. Submitted by: richb@sunaus.oz (Rich Burridge)
  13. Posting-number: Volume 15, Issue 12
  14. Archive-name: mp/Part01
  15.  
  16.  
  17.  
  18. The mp program is used in conjunction with the print option
  19. of your mail program. It generates a PostScript output file,
  20. which is a pretty printed version of your mail message. It
  21. has been tested on a Sun using /usr/ucb/mail and the window-
  22. based mailtool program. With little or no modification, it
  23. should be possible to make this work with other mailers.
  24.  
  25. See the README file for more details.
  26.  
  27.     Rich.
  28.  
  29. ------CUT HERE------CUT HERE------
  30. #! /bin/sh
  31. # this is a shell archive, meaning:
  32. # 1. Remove everything above the #! /bin/sh line
  33. # 2. Save the resulting text in a file.
  34. # 3. Execute the file with /bin/sh to create the files:
  35. #    README
  36. #    Makefile
  37. #    mp.c
  38. #    mp.pro.ps
  39. #    mp.1
  40. # This archive created: Wed May 25 12:00:29 EST 1988
  41. #
  42. #
  43. export PATH; PATH=/bin:$PATH
  44. #
  45. if [ -f README ]
  46. then
  47. echo shar: will not over-write existing file README
  48. else
  49. echo shar: extracting 'README',     1531 characters
  50. cat > README <<'Funky_Stuff'
  51.  
  52.   mp README v1.4    3/3/87
  53.   ------------------------
  54.  
  55. The mp program is to be used in conjunction with mailtool or mail for
  56. producing a pretty print of your mail items. It uses a PostScript
  57. prologue file which normally resides in /usr/local, but this can be
  58. overwritten by use of the -p option.
  59.  
  60. Do a "make" followed by a "make install" which will compile the mp program
  61. and put the files in their default locations. You will probably have to
  62. be super-user when you do the "make install"
  63.  
  64. This version of mp, which has been rewritten from the original by Steve
  65. Holden (Sun UK) in the ICON language, to C. 
  66.  
  67. It is designed to be used in conjunction with the print button in the
  68. mailtool program, or the 'pipe' command from withing mail.
  69.  
  70. Add (or alter) the following two lines in your .mailrc file:
  71.  
  72. set printmail='mp | lpr'
  73. set cmd="mp | lpr &"
  74.  
  75. Source your .mailrc file again, and you are ready. This has been tested
  76. with a LaserWriter with an A4 paper tray, running Transcript v2.0. Please
  77. let us know if this requires any modification to run in the US.
  78.  
  79. Any problems, suggestions, bugs or flames to me or Steve please.
  80.  
  81. Rich Burridge                             Steve Holden
  82. Sun Microsystems                          Sun Microsystems,
  83. 49/53 Hotham Parade,                      Lord Street,
  84. Sydney, N.S.W. 2164,                      Cheshire, SK1 3ND,
  85. AUSTRALIA.                                ENGLAND.
  86.  
  87. sun!sunaus!richb                          sun!sunuk!nuksun!steve
  88. rburridge@Sun.COM                         sholden@Sun.COM
  89. Funky_Stuff
  90. len=`wc -c < README`
  91. if [ $len !=     1531 ] ; then
  92. echo error: README was $len bytes long, should have been     1531
  93. fi
  94. fi # end of overwriting check
  95. if [ -f Makefile ]
  96. then
  97. echo shar: will not over-write existing file Makefile
  98. else
  99. echo shar: extracting 'Makefile',      539 characters
  100. cat > Makefile <<'Funky_Stuff'
  101. #
  102. #  mp distribtution source makefile    steve holden
  103. #  C version by Rich Burridge.
  104. #
  105. #  @(#)Makefile    1.4  3/3/88.
  106. #
  107.  
  108. FILES   = README Makefile mp.c mp.pro.ps mp.1
  109. CFLAGS  = -g
  110. TAPE    = /dev/rst0
  111.  
  112. mp:     mp.c
  113.     cc $(CFLAGS) -o mp mp.c
  114.  
  115. install:
  116.     install mp /usr/local/bin
  117.     cp mp.pro.ps /usr/local
  118.  
  119. backup:
  120.     cp mp.c mp.c~
  121.     cp mp.pro.ps mp.pro.ps~
  122.  
  123. lint:
  124.     lint mp.c
  125.  
  126. shar:
  127.     shar.script $(FILES) > archive
  128.  
  129. clean:
  130.     rm -f mp
  131.  
  132. distribution:
  133.     -mt -f $(TAPE) rewind
  134.     tar cvbf 126 $(TAPE) $(FILES)
  135. purge:
  136.     -rm -f *.c *.ps mp.1 testmail Makefile
  137. Funky_Stuff
  138. len=`wc -c < Makefile`
  139. if [ $len !=      539 ] ; then
  140. echo error: Makefile was $len bytes long, should have been      539
  141. fi
  142. fi # end of overwriting check
  143. if [ -f mp.c ]
  144. then
  145. echo shar: will not over-write existing file mp.c
  146. else
  147. echo shar: extracting 'mp.c',     7190 characters
  148. cat > mp.c <<'Funky_Stuff'
  149.  
  150. /*  mp.c - take a mail file and format each line for the LaserWriter.
  151.  *
  152.  *         Original written in the Icon language by Steve Holden - Sun UK.
  153.  *         Converted to C and modified by Rich Burridge - Sun Australia.
  154.  *
  155.  *         v1.4   3 March 1988.
  156.  */
  157.  
  158. #include <stdio.h>
  159. #include <sys/types.h>
  160. #include <sys/file.h>
  161. #include <string.h>
  162. #include <time.h>
  163.  
  164. #define  PATCHLEVEL   2
  165.  
  166. #define  FPRINTF      (void) fprintf    /* To make lint happy. */
  167. #define  PRINTF       (void) printf
  168. #define  SPRINTF      (void) sprintf
  169. #define  SSCANF       (void) sscanf
  170. #define  STRCPY       (void) strcpy
  171. #define  STRNCPY      (void) strncpy
  172.  
  173. /* States for the mail processing automation. */
  174. #define  FROMLINE     0      /* Searching for the initial From line. */
  175. #define  DOHEADER     1      /* Processing rest of message header. */
  176. #define  DOMESSAGE    2      /* Processing text in message body. */
  177.  
  178. #define  EQUAL(val)   !strncmp(val,nextline,strlen(val))
  179. #define  LINELENGTH   80     /* Number of characters per line. */
  180. #define  MAXLINE      256     /* Length of character strings. */
  181. #define  PAGELENGTH   60     /* Number of lines per page. */
  182.  
  183. time_t time() ;
  184. struct tm *localtime() ;
  185. char *asctime(), *getlogin(), *gets() ;
  186. char subject[MAXLINE] ;    /* Subject line for this message. */
  187. FILE *fopen(), *pf ;
  188.  
  189. int lindex ;             /* Index pointer to nextline. */
  190. int linect = 0 ;         /* Line count on current page. */
  191. int maybe_more = 0 ;     /* Message header continuation line indicator. */
  192. int non_space ;          /* Indicates if nextline has a non-space char. */
  193. int pn = 1 ;             /* Page number within message. */
  194. int removednl ;          /* Set if a newline was removed from this line. */
  195.  
  196.  
  197. /*ARGSUSED*/
  198. main(argc,argv)
  199. int argc ;
  200. char **argv ;
  201. {
  202.   char **args ;
  203.   char nextline[MAXLINE] ;   /* Next line of the mail message. */
  204.   char prologue[MAXLINE] ;   /* Name of PostScript prologue file. */
  205.   char username[MAXLINE] ;   /* The username of the mail file owner. */
  206.   int state ;                /* State of message processing automation. */
  207.   long clock ;               /* Used by the localtime function call. */
  208.   struct tm *tm ;            /* Used by the localtime and asctime calls. */
  209.  
  210.   char *progname = *argv ;                    /* This programs name. */
  211.   STRCPY(prologue, "/usr/local/mp.pro.ps") ;  /* Set up default values. */
  212.   STRCPY(username, getlogin()) ;
  213.  
  214.   if (argv)
  215.     {
  216.       for (args = ++argv; *args; args++)
  217.         if (strcmp(*args, "-p") == 0)
  218.           {
  219.             if (*(args+1) == NULL) prologue[0] = '\0' ;
  220.             else STRCPY(prologue, *(args+1)) ;
  221.             args++ ;
  222.             if (!strlen(prologue))
  223.               {
  224.                 FPRINTF(stderr,"%s: -p needs prologue name as next argument.\n",progname) ;
  225.                 exit(1) ;
  226.               }
  227.           }
  228.         else
  229.           {
  230.             FPRINTF(stderr,"%s: Unknown option %s\n",progname,*args) ;
  231.             exit(1) ;
  232.           }
  233.     }
  234.  
  235.   if ((pf = fopen(prologue, "r")) == NULL)
  236.     {
  237.       FPRINTF(stderr,"%s: Prologue file not found.\n",progname) ;
  238.       exit(1) ;
  239.     } 
  240.   while (fgets(nextline,MAXLINE,pf) != NULL) PRINTF("%s",nextline) ;
  241.  
  242.   defwrite("loginname",username) ;
  243.   clock = time((time_t *) 0) ;
  244.   tm = localtime(&clock) ;
  245.   defwrite("timenow",asctime(tm)) ;
  246.   PRINTF("%%%%EndProlog\n") ;
  247.  
  248.   state = FROMLINE ;
  249.   startpage() ;
  250.   while (fgets(nextline,LINELENGTH+1,stdin) != NULL)
  251.     {
  252.       removednl = 0 ;
  253.       if (nextline[strlen(nextline)-1] == '\n')
  254.         {
  255.           removednl = 1 ;
  256.           nextline[strlen(nextline)-1] = '\0' ;
  257.         }
  258.       non_space = 0 ;
  259.       for (lindex = 0; lindex < strlen(nextline); lindex++)
  260.         if (nextline[lindex] != ' ')
  261.           {
  262.             non_space = 1 ;
  263.             break ;
  264.           }
  265.       switch (state)
  266.         {
  267.           case FROMLINE  : if (EQUAL("From"))
  268.                              {
  269.                                boldshow(nextline) ;
  270.                                state = DOHEADER ;
  271.                              }
  272.                            break ;
  273.           case DOHEADER  : if (EQUAL("From") || EQUAL("Date") || EQUAL("Subject"))
  274.                              {
  275.                                mixedshow(nextline) ;
  276.                                maybe_more = 0 ;
  277.                              }
  278.                            else if (EQUAL("To") || EQUAL("Cc"))
  279.                              {
  280.                                mixedshow(nextline) ;
  281.                                maybe_more = 1 ;
  282.                              }
  283.                            else if (EQUAL(" ") && non_space && maybe_more)
  284.                              textshow(nextline) ;
  285.                            else if ((EQUAL(" ") && (!non_space)) || (!strlen(nextline)))
  286.                              {
  287.                                state = DOMESSAGE ;
  288.                                PRINTF("Courier\n") ;
  289.                                PRINTF("() showline\n") ;
  290.                              }
  291.                            else maybe_more = 0 ;
  292.                            break ;
  293.           case DOMESSAGE : textshow(nextline) ;
  294.         }
  295.     }
  296.   endpage() ;
  297.   PRINTF("%%%%Trailer\n") ;
  298.   PRINTF("%%%%Pages: %1d\n",pn) ;
  299. }
  300.  
  301.  
  302. boldshow(s)
  303. char *s ;
  304. {
  305.   useline() ;
  306.   PRINTF("Bold ") ;
  307.   startline() ;
  308.   expand(s) ;
  309.   endline() ;
  310. }
  311.  
  312.  
  313. mixedshow(s)
  314. char *s ;
  315. {
  316.   char first[MAXLINE] ;
  317.  
  318.   useline() ;
  319.   SSCANF(s,"%s",first) ;
  320.   PRINTF("Bold (%s) show Roman (",first) ;
  321.   expand(&s[strlen(first)]) ;
  322.   endline() ;
  323.   if (!strcmp("Subject:",first))
  324.     {
  325.       PRINTF("/subject (") ;
  326.       expand(&s[strlen(first)]) ;
  327.       STRCPY(subject,&s[strlen(first)]) ;
  328.       PRINTF(") def\n") ;
  329.     }
  330. }
  331.  
  332.  
  333. textshow(s)
  334. char *s ;
  335. {
  336.   if (*s == '\014')
  337.     {
  338.       if (removednl)        /* Is this the bogus formfeed at the end? */
  339.         {
  340.           linect = PAGELENGTH ;
  341.           useline() ;
  342.         }
  343.       return ;
  344.     }
  345.   useline() ;
  346.   startline() ;
  347.   expand(s) ;
  348.   endline() ;
  349. }
  350.  
  351.  
  352. expand(s)
  353. char *s ;
  354. {
  355.   int i,j,n ;
  356.  
  357.   n = 0 ;
  358.   for (i = 0; i < strlen(s); i++)
  359.     {
  360.       switch (s[i])
  361.         {
  362.           case '\\'   : PRINTF("\\\\") ;
  363.                         n++ ;
  364.                         break ;
  365.           case '('    : PRINTF("\\(") ;
  366.                         n++ ;
  367.                         break ;
  368.           case ')'    : PRINTF("\\)") ;
  369.                         n++ ;
  370.                         break ;
  371.           case '\t'   : for (j = 0; j < (8 - (n % 8)); j++)
  372.                         PRINTF(" ") ;
  373.                         n = n + 8 - (n % 8) ;
  374.                         break ;
  375.           default     : PRINTF("%c",s[i]) ;
  376.                         n++ ;
  377.         }
  378.       if (!(i % LINELENGTH) && i)
  379.         {
  380.           endline() ;
  381.           startline() ;
  382.         }
  383.     }
  384. }
  385.  
  386.  
  387. useline()
  388. {
  389.   if (++linect > PAGELENGTH)
  390.     {
  391.       endpage() ;
  392.       startpage() ;
  393.       PRINTF("/subject (") ;
  394.       expand(subject) ;
  395.       PRINTF(") def\n") ;
  396.     }
  397. }
  398.  
  399.  
  400. startline()
  401. {
  402.   PRINTF("(") ;
  403. }
  404.  
  405.  
  406. startpage()
  407. {
  408.   PRINTF("%%%%Page: ? %1d\n",pn) ;
  409. }
  410.  
  411.  
  412. endline()
  413. {
  414.   PRINTF(") showline\n") ;
  415. }
  416.  
  417.  
  418. endpage()
  419. {
  420.   linect = 0 ;
  421.   PRINTF("(%1d) endpage\n",pn++) ;
  422. }
  423.  
  424.  
  425. defwrite(name,def)
  426. char *name, *def ;
  427. {
  428.   PRINTF("/%s (%s) def\n",name,def) ;
  429. }
  430. Funky_Stuff
  431. len=`wc -c < mp.c`
  432. if [ $len !=     7190 ] ; then
  433. echo error: mp.c was $len bytes long, should have been     7190
  434. fi
  435. fi # end of overwriting check
  436. if [ -f mp.pro.ps ]
  437. then
  438. echo shar: will not over-write existing file mp.pro.ps
  439. else
  440. echo shar: extracting 'mp.pro.ps',     1754 characters
  441. cat > mp.pro.ps <<'Funky_Stuff'
  442. %!PS-Adobe-1.0
  443. %%Creator: Steve Holden
  444. %%Modifed: Rich Burridge
  445. %%Title: @(#)mp.pro.ps    1.4    3/3/88
  446. %%CreationDate: see above
  447. %%DocumentFonts: Times-Bold Times-Roman Courier
  448. %%Pages: (atend)
  449. %%EndComments
  450. %
  451.  
  452. /subject () def
  453. save /nuksunmailsave exch def
  454. /font1d /Times-Bold findfont 10 scalefont def
  455.  
  456. /font2d /Times-Roman findfont 10 scalefont def
  457.  
  458. /font3d /Courier findfont 9 scalefont def
  459.  
  460. /fontHd /Helvetica-BoldOblique findfont 15 scalefont def
  461.  
  462. /fontH2 /Helvetica-BoldOblique findfont 10 scalefont def
  463.  
  464. /fontNd /Times-Bold findfont 12 scalefont def
  465.  
  466. /Bold {font1d setfont} def
  467. /Roman {font2d setfont} def
  468. /Courier {font3d setfont} def
  469. /fontH {fontHd setfont} def
  470. /fontD {fontH2 setfont} def
  471. /fontN {fontNd setfont} def
  472.  
  473. Courier
  474.  
  475. /endpage
  476. {
  477.     gsave
  478.     fontH
  479.     newpath
  480.     90 756 moveto
  481.     100 736 10 180 270 arc
  482.     536 736 10 270 0 arc
  483.     536 756 10 0 90 arc
  484.     100 756 10 90 180 arc
  485.     closepath 0.75 setgray fill
  486.     newpath
  487.     318 746 15 0 360 arc
  488.     gsave 1 setgray fill grestore
  489.     closepath
  490.     0 setgray stroke
  491.     100 740 moveto
  492.     (Mail for ) show
  493.     loginname (\(null\)) eq {(printing)} {loginname} ifelse show
  494.     fontD
  495.     timenow stringwidth pop neg 536 add 740 moveto timenow show
  496.     fontN
  497.     dup stringwidth pop 2 div neg 318 add 740 moveto show
  498.     fontH
  499.     newpath
  500.     90 60 moveto
  501.     100 40 10 180 270 arc
  502.     536 40 10 270 0 arc
  503.     536 60 10 0 90 arc
  504.     100 60 10 90 180 arc
  505.     closepath 0.75 setgray fill
  506.     0 setgray
  507.     100 44 moveto subject show
  508.     grestore
  509.     showpage        % display it
  510.     newpage        % reset parameters for next
  511. } def
  512.  
  513. /newpage
  514. { /lct 0 def
  515.   /ypos 700 def
  516.   100 ypos moveto
  517. } def
  518.  
  519. /showline { show /ypos ypos 10 sub def 100 ypos moveto } def
  520.  
  521. newpage            % establish first page parameters
  522. Funky_Stuff
  523. len=`wc -c < mp.pro.ps`
  524. if [ $len !=     1754 ] ; then
  525. echo error: mp.pro.ps was $len bytes long, should have been     1754
  526. fi
  527. fi # end of overwriting check
  528. if [ -f mp.1 ]
  529. then
  530. echo shar: will not over-write existing file mp.1
  531. else
  532. echo shar: extracting 'mp.1',     1056 characters
  533. cat > mp.1 <<'Funky_Stuff'
  534. .TH MP 1 "3 March 1988"
  535. .\"@(#)mp.1    1.4    3/3/88
  536. .SH NAME
  537. mp \- mail printer
  538. .SH SYNOPSIS
  539. \fBmp\fP 
  540. [ \fB-p\fP \fIprolog filename\fP ]
  541. .SH DESCRIPTION
  542. .IX  mp "" "\fLmp\fP \(em mail printing program"
  543. .IX  mail "mp command" "" "\fLmp\fP \(em mail printing"
  544. .IX "mail printing" "mp command" "" "\fLmp\fP \(em mail printing"
  545. \fIMp\fP produces PostScript output which can be used to print mail on
  546. a LaserWriter.
  547. The format adopted has shaded stripes containing banner information
  548. at the top and bottom of every page.
  549. \fIMp\fP reads standard input for the mail file and sends its output
  550. to standard output.
  551. .SH OPTIONS
  552. .TP
  553. \fB-p\fP \fIprolog filename\fP
  554. The default location for the PostScript prologue file is
  555. /usr/local/mp.pro.ps. This options allows a different location to be
  556. specified.
  557. .SH FILES
  558. .TP
  559. /usr/local/mp.pro.ps
  560. PostScript prologue to define required vocabulary for mail printing.
  561. Editing this file will alow you to introduce some stylistic variation
  562. in the printing of mail.
  563. .TP
  564. .SH "SEE ALSO"
  565. mail(1)
  566. .SH BUGS
  567. Does not process more than one file.
  568. Funky_Stuff
  569. len=`wc -c < mp.1`
  570. if [ $len !=     1056 ] ; then
  571. echo error: mp.1 was $len bytes long, should have been     1056
  572. fi
  573. fi # end of overwriting check
  574.