home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume30 / psf3 / patch03a next >
Text File  |  1992-06-19  |  65KB  |  2,485 lines

  1. Newsgroups: comp.sources.misc
  2. From: tony@ajfcal.cuc.ab.ca (Tony Field)
  3. Subject:  v30i050:  psf3 - Postscript print filter system, Patch03a/4
  4. Message-ID: <csm-v30i050=psf3.151734@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: 9a19de9ac547b782895b878a9158ffe3
  6. Date: Sun, 14 Jun 1992 20:17:58 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: tony@ajfcal.cuc.ab.ca (Tony Field)
  10. Posting-number: Volume 30, Issue 50
  11. Archive-name: psf3/patch03a
  12. Environment: ISC, SUNOS, SYSVR3, DOS
  13. Patch-To: psf3: Volume 27, Issue 91-100
  14.  
  15.    PSF is a postscript print filter system designed to give reasonable
  16.    control over text output to a postscript printer. If desired, psf can
  17.    be installed as a filter for the lp/lpsched or lpr/lpd spooling systems.
  18.  
  19.    Printed output may be configured for:
  20.  
  21.         o  1-up, 2-up or 4-up on a page, landscape/portrait
  22.         o  fonts/point size
  23.         o  double sided printing
  24.         o  pages scaled by row and column count
  25.         o  lp banner page printing
  26.         o  reverse order printing
  27.         o  languages other than English
  28.         o  optional ISO Latin1 character encoding
  29.         o  left, right, top, bottom margin sizes
  30.         o  line clipping or left/right justified line wrap
  31.         o  page usage accounting
  32.         o  printing to a pipe for multiple filtering in a spooler
  33.            or for printing to an Apple network printer (via papif?)
  34.  
  35. This is the final set of enhancements to psf.
  36. As of this version, the following has been added:
  37.  
  38.      1. ISO-Latin1 encoding supported.
  39.      
  40.      2. Page usage accounting added (printcap "af" support)
  41.      
  42.      3. Psf can read page statistics from a serial/ethernet printer
  43.         (printcap "rw" support).
  44.      
  45.      4. If the printer supports duplex double sided printing,
  46.         the feature is invoked with -D
  47.      
  48.      5. Printing a ctl/D at eoj is not done unless psf is
  49.         printing to a printer device.
  50.      
  51.      6. the -u option to select alternate printer definition files
  52.         now works if psf is used as part of the spooler filter system.
  53.      
  54.      7. Some printer definitions in ./def have been fixed.
  55.  
  56.      8. psf can print to a pipe with the -O option.  Hopefully,
  57.         this allows printing to an apple network.  Usually, this
  58.         is installed as a print option in psfprint.def (for lpr/lpd).
  59. FTP
  60. ^^^
  61.    The current version of psf may be obtained by ftp from the
  62.    University of Calgary:
  63.    
  64.     host:      fsa.cpsc.ucalgary.ca, cpsc.ucalgary.ca or 136.159.2.1
  65.     login:     anonymous
  66.     password:  is your mail address, by convention
  67.     files:     pub/psf/psf3.5.tar.Z
  68.  
  69. These patches are applied to psf3, at patchlevel 3.  (NOTE: patchlevel 4
  70. was never posted to the net)
  71.  
  72. Apply these patch files with:
  73.  
  74.     patch -p -N < PatchXXX
  75.     
  76.  
  77.  --------------------- snip/snip --------------------------
  78.  
  79. *** net/psf.c    Sun Apr 19 13:33:26 1992
  80. --- psf.c    Tue Jun  2 02:18:45 1992
  81. ***************
  82. *** 5,53 ****
  83.   *    Print text files to postscript printer.                                    *
  84.   *                                                                            *
  85.   *    Tony Field: tony@ajfcal.cuc.ab.ca                                        *
  86.   ****************************************************************************/
  87.   /*
  88. !  * $Id: psf.c,v 3.3 1992/02/07 15:10:57 ajf Exp ajf $
  89.   */
  90.   /*    Three versions of psf can be compiled:
  91.   
  92.           psf:        postscript filter for command line use.
  93.               
  94.           psffilter:    used with lp/lpsched.  accepts command line argument.
  95.                       Input on stdin. compile with -DPSFFILTER.
  96.   
  97. !         psflpd:        used with lpr/lpd.  does not accept command line
  98. !                     arguments.  compile with -DPSFFILTER -DFORLPD
  99.    */
  100.   
  101.   #include <stdio.h>
  102.   #include <string.h>
  103.   #include <setjmp.h>
  104. ! #include <math.h>
  105. ! #include <time.h>
  106. ! #include <signal.h>
  107. ! #include "ctp.h"
  108. ! #include "patchlevel.h"
  109. ! #include "psf.h"
  110. ! #include "psfproto.h"
  111.   
  112. ! #if defined(MSDOS)  ||  defined (__MSDOS__)
  113. ! #ifndef BINDIR
  114. ! #define BINDIR "c:/bin"
  115.   #endif
  116. ! #ifndef PDEF
  117. ! #define PDEF "c:/lib/psfprint.def"
  118.   #endif
  119.   #endif
  120. - #ifndef PAPERTYPE
  121. - #define PAPERTYPE "letter"
  122.   #endif
  123. ! #ifndef PSFDOUB
  124. ! #define PSFDOUB "psfdoub"
  125.   #endif
  126.   
  127.   /*    set up the mechanism for underline display */
  128.   
  129.   #define SHOWU(fp,ps)    fprintf (fp, ") %d showuline\n", ps)
  130.   
  131. --- 5,56 ----
  132.   *    Print text files to postscript printer.                                    *
  133.   *                                                                            *
  134.   *    Tony Field: tony@ajfcal.cuc.ab.ca                                        *
  135.   ****************************************************************************/
  136.   /*
  137. !  * $Id: psf.c,v 3.5 1992/06/02 08:16:01 ajf Exp ajf $
  138.   */
  139.   /*    Three versions of psf can be compiled:
  140.   
  141.           psf:        postscript filter for command line use.
  142.               
  143.           psffilter:    used with lp/lpsched.  accepts command line argument.
  144.                       Input on stdin. compile with -DPSFFILTER.
  145.   
  146. !         psflpd:        like psffilter, but for lpr/lpd.
  147. !                     compile with -DPSFFILTER -DFORLPD
  148.    */
  149.   
  150.   #include <stdio.h>
  151. + #include <errno.h>
  152.   #include <string.h>
  153.   #include <setjmp.h>
  154. ! #include <sys/types.h>
  155.   
  156. ! #ifdef ISC22
  157. ! #define pid_t short
  158.   #endif
  159. ! #if !defined(MSDOS)  &&  !defined(__MSDOS__)
  160. ! #include <sys/wait.h>
  161. ! #ifndef WEXITSTATUS
  162. ! #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
  163. ! #undef WIFEXITED /* Avoid 4.3BSD incompatibility with Posix.  */
  164.   #endif
  165. + #ifndef WIFEXITED
  166. + #define WIFEXITED(stat_val) (!((stat_val) & 255))
  167.   #endif
  168.   #endif
  169. ! #include <math.h>
  170. ! #include <time.h>
  171. ! #if defined(MSDOS)  ||  defined(__MSDOS__)
  172. ! #include <process.h>
  173.   #endif
  174. + #include <signal.h>
  175. + #include "ctp.h"
  176. + #include "patchlevel.h"
  177. + #include "psf.h"
  178.   
  179.   /*    set up the mechanism for underline display */
  180.   
  181.   #define SHOWU(fp,ps)    fprintf (fp, ") %d showuline\n", ps)
  182.   
  183. ***************
  184. *** 57,76 ****
  185.   #define NORMAL        0x00        /* bitset for  print_attributes                */
  186.   #define ITALICS        0x01
  187.   #define BOLD        0x02
  188.   #define UNDERLINE    0x04        /* must be 0x04.  underline is not a font    */
  189.   
  190.   #define CTLD_EOJ    0x04        /* ctl/d is end of postscript job.            */
  191.   
  192.   /*    Paper physical dimensions.
  193.       The default paper sizes is for a NEC LC890 and is overridden in
  194.       "psfprint.def".
  195.   */
  196.   
  197.   typedef struct                     /*    measurement in point                    */
  198.   {    char    paper_name[60];        /*    name of paper size (for command line)    */
  199. !     char    paper_tray[100];    /*    postscript operator to select this tray    */
  200.       int        width;                /*    portrait point width of paper            */
  201.       int        height;                /*    portrait point height of paper            */
  202.       int        lx, ly, ux, uy;
  203.       int        left_marg;            /*    margin widths (unprintable area)        */
  204.       int        bot_marg;            /*            "                                */
  205. --- 60,84 ----
  206.   #define NORMAL        0x00        /* bitset for  print_attributes                */
  207.   #define ITALICS        0x01
  208.   #define BOLD        0x02
  209.   #define UNDERLINE    0x04        /* must be 0x04.  underline is not a font    */
  210.   
  211. + #define CTLC_CANCEL 0x03        /*    ctl/c is cancel current job                */
  212.   #define CTLD_EOJ    0x04        /* ctl/d is end of postscript job.            */
  213. + #define REQUEST_STATUS     '\024'    /* ^T */
  214. + char c_CTLC_CANCEL[] = { CTLD_EOJ, CTLC_CANCEL } ;
  215. + #define READ_ERROR    -2            /*    error cond when read from printer port    */
  216.   
  217.   /*    Paper physical dimensions.
  218.       The default paper sizes is for a NEC LC890 and is overridden in
  219.       "psfprint.def".
  220.   */
  221.   
  222.   typedef struct                     /*    measurement in point                    */
  223.   {    char    paper_name[60];        /*    name of paper size (for command line)    */
  224. !     char    paper_tray[200];    /*    postscript operator to select this tray    */
  225.       int        width;                /*    portrait point width of paper            */
  226.       int        height;                /*    portrait point height of paper            */
  227.       int        lx, ly, ux, uy;
  228.       int        left_marg;            /*    margin widths (unprintable area)        */
  229.       int        bot_marg;            /*            "                                */
  230. ***************
  231. *** 102,111 ****
  232. --- 110,120 ----
  233.                   "",
  234.                    0, 0,  0,  0, 0, 0, 0, 0, 0, 0 
  235.               }
  236.   };
  237.   
  238. + char    duplex_mode[200] = "\0";
  239.   char    order_default[20] = "Normal";
  240.   char    order_normal[100] = "\0";
  241.   char    order_reverse[100] = "\0";
  242.   char    *order_command = NULL;
  243.   
  244. ***************
  245. *** 122,138 ****
  246.   int        y_top_offset;            /*    offsets for each frame                    */
  247.   int        x_left_offset;
  248.   int        dx_home[4];                /*    page frame home (0,0) translations        */
  249.   int        dy_home[4];
  250.   
  251. - int        x,y;                    /* current x,y coordinate                    */
  252.   double    scale_x, scale_y;        /* scale factors for 2-up, 4-up printing    */
  253.   int        real_width;
  254.   
  255.   long    *pg_loc;                /* double side print byte ptr to %%Page:    */
  256.   int        npg_loc;                /* number of elements in pg_loc[]            */
  257.   
  258.   int        book             = 0;    /* book format: double sided                */
  259.   int        bookwork        = 0;    /* book format, 2-up print                    */
  260.   int        lines_on_page     = 60;    /* user print lines on page                    */
  261.   int        lines_total     = 0;    /* total number of lines for scale purposes    */
  262.   int        chars_on_line     = 80;    /* default number of chars on line            */
  263. --- 131,147 ----
  264.   int        y_top_offset;            /*    offsets for each frame                    */
  265.   int        x_left_offset;
  266.   int        dx_home[4];                /*    page frame home (0,0) translations        */
  267.   int        dy_home[4];
  268.   
  269.   double    scale_x, scale_y;        /* scale factors for 2-up, 4-up printing    */
  270.   int        real_width;
  271.   
  272.   long    *pg_loc;                /* double side print byte ptr to %%Page:    */
  273.   int        npg_loc;                /* number of elements in pg_loc[]            */
  274.   
  275. + int        duplex            = 0;    /* duplex mode                                */
  276.   int        book             = 0;    /* book format: double sided                */
  277.   int        bookwork        = 0;    /* book format, 2-up print                    */
  278.   int        lines_on_page     = 60;    /* user print lines on page                    */
  279.   int        lines_total     = 0;    /* total number of lines for scale purposes    */
  280.   int        chars_on_line     = 80;    /* default number of chars on line            */
  281. ***************
  282. *** 175,184 ****
  283. --- 184,194 ----
  284.   int        end_of_file        = 0;    /* end of printing file                        */
  285.   int        save_point_size ;        /* save original point size for headers        */
  286.   int        n_chars;                /*    number of characters on a line            */
  287.   int        reverse_order    = 0;    /*     print in reverse_order                    */
  288.   int        reverse_requested = 0;    /*    user option for reverse order            */
  289. + int        gen_eoj            = 0;    /*    psf: generate ctl/d on end of file        */
  290.   char    fname[100];
  291.   char    now[50];                /* time of day for page headers             */
  292.   
  293.   #ifdef HOPPER
  294.   int        hopper_available = 1;
  295. ***************
  296. *** 216,253 ****
  297.       "Helvetica-Condensed",        "Helvetica-Condensed-Oblique", "Helvetica-Condensed-Bold", "Helvetica-Condensed-BoldObl",
  298.       "ZapfChancery-MediumItalic","ZapfChancery-MediumItalic","ZapfChancery-MediumItalic","ZapfChancery-MediumItalic"
  299.   } ;
  300.   
  301.   int    fonts_used[NFONTS];
  302.   int    fonts_have[NFONTS];
  303.   unsigned char    xlate[256];            /*    translation vector     */
  304.   int        need_xlate = 0;                /*    no default xlate    */
  305.   char    copyfile[150];                /*    copy file name from psfprint.def */
  306.   
  307.   int    max_frame    = 1;        /* max number of frames in use */
  308.   int    frame        = -1;        /* current frame in use */
  309.   
  310.   FILE    *input_fp, *output_fp;
  311.   
  312.   /*    input line and input line pointer */
  313.   char    *c;
  314.   char    line[LONG_STR + 1];
  315.   char    shortline[150];
  316.   
  317.   char    *pgmname;
  318.   
  319. - void catch();
  320.   jmp_buf eof_env;
  321.   
  322.   char    *defref = NULL;
  323.   FILE    *pdef = NULL;        /*    psfprint.def file    */
  324.   
  325.   char *ascii_hex = "0123456789abcdefghijklmnopqrstuvwxyz";
  326. ! extern int atoi(), getpid();
  327.   
  328.   char *malloc();
  329.   
  330.   /****************************************************************************
  331.   *    main ()                                                                    *
  332.   ****************************************************************************/
  333.   
  334.   main (argc, argv)
  335. --- 226,292 ----
  336.       "Helvetica-Condensed",        "Helvetica-Condensed-Oblique", "Helvetica-Condensed-Bold", "Helvetica-Condensed-BoldObl",
  337.       "ZapfChancery-MediumItalic","ZapfChancery-MediumItalic","ZapfChancery-MediumItalic","ZapfChancery-MediumItalic"
  338.   } ;
  339.   
  340.   int    fonts_used[NFONTS];
  341. + int    fonts_iso[NFONTS];                /*    ioslatin1 encoded    */
  342. + #ifdef ISO
  343. + int    isolatin = 1;                    /*    enable ISOLatin1Encoding by default */
  344. + #else
  345. + int    isolatin = 0;                    /*    disable ISOLatin1Encoding by default */
  346. + #endif
  347.   int    fonts_have[NFONTS];
  348.   unsigned char    xlate[256];            /*    translation vector     */
  349.   int        need_xlate = 0;                /*    no default xlate    */
  350.   char    copyfile[150];                /*    copy file name from psfprint.def */
  351.   
  352.   int    max_frame    = 1;        /* max number of frames in use */
  353.   int    frame        = -1;        /* current frame in use */
  354.   
  355.   FILE    *input_fp, *output_fp;
  356. + char    *pipe_name;
  357.   
  358.   /*    input line and input line pointer */
  359.   char    *c;
  360.   char    line[LONG_STR + 1];
  361.   char    shortline[150];
  362.   
  363.   char    *pgmname;
  364.   
  365.   jmp_buf eof_env;
  366.   
  367.   char    *defref = NULL;
  368.   FILE    *pdef = NULL;        /*    psfprint.def file    */
  369.   
  370.   char *ascii_hex = "0123456789abcdefghijklmnopqrstuvwxyz";
  371. ! #if !defined(MSDOS)  &&  !defined(__MSDOS__)
  372. ! extern int getpid();
  373. ! #endif
  374. ! extern int atoi();
  375.   
  376.   char *malloc();
  377.   
  378. + char *account_file_name = NULL;        /*    accounting file name                */
  379. + char *host = NULL;                    /*    accounting host                        */
  380. + char *user = NULL;                    /*    accounting user                        */
  381. + int    printfd = 1;                    /*    read from stdout                    */
  382. + int    pid;                            /*    pid for accounting                    */
  383. + int    read_access = 0;                /*    spooler can read from printer, too     */
  384. + long pages_written = 0;                /*    page count if no access to printer    */
  385. + #ifdef __STDC__
  386. + measure *locate_pagetype(char *desired, int printerr);
  387. + #else
  388. + measure *locate_pagetype();
  389. + #endif
  390. + #include "psfproto.h"
  391.   /****************************************************************************
  392.   *    main ()                                                                    *
  393.   ****************************************************************************/
  394.   
  395.   main (argc, argv)
  396. ***************
  397. *** 255,283 ****
  398.   char    *argv[];
  399.   {    int        c, i, j, number;
  400.       extern char *optarg;
  401.       extern int    optind, getopt();
  402.       char    bookfile[100];
  403. -     char    *env_fname;            /*    environment specified output file */
  404.       char    *getenv();
  405.       int        narrow2x;
  406. !     char    alt_cmd[200];
  407.       char    *new_marg;
  408.       int        want_stats = 0;
  409.   
  410.       if ((pgmname = strrchr (argv[0], '/'))
  411.               || (pgmname = strrchr (argv[0], '\\'))
  412.               || (pgmname = strrchr (argv[0], ':')))
  413.           pgmname++;
  414.       else
  415.           pgmname = argv[0];
  416.   
  417.       copyfile[0] = 0;
  418.       for (i = 0; i < 256;  i++)            /*    initial xlate = no translation */
  419.           xlate[i] = i;
  420.       for (i = font_count;  i < NFONTS;  i++)
  421.           fonts[i] = "N/A";
  422.   
  423.       defref = NULL;
  424.       for (i = 0;  i < argc;  i++)        /*    if user sets -u alt.def */
  425.       {    if (strncmp (argv[i], "-u", 2) == 0)
  426.           {    if (strlen (argv[i]) > 2)
  427. --- 294,329 ----
  428.   char    *argv[];
  429.   {    int        c, i, j, number;
  430.       extern char *optarg;
  431.       extern int    optind, getopt();
  432.       char    bookfile[100];
  433.       char    *getenv();
  434.       int        narrow2x;
  435. !     char    *alt_cmd;
  436.       char    *new_marg;
  437.       int        want_stats = 0;
  438. +     char    alt_def_file[200];
  439. +     double    atof();
  440. +     int        modified_argv = 0;
  441. +     pid = getpid();
  442.   
  443.       if ((pgmname = strrchr (argv[0], '/'))
  444.               || (pgmname = strrchr (argv[0], '\\'))
  445.               || (pgmname = strrchr (argv[0], ':')))
  446.           pgmname++;
  447.       else
  448.           pgmname = argv[0];
  449.   
  450.       copyfile[0] = 0;
  451. +     pipe_name = NULL;
  452.       for (i = 0; i < 256;  i++)            /*    initial xlate = no translation */
  453.           xlate[i] = i;
  454.       for (i = font_count;  i < NFONTS;  i++)
  455.           fonts[i] = "N/A";
  456. +     for (i = 0;  i < NFONTS;  i++)
  457. +         fonts_iso[i] = 0;
  458.   
  459.       defref = NULL;
  460.       for (i = 0;  i < argc;  i++)        /*    if user sets -u alt.def */
  461.       {    if (strncmp (argv[i], "-u", 2) == 0)
  462.           {    if (strlen (argv[i]) > 2)
  463. ***************
  464. *** 292,302 ****
  465.               defref = PDEF;
  466.       }
  467.   
  468.       /*    Read the .def file if it exists    */
  469.   
  470. !     alt_cmd[0] = '\0';
  471.       if (access (defref, 0)  &&  defref != PDEF
  472.                               &&  strchr (defref, '/') == NULL  
  473.                               &&  strchr (defref, '\\') == NULL)
  474.       {    /* see if file is in same directory as PDEF */
  475.           char *c, *strrchr();
  476. --- 338,349 ----
  477.               defref = PDEF;
  478.       }
  479.   
  480.       /*    Read the .def file if it exists    */
  481.   
  482. ! redo_def:
  483. !     alt_cmd = malloc (200);
  484.       if (access (defref, 0)  &&  defref != PDEF
  485.                               &&  strchr (defref, '/') == NULL  
  486.                               &&  strchr (defref, '\\') == NULL)
  487.       {    /* see if file is in same directory as PDEF */
  488.           char *c, *strrchr();
  489. ***************
  490. *** 316,354 ****
  491.           
  492.       if ((pdef = fopen (defref, "r")) != NULL)
  493.       {    char    line_type[50];
  494.   #if defined(FORLPD)
  495.           char    *quote, *word;
  496. !         int        modified_argv = 0;
  497.   
  498.           /*    read lpd options from psfprint.def.  Format is:
  499.                   *psflpd argv0name opt1 opt2 opt3...
  500.           */            
  501.           while (fgets (alt_cmd, 200, pdef))
  502.           {    if (*alt_cmd == '#')
  503.                   continue;
  504.               alt_cmd[199] = '\0';
  505.               trim (alt_cmd);
  506. !             word = strtok (alt_cmd, " \t");
  507.               if (strcmp (word, "*psflpd") == 0)
  508. !             {    word = strtok (NULL, " \t");
  509.                   if (strcmp (word, pgmname) == 0)
  510. !                 {    argv = (char **) malloc (sizeof (char *) * 50);
  511.                       argv[0] = word;
  512.                       modified_argv = 1;
  513. !                     for (argc = 1;  word = strtok (NULL, " \t");  argc++)
  514.                       {    if (*word == '#')    /* quite on comments */
  515.                               break;
  516. !                         argv[argc] = word;
  517.                       }
  518.                       argv[argc] = NULL;
  519.                       break;
  520.                   }
  521.               }
  522.               else if (strcmp (word, "*printer") == 0)
  523.                   break;
  524.           }
  525.           if (modified_argv == 0)
  526.           {    argc = 1;
  527.               argv[1] = NULL;
  528.           }
  529.   
  530. --- 363,452 ----
  531.           
  532.       if ((pdef = fopen (defref, "r")) != NULL)
  533.       {    char    line_type[50];
  534.   #if defined(FORLPD)
  535.           char    *quote, *word;
  536. !         int        want_new_def = 0;
  537. !         /*    get original host, user, and accounting file */
  538. !         
  539. !         if (modified_argv == 0)
  540. !         {
  541. !             while ((c = getopt(argc, argv, "cw:l:i:n:h:")) != -1)
  542. !             {    switch (c)
  543. !                 {
  544. !                 case 'n':    user = optarg;        break;
  545. !                 case 'h':    host = optarg;        break;
  546. !                 case 'c':
  547. !                 case 'w':
  548. !                 case 'l':
  549. !                 case 'i':    continue;
  550. !                 default: ;
  551. !                 }
  552. !             }
  553. !             if (optind == argc - 1)
  554. !                 account_file_name = argv[optind];
  555. !             else
  556. !                 account_file_name = NULL;
  557. !         }
  558.   
  559.           /*    read lpd options from psfprint.def.  Format is:
  560.                   *psflpd argv0name opt1 opt2 opt3...
  561. +             If -u is in the options, read the new def file.
  562.           */            
  563. +         optind = 1;         /* reset getopt for possibly new arg list */
  564.           while (fgets (alt_cmd, 200, pdef))
  565.           {    if (*alt_cmd == '#')
  566.                   continue;
  567.               alt_cmd[199] = '\0';
  568.               trim (alt_cmd);
  569. !             word = nexttok (alt_cmd, " \t'\"");
  570.               if (strcmp (word, "*psflpd") == 0)
  571. !             {    word = nexttok (NULL, " \t'\"");
  572.                   if (strcmp (word, pgmname) == 0)
  573. !                 {    /*    create a new argument vector */
  574. !                     argv = (char **) malloc (sizeof (char *) * 50);
  575.                       argv[0] = word;
  576.                       modified_argv = 1;
  577. !                     argc = 1;
  578. !                     while (word = nexttok (NULL, " \t'\""))
  579.                       {    if (*word == '#')    /* quite on comments */
  580.                               break;
  581. !                         if (strncmp (word, "-u", 2) == 0)
  582. !                         {    /*    get another .def file - but keep all
  583. !                                 provided arguments.
  584. !                             */
  585. !                             if (strlen (word) == 2)
  586. !                             {    word = nexttok (NULL, " \t'\"");
  587. !                                 if (word)
  588. !                                     strcpy (alt_def_file, word);
  589. !                                 else
  590. !                                 {    fprintf (stderr, "%s: invalid -u option\n", pgmname);
  591. !                                     exit (DISCARD_JOB);
  592. !                                 }
  593. !                             }
  594. !                             else
  595. !                                 strcpy (alt_def_file, word + 2);
  596. !                             defref = alt_def_file;
  597. !                             want_new_def = 1;
  598. !                         }
  599. !                         else
  600. !                             argv[argc++] = word;
  601.                       }
  602.                       argv[argc] = NULL;
  603.                       break;
  604.                   }
  605.               }
  606.               else if (strcmp (word, "*printer") == 0)
  607.                   break;
  608.           }
  609. +         if (want_new_def)
  610. +         {    pdef = NULL;
  611. +             fclose (pdef);
  612. +             goto redo_def;
  613. +         }
  614.           if (modified_argv == 0)
  615.           {    argc = 1;
  616.               argv[1] = NULL;
  617.           }
  618.   
  619. ***************
  620. *** 445,454 ****
  621. --- 543,558 ----
  622.                       strcpy (slots[i], line);
  623.                       j = i;
  624.                   }
  625.                   nslots = j + 1;
  626.               }
  627. +             else if (strcmp (line_type, "*duplex") == 0)
  628. +             {    for (i = 0;  i < number;  i++)
  629. +                 {    if (fgets (duplex_mode, 200, pdef) == NULL)
  630. +                         bad_file();
  631. +                 }
  632. +             }
  633.   
  634.               else if (strcmp (line_type, "*eof") == 0)
  635.                   break;
  636.               else
  637.                   bad_file();
  638. ***************
  639. *** 459,475 ****
  640.       {    for (i = 0;  i < font_count;  i++)
  641.               fonts_have[i] = 1;
  642.       }
  643.   
  644.   #ifdef PAPERTYPE
  645. !     for (i = 0;  page_types[i].paper_name[0];  i++)
  646. !     {    if (strcmp (page_types[i].paper_name, PAPERTYPE) == 0)
  647. !         {    p = &page_types[i];
  648. !             break;
  649. !         }
  650. !     }
  651. !     if (page_types[i].paper_name[0] == '\0')
  652.           p = &page_types[0];
  653.   #else
  654.       p = &page_types[0];            /* default to letter size paper    */
  655.   #endif    /* PAPERTYPE */
  656.   
  657. --- 563,574 ----
  658.       {    for (i = 0;  i < font_count;  i++)
  659.               fonts_have[i] = 1;
  660.       }
  661.   
  662.   #ifdef PAPERTYPE
  663. !     p = locate_pagetype (PAPERTYPE, 1);
  664. !     if (p == NULL)
  665.           p = &page_types[0];
  666.   #else
  667.       p = &page_types[0];            /* default to letter size paper    */
  668.   #endif    /* PAPERTYPE */
  669.   
  670. ***************
  671. *** 477,487 ****
  672.       if (argc > 1  &&  (strcmp (argv[1], "-") == 0  || strcmp (argv[1], "--") == 0))
  673.           usage();
  674.   
  675.       narrow2x = 0;
  676.       new_marg = NULL;
  677. !     while ((c = getopt(argc, argv, "124Eexhnwdvzsi:m:b:c:g:H:l:L:M:f:t:P:p:r:R:u:-?")) != -1)
  678.       {    switch (c)
  679.           {
  680.           case '1':
  681.               max_frame = 1;
  682.               break;
  683. --- 576,586 ----
  684.       if (argc > 1  &&  (strcmp (argv[1], "-") == 0  || strcmp (argv[1], "--") == 0))
  685.           usage();
  686.   
  687.       narrow2x = 0;
  688.       new_marg = NULL;
  689. !     while ((c = getopt(argc, argv, "124aEejxhInwDdvzsA:i:m:b:c:g:H:l:L:M:f:t:O:P:p:r:R:u:Y:y:-?")) != -1)
  690.       {    switch (c)
  691.           {
  692.           case '1':
  693.               max_frame = 1;
  694.               break;
  695. ***************
  696. *** 493,518 ****
  697.               break;
  698.           
  699.           case '4':
  700.               max_frame = 4;
  701.               break;
  702.               
  703.           case 'b':
  704.               if ((set_paper_bin = atoi (optarg)) > nslots)
  705.               {    if (nslots == 0)
  706. !                     fprintf (stderr, "%s: no alternate bins permitted\n", nslots);
  707.                   else
  708.                       fprintf (stderr, "%s: paper bin greater than %d\n", pgmname, nslots);
  709. !                 exit (1);
  710.               }
  711.               break;
  712.   
  713.           case 'c':
  714.               chars_on_line = atoi (optarg);
  715.               set_char_count = 1;
  716.               break;
  717.   
  718.           case 'd':
  719.               book = 1;
  720.               break;
  721.                       
  722.           case 'e':
  723. --- 592,633 ----
  724.               break;
  725.           
  726.           case '4':
  727.               max_frame = 4;
  728.               break;
  729. +         case 'a':
  730. +             read_access = 1;
  731. +             break;
  732.               
  733. +         case 'A':
  734. +             account_file_name = optarg;        /*    for lpsched's benifit */
  735. +             break;
  736.           case 'b':
  737.               if ((set_paper_bin = atoi (optarg)) > nslots)
  738.               {    if (nslots == 0)
  739. !                     fprintf (stderr, "%s: no alternate bins permitted\n", pgmname);
  740.                   else
  741.                       fprintf (stderr, "%s: paper bin greater than %d\n", pgmname, nslots);
  742. !                 exit (DISCARD_JOB);
  743.               }
  744.               break;
  745.   
  746.           case 'c':
  747.               chars_on_line = atoi (optarg);
  748.               set_char_count = 1;
  749.               break;
  750.   
  751. +         case 'D':
  752. +             duplex = 1;
  753. +             if (duplex_mode[0] == 0)
  754. +             {    fprintf (stderr, "%s: duplex mode not available\n", pgmname);
  755. +                 exit (DISCARD_JOB);
  756. +             }
  757. +             break;
  758. +     
  759.           case 'd':
  760.               book = 1;
  761.               break;
  762.                       
  763.           case 'e':
  764. ***************
  765. *** 543,561 ****
  766.                       font_number = 0;
  767.               }
  768.               break;
  769.   
  770.           case 'g':
  771. !             p = NULL;
  772. !             for (i = 0;  page_types[i].paper_name[0];  i++)
  773. !             {    if (compare (optarg, page_types[i].paper_name) == 0)
  774. !                 {    p = &page_types[i];
  775. !                     break;
  776. !                 }
  777. !             }
  778.               if (p == NULL)
  779. !                 usage ();
  780.               set_paper_tray = 1;
  781.               break;
  782.   
  783.           case 'h':
  784.               header = 1;
  785. --- 658,670 ----
  786.                       font_number = 0;
  787.               }
  788.               break;
  789.   
  790.           case 'g':
  791. !             p = locate_pagetype (optarg, 1);
  792.               if (p == NULL)
  793. !                 exit (DISCARD_JOB);
  794.               set_paper_tray = 1;
  795.               break;
  796.   
  797.           case 'h':
  798.               header = 1;
  799. ***************
  800. *** 564,589 ****
  801.           case 'H':
  802.               header = 2;
  803.               strcpy (header_text, optarg);
  804.               break;
  805.   
  806.           case 'i':
  807. !             x_user_offset = atoi (optarg) * cvt_unit (optarg) + 0.01;
  808.               break;
  809.   
  810.           case 'l':
  811.               lines_on_page = atoi (optarg);
  812.               set_line_count = 1;
  813.               break;
  814.   
  815.           case 'L':
  816.               lines_total = atoi (optarg);
  817.               set_total_count = 1;
  818.               break;
  819.   
  820.           case 'm':
  821. !             y_user_offset = atoi (optarg) * cvt_unit(optarg) + 0.01;
  822.               break;
  823.           
  824.           case 'M':
  825.               new_marg = optarg;
  826.               break;
  827. --- 673,710 ----
  828.           case 'H':
  829.               header = 2;
  830.               strcpy (header_text, optarg);
  831.               break;
  832.   
  833. +         case 'I':
  834. + #ifdef ISO
  835. +             isolatin = 0;
  836. + #else
  837. +             isolatin = 1;
  838. + #endif
  839. +             break;
  840. +     
  841.           case 'i':
  842. !             x_user_offset = atof (optarg) * cvt_unit (optarg) + 0.01;
  843.               break;
  844.   
  845.           case 'l':
  846.               lines_on_page = atoi (optarg);
  847.               set_line_count = 1;
  848.               break;
  849.   
  850. +         case 'j':
  851. +             gen_eoj = 1;
  852. +             break;
  853. +     
  854.           case 'L':
  855.               lines_total = atoi (optarg);
  856.               set_total_count = 1;
  857.               break;
  858.   
  859.           case 'm':
  860. !             y_user_offset = atof (optarg) * cvt_unit(optarg) + 0.01;
  861.               break;
  862.           
  863.           case 'M':
  864.               new_marg = optarg;
  865.               break;
  866. ***************
  867. *** 591,600 ****
  868. --- 712,725 ----
  869.           case 'n':
  870.               landscape = 0;
  871.               narrow2x = 1;
  872.               break;
  873.   
  874. +         case 'O':
  875. +             pipe_name = optarg;
  876. +             break;
  877.           case 'p':
  878.               point_size = atoi (optarg);
  879.               set_point_size = 1;
  880.               break;
  881.   
  882. ***************
  883. *** 633,650 ****
  884. --- 758,785 ----
  885.               
  886.           case 'x':
  887.               cross = 1;
  888.               break;
  889.   
  890. +         case 'y':
  891. +             user = optarg;
  892. +             break;
  893. +     
  894. +         case 'Y':
  895. +             host = optarg;
  896. +             break;
  897.           case 'z':
  898.               print_postscript = 1;
  899.               break;
  900.   
  901.           default:    usage ();
  902.               break;
  903.           }
  904.       }
  905. +     if (duplex  ||  pipe_name)        /*    cannot support book mode */
  906. +         book = 0;
  907.   
  908.       if (strncmp (order_default, "Reverse", 7) == 0)        /*    stacking sequence         */
  909.           reverse_order = 1;                                /*    "Reverse"                */
  910.       else
  911.           reverse_order = 0;                                /*    "Normal"                */
  912. ***************
  913. *** 662,680 ****
  914.       nominal_high = p->uy - p->ly + 1;                    /* for default row/col scaling */
  915.       nominal_wide = p->ux - p->lx + 1;        
  916.   
  917.       if (reverse_requested && book)
  918.       {    fprintf (stderr, "Double sided or book in reverse ordered not supported\n");
  919. !         exit (1);
  920.       }
  921.       /*    if -M specified, set the imageable area coordinates to reflect
  922.           the deisred margin size.
  923.       */
  924.       if (new_marg)
  925.       {    char *mc, *v[6];
  926.           int    iv;
  927. !         double    fact, atof();
  928.   
  929.           mc = new_marg;
  930.           iv = 1;
  931.           v[0] = mc;
  932.           while (*mc  &&  iv < 6)
  933. --- 797,815 ----
  934.       nominal_high = p->uy - p->ly + 1;                    /* for default row/col scaling */
  935.       nominal_wide = p->ux - p->lx + 1;        
  936.   
  937.       if (reverse_requested && book)
  938.       {    fprintf (stderr, "Double sided or book in reverse ordered not supported\n");
  939. !         exit (DISCARD_JOB);
  940.       }
  941.       /*    if -M specified, set the imageable area coordinates to reflect
  942.           the deisred margin size.
  943.       */
  944.       if (new_marg)
  945.       {    char *mc, *v[6];
  946.           int    iv;
  947. !         double    fact;
  948.   
  949.           mc = new_marg;
  950.           iv = 1;
  951.           v[0] = mc;
  952.           while (*mc  &&  iv < 6)
  953. ***************
  954. *** 684,694 ****
  955.               }
  956.               mc++;
  957.           }
  958.           if (iv < 4)
  959.           {    fprintf (stderr, "Must have 4 margin sizes specified\n");
  960. !             exit (1);
  961.           }
  962.           if (iv > 4)
  963.               fact = cvt_unit (v[4]);
  964.           else
  965.               fact = cvt_unit (v[3]);
  966. --- 819,829 ----
  967.               }
  968.               mc++;
  969.           }
  970.           if (iv < 4)
  971.           {    fprintf (stderr, "Must have 4 margin sizes specified\n");
  972. !             exit (DISCARD_JOB);
  973.           }
  974.           if (iv > 4)
  975.               fact = cvt_unit (v[4]);
  976.           else
  977.               fact = cvt_unit (v[3]);
  978. ***************
  979. *** 713,723 ****
  980.               if ((iv = atof (v[3]) * fact) > 0)
  981.                   p->ly = max (p->ly, (iv + 1));
  982.           }
  983.           if (p->ux - p->lx < 200  ||  p->uy - p->ly < 200)
  984.           {    fprintf (stderr, "Margin size is inappropriate\n");
  985. !                 exit (1);
  986.           }
  987.       }
  988.       for (i = 0;  page_types[i].paper_name[0];  i++)
  989.       {    page_types[i].left_marg  = page_types[i].lx;
  990.           page_types[i].bot_marg   = page_types[i].ly;
  991. --- 848,858 ----
  992.               if ((iv = atof (v[3]) * fact) > 0)
  993.                   p->ly = max (p->ly, (iv + 1));
  994.           }
  995.           if (p->ux - p->lx < 200  ||  p->uy - p->ly < 200)
  996.           {    fprintf (stderr, "Margin size is inappropriate\n");
  997. !                 exit (DISCARD_JOB);
  998.           }
  999.       }
  1000.       for (i = 0;  page_types[i].paper_name[0];  i++)
  1001.       {    page_types[i].left_marg  = page_types[i].lx;
  1002.           page_types[i].bot_marg   = page_types[i].ly;
  1003. ***************
  1004. *** 727,737 ****
  1005.           page_types[i].x_size = page_types[i].ux - page_types[i].lx + 1;
  1006.           page_types[i].y_size = page_types[i].uy - page_types[i].ly + 1;
  1007.       }
  1008.       if (want_stats)
  1009.       {    size_display();
  1010. !         exit (1);
  1011.       }
  1012.       if (nslots <= 1)
  1013.           hopper_available = 0;
  1014.       if (reverse_order  ||  (book  &&  hopper_available))
  1015.           sprintf (bookfile, "%s%d.bok", TEMPFILE, getpid());
  1016. --- 862,872 ----
  1017.           page_types[i].x_size = page_types[i].ux - page_types[i].lx + 1;
  1018.           page_types[i].y_size = page_types[i].uy - page_types[i].ly + 1;
  1019.       }
  1020.       if (want_stats)
  1021.       {    size_display();
  1022. !         exit (DISCARD_JOB);
  1023.       }
  1024.       if (nslots <= 1)
  1025.           hopper_available = 0;
  1026.       if (reverse_order  ||  (book  &&  hopper_available))
  1027.           sprintf (bookfile, "%s%d.bok", TEMPFILE, getpid());
  1028. ***************
  1029. *** 740,787 ****
  1030.   
  1031.       if (optind >=  argc  &&  header == 1)    /* no file name header on stdin */
  1032.           header = 0;
  1033.       save_point_size = point_size;
  1034.       
  1035. !     (void)    signal (SIGINT, catch);        /*    for lpd quit */
  1036.   
  1037.   #ifdef PSFFILTER
  1038.   
  1039. !     output_fp = stdout;
  1040.       input_fp  = stdin;
  1041.       if (header == 1)
  1042.           strcpy (fname, argv[optind]);
  1043.       else
  1044.           *fname = 0;    
  1045.   
  1046.       if (fgets (line, LONG_STR, input_fp) == NULL)
  1047. !         exit (0);
  1048. !     if (tscan (line, "%!") >= 0  &&  print_postscript == 0)
  1049.       {    /*    already postscript  copy to output */
  1050.           if (fputs (line, output_fp) == EOF)
  1051. !             output_trouble (2);
  1052.           while ((i = fgetc (input_fp)) != EOF)
  1053.           {    if (fputc (i, output_fp) == EOF)
  1054. !                 output_trouble (2);
  1055.           }
  1056.       }
  1057.       else
  1058.       {    /*    standard postscript conversion for file on stdin */
  1059. ! bannerdone:
  1060.           if (font_number * 4 > font_count)
  1061.           {    fprintf (stderr,"Font number invalid....\n");
  1062.               usage ();
  1063.           }
  1064.   
  1065.           if (book  ||  reverse_order)
  1066.           {    if ((output_fp = fopen (bookfile, "w")) == NULL)
  1067.               {    fprintf (stderr, "%s: cannot create work file\n", pgmname);
  1068. !                 exit (1);
  1069.               }
  1070.               if ((pg_loc = (long *) malloc (sizeof (long) * MAX_PAGES)) == NULL)
  1071.               {    fprintf (stderr, "%s: cannot allocate enough memory\n", pgmname);
  1072. !                 exit (1);
  1073.               }
  1074.               npg_loc = 0;
  1075.           }
  1076.   
  1077.           for (i = 0;  i < NFONTS;  i++)
  1078. --- 875,948 ----
  1079.   
  1080.       if (optind >=  argc  &&  header == 1)    /* no file name header on stdin */
  1081.           header = 0;
  1082.       save_point_size = point_size;
  1083.       
  1084. !     (void)    signal (SIGINT, catch);            /*    for lpd quit */
  1085.   
  1086.   #ifdef PSFFILTER
  1087.   
  1088. !     if (pipe_name)
  1089. !     {    if ((output_fp = popen (pipe_name, "w")) == NULL)
  1090. !         {    fprintf (stderr, "%s: cannot open pipe to %s\n", pgmname, pipe_name);
  1091. !             exit (DISCARD_JOB);
  1092. !         }
  1093. !         read_access = 0;                    /*    can't read from pipe */
  1094. !     }
  1095. !     else
  1096. !         output_fp = stdout;
  1097.       input_fp  = stdin;
  1098.       if (header == 1)
  1099.           strcpy (fname, argv[optind]);
  1100.       else
  1101.           *fname = 0;    
  1102.   
  1103.       if (fgets (line, LONG_STR, input_fp) == NULL)
  1104. !         exit (JOB_IS_DONE);
  1105. !     if ((strncmp (line, "%!", 2) == 0  ||  strncmp (line, "%%!", 3) == 0)
  1106. !             &&  print_postscript == 0)
  1107.       {    /*    already postscript  copy to output */
  1108. +         char    last_char;
  1109. +         if (read_access)
  1110. +             create_fork ();
  1111. +         /*    attempt to force tray and bin selection */
  1112. +         set_bin (set_paper_bin);
  1113. +         set_tray (set_paper_tray);
  1114. +         
  1115.           if (fputs (line, output_fp) == EOF)
  1116. !             output_trouble (DISCARD_JOB);
  1117.           while ((i = fgetc (input_fp)) != EOF)
  1118.           {    if (fputc (i, output_fp) == EOF)
  1119. !                 output_trouble (DISCARD_JOB);
  1120. !             last_char = i;
  1121.           }
  1122. +         if (last_char != CTLD_EOJ)
  1123. +             fputc (CTLD_EOJ, output_fp);
  1124. +         pages_written = -1; /* i.e. we don't know */
  1125.       }
  1126.       else
  1127.       {    /*    standard postscript conversion for file on stdin */
  1128.           if (font_number * 4 > font_count)
  1129.           {    fprintf (stderr,"Font number invalid....\n");
  1130.               usage ();
  1131.           }
  1132.   
  1133. +         if (read_access)
  1134. +             create_fork ();
  1135.           if (book  ||  reverse_order)
  1136.           {    if ((output_fp = fopen (bookfile, "w")) == NULL)
  1137.               {    fprintf (stderr, "%s: cannot create work file\n", pgmname);
  1138. !                 exit (DISCARD_JOB);
  1139.               }
  1140.               if ((pg_loc = (long *) malloc (sizeof (long) * MAX_PAGES)) == NULL)
  1141.               {    fprintf (stderr, "%s: cannot allocate enough memory\n", pgmname);
  1142. !                 exit (DISCARD_JOB);
  1143.               }
  1144.               npg_loc = 0;
  1145.           }
  1146.   
  1147.           for (i = 0;  i < NFONTS;  i++)
  1148. ***************
  1149. *** 799,808 ****
  1150. --- 960,971 ----
  1151.           start_file ();
  1152.           process_file ();
  1153.           terminate_printer ();
  1154.           output_book (bookfile);
  1155.       }
  1156. +     if (read_access == 0)
  1157. +         write_accounting (pages_written, 0);
  1158.   
  1159.   #else    /* not PSFFILTER */
  1160.   
  1161.       /*    begin normal "psf" code */
  1162.   
  1163. ***************
  1164. *** 812,838 ****
  1165.       }
  1166.   
  1167.       if (book  ||  reverse_order)
  1168.       {    if ((output_fp = fopen (bookfile, "w")) == NULL)
  1169.           {    fprintf (stderr, "%s: cannot create work file\n", pgmname);
  1170. !             exit (1);
  1171.           }
  1172.           if ((pg_loc = (long *) malloc (sizeof (long) * MAX_PAGES)) == NULL)
  1173.           {    fprintf (stderr, "%s: cannot allocate enough memory\n", pgmname);
  1174. !             exit (1);
  1175.           }
  1176.           npg_loc = 0;
  1177.       }
  1178.       else    
  1179. !     {    if (env_fname = getenv ("PSFLP"))
  1180.   #if defined(MSDOS)  ||  defined (__MSDOS__)
  1181.           {    if ((output_fp = fopen (env_fname, "wt")) == NULL)
  1182.   #else
  1183.           {    if ((output_fp = fopen (env_fname, "w")) == NULL)
  1184.   #endif
  1185.               {    fprintf (stderr, "Cannot open output file %s\n", env_fname);
  1186. !                 exit (1);
  1187.               }
  1188.           }
  1189.           else
  1190.           {    output_fp = stdout;
  1191.           }
  1192. --- 975,1002 ----
  1193.       }
  1194.   
  1195.       if (book  ||  reverse_order)
  1196.       {    if ((output_fp = fopen (bookfile, "w")) == NULL)
  1197.           {    fprintf (stderr, "%s: cannot create work file\n", pgmname);
  1198. !             exit (DISCARD_JOB);
  1199.           }
  1200.           if ((pg_loc = (long *) malloc (sizeof (long) * MAX_PAGES)) == NULL)
  1201.           {    fprintf (stderr, "%s: cannot allocate enough memory\n", pgmname);
  1202. !             exit (DISCARD_JOB);
  1203.           }
  1204.           npg_loc = 0;
  1205.       }
  1206.       else    
  1207. !     {    char    *env_fname;            /*    environment specified output file */
  1208. !         if (env_fname = getenv ("PSFLP"))
  1209.   #if defined(MSDOS)  ||  defined (__MSDOS__)
  1210.           {    if ((output_fp = fopen (env_fname, "wt")) == NULL)
  1211.   #else
  1212.           {    if ((output_fp = fopen (env_fname, "w")) == NULL)
  1213.   #endif
  1214.               {    fprintf (stderr, "Cannot open output file %s\n", env_fname);
  1215. !                 exit (DISCARD_JOB);
  1216.               }
  1217.           }
  1218.           else
  1219.           {    output_fp = stdout;
  1220.           }
  1221. ***************
  1222. *** 874,886 ****
  1223.       output_book (bookfile);
  1224.       /*    end normal psf code */
  1225.   
  1226.   #endif    /* PSFFILTER */
  1227.   
  1228. !     exit (0);
  1229.   }
  1230.   
  1231.   
  1232.   /****************************************************************************
  1233.   *    cvt_unit ()                                                                *
  1234.   *    Determine the margin offset conversion factor to points.                *
  1235.   ****************************************************************************/
  1236. --- 1038,1327 ----
  1237.       output_book (bookfile);
  1238.       /*    end normal psf code */
  1239.   
  1240.   #endif    /* PSFFILTER */
  1241.   
  1242. !     exit (JOB_IS_DONE);
  1243. ! }
  1244. ! #ifdef PSFFILTER
  1245. ! /****************************************************************************
  1246. ! *    create_fork ()                                                            *
  1247. ! *    fork a child to send to printer.  parent reads from printer                *
  1248. ! ****************************************************************************/
  1249. ! void create_fork ()
  1250. ! {    int     parent;
  1251. !     long    pages_printed;
  1252. !     long    start_count;
  1253. !     int     status;
  1254. !     int        log_exit;
  1255. !     
  1256. !     request_pagecount (1);
  1257. !     if ((parent = fork ()) < 0)
  1258. !         expire ("fork");
  1259. !     if (parent)
  1260. !     {    /*    parent: read from printer port until child finishes print */
  1261. !         start_count = get_page_count ();
  1262. !         while (wait (&status) == -1)
  1263. !             if (errno != EINTR)
  1264. !                 expire ("fork wait");
  1265. !         request_pagecount (0);
  1266. !         pages_printed = get_page_count () - start_count;
  1267. !         log_exit = WIFEXITED (status) ? WEXITSTATUS (status) : DISCARD_JOB;
  1268. !         write_accounting (pages_printed, log_exit);
  1269. !         fflush (stdout);
  1270. !         fflush (stderr);
  1271. !         exit (log_exit);
  1272. !     }
  1273. !     /*    child: continue to print the job */
  1274. !     return;
  1275. ! }
  1276. ! /****************************************************************************
  1277. ! *    write_accounting ()                                                        *
  1278. ! *    send number of printed pages to accounting file. record non-zero exit    *
  1279. ! ****************************************************************************/
  1280. ! void write_accounting (pages_printed, log_exit)
  1281. ! long    pages_printed;
  1282. ! int        log_exit;
  1283. ! {    FILE    *accounting;
  1284. !     if (account_file_name == NULL)
  1285. !         return;
  1286. !     if ((accounting = fopen (account_file_name, "a")) != NULL)
  1287. !     {    if (log_exit)
  1288. !             (void) fprintf(accounting, "%ld\t%s:%s\ttermination:%d\n", pages_printed, host, user, log_exit);
  1289. !         else
  1290. !             (void) fprintf(accounting, "%ld\t%s:%s\n", pages_printed, host, user);
  1291. !         fclose (accounting);
  1292. !     }
  1293. !     else 
  1294. !     {    time_stamp();
  1295. !         perror(account_file_name);
  1296. !     }
  1297. ! }
  1298. ! /****************************************************************************
  1299. ! *    time_stamp ()                                                            *
  1300. ! *    record date stamp into error log file                                    *
  1301. ! ****************************************************************************/
  1302. ! void time_stamp()
  1303. ! {
  1304. !     int e = errno;
  1305. !     time_t clock = time((time_t *)0);
  1306. !     (void) fprintf (stderr, "%s: %.24s ", pgmname, ctime(&clock));
  1307. !     errno = e;
  1308. ! }
  1309. ! /****************************************************************************
  1310. ! *    expire ()                                                                *
  1311. ! *    create date-stamp and error message.                                    *
  1312. ! ****************************************************************************/
  1313. ! void expire(s)
  1314. ! char *s;
  1315. ! {
  1316. !     time_stamp ();
  1317. !     perror (s);
  1318. !     exit (DISCARD_JOB);
  1319. ! }
  1320. ! /****************************************************************************
  1321. ! *    getc_from_printer ()                                                    *
  1322. ! *    read a character from the printer,  return char or ERROR.                *
  1323. ! ****************************************************************************/
  1324. ! int getc_from_printer ()
  1325. ! {
  1326. !     char c;
  1327. !     int r;
  1328. !     
  1329. !     r = read (printfd, &c, 1);
  1330. !     if (r == 0)
  1331. !         return (EOF);
  1332. !     if (r == 1)
  1333. !         return (c);
  1334. !     return (READ_ERROR);        /* error during read */
  1335. ! }
  1336. ! /****************************************************************************
  1337. ! *    abort_job ()                                                            *
  1338. ! *    Abort the current printer job; don't wait for reply.                    *
  1339. ! ****************************************************************************/
  1340. ! void abort_job() 
  1341. ! {
  1342. !     (void) fwrite (c_CTLC_CANCEL, 1, sizeof(c_CTLC_CANCEL), output_fp); 
  1343. !     fflush (output_fp);
  1344. ! }
  1345. ! /****************************************************************************
  1346. ! *    abort_exit ()                                                            *
  1347. ! *    Abort the current printer job and exit.                                 *
  1348. ! ****************************************************************************/
  1349. ! void abort_exit() 
  1350. ! {    abort_job (); 
  1351. !     exit (DISCARD_JOB);
  1352. !     _exit (DISCARD_JOB);
  1353. ! }
  1354. ! /****************************************************************************
  1355. ! *    request_pagecount ()                                                    *
  1356. ! *    request page count from printer as a small postscript job.                *
  1357. ! ****************************************************************************/
  1358. ! void request_pagecount (cancel)
  1359. ! int cancel;
  1360. ! {    register int c;
  1361. !     char    pline[400];
  1362. !     if (cancel) {
  1363. !         /* Cancel any incomplete job and discard its output.  */
  1364. !         abort_job();
  1365. !         while ((c = getc_from_printer ()) != CTLD_EOJ)
  1366. !             if (c < 0)
  1367. !                 expire ("pagecount cancel");
  1368. !     }
  1369. !     sprintf (pline, "([%d] )print\n%s%s%s%s%s%s%s%s%s%c",
  1370. !                 pid,
  1371. !                 "/GetPageCount {\n",
  1372. !                 "    /str 64 string def\n",
  1373. !                 "    statusdict begin\n",
  1374. !                 "        currentdict/pagecount known {\n",
  1375. !                 "            pagecount str cvs print\n",
  1376. !                 "        } if \n",
  1377. !                 "     end %statusdict\n",
  1378. !                 "} def\n",
  1379. !                 "GetPageCount\n",
  1380. !                 CTLD_EOJ
  1381. !             );
  1382. !     c = strlen (pline);
  1383. !     if (fwrite (pline, 1, c, output_fp)  !=  c)
  1384. !         expire ("write pagecount");
  1385.   }
  1386.   
  1387. + /****************************************************************************
  1388. + *    get_page_count ()                                                        *
  1389. + *    get page count from printer.                                            *
  1390. + *    any other messages from printer are logged to the log file.                *
  1391. + ****************************************************************************/
  1392. + long get_page_count ()
  1393. + {    long    pc;
  1394. +     int        c, line_start = 1;
  1395. +     char    pline[100], *p;
  1396. +     (void) sprintf (pline, "[%d].", pid);
  1397. +     p = pline;
  1398. +     c = getc_from_printer ();
  1399. +     do
  1400. +     {    /* Print any false match from the last time through the loop.  */
  1401. +         fprintf (stderr, "%.*s", (int)(p - pline), pline);
  1402. +         /*    sync on [ */
  1403. +         for (;  c != '[';  c = getc_from_printer ())
  1404. +         {    if (c == EOF  ||  c == READ_ERROR)
  1405. +                 expire ("read page count (1)");
  1406. +             if (c != CTLD_EOJ)
  1407. +             {    if (line_start)
  1408. +                     {    time_stamp ();
  1409. +                         line_start = 0;
  1410. +                     }
  1411. +                 fputc (c, stderr);
  1412. +                 if (c == '\n')
  1413. +                     line_start = 1;
  1414. +             }
  1415. +         }
  1416. +         
  1417. +         p = pline + 1;
  1418. +         while (1)
  1419. +         {    c = getc_from_printer();
  1420. +             if (c == READ_ERROR  ||  c == EOF)
  1421. +                 expire ("read page count error (2)");
  1422. +             if (*p == c)
  1423. +                 p++;
  1424. +             else
  1425. +                 break;
  1426. +         }
  1427. +     
  1428. +     } while (*p != '.'  ||  c != ' ');
  1429. +     if (!line_start)
  1430. +         fputc ('\n', stderr);
  1431. +     /*    at page count number.  get value into pc */
  1432. +     pc = 0;
  1433. +     for (;;)
  1434. +     {    c = getc_from_printer ();
  1435. +         if (isdigit (c))
  1436. +             pc = pc * 10 + (c - '0');
  1437. +         else if (c == ' ')
  1438. +             continue;
  1439. +         else break;
  1440. +     }
  1441. +     wait_for_eoj (c);
  1442. +     return (pc);
  1443. + }
  1444. + /****************************************************************************
  1445. + *    wait_for_eoj ())                                                        *
  1446. + *    wait for the expected ctl/d eoj echo from the printer.                    *
  1447. + ****************************************************************************/
  1448. + void wait_for_eoj (c)
  1449. + int        c;
  1450. + {
  1451. +     for (;  c != CTLD_EOJ;  c = getc_from_printer())
  1452. +     {    if (c == EOF || c == READ_ERROR)
  1453. +             expire ("eof not eoj");
  1454. +         if (isascii (c) == 0)
  1455. +         {    fprintf (stderr, "non-ascii char = %02x\n", c);
  1456. +             expire("pagecount cancel");
  1457. +         }
  1458. +     }
  1459. + }
  1460. + #endif /* PSFFILTER */
  1461. + /****************************************************************************
  1462. + *    locate_pagetype ()                                                        *
  1463. + *    look for paper type in table of available types.                        *
  1464. + ****************************************************************************/
  1465. + measure    *locate_pagetype (desired, printerr)
  1466. + char    *desired;
  1467. + int        printerr;
  1468. + {    int        i;
  1469. +     measure    *p;
  1470. +     p = NULL;
  1471. +     for (i = 0;  page_types[i].paper_name[0];  i++)
  1472. +     {    if (compare (page_types[i].paper_name, desired) == 0)
  1473. +         {    p = &page_types[i];
  1474. +             break;
  1475. +         }
  1476. +     }
  1477. +     if (!p)
  1478. +     {    if (printerr)
  1479. +         {    fprintf (stderr, "Unknown page type %s.  Choose from: ", desired);
  1480. +             for (i = 0;  page_types[i].paper_name[0];  i++)
  1481. +                 fprintf (stderr, " %s", page_types[i].paper_name);
  1482. +             fprintf (stderr, "\n");
  1483. +         }
  1484. +     }
  1485. +     return (p);
  1486. + }
  1487.   
  1488.   /****************************************************************************
  1489.   *    cvt_unit ()                                                                *
  1490.   *    Determine the margin offset conversion factor to points.                *
  1491.   ****************************************************************************/
  1492. ***************
  1493. *** 890,900 ****
  1494.   {    double    fact;
  1495.   
  1496.       fact = 1.0;
  1497.       while (*which)
  1498.       {
  1499. !         if (isdigit (*which))
  1500.           {    which++;
  1501.               continue;
  1502.           }
  1503.           switch (toupper (*which))
  1504.           {
  1505. --- 1331,1341 ----
  1506.   {    double    fact;
  1507.   
  1508.       fact = 1.0;
  1509.       while (*which)
  1510.       {
  1511. !         if (*which == '.'  ||  isdigit (*which))
  1512.           {    which++;
  1513.               continue;
  1514.           }
  1515.           switch (toupper (*which))
  1516.           {
  1517. ***************
  1518. *** 901,911 ****
  1519.           case 'I':    fact = 72.0;        break;        /* inches     */
  1520.           case 'C':    fact = 72.0 / 2.54;    break;        /* cm          */
  1521.           case 'P':    fact = 1.0;            break;        /* points    */
  1522.           case ',':    break;
  1523.           default :    fprintf (stderr, "invalid margin unit '%c'\n", *which);
  1524. !                     exit (1);
  1525.           }
  1526.           if (*which++ != ',')
  1527.               break;
  1528.       }
  1529.       return (fact);
  1530. --- 1342,1352 ----
  1531.           case 'I':    fact = 72.0;        break;        /* inches     */
  1532.           case 'C':    fact = 72.0 / 2.54;    break;        /* cm          */
  1533.           case 'P':    fact = 1.0;            break;        /* points    */
  1534.           case ',':    break;
  1535.           default :    fprintf (stderr, "invalid margin unit '%c'\n", *which);
  1536. !                     exit (DISCARD_JOB);
  1537.           }
  1538.           if (*which++ != ',')
  1539.               break;
  1540.       }
  1541.       return (fact);
  1542. ***************
  1543. *** 924,934 ****
  1544.   void scale_factors ()
  1545.   {    int    wide;                /*    width needed for char count            */
  1546.       int    high;                /*    points needed for line count        */
  1547.       int    n_lines;            /*    number of lines on a page            */
  1548.       int    i;
  1549. !     double    char_width, scale;
  1550.       double    char_sf, line_sf;
  1551.       
  1552.       real_width = p->width;        /* for initial axis translate only    */
  1553.   
  1554.       if (landscape)
  1555. --- 1365,1375 ----
  1556.   void scale_factors ()
  1557.   {    int    wide;                /*    width needed for char count            */
  1558.       int    high;                /*    points needed for line count        */
  1559.       int    n_lines;            /*    number of lines on a page            */
  1560.       int    i;
  1561. !     double    char_width;
  1562.       double    char_sf, line_sf;
  1563.       
  1564.       real_width = p->width;        /* for initial axis translate only    */
  1565.   
  1566.       if (landscape)
  1567. ***************
  1568. *** 1154,1175 ****
  1569.               "    grestore\n",
  1570.               "    show\n",
  1571.               "} def\n",
  1572.               "/mv {moveto} def\n");
  1573.   
  1574.       /*    add additional startup prologue code from psfprint.def
  1575.           probably for non-English language support.
  1576.       */
  1577.       if (pdef)
  1578.       {
  1579. ! #ifdef PSFILTER
  1580.            char    line[LONG_STR + 1];        /* line already has text stream           */
  1581.                                           /* Jan Fernquist (fer@gorbie.n.tvt.se) */
  1582.   #endif
  1583.           while (fgets (line, LONG_STR, pdef))
  1584.           {    if (fputs (line, output_fp) == EOF)
  1585. !                 output_trouble (2);
  1586.           }
  1587.           fclose (pdef);
  1588.           pdef = NULL;
  1589.       }
  1590.       
  1591. --- 1595,1643 ----
  1592.               "    grestore\n",
  1593.               "    show\n",
  1594.               "} def\n",
  1595.               "/mv {moveto} def\n");
  1596.   
  1597. +     /* iso font encoding
  1598. +         % Header to convert StandardEncoded fonts to ISOLatin1Encoded fonts.
  1599. +         % Written by Magnus Hammerin 920226.
  1600. +         % Copyright (c) 1992 Magnus Hammerin.
  1601. +         % You may distribute this code freely as long as this note remains intact.
  1602. +         % Modification and adaption for usage with psf by Leif H (leif@ifm.liu.se)
  1603. +         %
  1604. +         % Test to see if the printer supports ISOLatin1Encoding.
  1605. +         /ReEncodeISO { % <newfontname> <oldfontname> ReEncodeISO
  1606. +     */
  1607. +     if (isolatin)
  1608. +         fprintf (output_fp, "%s%s%s%s%s%s%s%s%s%s%s%s",
  1609. +             "/ReEncodeISO {\n",
  1610. +             "  /ISOLatin1Encoding where {\n",
  1611. +             "    pop\n",
  1612. +             "    findfont\n",
  1613. +             "    dup length dict begin\n",
  1614. +             "      {1 index /FID ne {def} {pop pop} ifelse} forall\n",
  1615. +             "      /Encoding ISOLatin1Encoding def\n",
  1616. +             "      currentdict\n",
  1617. +             "    end\n",
  1618. +             "    definefont pop\n",
  1619. +             "  } { pop pop } ifelse\n",
  1620. +             "} bind def\n");
  1621.       /*    add additional startup prologue code from psfprint.def
  1622.           probably for non-English language support.
  1623.       */
  1624.       if (pdef)
  1625.       {
  1626. ! #ifdef PSFFILTER
  1627.            char    line[LONG_STR + 1];        /* line already has text stream           */
  1628.                                           /* Jan Fernquist (fer@gorbie.n.tvt.se) */
  1629.   #endif
  1630.           while (fgets (line, LONG_STR, pdef))
  1631.           {    if (fputs (line, output_fp) == EOF)
  1632. !                 output_trouble (DISCARD_JOB);
  1633.           }
  1634.           fclose (pdef);
  1635.           pdef = NULL;
  1636.       }
  1637.       
  1638. ***************
  1639. *** 1180,1203 ****
  1640.           {    while (1)
  1641.               {    c = fgetc (fp);
  1642.                   if (feof (fp)  ||  ferror (fp))
  1643.                       break;
  1644.                   if (fputc (c, fp) == EOF)
  1645. !                     output_trouble (2);
  1646.               }
  1647.               fclose (fp);
  1648.           }
  1649.       }
  1650.           
  1651.       fprintf (output_fp, "%%%%EndProlog\n");
  1652.   
  1653. !     if (set_paper_tray)
  1654. !         fprintf (output_fp, "%s\n", p->paper_tray);
  1655.   
  1656.       if (order_command)
  1657.           fprintf (output_fp, "%s\n", order_command);
  1658.       else if (set_paper_bin)
  1659.           fprintf (output_fp, "%s\n", slots[set_paper_bin - 1]);
  1660.   }
  1661.   
  1662.   /****************************************************************************
  1663.   *    showpage ()                                                                *
  1664. --- 1648,1694 ----
  1665.           {    while (1)
  1666.               {    c = fgetc (fp);
  1667.                   if (feof (fp)  ||  ferror (fp))
  1668.                       break;
  1669.                   if (fputc (c, fp) == EOF)
  1670. !                     output_trouble (DISCARD_JOB);
  1671.               }
  1672.               fclose (fp);
  1673.           }
  1674.       }
  1675.           
  1676.       fprintf (output_fp, "%%%%EndProlog\n");
  1677.   
  1678. !     set_tray (set_paper_tray);
  1679. !     if (duplex)
  1680. !         fprintf (output_fp, "%s\n", duplex_mode);
  1681.   
  1682.       if (order_command)
  1683.           fprintf (output_fp, "%s\n", order_command);
  1684.       else if (set_paper_bin)
  1685. +         set_bin (set_paper_bin);
  1686. + }
  1687. + /****************************************************************************
  1688. + *    set_tray ()                                                                *
  1689. + ****************************************************************************/
  1690. + void set_tray (set_paper_tray)
  1691. + int        set_paper_tray;
  1692. + {
  1693. +     if (set_paper_tray)
  1694. +         fprintf (output_fp, "%s\n", p->paper_tray);
  1695. + }
  1696. + /****************************************************************************
  1697. + *    set_bin ()                                                                *
  1698. + ****************************************************************************/
  1699. + void set_bin (set_paper_bin)
  1700. + int        set_paper_bin;
  1701. + {
  1702. +     if (set_paper_bin)
  1703.           fprintf (output_fp, "%s\n", slots[set_paper_bin - 1]);
  1704.   }
  1705.   
  1706.   /****************************************************************************
  1707.   *    showpage ()                                                                *
  1708. ***************
  1709. *** 1224,1241 ****
  1710. --- 1715,1734 ----
  1711.               ;
  1712.           if (skipping >= 0)
  1713.           {    end_of_file = 1;
  1714.               if (bookwork == 0)                /* psfdoub will re-insert this */
  1715.                   fprintf (output_fp, "showpage pg restore\n");
  1716. +             pages_written++;
  1717.               frame = 0;
  1718.               longjmp (eof_env, 1);
  1719.           }
  1720.       }
  1721.   
  1722.       if (++frame >= max_frame  ||  end_of_file)
  1723.       {    if (bookwork == 0)                    /* psfdoub will re-insert this */
  1724.               fprintf (output_fp, "showpage pg restore\n");
  1725. +         pages_written++;
  1726.           frame = 0;
  1727.       }
  1728.       if (!end_of_file)
  1729.           set_frame ();
  1730.       
  1731. ***************
  1732. *** 1353,1371 ****
  1733.       /*    psffilter already has a first line,  psf does not */
  1734.       do
  1735.   #else
  1736.       while (line_is_wrapped  ||  fgets (line, LONG_STR, input_fp) != NULL)
  1737.   #endif
  1738. !     {
  1739. !         if (*line == CTLD_EOJ)        /* printing postscript code: ^D at end    */
  1740. !             break;                    /* assume it is end of file also        */
  1741. !         if (lcount++ == 0)
  1742.           {    if ((i = tscan (line, "ta=")) >= 0)
  1743.               {    tab_size = atoi (line + i + 3);
  1744.               }
  1745.           }
  1746.   
  1747.           if (need_xlate)                /*    translate character set? */
  1748.           {    xln = (unsigned char *) line;
  1749.               while (*xln)
  1750.               {    i = *xln;
  1751. --- 1846,1872 ----
  1752.       /*    psffilter already has a first line,  psf does not */
  1753.       do
  1754.   #else
  1755.       while (line_is_wrapped  ||  fgets (line, LONG_STR, input_fp) != NULL)
  1756.   #endif
  1757. !     {    if (lcount++ == 0)
  1758.           {    if ((i = tscan (line, "ta=")) >= 0)
  1759.               {    tab_size = atoi (line + i + 3);
  1760.               }
  1761. +             if (*line == CTLD_EOJ)
  1762. +             {    /* postscript code may have leading ctl/d.  remove them */
  1763. +                 lc = line;
  1764. +                 while (*lc  && *lc == CTLD_EOJ)
  1765. +                     lc++;
  1766. +                 i = 0;
  1767. +                 do
  1768. +                 {    line[i++] = *lc;
  1769. +                 } while (*lc++);
  1770. +             }
  1771.           }
  1772. +         else if (*line == CTLD_EOJ)    /* printing postscript code: ^D at end    */
  1773. +             break;                    /* assume it is end of file also        */
  1774.   
  1775.           if (need_xlate)                /*    translate character set? */
  1776.           {    xln = (unsigned char *) line;
  1777.               while (*xln)
  1778.               {    i = *xln;
  1779. ***************
  1780. *** 1440,1450 ****
  1781.               moveto (x_coord, y_coord, 1);        /*    do gen moveto        */
  1782.   
  1783.           while (*c  && *c != '\n')
  1784.           {    if (char_type == 0)
  1785.               {    if (fputc ('(', output_fp) == EOF)
  1786. !                     output_trouble (2);
  1787.               }
  1788.               switch ((int) *c)
  1789.               {
  1790.               case ESCAPE:
  1791.                   previous_attribute = print_attribute;
  1792. --- 1941,1951 ----
  1793.               moveto (x_coord, y_coord, 1);        /*    do gen moveto        */
  1794.   
  1795.           while (*c  && *c != '\n')
  1796.           {    if (char_type == 0)
  1797.               {    if (fputc ('(', output_fp) == EOF)
  1798. !                     output_trouble (DISCARD_JOB);
  1799.               }
  1800.               switch ((int) *c)
  1801.               {
  1802.               case ESCAPE:
  1803.                   previous_attribute = print_attribute;
  1804. ***************
  1805. *** 1459,1469 ****
  1806.                       default:
  1807.                           if (char_type  &&  (previous_attribute & UNDERLINE))
  1808.                               SHOWU (output_fp, point_size);
  1809.                           else
  1810.                           {    if (fputs (")show\n", output_fp) == EOF)
  1811. !                                 output_trouble (2);
  1812.                           }
  1813.                           if (esc_type == '+'  ||  esc_type == '-')
  1814.                           {    /*    check for +/- 1/2 line feed        */
  1815.                               if (esc_type == '+')
  1816.                                   y_coord -= ((point_size + extra_space) / 2);
  1817. --- 1960,1970 ----
  1818.                       default:
  1819.                           if (char_type  &&  (previous_attribute & UNDERLINE))
  1820.                               SHOWU (output_fp, point_size);
  1821.                           else
  1822.                           {    if (fputs (")show\n", output_fp) == EOF)
  1823. !                                 output_trouble (DISCARD_JOB);
  1824.                           }
  1825.                           if (esc_type == '+'  ||  esc_type == '-')
  1826.                           {    /*    check for +/- 1/2 line feed        */
  1827.                               if (esc_type == '+')
  1828.                                   y_coord -= ((point_size + extra_space) / 2);
  1829. ***************
  1830. *** 1472,1482 ****
  1831.                               moveto (x_coord, y_coord, 1);
  1832.                               char_type = -1;
  1833.                               c++;
  1834.                               if (*c != '\n')
  1835.                               {    if (fputc ('(', output_fp) == EOF)
  1836. !                                     output_trouble (2);
  1837.                               }
  1838.                               continue;
  1839.                           }
  1840.                           else
  1841.                               findfont ();
  1842. --- 1973,1983 ----
  1843.                               moveto (x_coord, y_coord, 1);
  1844.                               char_type = -1;
  1845.                               c++;
  1846.                               if (*c != '\n')
  1847.                               {    if (fputc ('(', output_fp) == EOF)
  1848. !                                     output_trouble (DISCARD_JOB);
  1849.                               }
  1850.                               continue;
  1851.                           }
  1852.                           else
  1853.                               findfont ();
  1854. ***************
  1855. *** 1505,1523 ****
  1856.                   }
  1857.                   if (*c == '\t')
  1858.                   {    fputc (' ', output_fp);
  1859.                       while (++char_count % tab_size)
  1860.                       {    if (fputc (' ', output_fp) == EOF)
  1861. !                             output_trouble (2);
  1862.                       }
  1863.                   }
  1864.                   else
  1865.                   {    if (strchr ("\r\b\\()", *c) != NULL)
  1866.                           if (fputc ('\\', output_fp) == EOF)
  1867. !                             output_trouble (2);
  1868.                       if (fputc (*c, output_fp) == EOF)
  1869. !                         output_trouble (2);
  1870.                       char_count++;
  1871.                   }
  1872.                   break;
  1873.               }
  1874.               c++;
  1875. --- 2006,2024 ----
  1876.                   }
  1877.                   if (*c == '\t')
  1878.                   {    fputc (' ', output_fp);
  1879.                       while (++char_count % tab_size)
  1880.                       {    if (fputc (' ', output_fp) == EOF)
  1881. !                             output_trouble (DISCARD_JOB);
  1882.                       }
  1883.                   }
  1884.                   else
  1885.                   {    if (strchr ("\r\b\\()", *c) != NULL)
  1886.                           if (fputc ('\\', output_fp) == EOF)
  1887. !                             output_trouble (DISCARD_JOB);
  1888.                       if (fputc (*c, output_fp) == EOF)
  1889. !                         output_trouble (DISCARD_JOB);
  1890.                       char_count++;
  1891.                   }
  1892.                   break;
  1893.               }
  1894.               c++;
  1895. ***************
  1896. *** 1527,1537 ****
  1897.           if (char_type == 1)
  1898.           {    if (print_attribute & UNDERLINE)
  1899.                   SHOWU (output_fp, point_size);
  1900.               else
  1901.               {    if (fputs (")show\n", output_fp) == EOF)
  1902. !                     output_trouble (2);
  1903.               }
  1904.           }
  1905.   
  1906.           y_coord -= (point_size + extra_space);
  1907.           x_coord = 0;
  1908. --- 2028,2038 ----
  1909.           if (char_type == 1)
  1910.           {    if (print_attribute & UNDERLINE)
  1911.                   SHOWU (output_fp, point_size);
  1912.               else
  1913.               {    if (fputs (")show\n", output_fp) == EOF)
  1914. !                     output_trouble (DISCARD_JOB);
  1915.               }
  1916.           }
  1917.   
  1918.           y_coord -= (point_size + extra_space);
  1919.           x_coord = 0;
  1920. ***************
  1921. *** 1647,1667 ****
  1922.           fprintf (output_fp, "%d %d mv ", x + x_left_offset, y);
  1923.   }
  1924.   
  1925.   /****************************************************************************
  1926.   *    findfont ()                                                                *
  1927. ! *    generate a findfont statement                                            *
  1928.   ****************************************************************************/
  1929.   
  1930.   void findfont ()
  1931.   {    int    this;
  1932.   
  1933.       /*    remove reference to UNDERLINE.  Underline is not a font.    */
  1934.   
  1935.       this = (font_number * 4) + (print_attribute & 0x03);
  1936.       fonts_used[this] = 1;
  1937. !     fprintf (output_fp, "/%s findfont %d scalefont setfont\n", fonts[this], point_size);
  1938.   }
  1939.   
  1940.   /****************************************************************************
  1941.   *    start_file ()                                                            *
  1942.   *    Generate things that are appropriate for beginning of file processing    *
  1943. --- 2148,2183 ----
  1944.           fprintf (output_fp, "%d %d mv ", x + x_left_offset, y);
  1945.   }
  1946.   
  1947.   /****************************************************************************
  1948.   *    findfont ()                                                                *
  1949. ! *    generate a findfont statement. Do ISOLatin1 encoding if desired.        *
  1950.   ****************************************************************************/
  1951.   
  1952.   void findfont ()
  1953.   {    int    this;
  1954. +     char    new_font_name[100], *fontname;
  1955.   
  1956.       /*    remove reference to UNDERLINE.  Underline is not a font.    */
  1957.   
  1958.       this = (font_number * 4) + (print_attribute & 0x03);
  1959.       fonts_used[this] = 1;
  1960. !     if (isolatin)
  1961. !     {
  1962. !         strcpy (new_font_name, fonts[this]);
  1963. !         strcat (new_font_name, "-ISO");
  1964. !         if (fonts_iso[this] == 0)
  1965. !         {    fprintf (output_fp, "/%s /%s ReEncodeISO\n", new_font_name, fonts[this]);
  1966. !             fonts_iso[this] = 1;
  1967. !         }
  1968. !         fontname = new_font_name;
  1969. !     }
  1970. !     else
  1971. !         fontname = fonts[this];
  1972. !     fprintf (output_fp, "/%s findfont %d scalefont setfont\n", fontname, point_size);
  1973.   }
  1974.   
  1975.   /****************************************************************************
  1976.   *    start_file ()                                                            *
  1977.   *    Generate things that are appropriate for beginning of file processing    *
  1978. ***************
  1979. *** 1723,1733 ****
  1980. --- 2239,2258 ----
  1981.           for (i = 0;  i < npg_loc-1;  i++)
  1982.               fprintf (output_fp, "%%PsfPg: %d %d\n",  i, pg_loc[i]);
  1983.           fprintf (output_fp, "%%PsfPg: 9999 %d\n", pg_loc[npg_loc-1]);
  1984.           fprintf (output_fp, "%%PsfPtr: %d\n", psfptr);
  1985.       }
  1986. + #ifdef PSFFILTER
  1987.       fprintf (output_fp, "%c", CTLD_EOJ);        /* CTL/D = end job */
  1988. + #else
  1989. +     if (gen_eoj)
  1990. +         fprintf (output_fp, "%c", CTLD_EOJ);
  1991. + #ifdef CTLDALWAYS
  1992. +     if (gen_eoj == 0)
  1993. +         fprintf (output_fp, "%c", CTLD_EOJ);
  1994. + #endif
  1995. + #endif
  1996.   }
  1997.   
  1998.   /****************************************************************************
  1999.   *    draw_cross ()                                                            *
  2000.   *    Draw horizontal and vertical separation lines between pages 2/4-up        *
  2001. ***************
  2002. *** 1826,1835 ****
  2003. --- 2351,2421 ----
  2004.   #endif    /* HOPPER */
  2005.   }
  2006.   
  2007.   
  2008.   /************************************************************************
  2009. + *    nexttok()                                                            *
  2010. + *    like strtok() however assumes that quote or apostrophe delimit        *
  2011. + *    multi-word groups.                                                    *
  2012. + ************************************************************************/
  2013. + char *nexttok (ss, q)
  2014. + char *ss, *q;
  2015. + {
  2016. +     static char *s;
  2017. +     char    quote_char, *start, *quote, *apostrophe;
  2018. +     
  2019. +     if (ss)
  2020. +         s = ss;
  2021. +     if (s  &&  *s)
  2022. +     {
  2023. +         /*    use quote or apostrophe delimiting? */
  2024. +     
  2025. +         quote = strchr (q, '"');
  2026. +         apostrophe = strchr (q, '\'');
  2027. +         
  2028. +         /*    skip leading quote symbols */
  2029. +         
  2030. +         quote_char = *s;
  2031. +         while (*s)
  2032. +         {    if ((quote && *s == '"')  ||  (apostrophe  &&  *s == '\''))
  2033. +             {    quote_char = *s++;
  2034. +                 break;
  2035. +             }
  2036. +             if (strchr (q, *s) == NULL)
  2037. +                 break;
  2038. +             quote_char = *s++;
  2039. +         }
  2040. +         
  2041. +         /*    skip to next quote */
  2042. +         
  2043. +         start = s;                        /*    beginning of user string */
  2044. +         if (quote_char == '"' ||  quote_char == '\'')
  2045. +         {    while (*s  &&  *s != quote_char)
  2046. +                 s++;
  2047. +         }
  2048. +         else
  2049. +         {    while (*s  &&  strchr (q, *s) == NULL)
  2050. +                 s++;
  2051. +         }
  2052. +         
  2053. +         if (*s)                            /*    end of user string        */
  2054. +             *s++ = '\0';
  2055. +         else
  2056. +             s = NULL;
  2057. +     }
  2058. +     else
  2059. +     {    s = NULL;
  2060. +         start = NULL;
  2061. +     }
  2062. +     return (start);
  2063. + }
  2064. + /************************************************************************
  2065.   *        tscan (s,t)                                                        *        
  2066.   *    look for string t in s. return -1 if t does not exits in s else        *
  2067.   *    return array position of first character match                        *
  2068.   ************************************************************************/
  2069.   
  2070. ***************
  2071. *** 1847,1860 ****
  2072.   }
  2073.   
  2074.   void get_time (t)                /*    get current time of */
  2075.   char    *t;
  2076.   {
  2077. !     long    n_time, time ();
  2078.       char    *x_time, *cc, *strchr();
  2079.   
  2080. !     n_time = time (0);            /* get time */
  2081.       x_time = ctime (&n_time);    /* convert ascii */
  2082.       if ((cc = strchr (x_time, '\n')) != NULL)
  2083.           *cc = '\0';
  2084.       strcpy (t, x_time);
  2085.   }
  2086. --- 2433,2446 ----
  2087.   }
  2088.   
  2089.   void get_time (t)                /*    get current time of */
  2090.   char    *t;
  2091.   {
  2092. !     time_t    n_time, time ();
  2093.       char    *x_time, *cc, *strchr();
  2094.   
  2095. !     n_time = time ((time_t *)0);    /* get time */
  2096.       x_time = ctime (&n_time);    /* convert ascii */
  2097.       if ((cc = strchr (x_time, '\n')) != NULL)
  2098.           *cc = '\0';
  2099.       strcpy (t, x_time);
  2100.   }
  2101. ***************
  2102. *** 1883,1921 ****
  2103.               return (UCCHAR(aa) - UCCHAR(bb));
  2104.       }
  2105.       return (0);
  2106.   }
  2107.   
  2108. - int comparen (a,b, n)            /* case insensitive compare with count limit */
  2109. - char    *a, *b;
  2110. - int        n;
  2111. - {    int    aa, bb;
  2112. -     while (*a &&  n--)
  2113. -     {    aa = *a++;
  2114. -         bb = *b++;
  2115. -         if (UCCHAR (aa)  !=  UCCHAR (bb))
  2116. -             return (UCCHAR(aa) - UCCHAR(bb));
  2117. -     }
  2118. -     if (n <= 0)
  2119. -         return (0);
  2120. -     return (UCCHAR (*a) - UCCHAR (*b));
  2121. - }
  2122. - int endcompare (a,b)            /* compare end of a with b */
  2123. - char    *a, *b;
  2124. - {
  2125. -     int    na, nb;
  2126. -     
  2127. -     na = strlen (a);
  2128. -     nb = strlen (b);
  2129. -     if (na > nb)
  2130. -         a += na - nb;
  2131. -     return (strcmp (a,b));
  2132. - }
  2133.   void trim (s)                    /*    trim trailing blanks  and \n */
  2134.   char    *s;
  2135.   {    int many;
  2136.   
  2137.       for (many = strlen (s) - 1;  many >= 0;  many--)
  2138. --- 2469,2478 ----
  2139. ***************
  2140. *** 1927,1937 ****
  2141.   }
  2142.   
  2143.   void bad_file()
  2144.   {
  2145.       fprintf (stderr, "Bad %s file\n", defref);
  2146. !     exit (1);
  2147.   }
  2148.   
  2149.   int xtoi (c)                    /*    hex character to integer     */
  2150.   int c;                            /*    any letter is a 'hex' digit */
  2151.   {
  2152. --- 2484,2494 ----
  2153.   }
  2154.   
  2155.   void bad_file()
  2156.   {
  2157.       fprintf (stderr, "Bad %s file\n", defref);
  2158. !     exit (DISCARD_JOB);
  2159.   }
  2160.   
  2161.   int xtoi (c)                    /*    hex character to integer     */
  2162.   int c;                            /*    any letter is a 'hex' digit */
  2163.   {
  2164. ***************
  2165. *** 1957,1968 ****
  2166.   ********************************************************/
  2167.   
  2168.   void catch (signo)
  2169.   int    signo;
  2170.   {
  2171.           fprintf (output_fp, "%c", CTLD_EOJ);
  2172. !         exit (0);
  2173.   }
  2174.   
  2175.   void output_trouble (rc)
  2176.   int    rc;
  2177.   {
  2178. --- 2514,2534 ----
  2179.   ********************************************************/
  2180.   
  2181.   void catch (signo)
  2182.   int    signo;
  2183.   {
  2184. + #ifdef PSFFILTER
  2185. +     abort_exit ();
  2186. + #else
  2187. +     if (gen_eoj)
  2188. +         fprintf (output_fp, "%c", CTLD_EOJ);
  2189. + #ifdef CTLDALWAYS
  2190. +     if (gen_eoj == 0)
  2191.           fprintf (output_fp, "%c", CTLD_EOJ);
  2192. ! #endif
  2193. ! #endif
  2194. !         exit (JOB_IS_DONE);
  2195.   }
  2196.   
  2197.   void output_trouble (rc)
  2198.   int    rc;
  2199.   {
  2200. ***************
  2201. *** 2038,2071 ****
  2202.   *    octal to integer                                                        *
  2203.   ****************************************************************************/
  2204.   int    otoi (s)
  2205.   char    *s;
  2206.   {
  2207. !     int        v, p, quit;
  2208.   
  2209.       v = 0;
  2210.       while (*s == ' ')
  2211.           s++;
  2212. !     quit = 0;
  2213. !     while (*s)
  2214. !     {    switch (*s)
  2215. !         {
  2216. !         case '0':    p = 0;  break;
  2217. !         case '1':    p = 1;  break;
  2218. !         case '2':    p = 2;  break;
  2219. !         case '3':    p = 3;  break;
  2220. !         case '4':    p = 4;  break;
  2221. !         case '5':    p = 5;  break;
  2222. !         case '6':    p = 6;  break;
  2223. !         case '7':    p = 7;  break;
  2224. !         default:    quit = 1;
  2225. !         }
  2226. !         if (quit)
  2227. !             break;
  2228. !         v = (v << 3) + p;
  2229. !         s++;
  2230. !     }
  2231.       return (v);
  2232.   }
  2233.   
  2234.   /****************************************************************************
  2235.   *    usage ()                                                                *
  2236. --- 2604,2621 ----
  2237.   *    octal to integer                                                        *
  2238.   ****************************************************************************/
  2239.   int    otoi (s)
  2240.   char    *s;
  2241.   {
  2242. !     int v;
  2243. !     unsigned d;
  2244.   
  2245.       v = 0;
  2246.       while (*s == ' ')
  2247.           s++;
  2248. !     while ((d = *s++ - '0')  <  8)
  2249. !         v = (v << 3) + d;
  2250.       return (v);
  2251.   }
  2252.   
  2253.   /****************************************************************************
  2254.   *    usage ()                                                                *
  2255. ***************
  2256. *** 2072,2105 ****
  2257.   ****************************************************************************/
  2258.   
  2259.   #ifdef PSFFILTER
  2260.   
  2261.   void usage ()
  2262. ! {    exit (1);
  2263.   }
  2264.   void size_display ()
  2265. ! {    exit (1);
  2266.   }
  2267.   
  2268.   #else    /* not PSFFILTER */
  2269.   
  2270.   static char *usage_text[] =
  2271.   {
  2272. !     "Usage: %s [-124dEehnswx] [-b n] [-c n] [-f n] [-g type] [-H txt] [-i n] [-l n]\n",
  2273. !     "     [-m n] [-M l,r,t,b[,pic]] [-p n] [-P n] [-R n] [-r n] [-t n] [-u f] file..",
  2274. !     "where:",
  2275.       "   -1|2|4  print 1,2,4 up (default=1)",
  2276.       "   -b n    paper bin n",
  2277.       "   -c n    print columns",
  2278.       "   -d      double sided",
  2279.       "   -e      left-justified line wrap",
  2280.       "   -E      right-justified line wrap",
  2281.       "   -f n    font number (def=0:Courier)",
  2282.       "   -g type letter legal a4 b5",
  2283.       "   -h      file name header",
  2284.       "   -H text text header",
  2285.       "   -i n[pic] indent left margin points",
  2286.       "   -l n    print lines per page",
  2287.       "   -L n    lines per page",
  2288.       "   -m n[pic] top margin points",
  2289.       "   -M xxx  set all margins",
  2290.       "   -n      portrait (narrow) format",
  2291. --- 2622,2667 ----
  2292.   ****************************************************************************/
  2293.   
  2294.   #ifdef PSFFILTER
  2295.   
  2296.   void usage ()
  2297. ! {    exit (DISCARD_JOB);
  2298.   }
  2299.   void size_display ()
  2300. ! {    exit (DISCARD_JOB);
  2301.   }
  2302.   
  2303.   #else    /* not PSFFILTER */
  2304.   
  2305.   static char *usage_text[] =
  2306.   {
  2307. ! #ifdef CTLDALWAYS
  2308. !     "Usage: %s [-124DdehIjnswx][-b n][-c n][-f n][-g type][-H txt][-i n][-l n]\n",
  2309. ! #else
  2310. !     "Usage: %s [-124DdEehInswx][-b n][-c n][-f n][-g type][-H txt][-i n][-l n]\n",
  2311. ! #endif
  2312. !     "     [-m n][-M l,r,t,b[,pic]][-p n][-P n][-R n][-r n][-t n][-u f] file..",
  2313.       "   -1|2|4  print 1,2,4 up (default=1)",
  2314.       "   -b n    paper bin n",
  2315.       "   -c n    print columns",
  2316. +     "   -D      duplex double sided",
  2317.       "   -d      double sided",
  2318.       "   -e      left-justified line wrap",
  2319.       "   -E      right-justified line wrap",
  2320.       "   -f n    font number (def=0:Courier)",
  2321.       "   -g type letter legal a4 b5",
  2322.       "   -h      file name header",
  2323.       "   -H text text header",
  2324. + #ifdef ISO
  2325. +     "   -I      disable ISOLatin1 encoding",
  2326. + #else
  2327. +     "   -I      use ISOLatin1 encoding",
  2328. + #endif
  2329.       "   -i n[pic] indent left margin points",
  2330. + #ifndef CTLDALWAYS
  2331. +     "   -j      ctl/d at end of print job",
  2332. + #endif
  2333.       "   -l n    print lines per page",
  2334.       "   -L n    lines per page",
  2335.       "   -m n[pic] top margin points",
  2336.       "   -M xxx  set all margins",
  2337.       "   -n      portrait (narrow) format",
  2338. ***************
  2339. *** 2116,2126 ****
  2340.       "   file..  name of files (or stdin)",
  2341.       "   output: stdout",
  2342.       ""
  2343.   } ;
  2344.   
  2345. ! #define TOPCOUNT 3
  2346.   
  2347.   void usage ()
  2348.   {    int        i, many, n, ff;
  2349.   
  2350.       fprintf (stderr, usage_text[0], pgmname);
  2351. --- 2678,2688 ----
  2352.       "   file..  name of files (or stdin)",
  2353.       "   output: stdout",
  2354.       ""
  2355.   } ;
  2356.   
  2357. ! #define TOPCOUNT 2
  2358.   
  2359.   void usage ()
  2360.   {    int        i, many, n, ff;
  2361.   
  2362.       fprintf (stderr, usage_text[0], pgmname);
  2363. ***************
  2364. *** 2158,2168 ****
  2365.           many += n + 3;
  2366.           fprintf (stderr,"   %s", page_types[i].paper_name);
  2367.       }
  2368.       if (ff)
  2369.           fprintf (stderr, "\n");
  2370. !     exit (1);
  2371.   }
  2372.   
  2373.   /************************************************************************
  2374.   *    size_display ()                                                        *
  2375.   *    print a table of point size, page size, line count, column count    *
  2376. --- 2720,2730 ----
  2377.           many += n + 3;
  2378.           fprintf (stderr,"   %s", page_types[i].paper_name);
  2379.       }
  2380.       if (ff)
  2381.           fprintf (stderr, "\n");
  2382. !     exit (DISCARD_JOB);
  2383.   }
  2384.   
  2385.   /************************************************************************
  2386.   *    size_display ()                                                        *
  2387.   *    print a table of point size, page size, line count, column count    *
  2388. ***************
  2389. *** 2205,2212 ****
  2390.                   fprintf (stderr, " %4d%4d", n_lines, n_chars);
  2391.               }
  2392.               fprintf (stderr, "\n");
  2393.           }
  2394.       }
  2395. !     exit (1);
  2396.   }
  2397.   #endif /* PSFFILTER */
  2398. --- 2767,2774 ----
  2399.                   fprintf (stderr, " %4d%4d", n_lines, n_chars);
  2400.               }
  2401.               fprintf (stderr, "\n");
  2402.           }
  2403.       }
  2404. !     exit (DISCARD_JOB);
  2405.   }
  2406.   #endif /* PSFFILTER */
  2407.  
  2408. exit 0 # Just in case...
  2409.