home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 344a.lha / LPtoPS / lptops.c < prev    next >
Text File  |  1990-01-08  |  53KB  |  2,015 lines

  1. /* -*-C-*- LPTOPS.C */
  2. /*-->lptops*/
  3. /**********************************************************************/
  4. /******************************* lptops *******************************/
  5. /**********************************************************************/
  6.  
  7. /***********************************************************************
  8.  
  9. NB: In order to handle overprinting of input of the form
  10.  
  11. ...text...<CR>...overtext...<CR><LF>
  12.  
  13. this must be loaded with a special version of the C library I/O  routine
  14. (PCC:IOCR.REL on the DEC-20) which permits reading and writing of  <CR>.
  15. No special  action need  be taken  on Unix  systems, since  <CR> is  not
  16. filtered out, and is normally absent.    On PC-DOS, open options of  "rb"
  17. will usually  be necessary  (this  is the  default  on all  systems  but
  18. TOPS-20).
  19. ***********************************************************************/
  20.  
  21. /***********************************************************************
  22.  
  23.            Line printer file to PostScript converter
  24.                   [03-Jul-85]
  25.                   [12-Nov-85]
  26.                   [07-Apr-86]
  27.                               [03-May-88]
  28.                               [22-Dec-89]
  29.  
  30. lptops converts normal text  files into PostScript  for printing on  the
  31. Apple LaserWriter, or any  other PostScript-compatible printing  device.
  32. It supports selection of  a variety of fonts  at arbitrary point  sizes,
  33. margin specification, portrait and landscape page orientation, automatic
  34. page numbering, page outlining, and multi-column printing.  It can  also
  35. handle overstruck text used by many document formatters for underlining.
  36.  
  37. Usage:
  38.  
  39.     lptops [switches] <infile >outfile
  40.     lptops [switches] filelist >outfile
  41.  
  42. In the switch descriptions below, physical dimensions described as # may
  43. be specified as a single number with an optional fractional part, and  a
  44. required two-letter unit designator.  Letter case is ignored.    Possible
  45. forms are:
  46.  
  47. #.##bp  big point (1in = 72bp)         [Courier: 120.000/Pbp cpi]
  48. #.##cc  cicero (1cc = 12dd)         [Courier:     9.381/Pcc cpi]
  49. #.##cm  centimeter             [Courier:     4.233/Pcm cpi]
  50. #.##dd  didot point (1157dd = 1238pt)[Courier: 112.569/Pdd cpi]
  51. #.##in  inch                 [Courier:     1.667/Pin cpi]
  52. #.##mm  millimeter (10mm = 1cm)      [Courier:  42.333/Pmm cpi]
  53. #.##pc  pica (1pc = 12pt)         [Courier:  10.038/Ppc cpi]
  54. #.##pt  point (72.27pt = 1in)         [Courier: 120.450/Ppt cpi]
  55. #.##sp  scaled point (65536sp = 1pt) [Courier:     7.893/(Psp/1000000) cpi]
  56.  
  57. The bracketed values give the number of characters per inch (cpi) for  a
  58. point size of P units with  the fixed-width Courier font.  For  example,
  59. with point size  8bp, there are  120/8 = 15  characters per inch.   With
  60. point size 1000000sp, there are 7.893 characters/inch.
  61.  
  62. The optional switches are (letter case is ignored):
  63.  
  64.     -A    Turn Scribe-like bold and italic requests (@b[...] and
  65.         @i[...]) into bold or italic text.
  66.  
  67.     -B#    Bottom margin of #.
  68.  
  69.     -Cn    Print n copies of each page.
  70.  
  71.         -D[tb][n]
  72.                 Display header or footer in the following format:
  73.  
  74.                    Date/Time         File Name            Page #
  75.  
  76.         The position can  be selected  explicitly by  t (top) or
  77.                 b (bottom).  If  n is  given,  start numbering with that
  78.                 value, and otherwise with  1.  If an initial  top margin
  79.                 value is given  with the  -I#  option, numbering will be
  80.                 omitted  on the first page  if it is at the top.   Pages
  81.                 are  unnumbered  if this  option  or the N option is not
  82.                 specified.
  83.  
  84.     -Ffontname
  85.         PostScript fontname.   Possible values  with  acceptable
  86.         short abbreviations formed  from the upper-case  letters
  87.         in the font names, and the ditroff and Adobe  TranScript
  88.         abbreviations  are  as  follows.    The  first  13   are
  89.         available on all PostScript printers; the remainder  are
  90.         available only on enhanced  printers, such as the  Apple
  91.         LaserWriter Plus.
  92.  
  93.         ====================        =====    ======    ==========
  94.         full name            short    ditroff    TranScript
  95.         ====================        =====    ======    ==========
  96.         Courier                C    C    C
  97.         Courier-Bold            CB    CB    CB
  98.         Courier-BoldOblique        CBO    CD    CD
  99.         Courier-Oblique            CO    CO    CO
  100.         Helvetica            H    he    he
  101.         Helvetica-Bold            HB    He    He
  102.         Helvetica-BoldOblique        HBO    HE    HE
  103.         Helvetica-Oblique        HO    hE    hE
  104.         Symbol                S    S    S
  105.         Times-Bold            TB    R    ti
  106.         Times-BoldItalic        TBI    BI    TI
  107.         Times-Italic            TI    I    tI
  108.         Times-Roman            T    R    ti
  109.  
  110.         AvantGarde-Book            AGB    ag    ag
  111.         AvantGarde-BookOblique        AGBO    aG    aG
  112.         AvantGarde-Demi            AGD    Ag    Ag
  113.         AvantGarde-DemiOblique        AGDO    AG    AG
  114.         Bookman-Demi            BD    Bo    Bo
  115.         Bookman-DemiItalic        BDI    BO    BO
  116.         Bookman-Light            BL    bo    bo
  117.         Bookman-LightItalic        BLI    bO    bO
  118.         Helvetica-Narrow        HN    hn    hn
  119.         Helvetica-Narrow-Bold        HNB    Hn    Hn
  120.         Helvetica-Narrow-BoldOblique    HNBO    HN    HN
  121.         Helvetica-Narrow-Oblique    HNO    hN    hN
  122.         NewCenturySchlbk-Bold        NCSB    Nc    Nc
  123.         NewCenturySchlbk-BoldItalic    NCSBI    NC    NC
  124.         NewCenturySchlbk-Italic        NCSI    nC    nC
  125.         NewCenturySchlbk-Roman        NCSR    nc    nc
  126.         Palatino-Bold            PB    Pa    Pa
  127.         Palatino-BoldItalic        PBI    PA    PA
  128.         Palatino-Italic            PI    pA    pA
  129.         Palatino-Roman            PR    pa    pa
  130.         ZapfChancery-MediumItalic    ZCMI    ZC    ZC
  131.         ZapfDingbats            ZD    ZD    ZD
  132.         ====================        =====    ======    ==========
  133.  
  134.         The ditroff and  TranScript  abbreviations are the same,
  135.         except for the Courier and Times fonts.  They  are based
  136.         on two-letter  mnemonics, where upper-case  in the first
  137.         letter means bold, and upper-case  in the second  letter
  138.         means italic.
  139.  
  140.         Only the Courier fonts  are fixed-width like  typewriter
  141.         and line printer fonts are.  The others are proportional
  142.         spaced  for  improved  readability,  and   consequently,
  143.         tabular material will  not line up  properly with  them.
  144.         The Courier fonts  have a  width equal to  0.6 of  their
  145.         point size, so to fill a line W inches wide with up to N
  146.         characters, one must have  point size <=  (W/(0.6 * N  *
  147.         72)) = (W*120)/N pt.  Equivalently, with a point size  P
  148.         pt, the output spacing is 120/P char/inch.
  149.  
  150.     -H    Horizontal page orientation (landscape mode) instead  of
  151.         vertical page (portrait mode).
  152.  
  153.     -I#    Top margin of # for  initial page (for letterheads);  if
  154.         not specified, it  will default to  the value given  for
  155.         the top margin by default or by the -T# command.
  156.  
  157.     -L#    Left margin of #.
  158.  
  159.     -Mn    Multiple column output (n columns).  In multiple  column
  160.         mode, formfeeds  cause  column breaks  instead  of  page
  161.         breaks.
  162.  
  163.     -N[tb][lcr][n]
  164.         Number output pages.  The number is placed by default in
  165.         the center  of the  top margin,  but the  margin can  be
  166.         selected explicitly by  t (top) or  b (bottom), and  the
  167.         position of the page number can be further specified  by
  168.         l (left),  c (center),  or r  (right).  If  n is  given,
  169.         start numbering with that  value, and otherwise with  1.
  170.         If an initial  top margin  value is given  with the  -I#
  171.         option, numbering will be omitted  on the first page  if
  172.         it is at the top.   Pages are unnumbered if this  option
  173.         or the D is not specified.
  174.  
  175.     -O[#]    Outline pages  (and  columns) with  a  # units  wide.  A
  176.         narrow line of 0.4pt width  is assumed if # is  omitted;
  177.         this particular width is what TeX uses in typesetting.
  178.  
  179.     -P#    Font point  size  (default  10bp).   The  baseline  skip
  180.         (spacing  between  successive  character  baselines)  is
  181.         conventionally chosen to be 6/5  of this value, so  that
  182.         with 10bp  type,  we  have  12bp  between  lines,  or  6
  183.         lines/inch, the same as standard printer output.
  184.  
  185.     -R#    Right margin of #.
  186.  
  187.     -S[n]    special handling  (i.e. manual paper feed) for the first
  188.         n pages  of the  output.  If  N multiple  copies are  in
  189.         effect, then N*n sheets must  be fed manually.  If n  is
  190.         omitted, then all  pages are  to be  fed manually.   For
  191.         example, -S1 is convenient  to get the  first page of  a
  192.         letter on letterhead paper fed manually, with  remaining
  193.         pages from the paper cassette.
  194.  
  195.     -T#    Top margin of #.
  196.  
  197.     -U    Output pages in unsorted  (first to last) order  instead
  198.         of in  sorted  (page reversed)  order;  some  PostScript
  199.         printers have page handlers that stack the paper in this
  200.         order.     The   default  is   sorted  because   this   is
  201.         appropriate for the most common PostScript printer,  the
  202.         Apple LaserWriter.
  203.  
  204. Defaults are:
  205.  
  206.     -B1.0in -C1 -FCourier -L1.0in -M1 -P10bp -R1.0in -S0 -T1.0in
  207.  
  208.  
  209. Revision history (reverse time order):
  210.  
  211. [22-Dec-89]     Ported to the Amiga and added header-footer option. Also
  212.                 fixed initial page numbering options which never worked.
  213.                 - Pat Empleo -
  214.  
  215. [03-May-88]    Add ditroff and Adobe TranScript font abbreviations.
  216.  
  217. [19-Apr-86]    Change page/line status report from output in End_Page()
  218.         only to output in Beg_Page() and End_Column().
  219.  
  220. [07-Apr-86]    Fix some  incorrect  font  names, put  font  names  into
  221.         table, add font abbreviations and new font names, change
  222.         default font to Courier  (because most printing  expects
  223.         fixed-width fonts).  Add usage  message if bad  options,
  224.         and print  fontnames if  bad font  switch given.   Allow
  225.         multiple filenames on command line instead of just using
  226.         stdin -- this added  new function Do_File() and  changed
  227.         argument  lists  of  inchar()  and  Copy_Plist().    Add
  228.         save/restore around each page  image following new  1986
  229.         PostScript Language Reference Manual recommendation, and
  230.         change multiple  copies  sequence from  repeat  loop  to
  231.         setting of standard variable #copies.  Add -U option for
  232.         unsorted output.
  233.  
  234. [03-Feb-86]    Fix setting of final  entry of page_table[].  It  should
  235.         only be done when End_Page() is called, since  otherwise
  236.         Beg_Page() has already set the final entry, and we  just
  237.         have an empty page to  be discarded.  Without this  fix,
  238.         this left a hole (0), so  the entire file got copied  in
  239.         its entirety to the last page of the sorted file.
  240.  
  241. [18-Jan-86]    Add (void) to fprintf()/printf(), test for disk  storage
  242.         full at end  of page, add  OUTSTR() macro using  fputs()
  243.         instead of fprintf() for efficiency.
  244.  
  245. [20-Dec-85]    Change getchar() to inchar(); the latter supplies a
  246.         trailing LF at EOF in the event it is missing.
  247.         Otherwise, the output PostScript has two tokens
  248.         jammed together (P 1 {copypage} --> P1 {copypage})
  249.  
  250. [20-Dec-85]    Following recommendation of Allan Hetzel on LASER-LOVERS
  251.         ARPA BBOARD, added "() pop" at top of every page.  This
  252.         is selected by the switch FIX31OCT85:
  253.  
  254.         --------------------------------------------------------
  255.         From: Allan Hetzel  <SYSAL%UKCC.BITNET@WISCVM.ARPA>
  256.         Subject: Re: Apple Laserwriter XON/XOFF problem
  257.         To:  <LASER-LOVERS@WASHINGTON.ARPA>
  258.  
  259.         The note  posted to  Laser-Lovers on  Oct 28  by  Joseph
  260.         Goldstone of  Symbolics  Cambridge Research  Center  was
  261.         helpful but I didn't try his suggested fix correctly and
  262.         so I called Adobe.  They were very helpful (much more so
  263.         than Apple) and explained the problem and how to  bypass
  264.         it.
  265.  
  266.         My  apologies  to   Adobe  if  this   not  an    accurate
  267.         description of the problem.   The problem apparently  is
  268.         due to the  PostScript interpreter  getting confused  by
  269.         what it thinks is an excess of white space characters.
  270.  
  271.         The bypass is to place a special character (parenthesis,
  272.         bracket, brace, slash, etc.) to the right of some token,
  273.         but without an intervening white space character. As the
  274.         PostScript scanner  reads the  token it  also reads  the
  275.         special character which acts as a delimiter. The scanner
  276.         then has  to  back  up  one character  so  that  it  can
  277.         reprocess the special character  after it has  processed
  278.         the preceding token.  During  this backing up process  a
  279.         number of  internal values  are recalculated,  including
  280.         some pointer  into the  input buffer.    This causes  the
  281.         XON/XOFF protocol to work properly.  Doing this once per
  282.         page seems to keep everybody happy.
  283.  
  284.         Each page  in  the PostScript  file  built by  our  word
  285.         processing program  is surrounded  by a  "save  restore"
  286.         sequence.  We  changed     the  beginning  save    sequence
  287.         "/saveobj save def" to  read "/saveobj save def()  pop".
  288.         The "() pop" is effectively  a no-op and we are  assured
  289.         that the necessary recalculations are done on each page.
  290.         This seems to have corrected the problem completely.
  291.  
  292.         Allan Hetzel (sysal@ukcc.bitnet)
  293.         --------------------------------------------------------
  294.  
  295. [11-Dec-85]    Fix problem with extra () around overstruck text.
  296.  
  297. [13-Nov-85]    Insert FASTIO conditional compilation option to speed up
  298.         page reversal.  Under VAX  4.2BSD, fread() and  fwrite()
  299.         are already fast enough, and need not be replaced.
  300.  
  301. [12-Nov-85]    Add reversal of  pages, storing  output on  intermediate
  302.         file which is deleted before exiting.
  303.  
  304. [02-Nov-85]    Add code to write output on temporary file, then
  305.         retrieve in reverse page order and output on stdout.
  306.  
  307. [30-Oct-85]    Add code to handle overstruck lines:
  308.         ...text...<CR>...overtext...<CR><LF>
  309.         will appear as
  310.         (...text...) O
  311.         (...overtext...) P
  312.  
  313.         Macro definitions and font selection now repeated
  314.         on each page to allow selective reprinting.
  315.  
  316. [07-Oct-85]    Add code to discard input NUL's from word-padded files,
  317.         since the LaserWriter prints them as blanks.
  318.  
  319. [27-Sep-85]    Added missing 'N' switch, fixed Page_Switch() (it scanned
  320.         beyond last digit of page number)
  321.  
  322. [11-Jul-85]    Original version.
  323.  
  324.  
  325. ***********************************************************************/
  326.  
  327.  
  328. #ifndef OS_AMIGA
  329. #define OS_AMIGA     0
  330. #endif
  331.  
  332. #ifndef OS_TOPS20
  333. #define OS_TOPS20     0
  334. #endif
  335.  
  336. #ifndef KCC_20
  337. #define KCC_20         0
  338. #endif
  339.  
  340. #ifndef PCC_20
  341. #define PCC_20         0
  342. #endif
  343.  
  344. #if    (KCC_20 | PCC_20)
  345. #ifndef OS_TOPS20
  346. #define OS_TOPS20     1
  347. #endif
  348. #endif
  349.  
  350. #ifndef OS_VAXVMS
  351. #define OS_VAXVMS     0
  352. #endif
  353.  
  354. #ifndef OS_ATARI
  355. #define OS_ATARI     0
  356. #endif
  357.  
  358. #ifndef OS_PCDOS
  359. #define OS_PCDOS     0
  360. #endif
  361.  
  362. #ifndef IBM_PC_AZTEC
  363. #define IBM_PC_AZTEC     0
  364. #endif
  365.  
  366. #ifndef IBM_PC_LATTICE
  367. #define IBM_PC_LATTICE     0
  368. #endif
  369.  
  370. #ifndef IBM_PC_MICROSOFT
  371. #define IBM_PC_MICROSOFT 0
  372. #endif
  373.  
  374. #ifndef IBM_PC_WIZARD
  375. #define IBM_PC_WIZARD     0
  376. #endif
  377.  
  378. #if    (IBM_PC_AZTEC | IBM_PC_LATTICE | IBM_PC_MICROSOFT | IBM_PC_WIZARD)
  379. #ifndef OS_PCDOS
  380. #define OS_PCDOS     1
  381. #endif
  382. #endif
  383.  
  384. #if    (OS_AMIGA | OS_ATARI | OS_TOPS20 | OS_PCDOS | OS_VAXVMS)
  385. #define OS_UNIX         0
  386. #else
  387. #define OS_UNIX         1
  388. #endif
  389.  
  390. #if    (OS_AMIGA | OS_ATARI | PCC_20)
  391. #define DISKFULL(fp)    ferror(fp)    /* PCC-20 does not always set errno */
  392. #else
  393. #define DISKFULL(fp)    (ferror(fp) && (errno == ENOSPC))
  394. #endif
  395.  
  396. #if    OS_VAXVMS
  397. #define EXIT        vms_exit
  398. #else
  399. #define EXIT        exit
  400. #endif
  401.  
  402. #if    IBM_PC_LATTICE
  403. typedef int void;        /* Lattice C does not have this */
  404. #endif
  405.  
  406. #if    IBM_PC_MICROSOFT
  407. #define ANSI_PROTOTYPES        1
  408. #endif
  409.  
  410. #ifndef ANSI_PROTOTYPES
  411. #define ANSI_PROTOTYPES        0
  412. #endif
  413.  
  414. #ifndef ANSI_LIBRARY
  415. #define ANSI_LIBRARY        0
  416. #endif
  417.  
  418. /*
  419. ************************************************************************
  420. On  TOPS-20,   fread()/fwrite()   are  implemented   as   loops   around
  421. getc()/putc() calls, and these in turn also do CR/LF translation.  Calls
  422. to _read() and _write() translate into  direct calls to the Monitor  for
  423. fast efficient block I/O.   FASTIO selects this option.   It is used  in
  424. Copy_Block when the temporary  file is output in  reverse page order  to
  425. stdout.
  426. ************************************************************************
  427. */
  428.  
  429. #if OS_AMIGA
  430. extern    int strcmp();
  431. #endif
  432.  
  433. #if    OS_TOPS20
  434. #if    PCC_20
  435. #define FASTIO 1            /* TOPS-20 use only */
  436. #undef DISKFULL
  437. #define DISKFULL(fp)    ferror(fp)    /* PCC-20 does not always set errno */
  438. extern    int strcmp();
  439. #endif
  440. #endif
  441.  
  442. #define FIX31OCT85 1            /* Allan Hetzel's XON/XOFF fix */
  443.  
  444. typedef int BOOLEAN;
  445.  
  446. #define FALSE 0
  447. #define TRUE 1
  448.  
  449. #ifndef FASTIO
  450. #define FASTIO        0
  451. #endif
  452.  
  453. #define PXLID        0        /* used in inch.h */
  454.  
  455. #include <stdio.h>
  456. #include <ctype.h>
  457. #include <errno.h>
  458. #ifndef OS_AMIGA
  459. #include <string.h>
  460. #endif
  461.  
  462. #if    IBM_PC_MICROSOFT
  463. /* int errno; */        /* not in errno.h */
  464. #include <stdlib.h>
  465. #include <time.h>
  466. #endif
  467.  
  468. #if    OS_TOPS20
  469. #include <time.h>
  470. #endif
  471.  
  472. #if    FASTIO
  473. #include <file.h>
  474. #include <jsys.h>
  475. #include <mon_s.h>
  476. #endif
  477.  
  478. #if    (OS_AMIGA | OS_TOPS20 | OS_UNIX | OS_VAXVMS | IBM_PC_AZTEC)
  479. #define FOPEN_W "w"
  480. #define FOPEN_R "r"
  481. #else
  482. #define FOPEN_W "wb"
  483. #define FOPEN_R "rb"
  484. #endif
  485.  
  486. /***********************************************************************
  487. PostScript's basic units  are big  points (72bp =  1in).  Everything  in
  488. this routine works in terms of "Quite Small Units": 1 inch = QSU qsu.
  489. ***********************************************************************/
  490.  
  491.  
  492. #define NUL '\0'
  493.  
  494. #define QSU 100000L        /* quite small units per inch -- */
  495.                 /* should be large to avoid */
  496.                 /* truncation error accumulation */
  497.  
  498. #define INCH_TO_QSU(x) ((COORDINATE)(x * (float)QSU))
  499.                 /* inch to QSU conversion */
  500.  
  501. #define LEFT_X (left_margin + col_margin)
  502. #define BOT_Y  (bottom_margin + col_margin)
  503. #define TOP_Y(margin) (page_height - (margin) - baseline_skip - col_margin)
  504.  
  505. #if    OS_TOPS20    /* want <CR><LF> */
  506. #define NEWLINE(fp) {(void)putc((char)'\r',fp);(void)putc((char)'\n',fp);}
  507. #else
  508. #define NEWLINE(fp) (void)putc((char)'\n',fp)    /* want bare <LF> */
  509. #endif
  510.  
  511. #define OUTCHAR(c) (void)putc((char)(c),tf)
  512. #define OUTOCTAL(c) (void)fprintf(tf,"\\%03o",(c))
  513. #define OUTSTR(s) (void)fputs(s,tf)
  514.  
  515. #define MAX(a,b) ((a) > (b) ? (a) : (b))
  516. #define MIN(a,b) ((a) < (b) ? (a) : (b))
  517.  
  518. #define HEIGHT (11L * QSU)    /* page height in QSU */
  519. #define MAXBLOCK 4096L        /* block size for file copy */
  520. #define MAXLEN 256        /* font name length */
  521. #define MAXPAGE 1024        /* size of page location table */
  522. #define WIDTH ((85L * QSU)/10L)    /* page width in QSU */
  523. #define COL_TWIDDLE 40L        /* 1/fraction of column width for */
  524.                 /* column margin */
  525.  
  526. #define PAGE_T 001        /* flag bits for page_flag */
  527. #define PAGE_B 002
  528. #define PAGE_L 010
  529. #define PAGE_R 020
  530. #define PAGE_C 040
  531.  
  532. #define TEMPFILE "lptops.tmp"    /* temporary output file */
  533.  
  534.  
  535.                 /* global functions */
  536. #if    ANSI_PROTOTYPES
  537. int  main(int ,char *[]);
  538. void Beg_Column(void);
  539. void Beg_Line(void);
  540. void Beg_Page(void);
  541. void Beg_Text(char);
  542. void Copy_Block(long ,long);
  543. void Copy_Plist(char, FILE *);
  544. void Do_File(FILE *);
  545. void End_Column(void);
  546. void End_Page(void);
  547. void End_Line(void);
  548. void End_Text(char);
  549. float inch(char *);
  550. int inchar(FILE *);
  551. void Page_Switch(char *);
  552.  
  553. #if    ANSI_LIBRARY
  554. int     atoi(const char *);
  555. char*   ctime(const time_t *);
  556. #else /* NOT ANSI_LIBRARY */
  557. int     atoi(char *);
  558. char*   ctime(long *);
  559. #endif /* ANSI_LIBRARY */
  560.  
  561. char *cuserid(char *);
  562. void EXIT(int);
  563. char *getlogin(void);
  564.  
  565. #if    ANSI_LIBRARY
  566. void perror(const char *);
  567. char *strcpy(char *,const char *);
  568. int strcm2(char *,char *);
  569. size_t strlen(const char *);
  570. char *strncpy(char *,const char *,size_t);
  571. time_t time(time_t *);
  572. int unlink(const char *);
  573. #else /* NOT ANSI_LIBRARY */
  574. void perror(char *);
  575. char *strcpy(char *,char *);
  576. int strcm2(char *,char *);
  577. int strlen(char *);
  578. char *strncpy(char *,char *,int);
  579. long time(long *);
  580. int unlink(char *);
  581. #endif /* ANSI_LIBRARY */
  582.  
  583. #else
  584. void Beg_Column();
  585. void Beg_Line();
  586. void Beg_Page();
  587. void Beg_Text();
  588. void Copy_Block();
  589. void Copy_Plist();
  590. void Do_File();
  591. void End_Column();
  592. void End_Page();
  593. void End_Line();
  594. void End_Text();
  595. void Head_Foot_Switch();
  596. float inch();
  597. int  inchar();
  598. int  main();
  599. void Page_Switch();
  600.  
  601. int  atoi();
  602. char *ctime();
  603. char *cuserid();
  604. void EXIT();
  605. char *getlogin();
  606. void perror();
  607. char *strcpy();
  608. int  strcm2();
  609. int  strlen();
  610. char* strncpy();
  611. long time();
  612. int  unline();
  613. #endif
  614.  
  615. typedef long COORDINATE;    /* variables in QSU need >=32 bits */
  616.  
  617.  
  618.                 /* global variables */
  619.  
  620. FILE *tf;            /* temporary output file */
  621. BOOLEAN bad_option;        /* bad option flag */
  622. COORDINATE baseline_skip;    /* inter-line spacing */
  623. COORDINATE bottom_margin;    /* bottom margin width in QSU */
  624. int  column;            /* current text column (1..numcol) */
  625. COORDINATE col_margin;        /* column margin (extra space */
  626.                 /* between column borders in */
  627.                 /* multi-column mode) */
  628. COORDINATE col_width;        /* column width in QSU */
  629. int  copies;            /* number of copies of each page */
  630. BOOLEAN  do_headerfooter;       /* header-footer flag  */
  631. BOOLEAN  do_page_number;    /* page numbering flag */
  632. char *filename;                 /* file name           */
  633. char font_name[MAXLEN+1];    /* font name -- normal */
  634. char font_bold[MAXLEN+1];    /* font name -- bold */
  635. char font_italic[MAXLEN+1];    /* font name -- italic */
  636. BOOLEAN found;            /* search flag */
  637. int  in_col;            /* input line column */
  638. int  init_page_number;        /* initial page number */
  639. COORDINATE init_top_margin;    /* initial page top margin in QSU */
  640. BOOLEAN landscape_mode;        /* horizontal landscape mode output */
  641. COORDINATE left_margin;        /* left margin in QSU */
  642. int  level;            /* parenthesis level */
  643. int  line_number;        /* current line number */
  644. int  manual_feed;        /* manual feed page count */
  645. int  numcol;            /* number of text columns */
  646. COORDINATE outline;        /* page and column outline linewidth */
  647. int  page_flag;            /* page number location flag */
  648. COORDINATE page_height;        /* page height in QSU */
  649. int  page_number;        /* current page number */
  650. long page_table[MAXPAGE+1];    /* page location table (with space */
  651.                 /* for extra entry marking EOF) */
  652. char timestr[27];        /* result of ctime() */
  653. long timeval;            /* result of time() */
  654.  
  655. COORDINATE page_width;        /* page width in QSU */
  656. COORDINATE point_size;        /* font point size in big points */
  657. BOOLEAN reverse;        /* page reversal flag */
  658. COORDINATE right_margin;    /* right margin in QSU */
  659. BOOLEAN scribe;            /* recognize bold/italic sequences */
  660. COORDINATE top_margin;        /* top margin in QSU */
  661. COORDINATE x;            /* current horizontal coordinate */
  662. COORDINATE y;            /* current vertical coordinate */
  663.  
  664. /***********************************************************************
  665. Built-in PostScript font tables.  The first column in each list contains
  666. the full (case sensitive) PostScript  names, the second column  contains
  667. convenient short abbreviations  which can  be used in  the command  line
  668. -ffontname option,  the third  and fourth  columns contain  ditroff  and
  669. Adobe TranScript abbreviations.
  670.  
  671. The  first  four  lines  of   entries  are  available  on  the   regular
  672. LaserWriter, and the  remainder are  available only  on the  LaserWriter
  673. Plus.
  674. ***********************************************************************/
  675.  
  676. char* ps_normal[] =
  677. {
  678.     /* fullname                short    ditroff    TranScript */
  679.     "Courier",                "C",    "C",    "C",
  680.     "Helvetica",            "H",    "he",    "he",
  681.     "Times-Roman",            "T",    "R",    "ti",
  682.     "Symbol",                "S",    "S",    "S",
  683.     "AvantGarde-Book",            "AGB",    "ag",    "ag",
  684.     "AvantGarde-Demi",            "AGD",    "Ag",    "Ag",
  685.     "Bookman-Demi",            "BD",    "Bo",    "Bo",
  686.     "Bookman-Light",            "BL",    "bo",    "bo",
  687.     "Helvetica-Narrow",            "HN",    "hn",    "hn",
  688.     "NewCenturySchlbk-Roman",        "NCSR",    "nc",    "nc",
  689.     "Palatino-Roman",            "PR",    "pa",    "pa",
  690.     "ZapfChancery-MediumItalic",    "ZCMI",    "ZC",    "ZC",
  691.     "ZapfDingbats",            "ZD",    "ZD",    "ZD"
  692. };
  693.  
  694. char* ps_bold[] =
  695. {
  696.     /* fullname                short    ditroff    TranScript */
  697.     "Courier-Bold",            "CB",    "CB",    "CB",
  698.     "Helvetica-Bold",            "HB",    "He",    "He",
  699.     "Times-Bold",            "TB",    "B",    "Ti",
  700.     "Symbol",                "S",    "S",    "S",
  701.     "AvantGarde-Book",            "AGB",    "ag",    "ag",
  702.     "AvantGarde-Demi",            "AGD",    "Ag",    "Ag",
  703.     "Bookman-Demi",            "BD",    "Bo",    "Bo",
  704.     "Bookman-Light",            "BL",    "bo",    "bo",
  705.     "Helvetica-Narrow-Bold",        "HNB",    "Hn",    "Hn",
  706.     "NewCenturySchlbk-Bold",        "NCSB",    "Nc",    "Nc",
  707.     "Palatino-Bold",            "PB",    "Pa",    "Pa",
  708.     "ZapfChancery-MediumItalic",    "ZCMI",    "ZC",    "ZC",
  709.     "ZapfDingbats",            "ZD",    "ZD",    "ZD"
  710. };
  711.  
  712. char* ps_italic[] =
  713. {
  714.     /* fullname                short    ditroff    TranScript */
  715.     "Courier-Oblique",            "CO",    "CO",    "CO",
  716.     "Helvetica-Oblique",        "HO",    "hE",    "hE",
  717.     "Times-Italic",            "TI",    "I",    "tI",
  718.     "Symbol",                "S",    "S",    "S",
  719.     "AvantGarde-BookOblique",        "AGBO",    "aG",    "aG",
  720.     "AvantGarde-DemiOblique",        "AGDO",    "AG",    "AG",
  721.     "Bookman-DemiItalic",        "BDI",    "BO",    "BO",
  722.     "Bookman-LightItalic",        "BLI",    "bO",    "bO",
  723.     "Helvetica-Narrow-Oblique",        "HNO",    "hN",    "hN",
  724.     "NewCenturySchlbk-Italic",        "NCSI",    "nC",    "nC",
  725.     "Palatino-Italic",            "PI",    "pA",    "pA",
  726.     "ZapfChancery-MediumItalic",    "ZCMI",    "ZC",    "ZC",
  727.     "ZapfDingbats",            "ZD",    "ZD",    "ZD"
  728. };
  729.  
  730. char* ps_both[] =
  731. {
  732.     /* fullname                short    ditroff    TranScript */
  733.     "Courier-BoldOblique",        "CBO",    "CD",    "CD",
  734.     "Helvetica-BoldOblique",        "HBO",    "HE",    "HE",
  735.     "Times-BoldItalic",            "TBI",    "BI",    "TI",
  736.     "Symbol",                "S",    "S",    "S",
  737.     "AvantGarde-BookOblique",        "AGBO",    "aG",    "aG",
  738.     "AvantGarde-DemiOblique",        "AGDO",    "AG",    "AG",
  739.     "Bookman-DemiItalic",        "BDI",    "BO",    "BO",
  740.     "Bookman-LightItalic",        "BLI",    "bO",    "bO",
  741.     "Helvetica-Narrow-BoldOblique",    "HNBO",    "HN",    "HN",
  742.     "NewCenturySchlbk-BoldItalic",    "NCSBI","NC",    "NC",
  743.     "Palatino-BoldItalic",        "PBI",    "PA",    "PA",
  744.     "ZapfChancery-MediumItalic",    "ZCMI",    "ZC",    "ZC",
  745.     "ZapfDingbats",            "ZD",    "ZD",    "ZD"
  746. };
  747.  
  748.  
  749. #define PS_DEFAULT 0    /* index of default font in ps_normal[] */
  750. #define MAXFONT (sizeof(ps_normal)/sizeof(char *)) /* size of font table */
  751.  
  752.  
  753. int
  754. main(argc,argv)
  755. int argc;
  756. char* argv[];
  757. {
  758.     register int k;            /* loop index */
  759.     register char *p;            /* temporary pointer */
  760.     register int m,n;            /* loop indices */
  761.     FILE *fp;                /* input file pointer */
  762.     long last,next;            /* result of fseek() for */
  763.                     /* page_table[] construction */
  764.     int (*compare)();
  765.  
  766.     /* establish defaults for all parameters */
  767.     bottom_margin = 1L * QSU;
  768.     column = 1;
  769.     col_margin = 0L;
  770.     copies = 1;
  771.     do_headerfooter = FALSE;
  772.     do_page_number = FALSE;
  773.     init_page_number = 1;
  774.     init_top_margin = -1;    /* negative value flags unset state */
  775.     in_col = 0;
  776.     landscape_mode = FALSE;
  777.     left_margin = 1L * QSU;
  778.     manual_feed = 0;
  779.     numcol = 1;
  780.     outline = 0L;
  781.     page_height = HEIGHT;
  782.     page_width = WIDTH;
  783.     point_size = INCH_TO_QSU(inch("10bp"));
  784.     reverse = TRUE;
  785.     right_margin = 1L * QSU;
  786.     scribe = FALSE;
  787.     top_margin = 1L * QSU;
  788.  
  789.     strcpy(font_name,ps_normal[PS_DEFAULT]);
  790.     strcpy(font_bold,ps_bold[PS_DEFAULT]);
  791.     strcpy(font_italic,ps_italic[PS_DEFAULT]);
  792.  
  793.     bad_option = FALSE;
  794.     for (k = 1; k < argc; ++k)
  795.     {
  796.     p = argv[k];
  797.     if (argv[k][0] == '-')
  798.     {
  799.         switch(argv[k][1])
  800.         {
  801.         case 'a':
  802.         case 'A':
  803.         scribe = TRUE;
  804.         break;
  805.  
  806.         case 'b':
  807.         case 'B':
  808.         bottom_margin = INCH_TO_QSU(inch(&argv[k][2]));
  809.         break;
  810.  
  811.         case 'c':
  812.         case 'C':
  813.         copies = atoi(&argv[k][2]);
  814.         break;
  815.  
  816.         case 'd':
  817.         case 'D':
  818.         Head_Foot_Switch(&argv[k][1]);
  819.         break;
  820.  
  821.         case 'f':
  822.         case 'F':
  823.         (void)strncpy(font_name,&argv[k][2],MAXLEN);
  824.         font_name[MAXLEN] = '\0';
  825.         found = FALSE;
  826.         for (n = 0; n < MAXFONT; n += 4)
  827.         {
  828.             for (m = 3; m >= 0; --m)
  829.             {
  830.             /* compare case-sensitive ditroff and TranScript
  831.                names before case-insensitive ones */
  832.             compare = (m > 1) ? strcmp : strcm2;
  833.             if ((*compare)(font_name,ps_normal[n+m]) == 0)
  834.             {
  835.                 strcpy(font_name,ps_normal[n]);
  836.                 strcpy(font_bold,ps_bold[n]);
  837.                 strcpy(font_italic,ps_italic[n]);
  838.                 found = TRUE;
  839.                 break;
  840.             }
  841.             else if ((*compare)(font_name,ps_bold[n+m]) == 0)
  842.             {
  843.                 strcpy(font_name,ps_bold[n]);
  844.                 strcpy(font_bold,ps_bold[n]);
  845.                 strcpy(font_italic,ps_italic[n]);
  846.                 found = TRUE;
  847.                 break;
  848.             }
  849.             else if ((*compare)(font_name,ps_italic[n+m]) == 0)
  850.             {
  851.                 strcpy(font_name,ps_italic[n]);
  852.                 strcpy(font_bold,ps_both[n]);
  853.                 strcpy(font_italic,ps_normal[n]);
  854.                 found = TRUE;
  855.                 break;
  856.             }
  857.             else if ((*compare)(font_name,ps_both[n+m]) == 0)
  858.             {
  859.                 strcpy(font_name,ps_both[n]);
  860.                 strcpy(font_bold,ps_italic[n]);
  861.                 strcpy(font_italic,ps_normal[n]);
  862.                 found = TRUE;
  863.                 break;
  864.             }
  865.             }
  866.         }
  867.         if (!found)
  868.         {
  869.             NEWLINE(stderr);
  870.                 (void)fprintf(stderr,
  871.             "?Illegal font name [%s].  Possible values are:",
  872.             font_name);
  873.             NEWLINE(stderr);
  874.  
  875.             NEWLINE(stderr);
  876.             (void)fprintf(stderr,"Normal fonts");
  877.             NEWLINE(stderr);
  878.             for (m = 0; m < MAXFONT; m += 4)
  879.             {
  880.             (void)fprintf(stderr,"\t%-30s %-10s %-10s %-10s",
  881.                 ps_normal[m],ps_normal[m+1],ps_normal[m+2],
  882.                 ps_normal[m+3]);
  883.             NEWLINE(stderr);
  884.             }
  885.  
  886.             NEWLINE(stderr);
  887.             (void)fprintf(stderr,"Bold fonts");
  888.             NEWLINE(stderr);
  889.             for (m = 0; m < MAXFONT; m += 4)
  890.             {
  891.             (void)fprintf(stderr,"\t%-30s %-10s %-10s %-10s",
  892.                 ps_bold[m],ps_bold[m+1],ps_bold[m+2],
  893.                 ps_bold[m+3]);
  894.             NEWLINE(stderr);
  895.             }
  896.  
  897.             NEWLINE(stderr);
  898.             (void)fprintf(stderr,"Oblique/Italic fonts");
  899.             NEWLINE(stderr);
  900.             for (m = 0; m < MAXFONT; m += 4)
  901.             {
  902.             (void)fprintf(stderr,"\t%-30s %-10s %-10s %-10s",
  903.                 ps_italic[m],ps_italic[m+1],ps_italic[m+2],
  904.                 ps_italic[m+3]);
  905.             NEWLINE(stderr);
  906.             }
  907.  
  908.             NEWLINE(stderr);
  909.             (void)fprintf(stderr,"BoldOblique/BoldItalic fonts");
  910.             NEWLINE(stderr);
  911.             for (m = 0; m < MAXFONT; m += 4)
  912.             {
  913.             (void)fprintf(stderr,"\t%-30s %-10s %-10s %-10s",
  914.                 ps_both[m],ps_both[m+1],ps_both[m+2],
  915.                 ps_both[m+3]);
  916.             NEWLINE(stderr);
  917.             }
  918.             NEWLINE(stderr);
  919.             bad_option = TRUE;
  920.         }
  921.         break;
  922.  
  923.         case 'h':
  924.         case 'H':
  925.         landscape_mode = TRUE;
  926.         break;
  927.  
  928.         case 'i':
  929.         case 'I':
  930.         init_top_margin = INCH_TO_QSU(inch(&argv[k][2]));
  931.         break;
  932.  
  933.         case 'l':
  934.         case 'L':
  935.         left_margin = INCH_TO_QSU(inch(&argv[k][2]));
  936.         break;
  937.  
  938.         case 'm':
  939.         case 'M':
  940.         numcol = atoi(&argv[k][2]);
  941.         break;
  942.  
  943.         case 'n':
  944.         case 'N':
  945.         Page_Switch(&argv[k][1]);
  946.         break;
  947.  
  948.         case 'o':
  949.         case 'O':
  950.         if (argv[k][2])        /* have -O# */
  951.             outline = INCH_TO_QSU(inch(&argv[k][2]));
  952.         else            /* have -O, so give default */
  953.             outline = INCH_TO_QSU(inch("0.4pt"));  /* from TeX */
  954.         break;
  955.  
  956.         case 'p':
  957.         case 'P':
  958.         point_size = INCH_TO_QSU(inch(&argv[k][2]));
  959.         break;
  960.  
  961.         case 'r':
  962.         case 'R':
  963.         right_margin = INCH_TO_QSU(inch(&argv[k][2]));
  964.         break;
  965.  
  966.         case 's':
  967.         case 'S':
  968.         if (argv[k][2]) /* have count field */
  969.             manual_feed = atoi(&argv[k][2]);
  970.         else        /* omitted count ==> large number */
  971.             manual_feed = 32767;
  972.         break;
  973.  
  974.         case 't':
  975.         case 'T':
  976.         top_margin = INCH_TO_QSU(inch(&argv[k][2]));
  977.         break;
  978.  
  979.         case 'u':
  980.         case 'U':
  981.         reverse = FALSE;
  982.         break;
  983.  
  984.         default:
  985.         NEWLINE(stderr);
  986.         (void)fprintf(stderr,"?Unrecognized option [%s]",p);
  987.         NEWLINE(stderr);
  988.         bad_option = TRUE;
  989.         }
  990.     }
  991.         else
  992.         {
  993.            if(!filename)
  994.               {
  995.               filename = argv[k];
  996.               }
  997.         }
  998.     }
  999.  
  1000.     page_number = init_page_number;
  1001.  
  1002.     if (bad_option)
  1003.     {
  1004.     (void)fprintf(stderr,
  1005.         "Usage: %s -A -B# -Cn -Ffontname -H -I# -L# -Mn -N[tb][lcr]n \
  1006. -O[#] -P# -R# -S[n] -T# -U filelist >outfile",argv[0]);
  1007.     NEWLINE(stderr);
  1008.  
  1009.     (void)fprintf(stderr,"Default options: -B1.0in -C1 -FCourier -L1.0in \
  1010. -M1 -P10bp -R1.0in -S0 -T1.0in");
  1011.     NEWLINE(stderr);
  1012.  
  1013.     EXIT(1);
  1014.     }
  1015.  
  1016.  
  1017.     if (reverse)
  1018.     {
  1019.     if ((tf = fopen(TEMPFILE,FOPEN_W)) == (FILE *)NULL)
  1020.     {
  1021.         NEWLINE(stderr);
  1022.         (void)fprintf(stderr,"?Cannot open temporary file [%s]",TEMPFILE);
  1023.         NEWLINE(stderr);
  1024.         (void)perror("?perror() says");
  1025.         EXIT(1);
  1026.     }
  1027.     }
  1028.     else
  1029.     tf = stdout;
  1030.  
  1031.     /*******************************************************************
  1032.     Make the PostScript File Structure header according to Version  1.0,
  1033.     First Edition  (January 1985)  of  the PostScript  File  Structuring
  1034.     Conventions manual.  We add  one additional field  at the end  after
  1035.     the %%Pages: n field:
  1036.  
  1037.     %%PageTable: m1 n1 p1 ... mk nk pk
  1038.  
  1039.     where the triples (mj  nj pj) contain the  page number pair (mj  nj)
  1040.     like the field
  1041.  
  1042.     %%Page: mj nj
  1043.  
  1044.     and pj is the  byte position in  the file of  the beginning of  that
  1045.     "%%Page" command.  A spooler can  then easily position to  arbitrary
  1046.     pages in the file for reprinting.
  1047.     *******************************************************************/
  1048.  
  1049.     OUTSTR("%!PS-Adobe-1.0");        /* magical file header */
  1050.     NEWLINE(tf);
  1051.  
  1052.     OUTSTR("%%DocumentFonts: ");
  1053.     OUTSTR(font_name);            /* only use one font */
  1054.     NEWLINE(tf);
  1055.  
  1056.     OUTSTR("%%Dimensions: 0 0 612 792");    /* 8.5 x 11 inch page size */
  1057.     NEWLINE(tf);
  1058.  
  1059.     OUTSTR("%%Title:");            /* this contains our command line */
  1060.     for (k = 0; k < argc; ++k)
  1061.     {
  1062.     OUTCHAR(' ');
  1063.     OUTSTR(argv[k]);
  1064.     }
  1065.     NEWLINE(tf);               /* end of %%Title line */
  1066.  
  1067.     timeval = time((long *)NULL);
  1068.     strcpy(timestr,ctime(&timeval));
  1069.     k = strlen(timestr) - 1;    /* ctime has its own \n */
  1070.     timestr[k] = NUL;        /* so kill it */
  1071.     OUTSTR("%%CreationDate: ");
  1072.     OUTSTR(timestr);
  1073.     NEWLINE(tf);
  1074.  
  1075.     /* Under TOPS-20, JSYS GFUST% cannot be used to obtain file owner string
  1076.     of a terminal file, which stdout always is, so just use job login name */
  1077.  
  1078.     OUTSTR("%%Creator: ");
  1079. #ifndef OS_AMIGA
  1080.     if (cuserid((char*)NULL) != (char*)NULL)
  1081.         OUTSTR(cuserid((char*)NULL));
  1082. #else
  1083.     OUTSTR("lptops (Amiga version - 12/22/89)");
  1084. #endif
  1085.     NEWLINE(tf);
  1086.  
  1087.     OUTSTR("%%Pages: (atend)");
  1088.     NEWLINE(tf);
  1089.     OUTSTR("%%EndComments");
  1090.     NEWLINE(tf);
  1091.     OUTSTR("save");            /* has matching "restore" at end */
  1092.     NEWLINE(tf);
  1093.     OUTSTR("%%EndProlog");
  1094.     NEWLINE(tf);
  1095.  
  1096.              /* validate input settings */
  1097.     copies = MAX(1,copies);
  1098.     numcol = MAX(1,numcol);
  1099.     point_size = MAX(INCH_TO_QSU(inch("3bp")),point_size);
  1100.     if (point_size > INCH_TO_QSU(0.25))
  1101.     {
  1102.     NEWLINE(stderr);
  1103.     (void)fprintf(stderr,
  1104.         "%warning -- font point size > 18pt is unusually large!");
  1105.     NEWLINE(stderr);
  1106.     }
  1107.     outline = MAX(0L,outline);
  1108.  
  1109.     if (landscape_mode)        /* switch sizes for landscape mode */
  1110.     {
  1111.     page_height = WIDTH;
  1112.     page_width = HEIGHT;
  1113.     }
  1114.     if (((left_margin + right_margin) >= page_width) ||
  1115.     ((top_margin + bottom_margin) >= page_height) ||
  1116.     ((init_top_margin + bottom_margin) >= page_height))
  1117.     {
  1118.     NEWLINE(stderr);
  1119.     (void)fprintf(stderr,"?Margin values too large for page");
  1120.     NEWLINE(stderr);
  1121.     EXIT(1);
  1122.     }
  1123.  
  1124.     col_width = (page_width - left_margin - right_margin)/numcol;
  1125.     col_margin = ((numcol == 1) && (outline == 0)) ?
  1126.     0L : (col_width/COL_TWIDDLE);
  1127.  
  1128.     /* TeX's baselineskip is 12pt for 10pt type; we preserve the same ratio */
  1129.     baseline_skip = (point_size * 12L) / 10L;
  1130.  
  1131.     m = 0;                /* count of file names */
  1132.     for (k = 1; k < argc; ++k)
  1133.     {
  1134.     if (*argv[k] != '-')
  1135.     {
  1136.         m++;            /* count file name */
  1137.         if ((fp = fopen(argv[k],FOPEN_R)) != (FILE *)NULL)
  1138.         {
  1139.         Do_File(fp);
  1140.         (void)fclose(fp);
  1141.         }
  1142.         else
  1143.         {
  1144.         (void)fprintf(stderr,"?Open failure on [%s] -- file skipped",
  1145.             argv[k]);
  1146.         NEWLINE(stderr);
  1147.         }
  1148.     }
  1149.     }
  1150.     if (m == 0)
  1151.     Do_File(stdin);
  1152.  
  1153.     if (reverse)
  1154.     {
  1155.     /* Now close the temporary file and reopen for input, then transfer */
  1156.     /* complete pages in reverse order to stdout using large blocks */
  1157.  
  1158.     if (fclose(tf))
  1159.     {
  1160.         NEWLINE(stderr);
  1161.         (void)fprintf(stderr,"?Close failure on temporary file [%s]",
  1162.         TEMPFILE);
  1163.         NEWLINE(stderr);
  1164.         (void)perror("?perror() says");
  1165.         EXIT(1);
  1166.     }
  1167.  
  1168.     if ((tf = fopen(TEMPFILE,FOPEN_R)) == (FILE *)NULL)
  1169.     {
  1170.         NEWLINE(stderr);
  1171.         (void)fprintf(stderr,"?Cannot reopen temporary file [%s]",TEMPFILE);
  1172.         NEWLINE(stderr);
  1173.         (void)perror("?perror() says");
  1174.         EXIT(1);
  1175.     }
  1176.  
  1177.     NEWLINE(stderr);
  1178.     (void)fprintf(stderr,"[Reversing pages");
  1179.     Copy_Block(0L,page_table[0]-1);    /* first page is file header stuff */
  1180.     last = page_table[MIN(MAXPAGE,page_number-init_page_number+1)];
  1181.     for (k = MIN(MAXPAGE,page_number-init_page_number+1)-1; k >= 0; --k)
  1182.     {                /* copy remainder in reverse order */
  1183.         (void)putc('.',stderr);
  1184.         next = (long)ftell(stdout);
  1185.         Copy_Block(page_table[k],last-1);
  1186.         last = page_table[k];
  1187.         page_table[k] = next;
  1188.     }
  1189.     (void)putc(']',stderr);
  1190.     if (fclose(tf))
  1191.     {
  1192.         NEWLINE(stderr);
  1193.         (void)fprintf(stderr,"?Close failure on temporary file [%s]",
  1194.         TEMPFILE);
  1195.         NEWLINE(stderr);
  1196.         (void)perror("?perror() says");
  1197.         EXIT(1);
  1198.     }
  1199.  
  1200.     unlink(TEMPFILE);        /* delete the temporary file */
  1201.     }
  1202.     /* add file trailer stuff */
  1203.  
  1204.     tf = stdout;            /* so OUTSTR() macro works */
  1205.  
  1206.     OUTSTR("%%Trailer");
  1207.     NEWLINE(stdout);
  1208.     OUTSTR("restore");            /* matches "save" in prolog */
  1209.     NEWLINE(stdout);
  1210.     (void)printf("%%%%Pages: %d",page_number-init_page_number);
  1211.     NEWLINE(stdout);
  1212.     OUTSTR("%%PageTable: ");
  1213.     for (k = 0; k < MIN(MAXPAGE,page_number-init_page_number+1); ++k)
  1214.     (void)printf(" %d %d %ld",init_page_number+k,init_page_number+k,
  1215.         page_table[k]);
  1216.     NEWLINE(stdout);
  1217.     if (putchar('\004') == EOF)        /* CTL-D for EOF signal */
  1218.     {
  1219.     NEWLINE(stderr);
  1220.     (void)fprintf(stderr,"?Output error -- disk storage probably full");
  1221.     NEWLINE(stderr);
  1222.     (void)perror("?perror() says");
  1223.     EXIT(1);
  1224.     }
  1225.     (void)fprintf(stderr," [ok]");
  1226.     NEWLINE(stderr);
  1227.     EXIT(0);
  1228.     return (0);                /* keep lint and compilers happy */
  1229. }
  1230.  
  1231. void
  1232. Beg_Column()
  1233. {
  1234.     (void)fprintf(tf,"%ld %ld moveto",x,y);
  1235.     NEWLINE(tf);
  1236. }
  1237.  
  1238. void
  1239. Beg_Line()
  1240. {
  1241.     if (scribe)
  1242.     {
  1243.     OUTCHAR('S');
  1244.     OUTCHAR(' ');
  1245.     }
  1246. }
  1247.  
  1248. void
  1249. Beg_Page()
  1250. {
  1251.     int k;
  1252.  
  1253.     column = 1;
  1254.     (void)fflush(tf);
  1255.     k = page_number-init_page_number;
  1256.     if (k < MAXPAGE)
  1257.     page_table[k] = (long)ftell(tf);
  1258.     (void)fprintf(tf,"%%%%Page: %d %d",k+1,page_number);
  1259.     NEWLINE(tf);
  1260.     OUTSTR("save");    /* will be matched by "restore" from End_Page() */
  1261.     NEWLINE(tf);
  1262.     if (scribe)
  1263.     {
  1264.     (void)fprintf(tf,"/B {/%s findfont %ld scalefont setfont} def",
  1265.         font_bold,point_size);
  1266.     NEWLINE(tf);
  1267.  
  1268.     (void)fprintf(tf,"/E {grestore 0 %ld rmoveto} def",
  1269.         -baseline_skip);        /* End of line */
  1270.     NEWLINE(tf);
  1271.  
  1272.     (void)fprintf(tf,"/I {/%s findfont %ld scalefont setfont} def",
  1273.         font_italic,point_size);
  1274.     NEWLINE(tf);
  1275.  
  1276.     (void)fprintf(tf,"/N {/%s findfont %ld scalefont setfont} def",
  1277.         font_name,point_size);
  1278.     NEWLINE(tf);
  1279.  
  1280.     OUTSTR("/O {gsave show grestore} def");    /* OverPrint macro */
  1281.     NEWLINE(tf);
  1282.  
  1283.     OUTSTR("/S {gsave} def");    /* Start of line */
  1284.     NEWLINE(tf);
  1285.  
  1286.     OUTSTR("/W {show} def");    /* show text */
  1287.     NEWLINE(tf);
  1288.     }
  1289.     else
  1290.     {
  1291.     OUTSTR("/O {gsave show grestore} def");    /* OverPrint macro */
  1292.     NEWLINE(tf);
  1293.  
  1294.     (void)fprintf(tf,"/P {gsave show grestore 0 %ld rmoveto} def",
  1295.         -baseline_skip);  /* Print macro */
  1296.     NEWLINE(tf);
  1297.  
  1298.     (void)fprintf(tf,"/N {/%s findfont %ld scalefont setfont} def",
  1299.         font_name,point_size);
  1300.     NEWLINE(tf);
  1301.     }
  1302.     (void)fprintf(tf,"72 %ld div 72 %ld div scale",QSU,QSU);
  1303.     NEWLINE(tf);
  1304.     OUTCHAR('N');            /* select normal font */
  1305.  
  1306. #if    FIX31OCT85
  1307.     OUTSTR("()pop");            /* no-op for XON/XOFF bug workaround */
  1308. #endif
  1309.  
  1310.     NEWLINE(tf);
  1311.  
  1312.     if (landscape_mode)
  1313.     {
  1314.     (void)fprintf(tf,"%ld %ld translate",0L,HEIGHT);
  1315.     NEWLINE(tf);
  1316.     OUTSTR("-90 rotate");
  1317.     NEWLINE(tf);
  1318.     }
  1319.     (void)fprintf(stderr,
  1320.     " [%d",page_number);    /* begin [p.l.l...] status report */
  1321. }
  1322.  
  1323. void
  1324. Beg_Text(c)
  1325. char c;
  1326. {
  1327.     if (c)
  1328.     {
  1329.     OUTCHAR(' ');
  1330.     OUTCHAR(c);
  1331.     OUTCHAR(' ');
  1332.     }
  1333.     OUTCHAR('(');
  1334.     level++;
  1335. }
  1336.  
  1337. void
  1338. Copy_Block(b1,b2)    /* copy bytes b1..b2 from tf to stdout */
  1339. long b1,b2;                /* start,end byte positions */
  1340. {
  1341.     static char block[MAXBLOCK];    /* static to save stack space */
  1342.     long k;                /* loop index */
  1343.     long length;            /* number of bytes to copy */
  1344.  
  1345. #if    FASTIO
  1346.     (void)fflush(stdout);        /* empty any buffered output */
  1347. #endif
  1348.     for (k = b1; k <= b2; k += MAXBLOCK)
  1349.     {
  1350.     length = MIN(MAXBLOCK,b2-k+1);
  1351.  
  1352.     (void)fseek(tf,k,0);        /* position to desired block */
  1353.  
  1354. #if    FASTIO
  1355.     if (_read(jfnof(fileno(tf)),block,(int)length) != (int)length)
  1356. #else
  1357.     if (fread(block,1,(int)length,tf) != (int)length)
  1358. #endif
  1359.     {
  1360.         NEWLINE(stderr);
  1361.         (void)fprintf(stderr,
  1362.           "?Input block length error on temporary file [%s]",TEMPFILE);
  1363.         NEWLINE(stderr);
  1364.         (void)perror("?perror() says");
  1365.         EXIT(1);
  1366.     }
  1367. #if    FASTIO
  1368.     if (_write(jfnof(fileno(stdout)),block,(int)length) != (int)length)
  1369. #else
  1370.     if (fwrite(block,1,(int)length,stdout) != (int)length)
  1371. #endif
  1372.     {
  1373.         NEWLINE(stderr);
  1374.         (void)fprintf(stderr,
  1375.           "?Output block length error on stdout");
  1376.         NEWLINE(stderr);
  1377.         (void)perror("?perror() says");
  1378.         EXIT(1);
  1379.     }
  1380.     }
  1381.     (void)fflush(stdout);
  1382. }
  1383.  
  1384. void
  1385. Copy_Plist(fontc,fp)        /* copy parenthesized list to tf */
  1386. char fontc;
  1387. FILE *fp;
  1388. {
  1389.     static char p_open[] = {'(','[','<','{',NUL};
  1390.     static char p_close[] = {')',']','>','}',NUL};
  1391.     register int match;
  1392.     register int c;
  1393.  
  1394.     c = inchar(fp);
  1395.     match = 0;
  1396.     while (p_open[match] && (p_open[match] != (char)c))
  1397.     match++;
  1398.  
  1399.     if (!p_open[match])
  1400.     {
  1401.     NEWLINE(stderr);
  1402.     (void)fprintf(stderr,"?@b or @i not followed by open parenthesis!");
  1403.     NEWLINE(stderr);
  1404.     EXIT(1);
  1405.     }
  1406.  
  1407.     Beg_Text(fontc);
  1408.     while (((c = inchar(fp)) != EOF) && ((char)c != p_close[match]))
  1409.     {
  1410.     if (c < ' ')
  1411.     {
  1412.         NEWLINE(stderr);
  1413.         (void)fprintf(stderr,
  1414.         "?@b[...] or @i[...] contains control character!");
  1415.         NEWLINE(stderr);
  1416.         EXIT(1);
  1417.     }
  1418.     in_col++;
  1419.     switch(c)
  1420.     {
  1421.     case '(':
  1422.         OUTCHAR('\\');
  1423.         OUTCHAR(c);
  1424.         break;
  1425.  
  1426.     case ')':
  1427.         OUTCHAR('\\');
  1428.         OUTCHAR(c);
  1429.         break;
  1430.  
  1431.     case '\\':
  1432.         OUTCHAR('\\');
  1433.         OUTCHAR(c);
  1434.         break;
  1435.  
  1436.     default:
  1437.         OUTCHAR(c);
  1438.         break;
  1439.     }
  1440.     }
  1441.     End_Text('N');
  1442.     OUTCHAR(' ');
  1443. }
  1444.  
  1445. void
  1446. Do_File(fp)
  1447. FILE *fp;
  1448. {
  1449.     register int c;            /* character */
  1450.  
  1451. /**********************************************************************/
  1452. /*               PostScript Output Section              */
  1453. /**********************************************************************/
  1454.  
  1455.     x = LEFT_X;
  1456.     if (init_top_margin > 0)
  1457.     y = TOP_Y(init_top_margin);
  1458.     else
  1459.     y = TOP_Y(top_margin);
  1460.  
  1461.     Beg_Page();
  1462.     Beg_Column();
  1463.     level = 0;
  1464.     in_col = 0;
  1465.     line_number = 1;
  1466.  
  1467.     if ((c = inchar(fp)) != '\f')     /* discard any initial FF */
  1468.     (void)ungetc(c,fp);
  1469.  
  1470.     while ((c = inchar(fp)) != EOF)
  1471.     {
  1472.     switch (c)
  1473.     {
  1474.     case NUL:
  1475.         break;    /* discard NUL's from word-padded files */
  1476.  
  1477.     case '\b':
  1478.         if (in_col > 0)
  1479.         {
  1480.         in_col--;
  1481.         OUTCHAR('\\');
  1482.         OUTCHAR('b');
  1483.         }
  1484.         break;
  1485.  
  1486.     case '\f':
  1487.         in_col = 0;
  1488.         End_Text(NUL);
  1489.         NEWLINE(tf);
  1490.         End_Column();
  1491.         if (column > numcol)
  1492.         Beg_Page();
  1493.         Beg_Column();
  1494.         line_number = 1;
  1495.         break;
  1496.  
  1497.     case '\n':
  1498.         line_number++;
  1499.         if (in_col == 0)
  1500.         {
  1501.         Beg_Line();
  1502.         Beg_Text(NUL);
  1503.         }
  1504.         End_Text(NUL);
  1505.         End_Line();
  1506.         in_col = 0;
  1507.         y -= baseline_skip;
  1508.         if (y < BOT_Y)
  1509.         {
  1510.         End_Column();
  1511.         if (column > numcol)
  1512.             Beg_Page();
  1513.         Beg_Column();
  1514.         line_number = 1;
  1515.         }
  1516.         break;
  1517.  
  1518.  
  1519.     case '\r':    /* check for special case of overprinting */
  1520.         if ((c = inchar(fp)) != '\n') /* peek ahead one character */
  1521.         {            /* and if not LF, have overstrike */
  1522.         while (level > 0)
  1523.         {
  1524.             OUTCHAR(')');
  1525.             level--;
  1526.         }
  1527.         in_col = 0;
  1528.         OUTCHAR('O');
  1529.         NEWLINE(tf);    /* this lines up under previous line */
  1530.         }
  1531.         (void)ungetc(c,fp);  /* put back the peeked-at character */
  1532.         break;
  1533.  
  1534.     case '\t':
  1535.         if (in_col == 0)
  1536.         {
  1537.         Beg_Line();
  1538.         Beg_Text(NUL);
  1539.         }
  1540.         do
  1541.         {
  1542.         in_col++;
  1543.         OUTCHAR(' ');
  1544.         }
  1545.         while (in_col & 07); /* blank fill to multiple of 8 columns */
  1546.         break;
  1547.  
  1548.     case '(':
  1549.         if (in_col == 0)
  1550.         {
  1551.         Beg_Line();
  1552.         Beg_Text(NUL);
  1553.         }
  1554.         in_col++;
  1555.         OUTCHAR('\\');
  1556.         OUTCHAR('(');
  1557.         break;
  1558.  
  1559.     case ')':
  1560.         if (in_col == 0)
  1561.         {
  1562.         Beg_Line();
  1563.         Beg_Text(NUL);
  1564.         }
  1565.         in_col++;
  1566.         OUTCHAR('\\');
  1567.         OUTCHAR(')');
  1568.         break;
  1569.  
  1570.     case '\\':
  1571.         if (in_col == 0)
  1572.         {
  1573.         Beg_Line();
  1574.         Beg_Text(NUL);
  1575.         }
  1576.         in_col++;
  1577.         OUTCHAR('\\');
  1578.         OUTCHAR('\\');
  1579.         break;
  1580.  
  1581.     case '@':
  1582.         if (scribe)
  1583.         {
  1584.         c = inchar(fp);
  1585.         if ((c == 'b') || (c == 'B'))
  1586.         {
  1587.             if (in_col == 0)
  1588.             Beg_Line();
  1589.             else
  1590.                 End_Text(NUL);
  1591.             Copy_Plist('B',fp);
  1592.             Beg_Text(NUL);
  1593.             break;
  1594.         }
  1595.         else if ((c == 'i') || (c == 'I'))
  1596.         {
  1597.             if (in_col == 0)
  1598.             Beg_Line();
  1599.             else
  1600.                 End_Text(NUL);
  1601.             Copy_Plist('I',fp);
  1602.             Beg_Text(NUL);
  1603.             break;
  1604.         }
  1605.         (void)ungetc(c,fp);    /* put back the peeked-at character */
  1606.         c = (int)'@';        /* and restore original character */
  1607.         }
  1608.         /* ELSE fall through to default! */
  1609.  
  1610.     default:
  1611.         if (in_col == 0)
  1612.         {
  1613.         Beg_Line();
  1614.         Beg_Text(NUL);
  1615.         }
  1616.         in_col++;
  1617.         if ((c < 040) || (0176 < c))
  1618.         OUTOCTAL(c);
  1619.         else
  1620.         OUTCHAR(c);
  1621.         break;
  1622.     }
  1623.     }
  1624.     if (in_col > 0)
  1625.     End_Line();
  1626.     End_Text(NUL);
  1627.     column = numcol;            /* to force End_Page() action */
  1628.     End_Column();
  1629.  
  1630.     /* Normally, Beg_Page() sets the page_table[] entry.  Since this  is
  1631.     the last output  for this file,  we must set  it here manually.   If
  1632.     more files are  printed, this  entry will be  overwritten (with  the
  1633.     same value) at the next call to Beg_Page(). */
  1634.     page_table[page_number-init_page_number] = (long)ftell(tf);
  1635. }
  1636.  
  1637. void
  1638. End_Column()
  1639. {
  1640.     if (outline > 0)
  1641.     {
  1642.     NEWLINE(tf);
  1643.     OUTSTR("gsave");
  1644.     NEWLINE(tf);
  1645.     (void)fprintf(tf,"%ld setlinewidth",outline);
  1646.     NEWLINE(tf);
  1647.     (void)fprintf(tf,"newpath %ld %ld moveto",x - col_margin,bottom_margin);
  1648.     (void)fprintf(tf,
  1649.         " %ld %ld rlineto %ld %ld rlineto %ld %ld rlineto closepath stroke",
  1650.         col_width,0,
  1651.         0,page_height-bottom_margin-top_margin,
  1652.         -col_width,0);
  1653.     NEWLINE(tf);
  1654.     OUTSTR("grestore");
  1655.     NEWLINE(tf);
  1656.     }
  1657.     (void)fprintf(stderr,
  1658.     ".%d",line_number);    /* continue [p.l.l...] status report */
  1659.     if (++column > numcol)    /* columns filled, so start new page */
  1660.     {
  1661.     (void)putc(']',stderr);    /* close [p.l.l...] report */
  1662.     End_Page();
  1663.     }
  1664.     else            /* just start new column */
  1665.     {
  1666.     x += col_width;
  1667.     y = TOP_Y(top_margin);
  1668.     }
  1669. }
  1670.  
  1671. void
  1672. End_Page()
  1673. {
  1674.     register int k;
  1675.  
  1676.     if(do_headerfooter)
  1677.        {
  1678.        if((init_top_margin > 0) && (page_number == init_page_number)
  1679.       && (page_flag | PAGE_T));    /* omit leading top pagenumber */
  1680.        else
  1681.           switch (page_flag)
  1682.          {
  1683.              case (PAGE_T | PAGE_C):
  1684.                 (void)fprintf(tf,"%ld %ld moveto",left_margin,
  1685.                       page_height-top_margin/2-baseline_skip/2);
  1686.                 (void)fprintf(tf," (%s) show",timestr);
  1687.                 NEWLINE(tf);
  1688.                 (void)fprintf(tf,"%ld %ld moveto",page_width/2,
  1689.                       page_height-top_margin/2-baseline_skip/2);
  1690.                 (void)fprintf(tf,
  1691.                       " (%s) stringwidth pop 2 div neg 0 rmoveto",
  1692.                       filename);
  1693.                 (void)fprintf(tf," (%s) show",filename);
  1694.                 NEWLINE(tf);
  1695.                 (void)fprintf(tf,"%ld %ld moveto",page_width-left_margin,
  1696.                       page_height-top_margin/2-baseline_skip/2);
  1697.                 (void)fprintf(tf," (%d) stringwidth pop neg 0 rmoveto",
  1698.                       page_number);
  1699.                 (void)fprintf(tf," (%d) show",page_number);
  1700.         NEWLINE(tf);
  1701.                 break;
  1702.  
  1703.          case (PAGE_B | PAGE_C):
  1704.         (void)fprintf(tf,"%ld %ld moveto",left_margin,
  1705.               bottom_margin/2-baseline_skip/2);
  1706.         (void)fprintf(tf," (%s) show",timestr);
  1707.                 NEWLINE(tf);
  1708.         (void)fprintf(tf,"%ld %ld moveto",page_width/2,
  1709.               bottom_margin/2-baseline_skip/2);
  1710.         (void)fprintf(tf,
  1711.               " (%s) stringwidth pop 2 div neg 0 rmoveto",
  1712.               filename);
  1713.         (void)fprintf(tf," (%s) show",filename);
  1714.                 NEWLINE(tf);
  1715.         (void)fprintf(tf,"%ld %ld moveto",page_width-left_margin,
  1716.               bottom_margin/2-baseline_skip/2);
  1717.         (void)fprintf(tf," (%d) stringwidth pop neg 0 rmoveto",
  1718.               page_number);
  1719.         (void)fprintf(tf," (%d) show",page_number);
  1720.         NEWLINE(tf);
  1721.                 break;
  1722.  
  1723.              default:
  1724.                 break;
  1725.              }
  1726.        }
  1727.     else if (do_page_number)
  1728.     {
  1729.     if ((init_top_margin > 0) && (page_number == init_page_number)
  1730.         && (page_flag | PAGE_T))
  1731.         ;            /* omit leading top pagenumber */
  1732.     else
  1733.         switch (page_flag)
  1734.         {
  1735.         case (PAGE_T | PAGE_L):
  1736.         (void)fprintf(tf,"%ld %ld moveto",left_margin,
  1737.             page_height-top_margin/2-baseline_skip/2);
  1738.         (void)fprintf(tf," (%d) show",page_number);
  1739.         NEWLINE(tf);
  1740.         break;
  1741.  
  1742.         case (PAGE_T | PAGE_C):
  1743.                 (void)fprintf(tf,"%ld %ld moveto",page_width/2,
  1744.               page_height-top_margin/2-baseline_skip/2);
  1745.                 (void)fprintf(tf,
  1746.               " (- %d -) stringwidth pop 2 div neg 0 rmoveto",
  1747.                       page_number);
  1748.                 (void)fprintf(tf," (- %d -) show",page_number);
  1749.         NEWLINE(tf);
  1750.         break;
  1751.  
  1752.         case (PAGE_T | PAGE_R):
  1753.         (void)fprintf(tf,"%ld %ld moveto",page_width-left_margin,
  1754.             page_height-top_margin/2-baseline_skip/2);
  1755.         (void)fprintf(tf," (%d) stringwidth pop neg 0 rmoveto",
  1756.             page_number);
  1757.         (void)fprintf(tf," (%d) show",page_number);
  1758.         NEWLINE(tf);
  1759.         break;
  1760.  
  1761.         case (PAGE_B | PAGE_L):
  1762.         (void)fprintf(tf,"%ld %ld moveto",left_margin,
  1763.             bottom_margin/2-baseline_skip/2);
  1764.         (void)fprintf(tf," (%d) show",page_number);
  1765.         NEWLINE(tf);
  1766.         break;
  1767.  
  1768.         case (PAGE_B | PAGE_C):
  1769.                 (void)fprintf(tf,"%ld %ld moveto",page_width/2,
  1770.               bottom_margin/2-baseline_skip/2);
  1771.         (void)fprintf(tf,
  1772.               " (- %d -) stringwidth pop 2 div neg 0 rmoveto",
  1773.               page_number);
  1774.         (void)fprintf(tf," (- %d -) show",page_number);
  1775.         NEWLINE(tf);
  1776.         break;
  1777.  
  1778.         case (PAGE_B | PAGE_R):
  1779.         (void)fprintf(tf,"%ld %ld moveto",page_width-left_margin,
  1780.             bottom_margin/2-baseline_skip/2);
  1781.         (void)fprintf(tf," (%d) stringwidth pop neg 0 rmoveto",
  1782.             page_number);
  1783.         (void)fprintf(tf," (%d) show",page_number);
  1784.         NEWLINE(tf);
  1785.         break;
  1786.  
  1787.         default:            /* else no numbering */
  1788.         break;
  1789.         }
  1790.     }
  1791.     page_number++;
  1792.  
  1793.     if (manual_feed > 0)
  1794.     {
  1795.     OUTSTR("statusdict begin");
  1796.     NEWLINE(tf);
  1797.     OUTSTR("statusdict /manualfeed true put");
  1798.     NEWLINE(tf);
  1799.     }
  1800.  
  1801.     if ((fprintf(tf,"/#copies %d def showpage",copies) == EOF) ||
  1802.     DISKFULL(tf))
  1803.     {
  1804.     NEWLINE(stderr);
  1805.     (void)fprintf(stderr,"?Output error -- disk storage probably full");
  1806.     NEWLINE(stderr);
  1807.     (void)perror("?perror() says");
  1808.     EXIT(1);
  1809.     }
  1810.     NEWLINE(tf);
  1811.  
  1812.     if (manual_feed > 0)
  1813.     {
  1814.     OUTSTR("end");
  1815.     NEWLINE(tf);
  1816.     }
  1817.     manual_feed--;
  1818.  
  1819.     OUTSTR("restore");
  1820.     NEWLINE(tf);
  1821.  
  1822.     for (k = 1; k <= copies; ++k)
  1823.     OUTCHAR('\f'); /* output FF's for print spooler page accounting */
  1824.  
  1825.     x = LEFT_X;
  1826.     y = TOP_Y(top_margin);
  1827. }
  1828.  
  1829. void
  1830. End_Line()
  1831. {
  1832.     if (scribe)
  1833.     {
  1834.     OUTCHAR(' ');
  1835.     OUTCHAR('E');
  1836.     }
  1837.     NEWLINE(tf);
  1838. }
  1839.  
  1840.  
  1841. void
  1842. End_Text(c)
  1843. char c;
  1844. {
  1845.     register int k;
  1846.  
  1847.     k = level;
  1848.     while (level > 0)
  1849.     {
  1850.     OUTCHAR(')');
  1851.     level--;
  1852.     }
  1853.     if (k > 0)
  1854.     {
  1855.     if (scribe)
  1856.         OUTCHAR('W');
  1857.     else
  1858.         OUTCHAR('P');
  1859.     }
  1860.     if (c)
  1861.     {
  1862.     OUTCHAR(' ');
  1863.     OUTCHAR(c);
  1864.     }
  1865. }
  1866.  
  1867. #include "inch.h"
  1868.  
  1869. int
  1870. inchar(fp)
  1871. FILE *fp;
  1872. {
  1873.     static int lastc = NUL;    /* memory of previous input character */
  1874.     register int c;
  1875.  
  1876.     /* output is incorrect if the file does not end with a LF; this
  1877.     routine supplies one at EOF if it is lacking */
  1878.  
  1879.     c = getc(fp);
  1880.     if ((c == EOF) && (lastc != '\n'))
  1881.     c = '\n';
  1882.     lastc = c;
  1883.     return (c);
  1884. }
  1885.  
  1886. void
  1887. Head_Foot_Switch(parg)            /* parg -> "Dxnnn" */
  1888. register char *parg;
  1889. {
  1890.     register char *porg;
  1891.  
  1892.     porg = parg;
  1893.     do_headerfooter = TRUE;
  1894.     do_page_number = FALSE;
  1895.     init_page_number = 1;
  1896.     page_flag = (PAGE_T | PAGE_C);    /* default location */
  1897.     while (*++parg)
  1898.     {
  1899.     switch(*parg)
  1900.     {
  1901.     case 't':
  1902.     case 'T':
  1903.         page_flag &= ~(PAGE_B | PAGE_T);
  1904.         page_flag |= PAGE_T;
  1905.         break;
  1906.  
  1907.     case 'b':
  1908.     case 'B':
  1909.         page_flag &= ~(PAGE_B | PAGE_T);
  1910.         page_flag |= PAGE_B;
  1911.         break;
  1912.  
  1913.     case '0':
  1914.     case '1':
  1915.     case '2':
  1916.     case '3':
  1917.     case '4':
  1918.     case '5':
  1919.     case '6':
  1920.     case '7':
  1921.     case '8':
  1922.     case '9':
  1923.         init_page_number = atoi(parg);
  1924.         while (isdigit(*parg))
  1925.         ++parg;
  1926.         if (*parg == NUL)
  1927.         break;
  1928.                 /* else fall through to error exit */
  1929.     default:                        /* else fall through to error exit */
  1930.         NEWLINE(stderr);
  1931.         (void)fprintf(stderr,
  1932.         "?Unrecognized header, footer option [%s]",porg);
  1933.         NEWLINE(stderr);
  1934.         EXIT(1);
  1935.     }
  1936.     if (*parg == NUL)
  1937.         break;
  1938.     }
  1939. }
  1940.  
  1941. void
  1942. Page_Switch(parg)            /* parg -> "Nxxxnnn" */
  1943. register char *parg;
  1944. {
  1945.     register char *porg;
  1946.  
  1947.     porg = parg;
  1948.     do_headerfooter = FALSE;
  1949.     do_page_number = TRUE;
  1950.     init_page_number = 1;
  1951.     page_flag = (PAGE_T | PAGE_C);    /* default location */
  1952.     while (*++parg)
  1953.     {
  1954.     switch(*parg)
  1955.     {
  1956.     case 't':
  1957.     case 'T':
  1958.         page_flag &= ~(PAGE_B | PAGE_T);
  1959.         page_flag |= PAGE_T;
  1960.         break;
  1961.  
  1962.     case 'b':
  1963.     case 'B':
  1964.         page_flag &= ~(PAGE_B | PAGE_T);
  1965.         page_flag |= PAGE_B;
  1966.         break;
  1967.  
  1968.     case 'l':
  1969.     case 'L':
  1970.         page_flag &= ~(PAGE_L | PAGE_C | PAGE_R);
  1971.         page_flag |= PAGE_L;
  1972.         break;
  1973.  
  1974.     case 'c':
  1975.     case 'C':
  1976.         page_flag &= ~(PAGE_L | PAGE_C | PAGE_R);
  1977.         page_flag |= PAGE_C;
  1978.         break;
  1979.  
  1980.     case 'r':
  1981.     case 'R':
  1982.         page_flag &= ~(PAGE_L | PAGE_C | PAGE_R);
  1983.         page_flag |= PAGE_R;
  1984.         break;
  1985.  
  1986.     case '0':
  1987.     case '1':
  1988.     case '2':
  1989.     case '3':
  1990.     case '4':
  1991.     case '5':
  1992.     case '6':
  1993.     case '7':
  1994.     case '8':
  1995.     case '9':
  1996.         init_page_number = atoi(parg);
  1997.         while (isdigit(*parg))
  1998.         ++parg;
  1999.         if (*parg == NUL)
  2000.         break;
  2001.                 /* else fall through to error exit */
  2002.     default:
  2003.         NEWLINE(stderr);
  2004.         (void)fprintf(stderr,
  2005.         "?Unrecognized page number field [%s]",porg);
  2006.         NEWLINE(stderr);
  2007.         EXIT(1);
  2008.     }
  2009.     if (*parg == NUL)
  2010.         break;
  2011.     }
  2012. }
  2013.  
  2014. #include "strcm2.h"
  2015.