home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume7 / psf < prev    next >
Text File  |  1989-06-03  |  66KB  |  2,343 lines

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