home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / misc / volume07 / psf < prev    next >
Encoding:
Internet Message Format  |  1991-08-27  |  64.6 KB

  1. From decwrl!sun-barr!ames!lll-winken!uunet!allbery Sun Jun  4 14:43:33 PDT 1989
  2. Article 892 of comp.sources.misc:
  3. Path: decwrl!sun-barr!ames!lll-winken!uunet!allbery
  4. From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5. Newsgroups: comp.sources.misc
  6. Subject: v07i003: PSF: PostScript filters for SCO Xenix
  7. Message-ID: <56702@uunet.UU.NET>
  8. Date: 4 Jun 89 01:17:12 GMT
  9. Sender: allbery@uunet.UU.NET
  10. Reply-To: tony@ajfcal.UUCP (Tony Field)
  11. Lines: 2337
  12. Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  13.  
  14. Posting-number: Volume 7, Issue 3
  15. Submitted-by: tony@ajfcal.UUCP (Tony Field)
  16. Archive-name: psf
  17.  
  18. [WARNING:  One file in this shar ("testfile") contains ESC characters
  19. (hex 1B, decimal 27).  They may be lost in transmission (the shar will
  20. detect this.  I don't advise "cat"ting this submission to the terminal;
  21. I've made more than one terminal go catatonic that way....  ++bsa]
  22.  
  23. Since Xenix does not come with any postscript support, the PSF system can
  24. be automatically installed as a "postscript printer" with little more
  25. than "make xenix". The resulting installation correctly builds the
  26. Xenix-conformant printer back-end scripts in such a way that the system
  27. administrator can install the postscript system with the Xenix command
  28. "mkdev lp". It also supports Xenix-styled banner pages and correctly
  29. handles text that is or is not already in postscript format.
  30.  
  31. For non-Xenix users, the PSF system is a set of postscript filters
  32. that can be used for general text, mail, and nroff printing.  About
  33. the only thing different than other ps filters is the ability to
  34. print pages in landscape or portrait, 1-up, 2-up, or 4-up on a page.
  35.  
  36. I would like to consider psf's ability to recognize "escape sequences" as
  37. a useful feature - but probably no one will ever use it the way that I
  38. intended. PSF can recognize simple escape sequences for font and point
  39. size control. If you are using a text editor such as vi, you may insert
  40. escape sequences to cause underlines, italics, font changes. This is a
  41. nice way to quickly whip off a letter with a little class - no need to
  42. use a word processor or n/troff/TeX: simply send the text file to psf.
  43.  
  44. I happen to like to conserve paper. I tend to print source listings
  45. 2-up on a page with 80-100 lines per column; my mail boxes are
  46. printed 4-up for permanent records (240 possible printed mail lines
  47. on an 8.5x11 page).
  48.  
  49. Other ps filters generally tend to provide extensive "font and layout
  50. control" for various types of documents: recognition of c syntax,
  51. mail headers and summarization, etc. etc.  My filters are relatively
  52. weak in this area - although quite useful.
  53.  
  54. Unfortunately, I know nothing about other *nix systems. I don't know if
  55. the xenix installation is similar to that of AIX - which, i think, also
  56. knows nothing about postscript.
  57.  
  58. It surprises me that SCO and other vendors do not provide even minimal
  59. postscript support.
  60.  
  61. One file "testfile" should contain true ESCape characters (ctrl-[).
  62. I am pretty sure that the mail system will translate the ESCapes to
  63. the text string "\\033".  I have provided instructions in Readme to use 
  64. "sed" to correctly translate the strings back to the ESCape character.
  65.  
  66. I couldn't figure out a conversion shell script that I could mail that
  67. wouldn't undergo the same translation problem!
  68.  
  69. At any rate, here is the new release of PSF:  please destroy the
  70. old version..   I hope that the quality of source and documentation
  71. are up to the standards required by this demanding user community.
  72.  
  73. tony...   ((( ps..  howcome you are up at 11:30 on a Sunday Night?)))
  74.  ----------------------------------------------------------------------------
  75. #! /bin/sh
  76. # This is a shell archive.  Remove anything before this line, then unpack
  77. # it by saving it into a file and typing "sh file".  To overwrite existing
  78. # files, type "sh file -c".  You can also feed this as standard input via
  79. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  80. # will see the following message at the end:
  81. #        "End of shell archive."
  82. # Contents:  Readme Readme.Xenix psf.1 Makefile psf.c pnf.c pmf.c
  83. #   psbanner.c psdetect.c postscript.LP testfile
  84. # Wrapped by ajf@ajfcal on Mon May 15 14:30:49 1989
  85. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  86. if test -f 'Readme' -a "${1}" != "-c" ; then 
  87.   echo shar: Will not clobber existing file \"'Readme'\"
  88. else
  89. echo shar: Extracting \"'Readme'\" \(3901 characters\)
  90. sed "s/^X//" >'Readme' <<'END_OF_FILE'
  91. X                    PSF POSTSCRIPT FILTER
  92. X
  93. XThe postscript filter "psf" is used for general purpose printing.
  94. XProvisions are made for 1-up, 2-up or 4-up logical printing on each
  95. Xphysical page.  Changes in fonts or point size may be done within
  96. Xa page using prescribed escape sequences.  Such sequences are
  97. Xgenerated by the pre-filters "pnf" and "pmf".
  98. X
  99. XNroff'ed documents may be pre-filtered with "pnf" to provide italic,
  100. Xbold, or underlined text. Since nroff uses backspace/overstrike to
  101. Xgenerate underline and bold, "pnf" examines all backspace sequences
  102. Xand generates escape sequences that can be used by "psf" to print
  103. Xproper underlined and bold text.
  104. X
  105. XMail documents may be pre-filtered with "pmf" to provide some bolding 
  106. Xand line formatting on various mail header lines.
  107. X
  108. XThe man-page for psf and friends are in "psf.1".
  109. X
  110. XXenix users should examine the Readme.Xenix file if a postscript printer
  111. Xmodel should be implemented. This allows the use of the "lp" command for
  112. Xgeneral printing.
  113. X
  114. XIf you are not using Xenix but wish to use psf as a back-end filter for
  115. Xgeneral printing with "lp", then the Xenix-oriented back-end is in
  116. Xfile "postscript.LP".  This, and the banner-generating programme
  117. X"psbanner.c", may be modified for your system.
  118. X
  119. XINSTALLATION.
  120. X^^^^^^^^^^^^^
  121. XInstallation will generate the following binaries (name conflicts???)
  122. X
  123. X    psf    pmf    pnf     (and, for Xenix,  psdetect  psbanner)
  124. X
  125. XThe system is built with  "make all".
  126. X
  127. XIf you are using "non-standard fonts", there is a remote possibility that
  128. Xthe underline parametrics within FontInfo are missing. If this is the
  129. Xcase, you may use an optional underline strategy by adding the -DFONTINFO
  130. Xto the cc command line.  This generates underlines 2 points below
  131. Xthe text base line.  Psf does NOT verify that FontInfo is complete....
  132. X
  133. XThe system may be installed into a chosen binary directory (edit
  134. Xthe Makefile) with:
  135. X
  136. X    make install
  137. X
  138. XAfter you compile the system, test the printing with the command
  139. X(see the note below regarding possible problems with testfile):
  140. X
  141. X    psf testfile | lp
  142. X
  143. XAfter you have installed the man pages (psf.1), you may print them with:
  144. X
  145. X    man psf | pnf | psf -2 | lp
  146. X
  147. XTo test general file printing, print the source for the filters 4-up
  148. Xon a page with:
  149. X
  150. X    psf -4xh psf.c pnf.c pmf.c | lp
  151. X
  152. XTesting the mail print filter is easily done (assuming 4-up printing)
  153. X
  154. X    pmf < mail.box | psf -4x | lp
  155. X
  156. X
  157. XNOTE:  TESTFILE
  158. X^^^^^^^^^^^^^^^
  159. XThe "testfile" should contain many ESCape characters (octal 33). The mail
  160. Xsystem may change the escape character into the text string "\033". You
  161. Xmay have to edit the testfile and replace all "\033" strings with true
  162. Xescape characters. A true escape character is CTRL-[.
  163. X
  164. XOne easy way to correct this is with sed:
  165. X
  166. X    sed 's@\\033@<CTRL-[>@g' testfile > tfile
  167. X                     +------+
  168. X                     actually type the ESCape character CTRL-[ 
  169. X
  170. XOther Nonsense:
  171. X^^^^^^^^^^^^^^^
  172. XThe following fonts are assumed to be available in the postscript printer.
  173. X(These fonts are available in the Nec LC890 SilentWriter)
  174. X
  175. X         Courier               Helvetica
  176. X         Times-Roman           AvantGarde-Book
  177. X         Bookman-Light         NewCenturySchlbk-Roman
  178. X         Palatino-Roman        ZapfChancery-MediumItalic
  179. X         Helvetica-Narrow
  180. X         
  181. XIf your printer does not have all of these fonts, or if other fonts are
  182. Xavailable, you must change the font defintion table in psf.c. The man
  183. Xpage psf.1 should be changed reflect the font numbering and definition.
  184. XRoutines pmf.c, pnf.c and psbanner use Courier, Helvetica, and
  185. XTimes-Roman: these are probably available on all systems and need not be
  186. Xchanged.
  187. X
  188. XThe programmes have been used only on Xenix 2.2.3/386 and a NEC LC890
  189. Xpostscript printer. I hope the code is portable. If there are any
  190. Xproblems, please send email: I will attempt to correct the bugs, time
  191. Xbeing available.
  192. X
  193. XTony Field      calgary!ajfcal!tony@ai.toronto.edu
  194. END_OF_FILE
  195. if test 3901 -ne `wc -c <'Readme'`; then
  196.     echo shar: \"'Readme'\" unpacked with wrong size!
  197. fi
  198. # end of 'Readme'
  199. fi
  200. if test -f 'Readme.Xenix' -a "${1}" != "-c" ; then 
  201.   echo shar: Will not clobber existing file \"'Readme.Xenix'\"
  202. else
  203. echo shar: Extracting \"'Readme.Xenix'\" \(2619 characters\)
  204. sed "s/^X//" >'Readme.Xenix' <<'END_OF_FILE'
  205. XPSF:        X E N I X    I N S T A L L A T I O N    (xenix 2.2.3)
  206. X                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  207. XThe postscript filter system may be installed on Xenix 2.2.3 for all regular
  208. Xprinting operations. A new "printer model" (postscript.psf) is created which
  209. Xincludes banner printing support with "psbanner". The psbanner parameter
  210. Xlist is compatible with those generated by lp. Thus "lp my.file" 
  211. Xor "cat my.file | lp" works as expected with and without banners.
  212. X
  213. XIf you wish to use the default (binaries placed in /usr/bin, printing is
  214. Xto be done with 60 lines per page), then, as root, issue the command:
  215. X
  216. X        make xenix
  217. X
  218. XThe system will automatically compile and install.  After the binaries
  219. Xare copied to the appropriate directories, the print spooler back-end
  220. Xscript file is placed in /usr/spool/lp/model/postscript.psf and 
  221. X"mkdev lp" is invoked.
  222. X
  223. X
  224. XIf you do not wish to use the default conditions, then do the following:
  225. X
  226. X1.    Edit the Makefile (BINDIR=) to specify the destination directory
  227. X    in which the various printer binaries are to be installed.
  228. X    The default is /usr/bin.
  229. X
  230. X2.    Edit the Makefile (PSFOPT=) to specify default options for
  231. X    the psf filter.
  232. X
  233. X3.    Make the executables with   "make all".
  234. X
  235. X4.    As root,   "make xenix".
  236. X
  237. X    This will copy all executables to the chosen binary directory
  238. X    and will add a "printer model" named "postscript.psf" to
  239. X    the /usr/spool/lp/model directory.  (See  lp (C),  lpadmin (C))
  240. X    
  241. X    "mkdev lp" is automatically called to allow you to build your
  242. X    postscript printer.
  243. X
  244. X5.    Run the installation tests as described in "Readme".
  245. X
  246. XThe resulting "printer" will examine the print file for a "%!" string in
  247. Xthe first text line. If it does exist, it will NOT filter the file with "psf"
  248. Xbut simply "cat" the file to the printer. If the string cannot be found,
  249. Xthe the "psf" filter is automatically called to create postscript
  250. Xconformant output.
  251. X
  252. XThe mail filter (pmf) and nroff filter (pnf) output no longer have to
  253. Xbe piped through psf by hand.  For example:
  254. X
  255. X    man vi | pnf -ix | lp
  256. Xor
  257. X    pmf < my.mail.box | lp
  258. X
  259. XMultiple printers may be created using the psf filters.  The generated
  260. Xfiles in /usr/spool/interface may be edited to reflect different psf
  261. Xparameters such as 2-up, landscape or different lines per page.
  262. X
  263. X=============
  264. XNOTE:  Some software generating postscript output uses the string "%!"
  265. X       to identify the beginning of postscript code.  As a result,
  266. X       "psdetect.c" examines for this string.  If you wish, you might
  267. X       change it to examine for "%!PS-Adobe" which might be more robust
  268. X       but not as general.
  269. X==============
  270. X
  271. XTony Field.       tony@ajfcal
  272. END_OF_FILE
  273. if test 2619 -ne `wc -c <'Readme.Xenix'`; then
  274.     echo shar: \"'Readme.Xenix'\" unpacked with wrong size!
  275. fi
  276. # end of 'Readme.Xenix'
  277. fi
  278. if test -f 'psf.1' -a "${1}" != "-c" ; then 
  279.   echo shar: Will not clobber existing file \"'psf.1'\"
  280. else
  281. echo shar: Extracting \"'psf.1'\" \(8529 characters\)
  282. sed "s/^X//" >'psf.1' <<'END_OF_FILE'
  283. X.TH PSF 1 ""
  284. X.SH NAME
  285. Xpsf \- postscript filter
  286. X.br
  287. Xpnf \- postscript nroff pre-filter
  288. X.br
  289. Xpmf \- postscript mail pre-filter
  290. X.SH SYNOPSIS
  291. X.nf
  292. X
  293. Xpsf [ -l n ] [ -1|2|4 ] [ -f n ] [ -h ] [ -t n ]
  294. X    [ -H text ] [ -p n ] [ -w ] [ -x ] file file ..
  295. X
  296. X   where        -l n      lines per page (default=60)
  297. X                -1|2|4    print 1,2 or 4 up on a page (default=1)
  298. X                -f n      font number to use (default=0=Courier)
  299. X                -h        put file name as header on each page
  300. X                -H text   put text as header on each page
  301. X                -t n      set tabs to n (default=8)
  302. X                -p n      set point size to n
  303. X                -w        set landscape page (wide)
  304. X                -x        place a cross on 4-up printing
  305. X                file..    name of files to be printed (or stdin)
  306. X   output: stdout
  307. X
  308. X   Fonts selection with -f n
  309. X         0 Courier         1 Helvetica
  310. X         2 Times-Roman     3 AvantGarde-Book
  311. X         4 Bookman-Light   5 NewCenturySchlbk-Roman
  312. X         6 Palatino-Roman  7 ZapfChancery-MediumItalic
  313. X         8 Helvetica-Narrow
  314. X
  315. Xpnf [ -i ] [ -x ] <in.file >out.file
  316. X
  317. X   where     -i = use italic font instead of underline
  318. X             -x = adjust for 59 line man-pages on xenix
  319. X
  320. Xpmf [ -s ] <in.file >out.file
  321. X
  322. X   where     -s = show all header lines
  323. X.fi
  324. X
  325. X.RS -5
  326. XDESCRIPTION
  327. X.RE
  328. XPsf will accept text and filter it to print on postscript printers.
  329. XThe print may be "1-up", "2-up", or "4-up" on a page.  To allow
  330. Xconvenient printing of nroff'ed documents, the fixed pitch Courier
  331. Xfont is used as a default. 
  332. X
  333. XPsf is a general purpose filter for
  334. Xmost text and programme listings.  By using various escape 
  335. Xsequences (described below), any portion of the text may be printed in
  336. Xdifferent fonts and at different point sizes.
  337. X
  338. XAdditional filters, such as "pnf" and "pmf" can be used to automatically
  339. Xgenerate escape sequences to control font and sizes for
  340. Xprinted documents.
  341. X
  342. XIf an nroff'ed
  343. Xdocument is filtered with programme "pnf", then the document will
  344. Xprint properly with bold-face and underlining.  
  345. X
  346. XPnf is a filter that converts "backspaced text" into underlined or
  347. Xbold text.  Nroff'ed documents should be filtered by pnf before
  348. Xthey are passed to psf.
  349. X
  350. XFor example, you could print the "vi" man page "2-up" with:
  351. X
  352. X.nf
  353. X      man vi | pnf -x | psf -2 | lp
  354. Xor
  355. X      man vi | pnf -ix | psf -2 | lp
  356. X.fi
  357. X
  358. XSource listings or other text would use psf only:
  359. X.nf
  360. X
  361. X      psf main.c subs.c | lp
  362. X.fi
  363. X
  364. XPmf is a very simple filter for mail documents.
  365. XMail message may be printed with:
  366. X
  367. X.nf
  368. X      pmf <mail.file | psf -2 | lp
  369. X.fi
  370. X
  371. X.RS -5
  372. XOPTIONS
  373. X.RE
  374. X.TP .7i
  375. X.B \-1\|2\|4
  376. XSpecify the number of logical pages that are to be printed
  377. Xon a physical page.  By default, psf will print one logical
  378. Xpage per physical page.  If two logical pages are specified
  379. Xwith "-2", then two pages are printed in "landscape" format:
  380. X
  381. X.nf
  382. X      +-----------+-----------+
  383. X      |   pg 1    |   pg 2    |
  384. X      |           |           |
  385. X      |           |           |
  386. X      +-----------+-----------+
  387. X.fi
  388. X
  389. XIf four logical pages are specified with "-4", then the pages
  390. Xare printed in "portrait format:
  391. X
  392. X.nf
  393. X      +-----------+-----------+
  394. X      |   pg 1    |   pg 3    |
  395. X      |           |           |
  396. X      |           |           |
  397. X      +-----------+-----------+
  398. X      |   pg 2    |   pg 4    |
  399. X      |           |           |
  400. X      |           |           |
  401. X      +-----------+-----------+
  402. X.fi
  403. X
  404. X
  405. X.TP .7i
  406. X.B -l n
  407. XSets the number of lines per page.  The default is 60 lines.
  408. XIf more than 60 lines per page are specified, the point size is
  409. Xautomatically reduced to accomodate the line count. (Xenix man
  410. Xpages use a page length of 60.)
  411. X
  412. XIf you are printing text that is wider than the nominal 75-80 columns
  413. Xin width, then specify more than 60 lines per page.  Then number
  414. Xof print columns available will increase proportionately with the
  415. Xnumber of lines.
  416. X
  417. X.TP .7i
  418. X.B \-f n
  419. XAny of the standard postscript 
  420. Xfonts may be selected in lieu
  421. Xof the default Courier font.  These are selected from the following
  422. Xtable of fonts:
  423. X.nf
  424. X
  425. X         0 Courier
  426. X         1 Helvetica
  427. X         2 Times-Roman
  428. X         3 AvantGarde-Book
  429. X         4 Bookman-Light
  430. X         5 NewCenturySchlbk-Roman
  431. X         6 Palatino-Roman
  432. X         7 ZapfChancery-MediumItalic
  433. X         8 Helvetica-Narrow
  434. X.fi
  435. X
  436. XSince Courier is the only fixed-pitch font, it is usually used for
  437. Xprinting of man pages or programme listings.  The other fonts are
  438. Xproportionally spaced.
  439. X
  440. XThe selected font becomes the new "default font".
  441. X
  442. X.TP .7i
  443. X.B \-w
  444. XThe page is printed in landscape (wide, horizontal format).
  445. XThis is the default for 2-up printing.  If 1-up printing is
  446. Xdesired in landscape mode, then the -w switch must be specified.
  447. X
  448. X.TP .7i
  449. X.B \-h
  450. XThe file name, page number and current date will be printed at
  451. Xthe top of each page.  The point size is automatically scaled to
  452. Xpermit the specified number of text lines to be printed to account
  453. Xfor the additional two lines consumed by the title line.
  454. X
  455. X.TP .7i
  456. X.B \-H text
  457. XPlace a header (like -h) however use "text" rather than the filename.
  458. X
  459. X.TP .7i
  460. X.B \-t n
  461. XSets the width of the tab stops.  By default this is set to 8.
  462. XIf the first line of a text file contains the string "ta=", then
  463. Xthe tab stop width is automatically determined from this string.
  464. XFor example, if the first text line contains "/* ta=4 */" then
  465. Xthe tab width is automatically set to 4.  This feature is useful
  466. Xif programme source files are tabbed at 4.
  467. X
  468. X.TP .7i
  469. X.B \-p n
  470. XSets the nominal point size to "n" points.  This applies only
  471. Xto "1-up" printing.  If "2-up" or "4-up" or "1-up, landscape" 
  472. Xprinting is desired, the nominal point size is automatically scaled.
  473. X
  474. XThe selected point size becomes the new "default point size".
  475. X
  476. X.RS -5
  477. XPSF NOTES
  478. X.RE
  479. XPsf filters text in a postscript-compatible way. If the text contains
  480. Xescape sequences (possibly generated by pnf, another pre-filter or a
  481. Xtext editor), the escape sequences are analyzed to perform limited font
  482. Xselection. The permitted escape sequences have the following format: .nf
  483. X
  484. X        <escape><command>
  485. X.fi
  486. X
  487. XThe following sequences are recognized:
  488. X
  489. X.nf
  490. X         \\033B     begin bold (in current font family)
  491. X         \\033b     end bold
  492. X         \\033I     begin italics
  493. X         \\033i     end italics
  494. X         \\033U     begin underline
  495. X         \\033u     end underline.
  496. X         \\033Fn    begin font 'n' (0..7)
  497. X         \\033f     revert to default font
  498. X         \\033Pnn   begin point size 'nn' (2 digits)
  499. X         \\033p     revert to default point size
  500. X.fi
  501. X
  502. XNote that point sizes with \\033Pnn must be two digits such as \\033P07 or \\033P14.
  503. X
  504. XSequences may be nested: bold, italic, underlined would be 
  505. Xgenerated with:
  506. X.nf
  507. X
  508. X     \\033B\\033I\\033Ubold, italic and underlined\\033u\\033i\\033b
  509. X.fi
  510. X
  511. XThe underline sequence should be 'innermost' to ensure that the
  512. Xunderline follows the exact font width.
  513. X
  514. XAny unrecognized escape sequences are ignored.
  515. X
  516. XAny filter that can construct the above escape sequences may be
  517. Xused to provide input to psf.  The provided "pnf" and "pmf"
  518. Xare only two simple examples.
  519. X
  520. X.RS -5
  521. XPNF NOTES
  522. X.RE
  523. XPnf is a filter that converts "backspaced text" generated by nroff
  524. Xinto escape sequences that can be used by psf to generate
  525. Xunderlined or bold text. The conversion results 
  526. Xin the following generated sequences:
  527. X.nf
  528. X
  529. X        \\033B..text..\\033b   for bold
  530. X        \\033U..text..\\033u   for underline
  531. Xor
  532. X        \\033I..text..\\033i   for italics
  533. X
  534. X(italics instead of underline selected with -i option)
  535. X
  536. X.fi
  537. XSince the text from nroff does not have a decent way of identifying
  538. Xitalics, you may use the -i option to generate the "italic" instead of
  539. X"underline" escape sequence whenever an underline is detected in the
  540. Xinput text.
  541. X
  542. XThe logic cannot handle bold-underlined (nor italic-underlined).
  543. X
  544. XXenix man-pages sometime generate fewer than the expected 60
  545. Xlines per page.  The "-x" option ensures that extra
  546. Xblank lines are inserted to fill to 60 lines.  This may cause
  547. Xan unnecessary blank page at the end.
  548. X
  549. X.RS -5
  550. XPMF NOTES
  551. X.RE
  552. XPmf is a very simple mail printing filter.  It italicizes the 'Subject:'
  553. Xand attempts to place peoples names in boldface. 
  554. XIt can be used to print
  555. Xentire mail boxes, however all headers except 'Received:' 
  556. Xand 'Message-ID:' are printed.
  557. X
  558. XIf pmf and psf are used with ELM, the user's elmrc file should be modified
  559. Xto specify the following "print" line (or reasonable approximation):
  560. X
  561. X.nf
  562. X      print = /usr/bin/pmf < %s | /usr/bin/psf -2 | /usr/bin/lp
  563. X.fi
  564. X
  565. X.RS -5
  566. XAUTHOR
  567. X.RE
  568. X.nf
  569. XTony Field.         tony@ajfcal
  570. X.fi
  571. X
  572. END_OF_FILE
  573. if test 8529 -ne `wc -c <'psf.1'`; then
  574.     echo shar: \"'psf.1'\" unpacked with wrong size!
  575. fi
  576. # end of 'psf.1'
  577. fi
  578. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  579.   echo shar: Will not clobber existing file \"'Makefile'\"
  580. else
  581. echo shar: Extracting \"'Makefile'\" \(2240 characters\)
  582. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  583. X#    Make the psf postscript filter system
  584. X#
  585. X#    usage:    make all    -> to compile all source
  586. X#
  587. X#        make install    -> copy binaries to target directory (UNIX)
  588. X#
  589. X#        make xenix    -> copy binaries to target directory
  590. X#                   and invoke "mkdev lp"   (XENIX)
  591. X#
  592. X# - - - - Begin configuration - - - - -
  593. X#
  594. X# Underline parametrics within FontInfo is not guaranteed.
  595. X# If you have implemented non-standard fonts without underline information
  596. X# in FontInfo, the provide the -DFONTINFO manifest.
  597. X
  598. X# CFLAGS = -O  -DFONTINFO
  599. X
  600. XCFLAGS = -O
  601. X
  602. X
  603. X# Location of binaries
  604. X
  605. XBINDIR=/usr/bin
  606. X
  607. X
  608. X# Psf default options for use with Xenix lp system
  609. X#    The following are suggested:
  610. X#
  611. X#    PSFOPT =                      uses default of 60 line per page
  612. X#                                     in portrait mode
  613. X# or:
  614. X#       PSFOPT = -2 -l80              Prints pages 2-up in landscape
  615. X#                                     mode with 80 columns per logical page.
  616. X#                                     (A nice way to save paper)
  617. X
  618. XPSFOPT =
  619. X
  620. X
  621. X# - - - - - end configuration - - - - - - - -
  622. X
  623. X
  624. XSOURCES  = psf.c pnf.c pmf.c psbanner.c psdetect.c
  625. XOBJECTS  = psf.o pnf.o pmf.o psbanner.o psdetect.o
  626. XBINARIES = psf   pnf   pmf   psbanner   psdetect
  627. X
  628. Xall:    $(BINARIES)
  629. X
  630. Xshar:
  631. X    rm -f psf.shar
  632. X    shar Readme Readme.Xenix psf.1 Makefile $(SOURCES) postscript.LP testfile > psf.shar
  633. X
  634. Xtwoshar:
  635. X    rm -f psf1.shar
  636. X    rm -f psf2.shar
  637. X    shar -n1 -e2 Readme Readme.Xenix psf.1 Makefile postscript.LP testfile psbanner.c psdetect.c >psf1.shar
  638. X    shar -n2 -e2 psf.c pmf.c pnf.c > psf2.shar
  639. X
  640. X# Unix install
  641. X
  642. Xinstall:
  643. X    cp psf $(BINDIR)
  644. X    cp pnf $(BINDIR)
  645. X    cp pmf $(BINDIR)
  646. X
  647. X# Install Xenix: copy all executables to the binary directory
  648. X#         edit the BINARY and OPTIONS into postscript.psf model
  649. X#          copy the "postscript model" shell script to the
  650. X#               lp spool directory.
  651. X#         call "mkdev lp" to create a postscript printer.
  652. X
  653. Xxenix:    $(BINARIES)
  654. X    cp $(BINARIES) $(BINDIR)
  655. X    rm -f postscript.psf
  656. X    sed 's@BINARY@$(BINDIR)@g' postscript.LP | sed 's@OPTIONS@$(PSFOPT)@g' > postscript.psf
  657. X    chmod +rw postscript.psf
  658. X    cp postscript.psf /usr/spool/lp/model/postscript.psf
  659. X    chown lp  /usr/spool/lp/model/postscript.psf
  660. X    chgrp bin /usr/spool/lp/model/postscript.psf
  661. X    mkdev lp
  662. X
  663. Xclean:
  664. X    rm -f *.o core postscript.psf *.B
  665. X    rm -f $(BINARIES)
  666. END_OF_FILE
  667. if test 2240 -ne `wc -c <'Makefile'`; then
  668.     echo shar: \"'Makefile'\" unpacked with wrong size!
  669. fi
  670. # end of 'Makefile'
  671. fi
  672. if test -f 'psf.c' -a "${1}" != "-c" ; then 
  673.   echo shar: Will not clobber existing file \"'psf.c'\"
  674. else
  675. echo shar: Extracting \"'psf.c'\" \(21778 characters\)
  676. sed "s/^X//" >'psf.c' <<'END_OF_FILE'
  677. X/* ta=4 */
  678. X/****************************************************************************
  679. X*                    p s f . c        v1.1                                    *
  680. X*                                                                            *
  681. X*    Postscript filter                                                        *
  682. X*                                                                            *
  683. X*    Print text files to postscript printer.  Allow 1-up, 2-up and 4-up        *
  684. X*    pages.  Provisions are made to allow font selection by imbedded            *
  685. X*    escape sequences - to allow printing of man pages.  The escape sequence    *
  686. X*    generated by "pnf" and "pmf" are compatible with psf.                    *
  687. X*                                                                            *
  688. X*    Tony Field.       tony@ajfcal  (or: calgary!ajfcal!tony@ai.toronto.edu)    *
  689. X*                                                                            *
  690. X*    The orginal underline algorithm (/showunderline) was provided by        *
  691. X*    Anders Thulin        mcvax!helios!ath@uunet.uucp                        *
  692. X****************************************************************************/
  693. X
  694. X#include <stdio.h>
  695. X#include <time.h>
  696. X
  697. X/*    set up the mechanism for underline display */
  698. X
  699. X#ifndef FONTINFO
  700. X#define SHOWU(fp,ps)    fprintf (fp, ") %d showuline\n", ps)
  701. X#else
  702. X#define SHOWU(fp,ps)    fputs (") showunderline\n", fp)
  703. X#endif
  704. X
  705. X#define LONG_STR    1000    /* long buffer line                            */
  706. X#define ESCAPE        0x1b
  707. X
  708. X/* Paper physical dimensions. */
  709. X
  710. X#define    P_HEIGHT    792            /* 72dpi x 11 inch                            */
  711. X#define P_WIDTH        612            /* 72dpi x 8.5 inch                            */
  712. X#define NOMINAL        60            /* number of "expected" lines on page        */
  713. X
  714. X#define NORMAL        0x00        /* bitset for  print_attributes                */
  715. X#define ITALICS        0x01
  716. X#define BOLD        0x02
  717. X#define UNDERLINE    0x04        /* must be 0x04.  underline is not a font    */
  718. X
  719. X/* Current information about page.  Where are we, etc.  
  720. X*/
  721. X
  722. Xint        x,y;                    /* current x,y coordinate                    */
  723. X
  724. Xint        book = 0;                /* book format: double sided                */
  725. Xint        lines_on_page = 60;
  726. Xint        page_number;            /* current page number for this file        */
  727. Xint        physical_page = -1;        /* postscript physical page for multi-up    */
  728. Xfloat    scale_x, scale_y;        /* scale factors for 2-up, 4-up printing    */
  729. Xint        do_scale = 0;            /* 1 = must scale image,  0 = dont scale    */
  730. Xint        landscape = 0;            /* 1 = landscape, 0 = portrait layout        */
  731. Xint        header    = 0;            /* 1 = print header at top of each page        */
  732. Xint        cross      = 0;            /* 1 = print cross on 4-up pages            */
  733. Xint        line_number    = 0;        /* current logical line number on page        */
  734. Xint        tab_size   = 8;            /* space translation for tabs.                */
  735. Xint        print_attribute = 0;    /* such as BOLD, UNDERLINE, ITALICS            */
  736. Xint        font_number = 0;        /* one of the valid fonts in the printer    */
  737. Xint        default_font_number;    /* set with -f option, or 0                    */
  738. Xint        point_size    = 12;        /* can be changed with the -p option        */
  739. Xint        default_point_size;        /* assumes value due to -p option            */
  740. Xint        y_coord        = 0;        /* current logical page y-coordinate, points*/
  741. Xint        x_coord        = 0;        /* current logical page x-coordinate, points*/
  742. Xint        x_offset    = 0;
  743. Xint        y_offset    = 0;
  744. Xchar    header_text[100];
  745. X
  746. X/*    indent space "forbidden zone" */
  747. X
  748. Xint top_marg  = 36;            /* 1/2 inch = 36/72        */
  749. Xint bot_marg  = 36;
  750. Xint left_marg = 36;
  751. Xint    default_left_marg;
  752. Xint logical_top;            /* where does printing start at top of page, points */
  753. X
  754. Xchar    fname[100];
  755. Xchar    now[50];            /* time of day for page headers                 */
  756. X
  757. X
  758. X/*    to select a font, use 4 * font_number + print_attribute as index.
  759. X    e.g.   If font_number = 1    for Helvetica,
  760. X      and print_attribute = 0x02 for BOLD
  761. X
  762. X    then the actual font selected is    fonts[4 * 1 + 2]
  763. X                                        = Helvetica-Bold
  764. X
  765. X    The various print attributes can be OR'ed together:
  766. X            fonts [4 * 1 + ITALICS | BOLD] 
  767. X*/
  768. X      
  769. X#define NFONTS      36        /*     4 variations * 9 font families  */
  770. Xchar *fonts[NFONTS] =
  771. X{
  772. X    "Courier",                    "Courier-Oblique",            "Courier-Bold",             "Courier-BoldOblique",
  773. X    "Helvetica",                 "Helvetica-Oblique",         "Helvetica-Bold",            "Helvetica-BoldOblique",
  774. X    "Times-Roman",                 "Times-Italic",             "Times-Bold",                 "Times-BoldItalic",
  775. X    "AvantGarde-Book",          "AvantGarde-BookOblique",   "AvantGarde-Demi",          "AvantGarde-DemiOblique",
  776. X    "Bookman-Light",            "Bookman-LightItalic",      "Bookman-Demi",             "Bookman-DemiItalic",
  777. X    "NewCenturySchlbk-Roman",   "NewCenturySchlbk-Italic",  "NewCenturySchlbk-Bold",    "NewCenturySchlbk-BoldItalic",
  778. X    "Palatino-Roman",           "Palatino-Italic",          "Palatino-Bold",            "Palatino-BoldItalic",
  779. X    "ZapfChancery-MediumItalic","ZapfChancery-MediumItalic","ZapfChancery-MediumItalic","ZapfChancery-MediumItalic",
  780. X    "Helvetica-Narrow",         "Helvetica-Narrow-Oblique", "Helvetica-Narrow-Bold",    "Helvetica-Narrow-BoldOblique"
  781. X} ;
  782. X
  783. Xint    max_frame    = 1;        /* max number of frames in use */
  784. Xint    frame        = -1;        /* current frame in use */
  785. X
  786. X/*    incremental values to be added to the current "0,0" for translation
  787. X    to each display frame.  The printer starts at "start (0,0)"
  788. X    then moves to (0, P_HEIGHT), then (0,-P_HEIGHT), etc.
  789. X                +---+---+
  790. X                | 0 | 2 |
  791. X                +---+---+
  792. X                | 1 | 3 |
  793. X    start (0,0)>+---+---+
  794. X
  795. X*/
  796. Xint    up_4x[4] = {0,            0,            P_WIDTH,    0            };
  797. Xint    up_4y[4] = { P_HEIGHT,    -P_HEIGHT,    P_HEIGHT,    -P_HEIGHT    };
  798. X
  799. Xint    up_2x[2] = {0,            P_WIDTH };
  800. Xint up_2y[2] = {0,            0         };
  801. X
  802. Xint up_1x    = 0;
  803. Xint    up_1y     = 0;
  804. X
  805. Xint        home_x = 0;            /* logical (0,0) coordinate position in points    */
  806. Xint        home_y = 0;
  807. X
  808. X
  809. Xdouble    correction;            /* scale correction factor for lines on a page    */
  810. Xint        do_correction;
  811. X
  812. XFILE    *input_fp, *output_fp;
  813. X
  814. X/*    input line and input line pointer */
  815. Xunsigned char    *c;
  816. Xunsigned char    line[LONG_STR + 1];
  817. X
  818. Xmain (argc, argv)
  819. Xint        argc;
  820. Xchar    *argv[];
  821. X{    int        c, i;
  822. X    extern char *optarg;
  823. X    extern int    optind;
  824. X
  825. X    *header_text = '\0';
  826. X    correction = 1.0;
  827. X    scale_x = 1.0;
  828. X    scale_y = 1.0;
  829. X    while ((c = getopt(argc, argv, "124xhbwH:l:f:t:p:-")) != -1)
  830. X    {    switch (c)
  831. X        {
  832. X        case '1':
  833. X            max_frame = 1;
  834. X            scale_x = 1.0;
  835. X            scale_y = 1.0;
  836. X            do_scale = 0;
  837. X            break;
  838. X            
  839. X        case '2':
  840. X            landscape = 1;
  841. X            max_frame = 2;
  842. X            scale_x = 0.647;
  843. X            scale_y = 0.772;
  844. X            do_scale = 1;
  845. X            home_x = P_HEIGHT / 2;
  846. X            home_y = 0;
  847. X            break;
  848. X        
  849. X        case '4':
  850. X            max_frame = 4;
  851. X            scale_x = 0.5;
  852. X            scale_y = 0.5;
  853. X            do_scale = 1;
  854. X            home_x = P_WIDTH;
  855. X            home_y = 0;
  856. X            break;
  857. X        
  858. X        case 'h':
  859. X            header = 1;
  860. X            break;
  861. X            
  862. X        case 'H':
  863. X            header = 2;
  864. X            strcpy (header_text, optarg);
  865. X            break;
  866. X            
  867. X        case 'w':
  868. X            landscape = 1;
  869. X            do_scale = 1;
  870. X            break;
  871. X            
  872. X        case 'l':
  873. X            lines_on_page = atoi (optarg);
  874. X            break;
  875. X            
  876. X        case 'p':
  877. X            point_size = atoi (optarg);
  878. X            break;
  879. X            
  880. X        case 'x':
  881. X            cross = 1;
  882. X            break;
  883. X
  884. X        case 'f':
  885. X            font_number = atoi (optarg);
  886. X            if (font_number > (NFONTS / 4))
  887. X                font_number = (NFONTS / 4) - 1;
  888. X            break;
  889. X
  890. X        case 't':
  891. X            tab_size = atoi (optarg);
  892. X            break;
  893. X        
  894. X        default:    usage ();
  895. X            break;
  896. X        }
  897. X    }
  898. X
  899. X    if (max_frame == 4  &&  landscape)
  900. X    {
  901. X        scale_x = 0.500;
  902. X        scale_y = 0.380;
  903. X    }
  904. X    else if (max_frame ==  1 &&  landscape)
  905. X    {
  906. X        scale_x = 0.647;
  907. X        scale_y = 0.772;
  908. X    }
  909. X
  910. X    /*    all margins should be scaled.  However, if we do that, then the
  911. X        printing of man-pages 4-up will not work as desired.
  912. X    */
  913. X    if (do_scale)
  914. X    {
  915. X/*
  916. X        top_marg  = (float) top_marg / scale_y;
  917. X        bot_marg  = (float) bot_marg / scale_y;
  918. X*/
  919. X        left_marg = (float) left_marg / scale_x;
  920. X
  921. X    }
  922. X
  923. X    if (font_number * 4 > NFONTS)
  924. X    {    fprintf (stderr,"Font number invalid....\n");
  925. X        usage ();
  926. X    }
  927. X    
  928. X    if (header)
  929. X        lines_on_page += 2;
  930. X
  931. X    /*    If anything adjusts the number of lines on a page, then scale
  932. X        the page size rather than scale the point size.  Then point
  933. X        size can be an integer with little problem
  934. X    */
  935. X    if (lines_on_page > NOMINAL)
  936. X    {    correction = (((double) NOMINAL) / ((double) lines_on_page));
  937. X        scale_y *= correction;
  938. X        scale_x *= correction;
  939. X        top_marg /= correction;
  940. X        do_correction = 1;
  941. X    }
  942. X    else
  943. X        do_correction = 0;
  944. X
  945. X    output_fp = stdout;
  946. X    prologue (output_fp);
  947. X
  948. X    logical_top = P_HEIGHT - top_marg;
  949. X    page_number = -1;
  950. X    line_number = 32767;
  951. X    default_point_size = point_size;
  952. X    default_font_number = font_number;
  953. X    default_left_marg = left_marg;
  954. X
  955. X    *fname = 0;    
  956. X    get_time (now);        
  957. X    if (optind >=  argc)
  958. X    {    if (header == 1)
  959. X            header = 0;
  960. X        start_file ();
  961. X        input_fp = stdin;
  962. X        process_file ();
  963. X        terminate_file ();
  964. X    }
  965. X    else for ( ;  optind < argc;  optind++)
  966. X    {    i = strlen (argv[optind]);
  967. X        if (i > 38)
  968. X            i -= 38;
  969. X        else
  970. X            i = 0;
  971. X        strcpy (fname, argv[optind] + i);
  972. X        if ((input_fp = fopen (argv[optind], "r")) == NULL)
  973. X        {    fprintf (stderr, "Unknown file: %s\n", argv[optind]);
  974. X            continue;
  975. X        }
  976. X        start_file ();
  977. X        process_file ();
  978. X        terminate_file ();
  979. X        fclose (input_fp);
  980. X    }
  981. X    terminate_printer ();
  982. X    if (book)
  983. X        output_book ();
  984. X
  985. X    exit (0);
  986. X}
  987. X
  988. X/****************************************************************************
  989. X*    prologue ()                                                                *
  990. X*    generate the require postscript-conformant prologue                        *
  991. X****************************************************************************/
  992. X
  993. Xprologue ()
  994. X{
  995. X    fprintf (output_fp, "%%!PS-Adobe-\n");
  996. X
  997. X#ifndef FONTINFO
  998. X    /*     The red book (pg 93) indicates that the FontInfo dictionary
  999. X        "MAY" contain the /UnderlinePosition and /UnderlineThickness
  1000. X        This is the case for all Adobe fonts.  External non-Adobe fonts may
  1001. X        not have these values.
  1002. X        
  1003. X        usage:         (text to underline) <pointsize> showuline
  1004. X        where:        <pointsize> is current text point size.
  1005. X
  1006. X        eg:            (text to underline) 12 showuline
  1007. X    */
  1008. X    fprintf (output_fp, "%s%s%s%s%s%s%s%s%s%s",
  1009. X            "/showuline {\n",
  1010. X            "    /CurPointSize exch def\n",
  1011. X            "    dup stringwidth pop\n",
  1012. X            "    gsave\n",
  1013. X            "    currentfont /FontInfo get dup\n",
  1014. X            "    /UnderlinePosition get CurPointSize mul 1000 div 0 exch rmoveto exch 0 rlineto\n",
  1015. X            "    /UnderlineThickness get CurPointSize mul 1000 div setlinewidth stroke\n",
  1016. X            "    grestore\n",
  1017. X            "    show\n",
  1018. X            "} def\n");
  1019. X
  1020. X#else
  1021. X    /*    showunderline: without FontInfo:  underline is 2 points below base 
  1022. X        compliments of Anders Thulin
  1023. X                        mcvax!helios!ath@uunet.uucp (Anders Thulin)
  1024. X
  1025. X        usage:        (text to underline) showunderline
  1026. X    */
  1027. X    fprintf (output_fp, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
  1028. X            "/showunderline {\n",
  1029. X            "  /str exch def\n",
  1030. X            "  /dy     0 def\n",
  1031. X            "  currentpoint\n",
  1032. X            "    str show\n",
  1033. X            "  moveto\n",
  1034. X            "  /dy -2 def\n",
  1035. X            "  currentpoint\n",
  1036. X            "  dy add\n",
  1037. X            "  moveto\n",
  1038. X            "  str stringwidth\n",
  1039. X            "  rlineto \n",
  1040. X            "  currentpoint\n",
  1041. X            "    stroke\n",
  1042. X            "  moveto\n",
  1043. X            "  currentpoint\n",
  1044. X            "  dy sub\n",
  1045. X            "  moveto\n",
  1046. X            "} def\n");
  1047. X#endif
  1048. X
  1049. X    fprintf (output_fp, "%%%%EndProlog\n");
  1050. X}
  1051. X
  1052. X/****************************************************************************
  1053. X*    new_page ()                                                                *
  1054. X*    Generate a new page.  Send out required rotation,scale information        *
  1055. X*    This is the "prologue" to a page (not the end of the previous)            *
  1056. X****************************************************************************/
  1057. X
  1058. Xnew_page ()
  1059. X{
  1060. X}
  1061. X
  1062. X
  1063. X/****************************************************************************
  1064. X*    showpage ()                                                                *
  1065. X*    Generate a real "showpage" if we have really finished generating a        *
  1066. X*    physical page.  If we are processing 2 or 4 up, then generate             *
  1067. X*    coordinate "translates" if we really haven't finished all possible        *
  1068. X*    page frames of the page.                                                *
  1069. X****************************************************************************/
  1070. X
  1071. Xshowpage (end_of_file)
  1072. Xint end_of_file;
  1073. X{
  1074. X    line_number = 0;
  1075. X
  1076. X    if (++frame >= max_frame  ||  end_of_file) 
  1077. X    {
  1078. X        fprintf (output_fp, "showpage pg restore\n");
  1079. X        frame = 0;
  1080. X    }
  1081. X    if (!end_of_file)
  1082. X        set_frame ();
  1083. X}
  1084. X
  1085. X/****************************************************************************
  1086. X*    set_frame ()                                                            *
  1087. X*    Select the next logical frame in two-up or four-up mode.  If it is        *
  1088. X*    the first frame of a physical page, the generate the %%Page                *
  1089. X****************************************************************************/
  1090. X
  1091. Xset_frame ()
  1092. X{
  1093. X    if (frame == 0)
  1094. X    {    left_marg = default_left_marg;
  1095. X        fprintf (output_fp, "%%%%Page: ? %d\n", ++physical_page);
  1096. X        fprintf (output_fp, "/pg save def\n");
  1097. X
  1098. X        if (landscape)
  1099. X            fprintf (output_fp, "90 rotate 0 %d translate\n", -P_WIDTH);
  1100. X
  1101. X        if (do_scale  ||  do_correction)
  1102. X            fprintf (output_fp, "%.3f %.3f scale\n", scale_x, scale_y);
  1103. X
  1104. X        findfont();
  1105. X    }
  1106. X    set_y_coord ();
  1107. X    
  1108. X    switch (max_frame)
  1109. X    {
  1110. X    case 2:
  1111. X        fprintf (output_fp, "%d %d translate\n", (int) (up_2x[frame] / correction), (int) (up_2y[frame] / correction));
  1112. X        break;
  1113. X
  1114. X    case 4:
  1115. X        if (frame == 2)            /* better for 4-up layout */
  1116. X            left_marg /= 2;
  1117. X        fprintf (output_fp, "%d %d translate\n", (int) (up_4x[frame] / correction), (int) (up_4y[frame] / correction));
  1118. X        break;
  1119. X
  1120. X    default:
  1121. X        break;
  1122. X    }
  1123. X
  1124. X    if (frame == 0  &&  cross)
  1125. X        draw_cross();
  1126. X
  1127. X}
  1128. X
  1129. X
  1130. X/****************************************************************************
  1131. X*    set_y_coord                                                                *
  1132. X*    position next line to the top of a logical page.                        *
  1133. X*****************************************************************************/
  1134. X
  1135. Xset_y_coord ()
  1136. X{
  1137. X    y_coord = P_HEIGHT;
  1138. X    if (do_correction)
  1139. X    {    y_coord = ((double) y_coord) / correction;
  1140. X        x_coord = ((double) x_coord) / correction;
  1141. X    }
  1142. X}
  1143. X/****************************************************************************
  1144. X*    put_top                                                                    *
  1145. X*    put a header line at the top of the page                                *
  1146. X*****************************************************************************/
  1147. X
  1148. Xput_top ()
  1149. X{
  1150. X    int    save_attr, save_point;
  1151. X    
  1152. X    save_attr = print_attribute;
  1153. X    save_point = point_size;
  1154. X    print_attribute = BOLD;
  1155. X    point_size = 12;
  1156. X    
  1157. X    findfont();
  1158. X    moveto (x_coord + left_marg, y_coord - top_marg, 1);
  1159. X    if (header == 1)
  1160. X        fprintf (output_fp, "(%-40s %3d     %s)show\n", fname, page_number + 1, now);
  1161. X    else
  1162. X        fprintf (output_fp, "(%-40s %3d     %s)show\n", header_text, page_number + 1, now);
  1163. X    y_coord -= point_size * 2;
  1164. X    x_coord = 0;
  1165. X    print_attribute = save_attr;
  1166. X    point_size = save_point;
  1167. X    findfont();
  1168. X}
  1169. X
  1170. X/****************************************************************************
  1171. X*    process_file()                                                            *
  1172. X*    Read the file, look for escape sequences, put text in postscript form    *
  1173. X****************************************************************************/
  1174. X
  1175. Xprocess_file ()
  1176. X{
  1177. X    int        char_type, char_count, i, set_page, esc_type;
  1178. X    char    *strchr ();
  1179. X    int        previous_attribute;
  1180. X    int        lcount = 0;
  1181. X    
  1182. X    set_page = 0;
  1183. X    while (fgets (line, LONG_STR, input_fp) != NULL)
  1184. X    {
  1185. X        if (lcount++ == 0)
  1186. X        {    if ((i = tscan (line, "ta=")) >= 0)
  1187. X            {    tab_size = atoi (line + i + 3);
  1188. X            }
  1189. X        }
  1190. X        if ((c = strchr (line, '\f')) != NULL)
  1191. X        {
  1192. X            if (c == line)
  1193. X            {    line_number += 1000;
  1194. X                c = line + 1;
  1195. X            }
  1196. X            else
  1197. X            {    *c = 0;
  1198. X                set_page = 1;
  1199. X                c = line;
  1200. X            }
  1201. X        }
  1202. X        else
  1203. X            c = line;
  1204. X
  1205. X        if (line_number++ >= lines_on_page)
  1206. X        {    page_number++;
  1207. X            showpage (0);
  1208. X            line_number = 1;
  1209. X            if (header)
  1210. X            {
  1211. X                put_top();
  1212. X                line_number += 2;
  1213. X            }
  1214. X        }
  1215. X        char_type = char_count = 0;
  1216. X
  1217. X        if (*c == '\n')
  1218. X            moveto (x_coord + left_marg, y_coord - top_marg, 0);
  1219. X        else
  1220. X            moveto (x_coord + left_marg, y_coord - top_marg, 1);
  1221. X
  1222. X        while (*c  && *c != '\n')
  1223. X        {
  1224. X            if (char_type == 0)
  1225. X                fputc ('(', output_fp);
  1226. X                
  1227. X            switch ((int) *c)
  1228. X            {
  1229. X            case ESCAPE:
  1230. X                previous_attribute = print_attribute;
  1231. X                esc_type = *(++c);
  1232. X                if (escape_sequence (esc_type) == 0)
  1233. X                {
  1234. X                    switch (esc_type)
  1235. X                    {
  1236. X                    case 'u':
  1237. X                        SHOWU (output_fp, point_size);
  1238. X                        break;
  1239. X
  1240. X                    default:
  1241. X                        if (char_type  &&  (previous_attribute & UNDERLINE))
  1242. X                            SHOWU (output_fp, point_size);
  1243. X                        else
  1244. X                            fputs (")show\n", output_fp);
  1245. X                        findfont (output_fp);
  1246. X                    }
  1247. X                    char_type = 0;
  1248. X                }
  1249. X                break;
  1250. X                
  1251. X            default:
  1252. X                if (*c == '\t')
  1253. X                {
  1254. X                    fputc (' ', output_fp);
  1255. X                    while (++char_count % tab_size)
  1256. X                        fputc (' ', output_fp);
  1257. X                }
  1258. X                else
  1259. X                {    if (strchr ("\r\b\\()", *c) != NULL)
  1260. X                        fputc ('\\', output_fp);
  1261. X                    fputc (*c, output_fp);
  1262. X                    char_count++;
  1263. X                }
  1264. X                char_type = 1;
  1265. X                break;
  1266. X            }
  1267. X            c++;
  1268. X        }
  1269. X        if (char_type)
  1270. X        {    if (print_attribute & UNDERLINE)
  1271. X                SHOWU (output_fp, point_size);
  1272. X            else
  1273. X                fputs (")show\n", output_fp);
  1274. X        }
  1275. X
  1276. X        y_coord -= point_size;
  1277. X        x_coord = 0;
  1278. X        if (set_page)
  1279. X        {    line_number += 1000;
  1280. X            set_page = 0;
  1281. X        }
  1282. X    }
  1283. X}
  1284. X
  1285. X/****************************************************************************
  1286. X*    escape_sequence ()                                                        *
  1287. X*    If an escape sequence (esc,char) is found, mark which type of font        *
  1288. X****************************************************************************/
  1289. X
  1290. Xint escape_sequence (which)
  1291. Xint    which;
  1292. X{    unsigned char    s[10];
  1293. X
  1294. X    switch (which)
  1295. X    {
  1296. X    case 'I':
  1297. X        print_attribute |= ITALICS;
  1298. X        break;
  1299. X
  1300. X    case 'i':
  1301. X        print_attribute &= ~ITALICS;
  1302. X        break;
  1303. X
  1304. X    case 'B':
  1305. X        print_attribute |= BOLD;
  1306. X        break;
  1307. X
  1308. X    case 'b':
  1309. X        print_attribute &= ~BOLD;
  1310. X        break;
  1311. X
  1312. X    case 'U':
  1313. X        print_attribute |= UNDERLINE;
  1314. X        break;
  1315. X
  1316. X    case 'u':
  1317. X        print_attribute &= ~UNDERLINE;
  1318. X        break;
  1319. X    
  1320. X    case 'F':
  1321. X        s[0] = *(++c);
  1322. X        s[1] = '\0';
  1323. X        font_number = atoi (s);        
  1324. X        if (font_number > (NFONTS / 4))
  1325. X            font_number = (NFONTS / 4) - 1;
  1326. X        break;
  1327. X    
  1328. X    case 'f':
  1329. X        font_number = default_font_number;
  1330. X        break;
  1331. X        
  1332. X    case 'P':
  1333. X        s[0] = *(++c);
  1334. X        s[1] = *(++c);
  1335. X        s[2] = '\0';
  1336. X        point_size = atoi (s);
  1337. X        break;
  1338. X
  1339. X    case 'p':
  1340. X        point_size = default_point_size;
  1341. X        break;
  1342. X    
  1343. X    default:
  1344. X        return (-1);
  1345. X        ;
  1346. X    }
  1347. X    return (0);
  1348. X}
  1349. X
  1350. X/****************************************************************************
  1351. X*    moveto ()                                                                *
  1352. X*    Generate a postscript     x y moveto    statememt                        *
  1353. X****************************************************************************/
  1354. X
  1355. Xmoveto (x, y, do_move)
  1356. Xint    x;
  1357. Xint    y;
  1358. Xint do_move;
  1359. X{
  1360. X
  1361. X    if (line_number > lines_on_page  ||  y  < bot_marg)
  1362. X    {    showpage (0);
  1363. X        if (header)
  1364. X        {
  1365. X            put_top();
  1366. X            line_number += 2;
  1367. X        }
  1368. X        y = y_coord - top_marg;
  1369. X        x = x_coord + left_marg;
  1370. X    }
  1371. X    if (do_move)
  1372. X        fprintf (output_fp, "%d %d moveto\n", x, y);
  1373. X}
  1374. X
  1375. X/****************************************************************************
  1376. X*    findfont ()                                                                *
  1377. X*    generate a findfont statement                                            *
  1378. X****************************************************************************/
  1379. X
  1380. Xfindfont ()
  1381. X{    int    this;
  1382. X
  1383. X    /*    remove reference to UNDERLINE.  Underline is not a font.    */
  1384. X    
  1385. X    this = (font_number * 4) + (print_attribute & 0x03);
  1386. X    fprintf (output_fp, "/%s findfont %d scalefont setfont\n", fonts[this], point_size);
  1387. X}
  1388. X
  1389. X/****************************************************************************
  1390. X*    start_file ()                                                            *
  1391. X*    Generate things that are appropriate for beginning of file processing    *
  1392. X****************************************************************************/
  1393. X
  1394. Xstart_file ()
  1395. X{
  1396. X    line_number = 0;
  1397. X    print_attribute = 0;
  1398. X    page_number = 0;
  1399. X    frame = -1;
  1400. X    showpage (0);
  1401. X    if (header)
  1402. X    {
  1403. X        put_top();
  1404. X        line_number += 2;
  1405. X    }
  1406. X}
  1407. X
  1408. X/****************************************************************************
  1409. X*    terminate_file ()                                                        *
  1410. X*    Generate things that are appropriate for end of file processing            *
  1411. X****************************************************************************/
  1412. X
  1413. Xterminate_file ()
  1414. X{
  1415. X    showpage (1);
  1416. X}
  1417. X
  1418. X
  1419. X/****************************************************************************
  1420. X*    terminate_printer ()                                                    *
  1421. X*    Generate things that are appropriate wrap-up after all files printed    *
  1422. X****************************************************************************/
  1423. X
  1424. Xterminate_printer ()
  1425. X{
  1426. X    fprintf (output_fp, "%%%%Trailer\n");
  1427. X    fprintf (output_fp, "%c", 0x04);        /* CTL/D = end job */
  1428. X}
  1429. X
  1430. X/****************************************************************************
  1431. X*    draw_cross ()                                                            *
  1432. X*    Draw horizontal and vertical separation lines between pages 4-up        *
  1433. X****************************************************************************/
  1434. X
  1435. Xdraw_cross ()
  1436. X{    int     p_w, p_h;
  1437. X
  1438. X    
  1439. X    if (max_frame == 4)
  1440. X    {
  1441. X        p_w = P_WIDTH  / correction;
  1442. X        p_h = P_HEIGHT / correction;
  1443. X        fprintf (output_fp,"%d %d moveto\n", p_w, p_h);
  1444. X        fprintf (output_fp,"%d %d lineto\n", p_w, -p_h);
  1445. X        fprintf (output_fp,"%d %d moveto\n", 0, 0);
  1446. X        fprintf (output_fp,"%d %d lineto\n", p_w * 2, 0);
  1447. X        fprintf (output_fp,"%s\n", "stroke");
  1448. X    }
  1449. X}
  1450. X
  1451. X/****************************************************************************
  1452. X*    output_book ()                                                            *
  1453. X*    Send file "double sided print" mode.  Used to make a "book".            *
  1454. X*    Will pause the printer to ask for stack re-feed:  use /dev/lpt            *
  1455. X****************************************************************************/
  1456. X
  1457. Xoutput_book ()
  1458. X{
  1459. X    /* some day real soon now... */
  1460. X}
  1461. X
  1462. X
  1463. Xusage ()
  1464. X{    int        i;
  1465. X
  1466. X    fprintf (stderr,"%s\n%s\n\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n\n",
  1467. X    "Usage:    psf [ -l n ] [ -1|2|4 ] [ -f n ] [ -h ] [ -t n ]",
  1468. X    "              [ -H text ] [ -p n ] [ -w ] [ -x ] file file ..",
  1469. X    "   where        -l n      lines per page (default=60)",
  1470. X    "                -1|2|4    print 1,2 or 4 up on a page (default=1)",
  1471. X    "                -f n      font number to use (default=0=Courier)",
  1472. X    "                -h        put file name as header on each page",
  1473. X    "                -H text   put text as header on each page",
  1474. X    "                -t n      set tabs to n (default=8)",
  1475. X    "                -p n      set point size to n",
  1476. X    "                -w        set landscape (wide) format",
  1477. X    "                -x        draw cross with 4-up page",
  1478. X    "                file..    name of files to be printed (or stdin)",
  1479. X    "   output: stdout"),
  1480. X
  1481. X    fprintf (stderr,"Fonts selection with -f n\n");
  1482. X    for (i = 0;  i < NFONTS;  i+= 8)
  1483. X        if (i + 4 >= NFONTS)
  1484. X        fprintf (stderr, "%5d %-20s\n", i/4, fonts[i]);
  1485. X    else
  1486. X        fprintf (stderr, "%5d %-20s  %d %s\n", i/4, fonts[i], i/4+1, fonts[i+4]);
  1487. X    exit (0);
  1488. X}
  1489. X
  1490. X/************************************************
  1491. X*        tscan (s,t)                                *
  1492. X*        char    s[],t[];                        *
  1493. X*                                                *
  1494. X*    Index function as defined in K&R            *
  1495. X*    Look for string t in s                        *
  1496. X*                                                *
  1497. X*    return -1 if t does not exits in s            *
  1498. X*    else return array position of first            *
  1499. X*    character match                                *
  1500. X************************************************/
  1501. X
  1502. X
  1503. Xtscan (s, t)
  1504. Xchar     s[], t[];
  1505. X{
  1506. X    int    i, j, k;
  1507. X    for (i = 0;  s[i] != '\0';  i++)
  1508. X    {    for (j = i, k=0;  t[k] != '\0'  &&  s[j] == t[k];  j++, k++)
  1509. X            ;
  1510. X        if (t[k] == '\0')
  1511. X            return (i);
  1512. X    }
  1513. X    return (-1);
  1514. X}
  1515. X
  1516. Xget_time (t)
  1517. Xchar    *t;
  1518. X{
  1519. X    long    n_time, time ();
  1520. X    char    *x_time, *cc, *strchr();
  1521. X    
  1522. X    n_time = time (0);            /* get time */
  1523. X    x_time = ctime (&n_time);    /* convert ascii */
  1524. X    if ((cc = strchr (x_time, '\n')) != NULL)
  1525. X        *cc = '\0';
  1526. X    strcpy (t, x_time);
  1527. X}
  1528. X
  1529. END_OF_FILE
  1530. if test 21778 -ne `wc -c <'psf.c'`; then
  1531.     echo shar: \"'psf.c'\" unpacked with wrong size!
  1532. fi
  1533. # end of 'psf.c'
  1534. fi
  1535. if test -f 'pnf.c' -a "${1}" != "-c" ; then 
  1536.   echo shar: Will not clobber existing file \"'pnf.c'\"
  1537. else
  1538. echo shar: Extracting \"'pnf.c'\" \(4166 characters\)
  1539. sed "s/^X//" >'pnf.c' <<'END_OF_FILE'
  1540. X/* ta=4 */
  1541. X/****************************************************************************
  1542. X*                            p n f . c      v1.1                                *
  1543. X*                                                                            *
  1544. X*    postscript filter for nroff'ed text                                        *
  1545. X*                                                                            *
  1546. X*    Translate backspaces in n/troff documents to either BOLD or UNDERLINE    *
  1547. X*    for psf usage                                                            *
  1548. X*                                                                            *
  1549. X*    Tony Field.       tony@ajfcal (or: calgary!ajfcal!tony@ai.toronto.edu)    *
  1550. X****************************************************************************/
  1551. X
  1552. X/*    For each line in of input text, scan for backspaces.  Determine if
  1553. X    the operation is an underline (i.e. the preceeding character is
  1554. X    the "_") or if it is a bolding (the character after the underscore
  1555. X    is the same as the preceeding.
  1556. X    
  1557. X    Generate the sequence \033B..text..\033b   for bold
  1558. X                          \033U..text..\033u   for underline
  1559. X                          \033I..text..\033i   for italics
  1560. X
  1561. X    Since the text from nroff does not have a decent way of identifying
  1562. X    italics, you may make the decision to generate the "italic" or 
  1563. X    "underline" escape sequence  whenever an underline is detected in
  1564. X    the output.  Italic fonts look nicer than the underlines 2-up.
  1565. X
  1566. X    The logic cannot handle bold-underlined (nor italic-underlined).
  1567. X    This could be done with a bit of extra logic to manipulate bits
  1568. X    in the "how" vector.
  1569. X
  1570. X    Handle xenix 59 line man page error...  force to 60.
  1571. X*/
  1572. X
  1573. X#include <stdio.h>
  1574. X
  1575. X#define BEGIN_BOLD            "\033B"
  1576. X#define END_BOLD            "\033b"
  1577. X
  1578. X#define BEGIN_UNDERLINE        "\033U"
  1579. X#define END_UNDERLINE        "\033u"
  1580. X
  1581. X#define BEGIN_ITALICS        "\033I"
  1582. X#define END_ITALICS            "\033i"
  1583. X
  1584. X
  1585. Xmain (argc, argv)
  1586. Xint        argc;
  1587. Xchar    *argv[];
  1588. X{
  1589. X    int        c, n, i;
  1590. X    int        how[401];
  1591. X    char    line[401];
  1592. X    int        ii, lcount;
  1593. X    int        xenix = 0;
  1594. X    char    *underline_on, *underline_off;
  1595. X    extern char *optarg;
  1596. X    extern int    optind;
  1597. X    
  1598. X    underline_on  = BEGIN_UNDERLINE;
  1599. X    underline_off = END_UNDERLINE;
  1600. X    
  1601. X    while ((c = getopt(argc, argv, "ix-")) != -1)
  1602. X    {    switch (c)
  1603. X        {
  1604. X        case 'i':
  1605. X            underline_on  = BEGIN_ITALICS;
  1606. X            underline_off = END_ITALICS;
  1607. X            break;
  1608. X        
  1609. X        case 'x':
  1610. X            xenix = 1;
  1611. X            break;
  1612. X            
  1613. X        default:
  1614. X            usage ();
  1615. X        }
  1616. X    }
  1617. X        
  1618. X    n = lcount = 0;
  1619. X    clear (line, how, 400);
  1620. X    while (( c = getchar()) != EOF)
  1621. X    {
  1622. X        if (c == '\033')            /* ignore existing sequences */
  1623. X            getchar();
  1624. X            
  1625. X        else if (c == '\b')
  1626. X            n--;
  1627. X        else if (c == '\n')
  1628. X        {    how[n] = 0;
  1629. X            line[n] = 0;
  1630. X            if (xenix)                    /* adjust for xenix 59 line page */
  1631. X            {
  1632. X                lcount++;
  1633. X                if ((ii = tscan (line, "Page ")) > 0)
  1634. X                {
  1635. X                    /*    Xenix can generate less than 60 lines per page
  1636. X                        This almost guarantees an extra blank page.
  1637. X                    */
  1638. X                    if (tscan (line, "(printed ") > ii)
  1639. X                    {    while (lcount++ < 60)
  1640. X                        {    putchar ('\n');
  1641. X                        }
  1642. X                        lcount = 0;
  1643. X                    }
  1644. X                }
  1645. X            }
  1646. X            for (i = 0;  i <= n;  i++)
  1647. X            {
  1648. X                if (how[i])
  1649. X                {    /*    either bold or underlined see if previous char
  1650. X                        is not escaped - indicates the beginning of 
  1651. X                        an escape sequence
  1652. X                    */
  1653. X                    if (how[i] == 1  &&  how[i-1] == 0)
  1654. X                        send (BEGIN_BOLD);
  1655. X                    else if (how[i] == 2  &&  how[i-1] == 0)
  1656. X                        send (underline_on);
  1657. X                }
  1658. X                else    /* zero means just a character, unmodified */
  1659. X                {    /* are we at the end of an escape sequence? */
  1660. X                    if (how[i-1] == 1)
  1661. X                        send (END_BOLD);
  1662. X                    else if (how[i-1] == 2)
  1663. X                        send (underline_off);
  1664. X                }
  1665. X                if (line[i])
  1666. X                    putchar (line[i]);
  1667. X            }
  1668. X            putchar ('\n');    
  1669. X            clear (line, how, n);
  1670. X            n = 0;
  1671. X        }
  1672. X        else
  1673. X        {    if (line[n])
  1674. X            {    if (line[n] == c)        /* same character?        */
  1675. X                    how[n] = 1;            /*    yes:    bold        */
  1676. X                else
  1677. X                    how[n] = 2;            /*    no:        underline    */
  1678. X            }
  1679. X            line[n++] = c;
  1680. X        }
  1681. X    }
  1682. X    exit (0);
  1683. X}
  1684. X
  1685. Xclear (line, how, n)
  1686. Xchar    *line;
  1687. Xint        *how;
  1688. Xint        n;
  1689. X{
  1690. X    int        i;
  1691. X    
  1692. X    for (i  = 0;  i <= n;  i++)
  1693. X    {    line[i] = '\0';
  1694. X        how[i] = 0;
  1695. X    }
  1696. X}
  1697. X
  1698. Xsend (s)
  1699. Xchar    *s;
  1700. X{
  1701. X    while (*s)
  1702. X        putchar (*s++);
  1703. X}
  1704. X
  1705. Xusage ()
  1706. X{
  1707. X    fprintf (stderr, "Usage:   pnf [-i] [-x] <in.file >out.file\n");
  1708. X    fprintf (stderr, " where        -i  = use italics in lieu of underline\n");
  1709. X    fprintf (stderr, "              -x  = ensure xenix man pages print fine\n");
  1710. X    exit (0);    
  1711. X}
  1712. X
  1713. Xtscan (s, t)
  1714. Xchar     s[], t[];
  1715. X{
  1716. X    int    i, j, k;
  1717. X    for (i = 0;  s[i] != '\0';  i++)
  1718. X    {    for (j = i, k=0;  t[k] != '\0'  &&  s[j] == t[k];  j++, k++)
  1719. X            ;
  1720. X        if (t[k] == '\0')
  1721. X            return (i);
  1722. X    }
  1723. X    return (-1);
  1724. X}
  1725. X
  1726. END_OF_FILE
  1727. if test 4166 -ne `wc -c <'pnf.c'`; then
  1728.     echo shar: \"'pnf.c'\" unpacked with wrong size!
  1729. fi
  1730. # end of 'pnf.c'
  1731. fi
  1732. if test -f 'pmf.c' -a "${1}" != "-c" ; then 
  1733.   echo shar: Will not clobber existing file \"'pmf.c'\"
  1734. else
  1735. echo shar: Extracting \"'pmf.c'\" \(5586 characters\)
  1736. sed "s/^X//" >'pmf.c' <<'END_OF_FILE'
  1737. X/* ta=4 */
  1738. X/****************************************************************************
  1739. X*                            p m f . c        v1.1                            *
  1740. X*                                                                            *
  1741. X*    postscript mail filter                                                    *
  1742. X*                                                                            *
  1743. X*    very simple mail filter to print name and subject in bold letters        *
  1744. X*    for psf usage.  Generates escape sequences that psf can understand.        *
  1745. X*    Modify the code if you wish to have various headers ignored for print.    *
  1746. X*                                                                            *
  1747. X*    Tony Field.       tony@ajfcal (or: calgary!ajfcal!tony@ai.toronto.edu)    *
  1748. X****************************************************************************/
  1749. X
  1750. X#include <stdio.h>
  1751. X#include <string.h>
  1752. X#include <ctype.h>
  1753. X
  1754. X#define BEGIN_BOLD            "\033B"
  1755. X#define END_BOLD            "\033b"
  1756. X
  1757. X#define BEGIN_UNDERLINE        "\033U"
  1758. X#define END_UNDERLINE        "\033u"
  1759. X
  1760. X#define BEGIN_ITALICS        "\033I"
  1761. X#define END_ITALICS            "\033i"
  1762. X
  1763. X#define    BEGIN_NAME            "\033F1\033B\033P13"    /* Helvetical bold 13 point */
  1764. X#define END_NAME            "\033p\033b\033f"        
  1765. X
  1766. X#define BEGIN_SUBJECT        "\033P13\033F1\033B\033I"    /*    Helvetica bold italic 13 point */
  1767. X#define END_SUBJECT            "\033i\033b\033f\033p"        /*    return to normal point, font */
  1768. X
  1769. X#define MAX_C                64
  1770. X
  1771. Xmain (argc, argv)
  1772. Xint        argc;
  1773. Xchar    *argv[];
  1774. X{
  1775. X    char    line[900], first[100], tail[800], *strchr();
  1776. X    int        i, many, nchar, last_char, header, garbage;
  1777. X    int        ignore_garbage;
  1778. X    extern char *optarg;
  1779. X    extern int    optind;
  1780. X
  1781. X    ignore_garbage = 1;
  1782. X    while ((i = getopt(argc, argv, "r-")) != -1)
  1783. X    {    switch (i)
  1784. X        {
  1785. X        case 'r':
  1786. X            ignore_garbage = 0;        /*    print all headers    */
  1787. X            break;
  1788. X
  1789. X        default:
  1790. X            usage ();
  1791. X        }
  1792. X    }
  1793. X        
  1794. X    
  1795. X    header = garbage = 0;
  1796. X    while (gets (line)  != NULL)
  1797. X    {
  1798. Xnewmail:
  1799. X        last_char = split (line, first, tail);
  1800. X
  1801. X        /*    The following headers will be ignored during printing    */
  1802. X        
  1803. X        if (ignore_garbage  
  1804. X            &&  (strcmp (first, "Received:") == 0
  1805. X            ||   strcmp (first, "References:") == 0
  1806. X            ||     strcmp (first, "Path:") == 0
  1807. X            ||     strcmp (first, "Message-Id:") == 0
  1808. X            ||     strcmp (first, "Message-ID:") == 0))
  1809. X        {    garbage = 1;
  1810. X        }
  1811. X        else if (strcmp (first, "From") == 0)
  1812. X        {    printclean (first, tail);
  1813. X            garbage = 0;
  1814. X        }
  1815. X        else if (strcmp (first, "From:") == 0
  1816. X                ||  strcmp (first, "Reply-To:") == 0
  1817. X                ||  strcmp (first, "To:") == 0)
  1818. X        {    header = 1;
  1819. X            if ((strchr (tail, '(') == NULL)  &&  (strchr (tail, '<') == NULL))
  1820. X                printbold (first, tail);
  1821. X            else
  1822. X                printname (first, tail);
  1823. X            garbage = 0;
  1824. X        }
  1825. X        else if (strcmp (first, "Bcc:") == 0 ||  strcmp (first, "Cc:") == 0)
  1826. X        {    header = 1;
  1827. X            printname (first, tail);
  1828. X            garbage = 0;
  1829. X        }
  1830. X        else if (strcmp (first, "Subject:") == 0)
  1831. X        {    printsubject (first, tail);
  1832. X            garbage = 0;
  1833. X        }
  1834. X        else if (last_char == ':')
  1835. X        {
  1836. X            header = 1;
  1837. X            printclean (first, tail);
  1838. X            garbage = 0;
  1839. X        }
  1840. X        else if (empty (line))
  1841. X        {    
  1842. X            send ("\n");
  1843. X            while (gets (line) != NULL)
  1844. X            {    if (strncmp (line, "From ", 5) == 0
  1845. X                    &&  (strchr (line, ':') < strrchr (line, ':')))
  1846. X                {    send ("\f");
  1847. X                    goto newmail;    /* goto's considered harmful since 1964 */
  1848. X                }
  1849. X                printf ("%s\n", line);
  1850. X            }
  1851. X            break;
  1852. X        }
  1853. X        else if (garbage == 0)
  1854. X            printclean (" ", line);
  1855. X    }
  1856. X    exit (0);
  1857. X}
  1858. X
  1859. Xprintclean (first, tail)
  1860. Xchar    *first, *tail;
  1861. X{    char    *c, *prefix;
  1862. X    int        marks[100], nmarks, i, j, nchar;
  1863. X
  1864. X    /*    locate all marks that can be use for a line break     */
  1865. X
  1866. X    marks[0] = 0;
  1867. X    marks[1] = 0;
  1868. X    c = tail;
  1869. X    for ( i = nchar = 0, nmarks = 1;  nmarks < 100;  i++, c++, nchar++)
  1870. X    {
  1871. X        if (*c == '!'  ||  *c == ' ' ||  *c == '<'  
  1872. X            ||  *c == '('  ||  *c == '\0')
  1873. X        {    if (nchar < MAX_C)
  1874. X                marks[nmarks] = i;
  1875. X            else
  1876. X            {    nchar = i - marks[nmarks];
  1877. X                marks[++nmarks] = i;
  1878. X            }
  1879. X            if (*c == '\0')
  1880. X                break;
  1881. X        }
  1882. X    }
  1883. X    marks[nmarks] = i;
  1884. X    prefix = first;
  1885. X    for (i = 0;  i < nmarks;  i++)
  1886. X    {
  1887. X        printf ("%-14s", prefix);
  1888. X        for (j = marks[i];  j < marks[i+1];  j++)
  1889. X            putchar (tail[j]);
  1890. X        putchar ('\n');
  1891. X        prefix = " ";
  1892. X    }
  1893. X}
  1894. X
  1895. Xprintsubject (first, tail)
  1896. Xchar    *first, *tail;
  1897. X{
  1898. X    printf ("%-14s", first);
  1899. X    send (BEGIN_SUBJECT);
  1900. X    send (tail);
  1901. X    send (END_SUBJECT);
  1902. X    send ("\n");
  1903. X}
  1904. X
  1905. Xprintbold (first, tail)
  1906. Xchar    *first, *tail;
  1907. X{
  1908. X    printf ("%-14s", first);
  1909. X    send (BEGIN_BOLD);
  1910. X    send (tail);
  1911. X    send (END_BOLD);    
  1912. X    send ("\n");
  1913. X}
  1914. X
  1915. Xprintname (first, tail)
  1916. Xchar    *first, *tail;
  1917. X{
  1918. X    printf ("%-14s", first);
  1919. X
  1920. X    if (strchr (tail, '<') != NULL)
  1921. X    {    /*    address syntax "name <address> stuff" */
  1922. X        send (BEGIN_NAME);
  1923. X        while (*tail != '<')
  1924. X            putchar (*tail++);
  1925. X        send (END_NAME);
  1926. X        putchar (*tail++);
  1927. X        while (*tail)
  1928. X        {    putchar (*tail);
  1929. X            if (*tail++ == '>')
  1930. X            {    if (*tail)
  1931. X                {    send (BEGIN_NAME);
  1932. X                    while (*tail)
  1933. X                        putchar (*tail++);
  1934. X                    send (END_NAME);
  1935. X                }
  1936. X            }
  1937. X        }
  1938. X    }
  1939. X    else
  1940. X    {    /*    address syntax "address (name)" */
  1941. X        while (*tail  &&  *tail != '(')
  1942. X            putchar (*tail++);
  1943. X        if (*tail)
  1944. X        {    send (BEGIN_NAME);
  1945. X            putchar (*tail++);
  1946. X            while (*tail)
  1947. X            {    putchar (*tail);
  1948. X                if (*tail++ == ')')
  1949. X                {    send (END_NAME);
  1950. X                    while (*tail)
  1951. X                        putchar (*tail++);
  1952. X                    putchar ('\n');
  1953. X                    return;
  1954. X                }
  1955. X            }
  1956. X        }
  1957. X    }
  1958. X    putchar ('\n');
  1959. X}
  1960. X
  1961. Xsend (s)
  1962. Xchar    *s;
  1963. X{
  1964. X    while (*s)
  1965. X        putchar (*s++);
  1966. X}
  1967. X
  1968. Xempty (s)
  1969. Xchar    *s;
  1970. X{    while (*s  &&  *s <= ' ')
  1971. X        s++;
  1972. X    if (*s)
  1973. X        return (0);
  1974. X    else
  1975. X        return (1);
  1976. X}
  1977. X
  1978. Xsplit (line, first, tail)
  1979. Xchar    *line;            /*    input:    full input line            */
  1980. Xchar    *first;            /*    return:    first word of line        */
  1981. Xchar    *tail;            /*    return:    all others words of line*/
  1982. X{    int    last;
  1983. X
  1984. X    last = 0;
  1985. X    while (*line  &&  isspace (*line) == 0)
  1986. X    {    last = *line;
  1987. X        *first++ = *line++;
  1988. X    }
  1989. X    *first = '\0';
  1990. X    
  1991. X    while (*line  &&  isspace (*line))
  1992. X        line++;
  1993. X    
  1994. X    while (*line)
  1995. X        *tail++ = *line++;
  1996. X    *tail = '\0';
  1997. X    return (last);
  1998. X}
  1999. X
  2000. Xusage ()
  2001. X{
  2002. X    fprintf (stderr, "Usage:   pmf [-s] <in.file >out.file\n");
  2003. X    fprintf (stderr, " where        -s  = show all header lines\n");
  2004. X    exit (0);    
  2005. X}
  2006. END_OF_FILE
  2007. if test 5586 -ne `wc -c <'pmf.c'`; then
  2008.     echo shar: \"'pmf.c'\" unpacked with wrong size!
  2009. fi
  2010. # end of 'pmf.c'
  2011. fi
  2012. if test -f 'psbanner.c' -a "${1}" != "-c" ; then 
  2013.   echo shar: Will not clobber existing file \"'psbanner.c'\"
  2014. else
  2015. echo shar: Extracting \"'psbanner.c'\" \(3524 characters\)
  2016. sed "s/^X//" >'psbanner.c' <<'END_OF_FILE'
  2017. X/* ta=4 */
  2018. X/****************************************************************************
  2019. X*                p s b a n n e r . c        v 1 . 1                                *
  2020. X*                                                                            *
  2021. X*    Print a banner page on a postscript printer for Xenix 2.2.3                *
  2022. X*                                                                            *
  2023. X*    Tony Field.       tony@ajfcal  (or: calgary!ajfcal!tony@ai.toronto.edu)    *
  2024. X****************************************************************************/
  2025. X
  2026. X#include <stdio.h>
  2027. X
  2028. X#define MAX_X        612        /*    8.5 inches * 72 points        */
  2029. X#define MAX_Y        792        /*    11  inches * 72 points        */
  2030. X#define X_INDENT    40        /*    points                        */
  2031. X#define Y_INDENT    40
  2032. X#define    BIG_POINT    60        /* changes to point size automatically scale    */
  2033. X#define MED_POINT    35        /* the printout.                                */
  2034. X#define    SMALL_POINT    15
  2035. X#define    UX            X_INDENT
  2036. X#define UY            (MAX_Y - Y_INDENT)
  2037. X#define DX            (MAX_X - 2 * X_INDENT)
  2038. X#define DY            (BIG_POINT * 3)
  2039. X
  2040. X/*    The following arguments are received in the command line    */
  2041. X
  2042. X#define    Userid        argv[1]
  2043. X#define    Name        argv[2]
  2044. X#define    Requestid    argv[3]
  2045. X#define    Printer        argv[4]
  2046. X#define    Options        argv[5]
  2047. X#define    Date        argv[6]
  2048. X#define    Machineid    argv[7]
  2049. X#define    Title        argv[8]
  2050. X
  2051. Xmain (argc, argv)
  2052. Xint        argc;
  2053. Xchar    *argv[];
  2054. X{    int        x, y;
  2055. X
  2056. X    /*    center text used for userid and job title print  */
  2057. X    
  2058. X    send ("%!PS-Adobe-\n");
  2059. X    send ("/ctext {     % center text:   string x y dx\n");
  2060. X    send ("   2 div\n");
  2061. X    send ("   /Dx exch def\n");
  2062. X    send ("   /Yv exch def\n");
  2063. X    send ("   /Xv exch def\n");
  2064. X    send ("   dup stringwidth pop\n");
  2065. X    send ("   2 div\n");
  2066. X    send ("   Dx exch sub\n");
  2067. X    send ("   Xv add\n");
  2068. X    send ("   Yv moveto\n");
  2069. X    send ("   show\n");
  2070. X    send ("} def\n");
  2071. X    send ("%%EndProlog\n");
  2072. X
  2073. X    send ("%%Page: ? 0\n");
  2074. X    send ("/pg save def\n");
  2075. X
  2076. X    /*    draw a box for the userid */
  2077. X    
  2078. X    printf ("newpath\n");
  2079. X    printf ("%d %d moveto\n", UX,UY);
  2080. X    printf ("%d %d rlineto\n", DX, 0);
  2081. X    printf ("%d %d rlineto\n", 0, -DY);
  2082. X    printf ("%d %d rlineto\n", -DX, 0);
  2083. X    printf ("closepath\n");
  2084. X    printf ("4 setlinewidth\n");
  2085. X    printf ("stroke\n");
  2086. X
  2087. X    /*    center the userid and the job title */
  2088. X    
  2089. X    y = UY - DY / 2 - BIG_POINT / 2;
  2090. X    printf ("/Helvetica-BoldOblique findfont %d scalefont setfont\n", BIG_POINT);
  2091. X    printf ("(%s) %d %d %d ctext\n", Userid, X_INDENT, y, DX);
  2092. X
  2093. X    y = UY - (DY + MED_POINT * 3);
  2094. X    printf ("/Helvetica-Bold findfont %d scalefont setfont\n", MED_POINT);
  2095. X    printf ("(%s) %d %d %d ctext\n", Title, X_INDENT, y, DX);
  2096. X
  2097. X    /*    print other banner page parameters */
  2098. X    
  2099. X    x = X_INDENT;
  2100. X    y -= (MED_POINT * 2);
  2101. X    printf ("%d %d moveto\n", x,y);    
  2102. X    sendnormal ("User:       ");
  2103. X    sendbold (Name);
  2104. X
  2105. X    y -= SMALL_POINT + (SMALL_POINT / 2);
  2106. X    printf ("%d %d moveto\n", x,y);    
  2107. X    sendnormal ("Request ID: ");
  2108. X    sendbold (Requestid);
  2109. X    
  2110. X    y -= SMALL_POINT + (SMALL_POINT / 2);
  2111. X    printf ("%d %d moveto\n", x,y);    
  2112. X    sendnormal ("Printer ID: ");
  2113. X    sendbold (Printer);
  2114. X    
  2115. X    y -= SMALL_POINT + (SMALL_POINT / 2);
  2116. X    printf ("%d %d moveto\n", x,y);    
  2117. X    sendnormal ("Options:    ");
  2118. X    sendbold (Options);
  2119. X    
  2120. X    y -= SMALL_POINT + (SMALL_POINT / 2);
  2121. X    printf ("%d %d moveto\n", x,y);    
  2122. X    sendnormal ("Date:       ");
  2123. X    sendbold (Date);
  2124. X    
  2125. X    y -= SMALL_POINT + (SMALL_POINT / 2);
  2126. X    printf ("%d %d moveto\n", x,y);    
  2127. X    sendnormal ("Machine:    ");
  2128. X    sendbold (Machineid);
  2129. X
  2130. X    send ("showpage pg restore\n");
  2131. X    send ("%%Trailer\n");    
  2132. X    exit (0);
  2133. X}
  2134. X
  2135. Xsend (s)
  2136. Xchar    *s;
  2137. X{
  2138. X    while (*s)
  2139. X        putchar (*s++);
  2140. X}
  2141. X
  2142. Xsendnormal (s)
  2143. Xchar     *s;
  2144. X{
  2145. X    printf ("/Courier findfont %d scalefont setfont\n", SMALL_POINT);
  2146. X    send ("(");
  2147. X    send (s);
  2148. X    send (")show\n");
  2149. X}
  2150. X
  2151. Xsendbold (s)
  2152. Xchar     *s;
  2153. X{
  2154. X    printf ("/Helvetica-Bold findfont %d scalefont setfont\n", SMALL_POINT);
  2155. X    send ("(");
  2156. X    send (s);
  2157. X    send (")show\n");
  2158. X}
  2159. X
  2160. END_OF_FILE
  2161. if test 3524 -ne `wc -c <'psbanner.c'`; then
  2162.     echo shar: \"'psbanner.c'\" unpacked with wrong size!
  2163. fi
  2164. # end of 'psbanner.c'
  2165. fi
  2166. if test -f 'psdetect.c' -a "${1}" != "-c" ; then 
  2167.   echo shar: Will not clobber existing file \"'psdetect.c'\"
  2168. else
  2169. echo shar: Extracting \"'psdetect.c'\" \(631 characters\)
  2170. sed "s/^X//" >'psdetect.c' <<'END_OF_FILE'
  2171. X/* ta=4 */
  2172. X/************************************************************************
  2173. X*        p s d e t e c t . c        v1.1                                    *
  2174. X*                                                                        *
  2175. X*    determine if a a text file contains postscript code.                *
  2176. X************************************************************************/
  2177. X
  2178. X/*    this routine is intended for use within shell scripts.  It exits
  2179. X    with a return code of 0 if it detects a postscript file or
  2180. X    a value of 1 if it is not a postscript file
  2181. X*/
  2182. X
  2183. X#include <stdio.h>
  2184. X
  2185. Xmain ()
  2186. X{
  2187. X    char    line[1000];
  2188. X    
  2189. X    gets (line);
  2190. X/*
  2191. X    if (strncmp (line, "%!PS-Adobe", 10) == 0)
  2192. X*/
  2193. X    if (strncmp (line, "%!", 2) == 0)
  2194. X        exit (0);
  2195. X    exit (1);
  2196. X}
  2197. END_OF_FILE
  2198. if test 631 -ne `wc -c <'psdetect.c'`; then
  2199.     echo shar: \"'psdetect.c'\" unpacked with wrong size!
  2200. fi
  2201. # end of 'psdetect.c'
  2202. fi
  2203. if test -f 'postscript.LP' -a "${1}" != "-c" ; then 
  2204.   echo shar: Will not clobber existing file \"'postscript.LP'\"
  2205. else
  2206. echo shar: Extracting \"'postscript.LP'\" \(2246 characters\)
  2207. sed "s/^X//" >'postscript.LP' <<'END_OF_FILE'
  2208. X:
  2209. X#
  2210. X#!    Postscript serial or parallel printer using psf filters
  2211. X#
  2212. X#    NOTE: the above line is displayed on the "mkdev lp" printer
  2213. X#    ^^^^^ selection list.  If you create multiple printer models,
  2214. X#          edit the above to signify the options invoked with psf.
  2215. X#
  2216. X#    This print model works with Xenix 2.2.3.  It is the printer
  2217. X#    back-end that is called by lp for physical printing.
  2218. X#
  2219. X#    The Makefile will use sed to replace "BINARY" with
  2220. X#        the binary library directory name.
  2221. X#        "OPTIONS" will be replaced by the desired default
  2222. X#        options specified in the Makefile.
  2223. X
  2224. X# The following parameters are passed from "lp" at print time.
  2225. X
  2226. Xprinter=`basename $0`
  2227. Xrequest=$1
  2228. Xname=$2
  2229. Xtitle=$3
  2230. Xcopies=$4
  2231. Xoptions=$5
  2232. Xshift; shift; shift; shift; shift
  2233. X
  2234. X# Modify the following for required stty settings.
  2235. X
  2236. Xstty ixon ixoff 0<&1
  2237. X
  2238. Xbanner=yes
  2239. Xtoday=`date`
  2240. Xfor i in $options; do
  2241. X    case $i in
  2242. X    b)    banner=no ;;
  2243. X    esac
  2244. Xdone
  2245. X
  2246. X[ "$banner" = yes ] && {
  2247. X
  2248. X#    get the machine name from /etc/systemid or with uname.
  2249. X
  2250. X    if test -r /etc/systemid; then
  2251. X        sysid=`sed 1q /etc/systemid`
  2252. X    else
  2253. X        sysid=`uname -n`
  2254. X    fi
  2255. X
  2256. X#    get the user name from the GCOS field in /etc/passwd
  2257. X
  2258. X    user=`sed -n "s/^$name:.*:.*:.*:\(.*\):.*:.*$/\1/p" /etc/passwd`
  2259. X
  2260. X#    get the count of the number of banner pages from /etc/default/lpd
  2261. X
  2262. X    nhead=`sed -n 's/^BANNERS=//p' /etc/default/lpd`
  2263. X    [ "$nhead" -ge 0 -a "$nhead" -le 5 ] || nhead=1
  2264. X    while    [ "$nhead" -gt 0 ]
  2265. X    do
  2266. X        BINARY/psbanner "$name" "$user" "$request" "$printer" "$options" "$today" "$sysid" "$title"
  2267. X        nhead=`expr $nhead - 1`
  2268. X    done
  2269. X}
  2270. X
  2271. X#    If the input text file contains %! in the first line,
  2272. X#    then assume that it has already been encapusulated in postscript
  2273. X#    code.  If the %! is missing, then filter through psf
  2274. X#
  2275. X#    Edit the psf entry below to specify alternate defaults.  For example,
  2276. X#    80 line pages printed 2-up (for a total of 160 lines on a page)
  2277. X#    in landscape layout could be specified with:
  2278. X#
  2279. X#        BINARY/psf -2 -l80 "$file" 2>&1
  2280. X#
  2281. X#    If you do not provide any options, the default is 60 lines
  2282. X#    per page in portrait layout:
  2283. X#
  2284. X#        BINARY/psf "$file" 2>&1
  2285. X
  2286. Xwhile    [ "$copies" -gt 0 ]
  2287. Xdo
  2288. X    for file
  2289. X    do
  2290. X        BINARY/psdetect < "$file"
  2291. X
  2292. X        case $? in
  2293. X
  2294. X        0)    cat "$file" 2>&1;;
  2295. X
  2296. X        1)    BINARY/psf OPTIONS "$file" 2>&1;;
  2297. X
  2298. X        esac
  2299. X    done
  2300. X    copies=`expr $copies - 1`
  2301. Xdone
  2302. Xexit 0
  2303. END_OF_FILE
  2304. if test 2246 -ne `wc -c <'postscript.LP'`; then
  2305.     echo shar: \"'postscript.LP'\" unpacked with wrong size!
  2306. fi
  2307. # end of 'postscript.LP'
  2308. fi
  2309. if test -f 'testfile' -a "${1}" != "-c" ; then 
  2310.   echo shar: Will not clobber existing file \"'testfile'\"
  2311. else
  2312. echo shar: Extracting \"'testfile'\" \(648 characters\)
  2313. sed "s/^X//" >'testfile' <<'END_OF_FILE'
  2314. XTest file for PSF postscript filter.
  2315. X
  2316. XThis is a simple test file.  This line is in default configuration.
  2317. X
  2318. XAny words within a line Umay be underlinedu or they Bmay be boldface.b
  2319. X
  2320. XIf you wish, F1you could changes fontsF2I multiple timesif in a line.
  2321. X
  2322. X
  2323. XChange P16point sizeP20 if you like.p
  2324. X
  2325. X
  2326. XMixing F3P22Ufonts, point sizes upf is quite reasonable.
  2327. X
  2328. X
  2329. XMixing P22F4fonts, and point sizes is quite Ureasonable
  2330. X
  2331. X
  2332. Xacross lines.upf  However, line skip size is based upon the
  2333. X
  2334. Xcurrent point size.  Nothing to Iworryi about, but do Urememberu.
  2335. X
  2336. X
  2337. Xhave   P20F7BUfunubfp
  2338. X
  2339. X
  2340. XF7Tony Field     ..!alberta!calgary!ajfcal!tonyf
  2341. END_OF_FILE
  2342. echo shar: 38 control characters may be missing from \"'testfile'\"
  2343. if test 648 -ne `wc -c <'testfile'`; then
  2344.     echo shar: \"'testfile'\" unpacked with wrong size!
  2345. fi
  2346. # end of 'testfile'
  2347. fi
  2348. echo shar: End of shell archive.
  2349. exit 0
  2350.  
  2351.  
  2352.