richb@sunchat.sun.oz.AU (Rich Burridge) (03/08/89)
Posting-number: Volume 6, Issue 43 Submitted-By: Rich Burridge <richb@sunchat.sun.oz.AU> Archive-name: 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. See the README and the manual page for further details. Note that the code is already at patchlevel 1. Rich. ------CUT HERE------CUT HERE------ #! /bin/sh # this is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh to create the files: # README # Makefile # mailp # mp.pro.ps # mp.1 # mp.c # This archive created: Sat Mar 4 09:50:38 EST 1989 # # export PATH; PATH=/bin:$PATH # if [ -f README ] then echo shar: will not over-write existing file README else echo shar: extracting 'README', 1968 characters cat > README <<'Funky_Stuff' README for mp, the PostScript pretty printer. Version 2.0 December 1988. Permission is given to distribute these sources, as long as the authorship messages are not removed, and no monies are exchanged. 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. 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. 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" 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. Thanks go also to Bill Shannon, Roger De Salis, L. Jill Debord and David Fiedler for bug reports and/or bug fixes. I'm grateful to all these people, plus everybody who has suggested enhancements, and fixed bugs in the previous versions. I welcome further bug reports and suggestions for improvements. Rich. Rich Burridge, DOMAIN: richb@sunaus.oz.au PHONE: +61 2 413 2666 UUCP: {uunet,mcvax,ukc}!munnari!sunaus.oz!richb Funky_Stuff len=`wc -c < README` if [ $len != 1968 ] ; then echo error: README was $len bytes long, should have been 1968 fi fi # end of overwriting check if [ -f Makefile ] then echo shar: will not over-write existing file Makefile else echo shar: extracting 'Makefile', 2071 characters cat > Makefile <<'Funky_Stuff' # # Makefile for mp, the PostScript pretty printer. # # @(#)Makefile 1.2 88/12/28 # # 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. # # 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. # #------------------------------------------------------------------ # It is possible to change the location of the mp prologue file # with the -p command line option. It can also be defined at compile # time. If it's not present, then a sensible default value is used. # # # Prologue file used with mp. # PROLOGUE = -DPROLOGUE=\"$(LIBDIR)/mp.pro.ps\" #--------------------------------------------------------------------- BINARIES = mp BINDIR = /usr/local/bin LIBDIR = /usr/local/lib MANDIR = /usr/man/man$(MANSECT) MANSECT = l CFLAGS = -g $(PROLOGUE) OBJS = mp.o SRCS = mp.c OTHERS = README Makefile mailp mp.pro.ps mp.1 all: $(BINARIES) mp: $(OBJS) cc $(CFLAGS) -o mp $(OBJS) install: $(BINARIES) install -s -m 751 mp $(BINDIR) install -c -m 644 mp.1 $(MANDIR)/mp.$(MANSECT) install -c -m 644 mp.pro.ps $(LIBDIR) backup:; cp $(SRCS) $(OTHERS) backdir clean:; rm -rf mp *.o core create: SCCS -sccs create $(SRCS) $(OTHERS) lint:; lint $(SRCS) shar:; shar.script $(OTHERS) $(SRCS) > archive SCCS: mkdir SCCS chmod 755 SCCS mp.o: mp.c Funky_Stuff len=`wc -c < Makefile` if [ $len != 2071 ] ; then echo error: Makefile was $len bytes long, should have been 2071 fi fi # end of overwriting check if [ -f mailp ] then echo shar: will not over-write existing file mailp else echo shar: extracting 'mailp', 523 characters cat > mailp <<'Funky_Stuff' #! /bin/sh # # @(#)mailp 1.2 88/12/28 # # mailp, newsp, filep, mhp and digestp # shell script de lancement de mp (mail/news/file pretty printer) # # Bruno Pillard - October 1988. BIN=/usr/local/bin case $0 in *mailp) PROG=mp ;; *mhp) PROG="mp -mh" ;; *newsp) PROG="mp -n" ;; *digestp) PROG="mp -d" ;; *filep) PROG="mp -o" ;; *) echo Unknown pretty printer: $0 exit;; esac if [ $# -eq 0 ] then set - " - " fi while [ $# -gt 0 ] do /bin/cat $1 | ${BIN}/${PROG} | lpr -h -Plw shift done Funky_Stuff len=`wc -c < mailp` if [ $len != 523 ] ; then echo error: mailp was $len bytes long, should have been 523 fi fi # end of overwriting check if [ -f mp.pro.ps ] then echo shar: will not over-write existing file mp.pro.ps else echo shar: extracting 'mp.pro.ps', 1764 characters cat > mp.pro.ps <<'Funky_Stuff' %!PS-Adobe-1.0 %%Creator: Steve Holden %%Modifed: Rich Burridge %%Title: @(#)mp.pro.ps 1.2 88/12/28 %%CreationDate: see above %%DocumentFonts: Times-Bold Times-Roman Courier %%Pages: (atend) %%EndComments /font1d /Times-Bold findfont 10 scalefont def /font2d /Times-Roman findfont 10 scalefont def /font3d /Courier findfont 9 scalefont def /fontHd /Helvetica-BoldOblique findfont 15 scalefont def /fontH2 /Helvetica-BoldOblique findfont 10 scalefont def /fontNd /Times-Bold findfont 12 scalefont def /BoldFont { font1d setfont } def /PrimaryFont { font2d setfont } def /SecondaryFont { font3d setfont } def /fontH { fontHd setfont } def /fontD { fontH2 setfont } def /fontN { fontNd setfont } def SecondaryFont /endpage { gsave fontH newpath 90 756 moveto 100 736 10 180 270 arc 536 736 10 270 0 arc 536 756 10 0 90 arc 100 756 10 90 180 arc closepath 0.75 setgray fill newpath 318 746 15 0 360 arc gsave 1 setgray fill grestore closepath 0 setgray stroke 100 740 moveto MailFor show User show fontD TimeNow stringwidth pop neg 536 add 740 moveto TimeNow show fontN dup stringwidth pop 2 div neg 318 add 740 moveto show fontH newpath 90 60 moveto 100 40 10 180 270 arc 536 40 10 270 0 arc 536 60 10 0 90 arc 100 60 10 90 180 arc closepath 0.75 setgray fill 0 setgray 100 44 moveto Subject show grestore showpage % display it newpage % reset parameters for next } def /newpage { /lct 0 def /ypos 700 def 100 ypos moveto } def /showline { show /ypos ypos 10 sub def 100 ypos moveto } def newpage % establish first page parameters Funky_Stuff len=`wc -c < mp.pro.ps` if [ $len != 1764 ] ; then echo error: mp.pro.ps was $len bytes long, should have been 1764 fi fi # end of overwriting check if [ -f mp.1 ] then echo shar: will not over-write existing file mp.1 else echo shar: extracting 'mp.1', 2751 characters cat > mp.1 <<'Funky_Stuff' .\" @(#)mp.1 1.2 88/12/28 .TH MP 1L "28 December 1988" .SH NAME mp \- Postscript pretty printer .SH SYNOPSIS .B mp [ .B \-d ] [ .B \-mh ] [ .B \-n ] [ .B \-o ] [ .B \-p .I prologue ] [ .B \-s .I subject ] [ .B \-v ] [ .B \-? ] .SH DESCRIPTION .B mp will take a mail item, a news article or an ordinary ASCII file on standard input and generate a Postscript file on standard output, which is a pretty print of the original. It is also possible to print out complete mail folders and digests. .LP The format adopted has shaded stripes containing banner information at the top and bottom of every page. It is also possible to supply a complete mail folder to be printed. .LP .B mp was originally designed to be used in conjunction with the print button in the .B "mailtool (1)" program, or the .B pipe command from within mail. Add (or alter) the following two line in your .B .mailrc file: .in +1.0i .nf \fCset printmail='mp | lpr' set cmd="mp | lpr &"\fP .fi .in -1.0i .LP Source the .B .mailrc file again, and you are ready. .LP A useful alias to use used in conjunction with your .I .cshrc file for printing out ordinary text files is: .in +1.0i .nf \fCalias print 'mp -o -s "\\!*" <\\!* | lpr'\fP .fi .in -1.0i .SH OPTIONS .TP .B \-d The file on standard input is a digest so print accordingly. .TP .B \-mh Use if the mail article on standard input comes from the .B "MH Mail (1L)" package, because the .I From mail header lines are of a slightly different format. .TP .B \-n The file on standard input is a news article so print accordingly. .TP .B \-o The file on standard input is an ASCII file so print accordingly. .TP .BI \-p " prologue filename" Employ .I "prologue filename" as the Postscript prologue file. The default location is .I /usr/local/lib/mp.pro.ps .TP .BI \-s " subject" Use .I " subject" as the new subject for the printout. .TP .B \-v Print the version number of this release of the .B mp program. .TP .B \-? Print the usage line for this program. Note that the .B ? character should be escaped if running from .BR csh (1). .SH FILES .TP .B /usr/local/bin/mp executable .TP .B /usr/local/lib/mp.pro.ps PostScript prologue to define required vocabulary for mail printing. Editing this file will allow you to introduce some stylistic variation in the printing of mail. .SH "SEE ALSO" mail(1) .SH AUTHORS Original version by Steve Holden. .br Converted to C, modified and maintained by Rich Burridge, Sun Microsystems Australia, .br Modified to handle net news articles and MH mail by Bruno Pillard, Chorus Systemes, France, .br Handling of mail digests added by Dave Glowacki of Public Works Computer Services, St Paul, MN. .br Manual page for the initial version revised by Rick Rodgers, UCSF School of Pharmacy, San Francicso. Funky_Stuff len=`wc -c < mp.1` if [ $len != 2751 ] ; then echo error: mp.1 was $len bytes long, should have been 2751 fi fi # end of overwriting check if [ -f mp.c ] then echo shar: will not over-write existing file mp.c else echo shar: extracting 'mp.c', 12580 characters cat > mp.c <<'Funky_Stuff' #ifndef lint static char sccsid[] = "@(#)mp.c 1.4 89/01/03" ; #endif /* Takes a mail file, a news article or an ordinary file * and pretty prints it on a Postscript printer. * * 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. * * 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 <stdio.h> #include <sys/types.h> #include <sys/file.h> #include <string.h> #include <time.h> #include <pwd.h> #define PATCHLEVEL 1 #define FPRINTF (void) fprintf /* To make lint happy. */ #define PRINTF (void) printf #define SPRINTF (void) sprintf #define SSCANF (void) sscanf #define STRCPY (void) strcpy #define STRNCPY (void) strncpy enum print_type { PRINTMAIL, PRINTNEWS, PRINTORD } ; /* States for the mail processing automation. */ #define FROMLINE 0 /* Searching for the initial From line. */ #define DOHEADER 1 /* Processing rest of message header. */ #define DOMESSAGE 2 /* Processing text in message body. */ #define DOTEXT 3 /* Ordinary file - just print it. */ #define EQUAL(val) !strncmp(val,nextline,strlen(val)) #define INC argc-- ; argv++ ; #define LINELENGTH 80 /* Number of characters per line. */ #define MAXLINE 256 /* Length of character strings. */ #define PAGELENGTH 60 /* Number of lines per page. */ time_t time() ; struct tm *localtime() ; char *asctime(), *getlogin(), *gets() ; char mf[MAXLINE] ; /* "[Mail,News,Listing] for ". */ char nextline[MAXLINE] ; /* Next line of the mail message. */ char progname[MAXLINE] ; /* Name of this program. */ char prologue[MAXLINE] ; /* Name of PostScript prologue file. */ char username[MAXLINE] ; /* The username of the mail file owner. */ char subject[MAXLINE] ; /* Subject line for this message. */ FILE *fopen(), *pf ; enum print_type ptype ; /* Type of printing to do. */ int digest = 0 ; /* Set if we are printing a mail digest. */ int lindex ; /* Index pointer to nextline. */ int linect = 0 ; /* Line count on current page. */ int maybe_more = 0 ; /* Message header continuation line indicator. */ int mhflag = 0 ; /* Set if we are printing an MHmail message. */ int non_space ; /* Indicates if nextline has a non-space char. */ int pn = 1 ; /* Page number within message. */ int rec_line = 0 ; /* "Received:" line in message header. */ int removednl ; /* Set if a newline was removed from this line. */ int state ; /* Current state of the print automation. */ int tpn = 0 ; /* Total number of pages printed. */ /*ARGSUSED*/ main(argc,argv) int argc ; char **argv ; { long clock ; /* Used by the localtime function call. */ struct tm *tm ; /* Used by the localtime and asctime calls. */ STRCPY(progname, argv[0]) ; /* Save this program name. */ initialise() ; /* Set default values for various options. */ get_options(argc,argv) ; /* Read and process command line options. */ if ((pf = fopen(prologue, "r")) == NULL) { FPRINTF(stderr,"%s: Prologue file not found.\n",progname) ; exit(1) ; } while (fgets(nextline,MAXLINE,pf) != NULL) PRINTF("%s",nextline) ; defwrite("MailFor", mf) ; /* Output initial definitions. */ defwrite("User", username) ; clock = time((time_t *) 0) ; tm = localtime(&clock) ; defwrite("TimeNow",asctime(tm)) ; defwrite("Subject", subject) ; PRINTF("%%%%EndProlog\n") ; if (ptype == PRINTORD) state = DOTEXT ; else state = FROMLINE ; startpage() ; while (fgets(nextline,LINELENGTH+1,stdin) != NULL) { removednl = 0 ; if (nextline[strlen(nextline)-1] == '\n') { removednl = 1 ; nextline[strlen(nextline)-1] = '\0' ; } non_space = 0 ; for (lindex = 0; lindex < strlen(nextline); lindex++) if (nextline[lindex] != ' ') { non_space = 1 ; break ; } process() ; } endpage() ; PRINTF("%%%%Trailer\n") ; PRINTF("%%%%Pages: %1d\n",tpn) ; } boldshow(s) char *s ; { useline() ; PRINTF("BoldFont ") ; startline() ; expand(s) ; endline() ; } defwrite(name,def) char *name, *def ; { PRINTF("/%s (%s) def\n",name,def) ; } endline() { PRINTF(") showline\n") ; } endpage() { linect = 0 ; PRINTF("(%1d) endpage\n",pn++) ; } expand(s) char *s ; { int i,j,n ; n = 0 ; for (i = 0; i < strlen(s); i++) { switch (s[i]) { case '\\' : PRINTF("\\\\") ; n++ ; break ; case '(' : PRINTF("\\(") ; n++ ; break ; case ')' : PRINTF("\\)") ; n++ ; break ; case '\t' : for (j = 0; j < (8 - (n % 8)); j++) PRINTF(" ") ; n = n + 8 - (n % 8) ; break ; case '\004' : break ; default : PRINTF("%c",s[i]) ; n++ ; } if (!(i % LINELENGTH) && i) { endline() ; startline() ; } } } get_options(argc,argv) /* Read and process command line options. */ int argc ; char *argv[] ; { INC ; while (argc > 0) { if (argv[0][0] == '-') switch (argv[0][1]) { case 'd' : digest = 1 ; /* Print mail digest. */ break ; case 'm' : if (argv[0][2] == 'h') mhflag = 1 ; /* Handle MHmail. */ break ; case 'n' : ptype = PRINTNEWS ; /* Print news article. */ STRCPY(mf, "News for ") ; break ; case 'o' : ptype = PRINTORD ; /* Print ordinary file. */ STRCPY(mf, "Listing for ") ; break ; case 'p' : INC ; if (*argv != NULL && argv[0][0] != '-') STRCPY(prologue, *argv) ; /* New prologue file. */ else { FPRINTF(stderr,"%s: -p needs prologue name as next argument.\n", progname) ; exit(1) ; } break ; case 's' : INC ; if (*argv != NULL && argv[0][0] != '-') STRCPY(subject, *argv) ; /* New subject line. */ else { FPRINTF(stderr,"%s: -s needs subject name as next argument.\n", progname) ; exit(1) ; } break ; case 'v' : FPRINTF(stderr,"%s version 2.0.%1d\n",progname,PATCHLEVEL) ; exit(1) ; case '?' : FPRINTF(stderr,"Usage: %s [-d] [-mh] [-n] [-o] [-p prologue] [-v] [-?]\n", progname) ; exit(1) ; } argc-- ; argv++ ; } } initialise() /* Set default values for various options. */ { char *ptr ; struct passwd *pp ; #ifdef PROLOGUE STRCPY(prologue, PROLOGUE) ; /* Location of the mp prologue file. */ #else STRCPY(prologue, "/usr/local/lib/mp.pro.ps") ; #endif STRCPY(mf,"Mail for ") ; /* Assume mail as default. */ ptr = getlogin() ; /* Pointer to users login name. */ if (ptr != NULL) STRCPY(username, getlogin()) ; /* Users' login name. */ else /* Else get it from the passwd file. */ { pp = getpwuid(geteuid()) ; if (pp == NULL) STRCPY(username, "printing") ; else STRCPY(username, pp -> pw_name) ; } ptype = PRINTMAIL ; /* Pretty print mail item by default. */ } mixedshow(s) char *s ; { char first[MAXLINE] ; useline() ; SSCANF(s,"%s",first) ; PRINTF("BoldFont (%s) show PrimaryFont (",first) ; expand(&s[strlen(first)]) ; endline() ; if (!strcmp("Subject:",first)) { PRINTF("/Subject (") ; expand(&s[strlen(first)]) ; STRCPY(subject,&s[strlen(first)]) ; PRINTF(") def\n") ; } } process() { switch (state) { case FROMLINE : if (EQUAL(ptype == PRINTNEWS ? "From:" : (mhflag ? "From" : "From "))) { boldshow(nextline) ; state = DOHEADER ; } break ; case DOHEADER : if (ptype == PRINTNEWS && EQUAL("Newsgroups")) { mixedshow(nextline) ; maybe_more = 0 ; rec_line = 0 ; } if (EQUAL(mhflag ? "From" : "From:") || EQUAL("Date") || EQUAL("Subject")) { mixedshow(nextline) ; maybe_more = 0 ; rec_line = 0 ; } else if (EQUAL("To") || EQUAL("Cc")) { mixedshow(nextline) ; maybe_more = 1 ; rec_line = 0 ; } else if (EQUAL("Received:")) { maybe_more = 0 ; rec_line = 1 ; } else if (EQUAL(" ") && non_space && maybe_more) { rec_line = 0 ; textshow(nextline) ; } else if ((EQUAL(" ") && (!non_space)) || (!strlen(nextline) && !rec_line)) { state = DOMESSAGE ; PRINTF("SecondaryFont\n") ; PRINTF("() showline\n") ; } else maybe_more = 0 ; break ; case DOMESSAGE : if (digest && (EQUAL("Date: ") || EQUAL("From: "))) { linect = PAGELENGTH ; useline() ; mixedshow(nextline) ; state = DOHEADER ; } else if (EQUAL("From ") && (ptype == PRINTMAIL)) { linect = PAGELENGTH ; useline() ; pn = 1 ; boldshow(nextline) ; state = DOHEADER ; } else textshow(nextline) ; break ; case DOTEXT : textshow(nextline) ; } } startline() { PRINTF("(") ; } startpage() { PRINTF("%%%%Page: ? %1d\n",++tpn) ; defwrite("MailFor", mf) ; defwrite("User", username) ; } textshow(s) char *s ; { if (*s == '\014') { if (removednl) /* Is this the bogus formfeed at the end? */ { linect = PAGELENGTH ; useline() ; } return ; } useline() ; startline() ; expand(s) ; endline() ; } useline() { if (++linect > PAGELENGTH) { endpage() ; startpage() ; PRINTF("/Subject (") ; expand(subject) ; PRINTF(") def\n") ; } } Funky_Stuff len=`wc -c < mp.c` if [ $len != 12580 ] ; then echo error: mp.c was $len bytes long, should have been 12580 fi fi # end of overwriting check