home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume27 / psf3 / part09 / psf.c
Encoding:
C/C++ Source or Header  |  1992-01-20  |  51.2 KB  |  2,019 lines

  1. /* ta=4        set tabstop=4    */
  2. /****************************************************************************
  3. *                     p s f . c        v3                                        *
  4. *                                                                            *
  5. *    Print text files to postscript printer.                                    *
  6. *                                                                            *
  7. *    Tony Field: tony@ajfcal.cuc.ab.ca                                        *
  8. ****************************************************************************/
  9. /*
  10.  * $Id: psf.c,v 3.2 1992/01/19 05:50:33 ajf Exp ajf $
  11. */
  12. /*    Three versions of psf can be compiled:
  13.  
  14.         psf:        postscript filter for command line use.
  15.             
  16.         psffilter:    used with lp/lpsched.  accepts command line argument.
  17.                     Input on stdin. compile with -DPSFFILTER.
  18.  
  19.         psflpd:        used with lpr/lpd.  does not accept command line
  20.                     arguments.  compile with -DPSFFILTER -DFORLPD
  21.  */
  22.  
  23. #include <stdio.h>
  24. #include <malloc.h>
  25. #include <string.h>
  26. #include <setjmp.h>
  27. #include <math.h>
  28. #include <time.h>
  29. #include <signal.h>
  30. #include "ctp.h"
  31. #include "patchlevel.h"
  32. #include "psf.h"
  33. #include "psfproto.h"
  34.  
  35. #if defined(MSDOS)  ||  defined (__MSDOS__)
  36. #ifndef BINDIR
  37. #define BINDIR "c:/bin"
  38. #endif
  39. #ifndef PDEF
  40. #define PDEF "c:/lib/psfprint.def"
  41. #endif
  42. #endif
  43.  
  44. #ifndef PAPERTYPE
  45. #define PAPERTYPE "letter"
  46. #endif
  47. #ifndef PSFDOUB
  48. #define PSFDOUB "psfdoub"
  49. #endif
  50.  
  51. /*    set up the mechanism for underline display */
  52.  
  53. #define SHOWU(fp,ps)    fprintf (fp, ") %d showuline\n", ps)
  54.  
  55. #define NOMINAL_CWIDE    7.2001    /* point width for Courier 12-point            */
  56. #define NOMINAL_POINTS    12        /* standard 12-point for printing            */
  57.  
  58. #define NORMAL        0x00        /* bitset for  print_attributes                */
  59. #define ITALICS        0x01
  60. #define BOLD        0x02
  61. #define UNDERLINE    0x04        /* must be 0x04.  underline is not a font    */
  62.  
  63. #define CTLD_EOJ    0x04        /* ctl/d is end of postscript job.            */
  64.  
  65. /*    Paper physical dimensions.
  66.     The default paper sizes is for a NEC LC890 and is overridden in
  67.     "psfprint.def".
  68. */
  69.  
  70. typedef struct                     /*    measurement in point                    */
  71. {    char    paper_name[60];        /*    name of paper size (for command line)    */
  72.     char    paper_tray[100];    /*    postscript operator to select this tray    */
  73.     int        width;                /*    portrait point width of paper            */
  74.     int        height;                /*    portrait point height of paper            */
  75.     int        lx, ly, ux, uy;
  76.     int        left_marg;            /*    margin widths (unprintable area)        */
  77.     int        bot_marg;            /*            "                                */
  78.     int        right_marg;            /*            "                                */
  79.     int        top_marg;            /*            "                                */
  80.     int        x_size;                /*    generated by psf.                        */
  81.     int        y_size;                /*    size after correction for line count    */
  82. } measure;
  83.  
  84. measure    *p;        /*    working set of parameters  (points to something below)     */
  85. measure    page_types[NPAGE] =
  86. {            {     "letter",
  87.                 "statusdict begin lettertray end",
  88.                   612,   792,    18,    15,   593,   777
  89.             },
  90.             {     "legal",
  91.                 "statusdict begin legaltray end",
  92.                   612,  1008,    18,    15,   593,   993
  93.             },
  94.             {    "a4",
  95.                 "statusdict begin a4tray end",
  96.                   595,   842,    18,    15,   578,   827
  97.             },
  98.             {    "b5",
  99.                 "statusdict begin b5tray end",
  100.                   516,   729,    18,    15,   497,   712
  101.             },
  102.             {    "",            /* end of paper list */
  103.                 "",
  104.                  0, 0,  0,  0, 0, 0, 0, 0, 0, 0 
  105.             }
  106. };
  107.  
  108. char    order_default[20] = "Normal";
  109. char    order_normal[100] = "\0";
  110. char    order_reverse[100] = "\0";
  111. char    *order_command = NULL;
  112.  
  113. char    slots[NSLOTS][200] = 
  114. {            "statusdict begin 1 setpapertray end",
  115.             "statusdict begin 2 setpapertray end",
  116.             "", "", "", ""
  117. } ;
  118. int        nslots = 2;
  119.  
  120. int        y_top_offset;            /*    offsets for each frame                    */
  121. int        x_left_offset;
  122. int        dx_home[4];                /*    page frame home (0,0) translations        */
  123. int        dy_home[4];
  124.  
  125. int        x,y;                    /* current x,y coordinate                    */
  126. double    scale_x, scale_y;        /* scale factors for 2-up, 4-up printing    */
  127. int        real_width;
  128.  
  129. long    *pg_loc;                /* double side print byte ptr to %%Page:    */
  130. int        npg_loc;                /* number of elements in pg_loc[]            */
  131.  
  132. int        book             = 0;    /* book format: double sided                */
  133. int        bookwork        = 0;    /* book format, 2-up print                    */
  134. int        lines_on_page     = 60;    /* user print lines on page                    */
  135. int        lines_total     = 0;    /* total number of lines for scale purposes    */
  136. int        chars_on_line     = 80;    /* default number of chars on line            */
  137. int        landscape         = 0;    /* 1 = landscape, 0 = portrait layout        */
  138. int        header            = 0;    /* 1 = print header at top of each page        */
  139. int        cross              = 0;    /* 1 = print cross on 4-up pages            */
  140. int        line_number        = 0;    /* current logical line number on page        */
  141. int        tab_size           = 8;    /* space translation for tabs.                */
  142. int        font_number     = 0;    /* one of the valid fonts in the printer    */
  143. int        point_size        = 12;    /* can be changed with the -p option        */
  144. int        x_user_offset     = 0;    /* offsets specified buy user                */
  145. int        y_user_offset     = 0;    /* points from physical page edge.            */
  146. int        set_paper_tray     = 0;    /* user has set paper tray selection        */
  147. int        set_line_count     = 0;    /*                print line count on page    */
  148. int        set_total_count    = 0;    /*                total line count on page    */
  149. int        set_point_size     = 0;    /*                point size                    */
  150. int        set_char_count     = 0;    /*                characters on a line        */
  151. int        set_paper_bin    = 0;    /*                paper bin (not page size)    */
  152. char    header_text[100];        /*                header line text            */
  153.  
  154. int        print_attribute = 0;    /* such as BOLD, UNDERLINE, ITALICS            */
  155. int        default_font_number;    /* set with -f option, or 0                    */
  156. int        default_point_size;        /* assumes value due to -p option            */
  157. int        y_coord            = 0;    /* current logical page y-coordinate, points*/
  158. int        x_coord            = 0;    /* current logical page x-coordinate, points*/
  159. int        page_number;            /* current page number for this file        */
  160. int        physical_page     = 0;    /* postscript physical page for multi-up    */
  161. int        print_postscript = 0;     /* force print of postscript                */
  162. int        remove_beginning = 0;    /* remove lines at beginning of job            */
  163. int        remove_between    = 0;    /* remove lines between printed pages        */
  164. int        is_a_formfeed    = 0;    /* skip to top of page caused by formfeed    */
  165. int        end_of_file        = 0;    /* end of printing file                        */
  166. int        save_point_size ;        /* save original point size for headers        */
  167. int        n_chars;                /*    number of characters on a line            */
  168. int        reverse_order    = 0;    /*     print in reverse_order                    */
  169. int        reverse_requested = 0;    /*    user option for reverse order            */
  170. char    fname[100];
  171. char    now[50];                /* time of day for page headers             */
  172.  
  173. #ifdef HOPPER
  174. int        hopper_available = 1;
  175. #else
  176. int        hopper_available = 0;
  177. #endif
  178.  
  179. /*    to select a font, use 4 * font_number + print_attribute as index.
  180.  
  181.     Helvetica-Bold = fonts[4 * 1 + 2]
  182.                    = fonts [4 * 1 + ITALICS | BOLD]
  183.  
  184.     If one of the following fonts is found in "psfprint.def", then it is
  185.     flagged as "available" (fonts_have[i] = 1), if not, it is
  186.     "unavailable". This font list should include all known adobe fonts.
  187. */
  188.       
  189. #define NFONTS      144        /*     4 variations * 36 font families  */
  190.  
  191. int    font_count = 48;        /*    4 * 12 default fonts for fonts below    */
  192. char *fonts[NFONTS] =
  193. {
  194.     /* base font                italics font                bold font                   bold-italics   */
  195.  
  196.     "Courier",                    "Courier-Oblique",            "Courier-Bold",             "Courier-BoldOblique",
  197.     "Helvetica",                 "Helvetica-Oblique",         "Helvetica-Bold",            "Helvetica-BoldOblique",
  198.     "Times-Roman",                 "Times-Italic",             "Times-Bold",                 "Times-BoldItalic",
  199.     "AvantGarde-Book",          "AvantGarde-BookOblique",   "AvantGarde-Demi",          "AvantGarde-DemiOblique",
  200.     "Bookman-Light",            "Bookman-LightItalic",      "Bookman-Demi",             "Bookman-DemiItalic",
  201.     "NewCenturySchlbk-Roman",   "NewCenturySchlbk-Italic",  "NewCenturySchlbk-Bold",    "NewCenturySchlbk-BoldItalic",
  202.     "Palatino-Roman",           "Palatino-Italic",          "Palatino-Bold",            "Palatino-BoldItalic",
  203.     "Helvetica-Narrow",         "Helvetica-Narrow-Oblique", "Helvetica-Narrow-Bold",    "Helvetica-Narrow-BoldOblique",
  204.     "Garamond-Light",            "Garamond-LightItalic",        "Garamond-Bold",            "Garamond-BoldItalic",
  205.     "Korinna-Regular",            "Korinna-KursivRegular",    "Korinna-Bold",                "Korinna-KursivBold",
  206.     "Helvetica-Condensed",        "Helvetica-Condensed-Oblique", "Helvetica-Condensed-Bold", "Helvetica-Condensed-BoldObl",
  207.     "ZapfChancery-MediumItalic","ZapfChancery-MediumItalic","ZapfChancery-MediumItalic","ZapfChancery-MediumItalic"
  208. } ;
  209.  
  210. int    fonts_used[NFONTS];
  211. int    fonts_have[NFONTS];
  212. unsigned char    xlate[256];            /*    translation vector     */
  213. int        need_xlate = 0;                /*    no default xlate    */
  214. char    copyfile[150];                /*    copy file name from psfprint.def */
  215.  
  216. int    max_frame    = 1;        /* max number of frames in use */
  217. int    frame        = -1;        /* current frame in use */
  218.  
  219. FILE    *input_fp, *output_fp;
  220.  
  221. /*    input line and input line pointer */
  222. char    *c;
  223. char    line[LONG_STR + 1];
  224.  
  225. char    *pgmname;
  226.  
  227. void catch();
  228. jmp_buf eof_env;
  229.  
  230. char    *defref = NULL;
  231. FILE    *pdef = NULL;        /*    psfprint.def file    */
  232.  
  233. char *ascii_hex = "0123456789abcdefghijklmnopqrstuvwxyz";
  234. extern int atoi(), getpid();
  235.  
  236. /****************************************************************************
  237. *    main ()                                                                    *
  238. ****************************************************************************/
  239.  
  240. main (argc, argv)
  241. int        argc;
  242. char    *argv[];
  243. {    int        c, i, j, number;
  244.     extern char *optarg;
  245.     extern int    optind, getopt();
  246.     char    bookfile[100];
  247.     char    *env_fname;            /*    environment specified output file */
  248.     char    *getenv();
  249.     int        narrow2x;
  250.     char    alt_cmd[200];
  251.  
  252.     if ((pgmname = strrchr (argv[0], '/'))
  253.             || (pgmname = strrchr (argv[0], '\\'))
  254.             || (pgmname = strrchr (argv[0], ':')))
  255.         pgmname++;
  256.     else
  257.         pgmname = argv[0];
  258.  
  259.     copyfile[0] = 0;
  260.     for (i = 0; i < 256;  i++)            /*    initial xlate = no translation */
  261.         xlate[i] = i;
  262.     for (i = font_count;  i < NFONTS;  i++)
  263.         fonts[i] = "N/A";
  264.  
  265.     for (i = 0;  i < argc;  i++)        /*    if user sets -u alt.def */
  266.     {    if (strncmp (argv[i], "-u", 2) == 0)
  267.         {    if (strlen (argv[i]) > 2)
  268.                 defref = argv[i] + 2;
  269.          else
  270.                 defref = argv[i+1];
  271.             break;
  272.         }
  273.     }
  274.     if (i >= argc)
  275.     {    if ((defref = getenv ("PSFDEF")) == NULL)
  276.             defref = PDEF;
  277.     }
  278.  
  279.     /*    Read the .def file if it exists    */
  280.  
  281.     alt_cmd[0] = '\0';
  282.     if ((pdef = fopen (defref, "r")) != NULL)
  283.     {    char    line_type[50];
  284. #if defined(FORLPD)
  285.         char    *quote, *word;
  286.         int        modified_argv = 0;
  287.  
  288.         /*    read lpd options from psfprint.def.  Format is:
  289.                 *psflpd argv0name opt1 opt2 opt3...
  290.         */            
  291.         while (fgets (alt_cmd, 200, pdef))
  292.         {    if (*alt_cmd == '#')
  293.                 continue;
  294.             alt_cmd[199] = '\0';
  295.             trim (alt_cmd);
  296.             word = strtok (alt_cmd, " \t");
  297.             if (strcmp (word, "*psflpd") == 0)
  298.             {    word = strtok (NULL, " \t");
  299.                 if (strcmp (word, pgmname) == 0)
  300.                 {    argv = (char **) malloc (sizeof (char *) * 50);
  301.                     argv[0] = word;
  302.                     modified_argv = 1;
  303.                     for (argc = 1;  word = strtok (NULL, " \t");  argc++)
  304.                     {    if (*word == '#')    /* quite on comments */
  305.                             break;
  306.                         argv[argc] = word;
  307.                     }
  308.                     argv[argc] = NULL;
  309.                     break;
  310.                 }
  311.             }
  312.             else if (strcmp (word, "*printer") == 0)
  313.                 break;
  314.         }
  315.         if (modified_argv == 0)
  316.         {    argc = 1;
  317.             argv[1] = NULL;
  318.         }
  319.  
  320. #endif    /* FORLPD */
  321.  
  322.         /*    skip to printer definition */
  323.         if (strncmp (alt_cmd, "*printer", 8))
  324.         {    while (fgets (line, 200, pdef))
  325.             {    if (strncmp (line, "*printer", 8) == 0)
  326.                     break;
  327.             }
  328.         }
  329.         nslots = 0;
  330.         fgets (line, 200, pdef);        /*    skip printer name     */
  331.         while (fgets (line, 200, pdef))
  332.         {    trim (line);
  333.             sscanf (line, "%s%d", line_type, &number);
  334.  
  335.             if (strcmp (line_type, "*paper") == 0)
  336.             {    for (i = j = 0;  i < number;  i++)
  337.                 {    if (i >= NPAGE - 1)
  338.                     {    fgets (line, 200, pdef);
  339.                         fgets (line, 200, pdef);
  340.                         fgets (line, 200, pdef);
  341.                         continue;
  342.                     }
  343.                     if (fgets (line, 200, pdef) == NULL)
  344.                         bad_file();
  345.                     line[59] = 0;
  346.                     trim (line);
  347.                     strcpy (page_types[i].paper_name, line);
  348.                     if (fgets (line, 99, pdef) == NULL)
  349.                         bad_file();
  350.                     line[99] = 0;
  351.                     trim (line);
  352.                     strcpy (page_types[i].paper_tray, line);
  353.                     if (fgets (line, 100, pdef) == NULL)
  354.                         bad_file();
  355.                     trim (line);
  356.                     sscanf (line, "%d%d%d%d%d%d",
  357.                         &page_types[i].width, &page_types[i].height,
  358.                         &page_types[i].lx,    &page_types[i].ly,
  359.                         &page_types[i].ux,    &page_types[i].uy);
  360.                     j = i;
  361.                 }
  362.                 page_types[j+1].paper_name[0] = '\0';
  363.             }
  364.                 
  365.             else if (strcmp (line_type, "*order") == 0)
  366.             {    fgets (line, 200, pdef);
  367.                 line[19] = 0;
  368.                 trim (line);
  369.                 strcpy (order_default, line);
  370.                 if (number > 1)
  371.                 {    if (fgets (line, 200, pdef) == NULL)
  372.                         bad_file();
  373.                     trim (line);
  374.                     line[99] = 0;
  375.                     strcpy (order_normal, line);
  376.                     if (fgets (line, 200, pdef) == NULL)
  377.                         bad_file();
  378.                     trim (line);
  379.                     line[99] = 0;
  380.                     strcpy (order_reverse, line);
  381.                 }
  382.             }
  383.             
  384.             else if (strcmp (line_type, "*fonts") == 0)
  385.             {    for (i = 0;  i < NFONTS;  i++)
  386.                     fonts_have[i] = 0;
  387.                 for (i = 0;  i < number;  i++)
  388.                 {    if (fgets (line, 200, pdef) == NULL)
  389.                         bad_file();
  390.                     trim (line);
  391.                     for (j = 0;  j < font_count;  j++)
  392.                     {    if (compare (fonts[j], line) == 0)
  393.                         {    fonts_have[j] = 1;
  394.                             break;
  395.                         }
  396.                     }
  397.                 }
  398.             }
  399.  
  400.             else if (strcmp (line_type, "*slots") == 0)
  401.             {    for (j = 0;  j < NSLOTS;  j++)
  402.                     slots[j][0] = 0;
  403.                 for (i = j = 0;  i < number;  i++)
  404.                 {    if (fgets (line, 200, pdef) == NULL)
  405.                         bad_file();
  406.                     if (i >= NSLOTS)
  407.                         continue;
  408.                     line[99] = 0;
  409.                     trim (line);
  410.                     strcpy (slots[i], line);
  411.                     j = i;
  412.                 }
  413.                 nslots = j + 1;
  414.             }
  415.  
  416.             else if (strcmp (line_type, "*eof") == 0)
  417.                 break;
  418.             else
  419.                 bad_file();
  420.         }
  421.         replacement_fonts ();
  422.     }
  423.     else /* if no .def, assume all fonts exist */
  424.     {    for (i = 0;  i < font_count;  i++)
  425.             fonts_have[i] = 1;
  426.     }
  427.  
  428.     for (i = 0;  page_types[i].paper_name[0];  i++)
  429.     {    page_types[i].left_marg  = page_types[i].lx;
  430.         page_types[i].bot_marg   = page_types[i].ly;
  431.         page_types[i].top_marg   = (page_types[i].height - 1) - page_types[i].uy;
  432.         page_types[i].right_marg = (page_types[i].width  - 1) - page_types[i].ux;
  433.  
  434.         page_types[i].x_size = page_types[i].ux - page_types[i].lx + 1;
  435.         page_types[i].y_size = page_types[i].uy - page_types[i].ly + 1;
  436.     }
  437.         
  438. #ifdef PAPERTYPE
  439.     for (i = 0;  page_types[i].paper_name[0];  i++)
  440.     {    if (strcmp (page_types[i].paper_name, PAPERTYPE) == 0)
  441.         {    p = &page_types[i];
  442.             break;
  443.         }
  444.     }
  445.     if (page_types[i].paper_name[0] == '\0')
  446.         p = &page_types[0];
  447. #else
  448.     p = &page_types[0];            /* default to letter size paper    */
  449. #endif    /* PAPERTYPE */
  450.  
  451.     *header_text = '\0';
  452.     if (argc > 1  &&  (strcmp (argv[1], "-") == 0  || strcmp (argv[1], "--") == 0))
  453.         usage();
  454.  
  455.     narrow2x = 0;
  456.     while ((c = getopt(argc, argv, "124xhnwdvzsi:m:b:c:g:H:l:L:f:t:p:r:R:u:-?")) != -1)
  457.     {    switch (c)
  458.         {
  459.         case '1':
  460.             max_frame = 1;
  461.             break;
  462.             
  463.         case '2':
  464.             if (narrow2x == 0)
  465.                 landscape = 1;
  466.             max_frame = 2;
  467.             break;
  468.         
  469.         case '4':
  470.             max_frame = 4;
  471.             break;
  472.             
  473.         case 'b':
  474.             if ((set_paper_bin = atoi (optarg)) > nslots)
  475.             {    if (nslots = 0)
  476.                     fprintf (stderr, "%s: no alternate bins permitted\n", nslots);
  477.                 else
  478.                     fprintf (stderr, "%s: paper bin greater than %d\n", pgmname, nslots);
  479.                 exit (1);
  480.             }
  481.             break;
  482.  
  483.         case 'c':
  484.             chars_on_line = atoi (optarg);
  485.             set_char_count = 1;
  486.             break;
  487.  
  488.         case 'd':
  489.             book = 1;
  490.             break;
  491.                     
  492.         case 'f':
  493.             if (*optarg > '9'  &&  optarg[1])        /*    at least 2 chars */
  494.             {    /*    character string name of font */
  495.                 for (i = 0;  i < font_count;  i += 4)
  496.                 {    if (partial_compare (optarg, fonts[i]) == 0)
  497.                     {    font_number =  i / 4;
  498.                         break;
  499.                     }
  500.                 }
  501.                 if (i >= font_count)
  502.                     font_number = 0;
  503.             }
  504.             else
  505.             {    /*    single digit hex */
  506.                 font_number = xtoi ((int) *optarg);
  507.                 if (font_number > (font_count / 4))
  508.                     font_number = 0;
  509.             }
  510.             break;
  511.  
  512.         case 'g':
  513.             p = NULL;
  514.             for (i = 0;  page_types[i].paper_name[0];  i++)
  515.             {    if (compare (optarg, page_types[i].paper_name) == 0)
  516.                 {    p = &page_types[i];
  517.                     break;
  518.                 }
  519.             }
  520.             if (p == NULL)
  521.                 usage ();
  522.             set_paper_tray = 1;
  523.             break;
  524.  
  525.         case 'h':
  526.             header = 1;
  527.             break;
  528.  
  529.         case 'H':
  530.             header = 2;
  531.             strcpy (header_text, optarg);
  532.             break;
  533.  
  534.         case 'i':
  535.             x_user_offset = atoi (optarg);
  536.             break;
  537.  
  538.         case 'l':
  539.             lines_on_page = atoi (optarg);
  540.             set_line_count = 1;
  541.             break;
  542.  
  543.         case 'L':
  544.             lines_total = atoi (optarg);
  545.             set_total_count = 1;
  546.             break;
  547.  
  548.         case 'm':
  549.             y_user_offset = atoi (optarg);
  550.             break;
  551.  
  552.         case 'n':
  553.             landscape = 0;
  554.             narrow2x = 1;
  555.             break;
  556.  
  557.         case 'p':
  558.             point_size = atoi (optarg);
  559.             set_point_size = 1;
  560.             break;
  561.  
  562.         case 'r':
  563.             remove_between = atoi (optarg);
  564.             break;
  565.         
  566.         case 'R':
  567.             remove_beginning = atoi (optarg);
  568.             break;
  569.             
  570.         case 's':
  571.             size_display();
  572.             exit (1);
  573.     
  574.         case 't':
  575.             tab_size = atoi (optarg);
  576.             break;
  577.             
  578.         case 'u':        /* already processed */
  579.             break;
  580.  
  581.         case 'v':
  582.             reverse_requested = 1;
  583.             break;
  584.  
  585.         case 'w':
  586.             landscape = 1;
  587.             break;
  588.             
  589.         case 'x':
  590.             cross = 1;
  591.             break;
  592.  
  593.         case 'z':
  594.             print_postscript = 1;
  595.             break;
  596.  
  597.         default:    usage ();
  598.             break;
  599.         }
  600.     }
  601.  
  602.     if (strncmp (order_default, "Reverse", 7) == 0)        /*    stacking sequence         */
  603.         reverse_order = 1;                                /*    "Reverse"                */
  604.     else
  605.         reverse_order = 0;                                /*    "Normal"                */
  606.     if (reverse_requested)                                /*    User wants reverse ?    */
  607.         reverse_order = !reverse_order;                    /*        yes                    */
  608.     if (reverse_order  &&  order_reverse[0])            /*    Reverse tray command     */
  609.     {    order_command = order_reverse;                    /*        yes                    */
  610.         reverse_order = 0;                                /*        order_command does the work*/
  611.     }
  612.     else if (reverse_order == 0  &&  order_normal[0])    /*    Force normal order tray?*/
  613.         order_command = order_normal;                    /*        yes                    */
  614.     else
  615.         order_command = NULL;                            /*    use default action         */
  616.  
  617.     if (reverse_requested && book)
  618.     {    fprintf (stderr, "Double sided or book in reverse ordered not supported\n");
  619.         exit (1);
  620.     }
  621.  
  622.  
  623.     if (nslots <= 1)
  624.         hopper_available = 0;
  625.     if (reverse_order  ||  (book  &&  hopper_available))
  626.         sprintf (bookfile, "%s%d.bok", TEMPFILE, getpid());
  627.     else
  628.         strcpy (bookfile, BOOKFILE);
  629.  
  630.     if (max_frame == 2  &&  landscape == 0)
  631.         set_point_size = 1;
  632.     if (optind >=  argc  &&  header == 1)    /* no file name header on stdin */
  633.         header = 0;
  634.     save_point_size = point_size;
  635.     
  636.     (void)    signal (SIGINT, catch);        /*    for lpd quit */
  637.  
  638.  
  639. #ifdef PSFFILTER
  640.  
  641.     output_fp = stdout;
  642.     input_fp  = stdin;
  643.     if (header == 1)
  644.         strcpy (fname, argv[optind]);
  645.     else
  646.         *fname = 0;    
  647.  
  648.     if (fgets (line, LONG_STR, input_fp) == NULL)
  649.         exit (0);
  650.     if (tscan (line, "%!") >= 0  &&  print_postscript == 0)
  651.     {    /*    already postscript  copy to output */
  652.         if (fputs (line, output_fp) == EOF)
  653.             output_trouble (2);
  654.         while ((i = fgetc (input_fp)) != EOF)
  655.         {    if (fputc (i, output_fp) == EOF)
  656.                 output_trouble (2);
  657.         }
  658.     }
  659.     else
  660.     {    /*    standard postscript conversion for file on stdin */
  661. bannerdone:
  662.         if (font_number * 4 > font_count)
  663.         {    fprintf (stderr,"Font number invalid....\n");
  664.             usage ();
  665.         }
  666.  
  667.         if (book  ||  reverse_order)
  668.         {    if ((output_fp = fopen (bookfile, "w")) == NULL)
  669.             {    fprintf (stderr, "%s: cannot create work file\n", pgmname);
  670.                 exit (1);
  671.             }
  672.             if ((pg_loc = (long *) malloc (sizeof (long) * MAX_PAGES)) == NULL)
  673.             {    fprintf (stderr, "%s: cannot allocate enough memory\n", pgmname);
  674.                 exit (1);
  675.             }
  676.             npg_loc = 0;
  677.         }
  678.  
  679.         for (i = 0;  i < NFONTS;  i++)
  680.             fonts_used[i] = 0;
  681.  
  682.         page_number = -1;
  683.         line_number = 32000;
  684.         default_point_size = point_size;
  685.         default_font_number = font_number;
  686.         bookwork = book  &&  landscape  &&  (max_frame == 2);
  687.  
  688.         input_fp = stdin;
  689.         get_time (now);        
  690.         scale_factors ();
  691.         prologue ();
  692.         start_file ();
  693.         process_file ();
  694.         terminate_printer ();
  695.         output_book (bookfile);
  696.     }
  697.  
  698. #else    /* not PSFFILTER */
  699.  
  700.     /*    begin normal "psf" code */
  701.  
  702.     if (font_number * 4 > font_count)
  703.     {    fprintf (stderr,"Font number invalid....\n");
  704.         usage ();
  705.     }
  706.  
  707.     if (book  ||  reverse_order)
  708.     {    if ((output_fp = fopen (bookfile, "w")) == NULL)
  709.         {    fprintf (stderr, "%s: cannot create work file\n", pgmname);
  710.             exit (1);
  711.         }
  712.         if ((pg_loc = (long *) malloc (sizeof (long) * MAX_PAGES)) == NULL)
  713.         {    fprintf (stderr, "%s: cannot allocate enough memory\n", pgmname);
  714.             exit (1);
  715.         }
  716.         npg_loc = 0;
  717.     }
  718.     else    
  719.     {    if (env_fname = getenv ("PSFLP"))
  720. #if defined(MSDOS)  ||  defined (__MSDOS__)
  721.         {    if ((output_fp = fopen (env_fname, "wt")) == NULL)
  722. #else
  723.         {    if ((output_fp = fopen (env_fname, "w")) == NULL)
  724. #endif
  725.             {    fprintf (stderr, "Cannot open output file %s\n", env_fname);
  726.                 exit (1);
  727.             }
  728.         }
  729.         else
  730.         {    output_fp = stdout;
  731.         }
  732.     }
  733.  
  734.  
  735.     for (i = 0;  i < NFONTS;  i++)
  736.         fonts_used[i] = 0;
  737.  
  738.     page_number = -1;
  739.     line_number = 32000;
  740.     default_point_size = point_size;
  741.     default_font_number = font_number;
  742.     bookwork = book  &&  landscape  &&  (max_frame == 2);
  743.     *fname = 0;    
  744.  
  745.     get_time (now);        
  746.     scale_factors ();
  747.     prologue ();
  748.     if (optind >=  argc)                        /*    process on stdin */
  749.     {    input_fp = stdin;
  750.         start_file ();
  751.         process_file ();
  752.     }
  753.     else 
  754.     {    for ( ;  optind < argc;  optind++)        /*    files from cmd line */
  755.         {    strcpy (fname, argv[optind]);
  756.             if ((input_fp = fopen (argv[optind], "r")) == NULL)
  757.             {    fprintf (stderr, "Unknown file: %s\n", argv[optind]);
  758.                 continue;
  759.             }
  760.             start_file ();
  761.             process_file ();
  762.             fclose (input_fp);
  763.         }
  764.     }
  765.     terminate_printer ();
  766.  
  767.     output_book (bookfile);
  768.     /*    end normal psf code */
  769.  
  770. #endif    /* PSFFILTER */
  771.  
  772.     exit (0);
  773. }
  774.  
  775.  
  776. /****************************************************************************
  777. *    scale_factors ()                                                        *
  778. *    Compute the x and y scale factors.                                        *
  779. ****************************************************************************/
  780.  
  781. /*                    total paper size - unprintable size
  782.     scale factor = --------------------------------------
  783.                             print size
  784. */
  785.  
  786. void scale_factors ()
  787. {    int    wide;                /*    width needed for char count            */
  788.     int    high;                /*    points needed for line count        */
  789.     int    n_lines;            /*    number of lines on a page            */
  790.     int    i;
  791.     double    char_width, scale;
  792.     double    char_sf, line_sf;
  793.     int        nominal_high, nominal_wide;
  794.     int        on_portrait;
  795.  
  796.     /*    use either the "portrait" or landscape width/height for basic scaling
  797.     */
  798.     switch (max_frame)
  799.     {
  800.     case 1:    on_portrait = 0;
  801.             break;
  802.     case 2: if (landscape)
  803.                 on_portrait = 1;
  804.             else
  805.                 on_portrait = 0;
  806.             break;
  807.     case 4: if (landscape)
  808.                 on_portrait = 0;
  809.             else
  810.                 on_portrait = 1;
  811.     }
  812.  
  813.     real_width = p->width;        /* for initial axis translate only    */
  814.  
  815.     /*    if 4up in portrait or 2up, we want to shrink the image as
  816.         though it were a proper 8.5x11 page.  thus do all calculations
  817.         of line and column count as though it were a normal portrait page.
  818.     */
  819.     if (on_portrait)
  820.     {    nominal_high = p->y_size;
  821.         nominal_wide = p->x_size;
  822.     }
  823.     if (landscape)
  824.     {
  825.         i = p->height;      p->height    = p->width;        p->width      = i;
  826.         i = p->left_marg;   p->left_marg = p->bot_marg;     p->bot_marg   = i;
  827.         i = p->top_marg;    p->top_marg  = p->right_marg;   p->right_marg = i;
  828.         i = p->lx;            p->lx        = p->ly;            p->ly          = i;
  829.         i = p->ux;            p->ux        = p->uy;            p->uy          = i;
  830.         i = p->x_size;        p->x_size    = p->y_size;        p->y_size      = i;
  831.     }
  832.     if (on_portrait == 0)
  833.     {    nominal_high = p->y_size;
  834.         nominal_wide = p->x_size;
  835.     }
  836.  
  837.     if (set_point_size)
  838.     {    /*    if point size specified, ignore changes to rows and columns
  839.             with -L, -l & -c.  They destroy character shape.
  840.         */
  841.         char_width = point_size / 12.0 * NOMINAL_CWIDE;
  842.         n_chars = ceil ((double) nominal_wide / (double) char_width);
  843.         n_lines = (double) nominal_high / (double) point_size;
  844.         char_sf = 1.0;
  845.         line_sf = 1.0;
  846.  
  847.         if (set_total_count == 0  ||  lines_total > n_lines)
  848.             lines_total = n_lines;
  849.         if (set_line_count == 0  ||  lines_on_page > n_lines)
  850.             lines_on_page = n_lines;
  851.         if (lines_total < lines_on_page)
  852.             lines_on_page = lines_total;
  853.         if (header)                /* compress scale to allow headers */
  854.         {    lines_on_page += 2;
  855.             lines_total += 2;
  856.             line_sf = (double) n_lines / (double) lines_total;
  857.         }
  858.     }
  859.     else
  860.     {    /*    determine independent scale factors to lines and columns
  861.             based on user line and column count. This changes
  862.             the character aspect ration - squashing it vertically
  863.             and/or horizontally.
  864.         */
  865.         char_width = NOMINAL_CWIDE;
  866.         n_chars = ceil ((double) nominal_wide / (double) char_width);
  867.  
  868.         if (set_char_count)
  869.             char_sf = (double) n_chars / (double) chars_on_line;
  870.         else
  871.         {    char_sf = 1.0;                /*    no change to char count */
  872.             chars_on_line = n_chars;
  873.         }
  874.  
  875.         n_lines = (double) nominal_high / (double) point_size;
  876.  
  877.         if (set_total_count == 0)
  878.             lines_total = n_lines;
  879.         if (set_line_count == 0)
  880.             lines_on_page = n_lines;
  881.         if (lines_total < lines_on_page)
  882.         {    if (set_total_count)
  883.                 lines_on_page = lines_total;
  884.             else
  885.                 lines_total = lines_on_page;
  886.         }
  887.         if (header)                /* compress scale to allow headers */
  888.         {    lines_on_page += 2;
  889.             lines_total += 2;
  890.         }
  891.         line_sf = (double) n_lines / (double) lines_total;
  892.     }
  893.  
  894.     /*    theoretical points high and wide that we would "like" to
  895.         have for our page - before scaling - including a 1/2 line
  896.         for descenders for the last line.
  897.     */
  898.     high = ceil ((double) point_size * ((double) n_lines + 0.51));
  899.     wide = ceil (n_chars * char_width);
  900.  
  901.     x_user_offset = max (0, x_user_offset - p->left_marg);
  902.     y_user_offset = max (0, y_user_offset - p->top_marg );
  903.  
  904.     switch (max_frame)
  905.     {
  906.     case 1:
  907.         scale_x = (double) (p->x_size) / (double) wide * char_sf;
  908.         scale_y = (double) (p->y_size) / (double) high * line_sf;
  909.         x_left_offset  = (int) ceil ((double) (p->left_marg + x_user_offset) / scale_x);
  910.         y_top_offset   = (int) ceil ((double) (p->top_marg  + y_user_offset) / scale_y);
  911.         dx_home[0] = 0;
  912.         dy_home[0] = 0;
  913.         p->height = ceil ((double) p->height / scale_y);
  914.         p->width  = ceil ((double) p->width / scale_x);
  915.         p->bot_marg = ceil ((double) p->bot_marg / scale_y);
  916.         break;
  917.  
  918.     case 2:
  919.         scale_x = (double) (p->width - 2 * p->left_marg - 2 * p->right_marg)
  920.                 / (double) (2 * wide) * char_sf;
  921.         scale_y = (double) (p->y_size) / (double) high * line_sf;
  922.  
  923.         if (landscape == 0)
  924.         {    scale_y /= 2.0;
  925.             lines_total *= 2.0;
  926.             lines_on_page *= 2.0;
  927.         }
  928.  
  929.         /*    point offsets for margins account for physical "forbidden" area */
  930.  
  931.         x_left_offset  = (int) ceil ((double) p->left_marg / scale_x);
  932.         y_top_offset   = (int) ceil ((double) p->top_marg / scale_y);
  933.  
  934.         /*    page origin translation vectors    */
  935.  
  936.         p->height = ceil ((double) p->height / scale_y);
  937.         p->width  = ceil ((double) p->width  / (scale_x * 2.0));
  938.         p->bot_marg = ceil ((double) p->bot_marg / scale_y);
  939.         dx_home[0] = 0;
  940.         dy_home[0] = 0;
  941.         dx_home[1] = p->width;
  942.         dy_home[1] = 0;
  943.         break;
  944.     
  945.     case 4:
  946.         scale_x = (double) (p->width - 2 * p->left_marg - 2 * p->right_marg)
  947.                 / (double) (2 * wide) * char_sf;
  948.         scale_y = (double) (p->height - 2 * p->top_marg - 2 * p->bot_marg)
  949.                 / (double) (2 * high) * line_sf;
  950.  
  951.         /*    point offsets for margins account for physical "forbidden" area */
  952.  
  953.         x_left_offset = (int) ceil ((double) p->left_marg / scale_x);
  954.         y_top_offset  = (int) ceil ((double) p->top_marg / scale_y);
  955.  
  956.         /*    page origin tranlsation vectors    */
  957.  
  958.         p->height = ceil ((double) p->height / (scale_y * 2.0));
  959.         p->width  = ceil ((double) p->width  / (scale_x * 2.0));
  960.         p->bot_marg = ceil ((double) p->bot_marg / scale_y);
  961.         dx_home[0] = 0;
  962.         dy_home[0] = p->height;
  963.         dx_home[1] = p->width;
  964.         dy_home[1] = 0;
  965.         dx_home[2] = -p->width;
  966.         dy_home[2] = -p->height;
  967.         dx_home[3] = p->width;
  968.         dy_home[3] = 0;
  969.         break;
  970.  
  971.     default: ;
  972.     }
  973.  
  974.     if (max_frame > 1)
  975.     {    x_left_offset += x_user_offset;
  976.         y_top_offset  += y_user_offset;
  977.     }
  978. }
  979.  
  980.  
  981. /****************************************************************************
  982. *    prologue ()                                                                *
  983. *    generate the require postscript-conformant prologue                        *
  984. ****************************************************************************/
  985.  
  986. void prologue ()
  987. {    char    *getlogin(), *me;
  988.     int        c;
  989.     FILE    *fp;
  990.  
  991.     if (book  || reverse_order)
  992.         fprintf (output_fp, "%%Book file: psf-to-psfdoub\n");
  993.     else
  994.         fprintf (output_fp, "%%!PS-Adobe-\n");
  995. #if !defined(MSDOS)  && !defined(__MSDOS__)
  996.     me = getlogin();
  997.     if (me == NULL)                /* AT&T Unix 3.2 getlogin() is broken */
  998. #endif
  999.       me = "psf";                /* could use cuserid() instead        */
  1000.     fprintf (output_fp, "%%%%Creator: %s\n", me);
  1001.     fprintf (output_fp, "%%%%CreationDate: %s\n", now);
  1002.     fprintf (output_fp, "%%%%DocumentFonts: (atend)\n");
  1003.     fprintf (output_fp, "%%%%Pages: (atend)\n");
  1004.     fprintf (output_fp, "%%%%EndComments\n");
  1005.  
  1006.     /*    usage:         (text to underline) <pointsize> showuline
  1007.         where:        <pointsize> is current text point size.
  1008.  
  1009.         eg:            (text to underline) 12 showuline
  1010.     */
  1011.     fprintf (output_fp, "%s%s%s%s%s%s%s%s%s%s%s",
  1012.             "/showuline {\n",
  1013.             "    /CurPointSize exch def\n",
  1014.             "    dup stringwidth pop\n",
  1015.             "    gsave\n",
  1016.             "    currentfont /FontInfo get dup\n",
  1017.             "    /UnderlinePosition get CurPointSize mul 1000 div 0 exch rmoveto exch 0 rlineto\n",
  1018.             "    /UnderlineThickness get CurPointSize mul 1000 div setlinewidth stroke\n",
  1019.             "    grestore\n",
  1020.             "    show\n",
  1021.             "} def\n",
  1022.             "/mv {moveto} def\n");
  1023.  
  1024.     /*    add additional startup prologue code from psfprint.def
  1025.         probably for non-English language support.
  1026.     */
  1027.     if (pdef)
  1028.     {    while (fgets (line, LONG_STR, pdef))
  1029.         {    if (fputs (line, output_fp) == EOF)
  1030.                 output_trouble (2);
  1031.         }
  1032.         fclose (pdef);
  1033.         pdef = NULL;
  1034.     }
  1035.     
  1036.     /*    copy a copyfile requested from psfprint.def */
  1037.     
  1038.     if (copyfile[0])
  1039.     {    if (fp = fopen (copyfile, "r"))
  1040.         {    while (1)
  1041.             {    c = fgetc (fp);
  1042.                 if (feof (fp)  ||  ferror (fp))
  1043.                     break;
  1044.                 if (fputc (c, fp) == EOF)
  1045.                     output_trouble (2);
  1046.             }
  1047.             fclose (fp);
  1048.         }
  1049.     }
  1050.         
  1051.     fprintf (output_fp, "%%%%EndProlog\n");
  1052.  
  1053.     if (set_paper_tray)
  1054.         fprintf (output_fp, "%s\n", p->paper_tray);
  1055.  
  1056.     if (order_command)
  1057.         fprintf (output_fp, "%s\n", order_command);
  1058.     else if (set_paper_bin)
  1059.         fprintf (output_fp, "%s\n", slots[set_paper_bin - 1]);
  1060. }
  1061.  
  1062. /****************************************************************************
  1063. *    showpage ()                                                                *
  1064. *    Generate a real "showpage" if we have really finished generating a        *
  1065. *    physical page.  If we are processing 2 or 4 up, then generate             *
  1066. *    coordinate "translates" if we really haven't finished all possible        *
  1067. *    page frames of the page.                                                *
  1068. ****************************************************************************/
  1069.  
  1070. void showpage (end_of_file)
  1071. int end_of_file;
  1072. {    int        skipping;
  1073.  
  1074.     line_number = 0;
  1075.  
  1076.     if (max_frame > 1)
  1077.         fprintf (output_fp, "grestore\n");
  1078.  
  1079.     if (is_a_formfeed)            /*    don't skip if caused by form feed */
  1080.         is_a_formfeed = 0;        /*    needed for lpr of= processing      */
  1081.     else if (page_number > 0  &&  end_of_file == 0)
  1082.     {    skipping = remove_between;
  1083.         while (skipping--  &&  fgets (line, LONG_STR, input_fp))
  1084.             ;
  1085.         if (skipping >= 0)
  1086.         {    end_of_file = 1;
  1087.             if (bookwork == 0)                /* psfdoub will re-insert this */
  1088.                 fprintf (output_fp, "showpage pg restore\n");
  1089.             frame = 0;
  1090.             longjmp (eof_env, 1);
  1091.         }
  1092.     }
  1093.  
  1094.     if (++frame >= max_frame  ||  end_of_file)
  1095.     {    if (bookwork == 0)                    /* psfdoub will re-insert this */
  1096.             fprintf (output_fp, "showpage pg restore\n");
  1097.         frame = 0;
  1098.     }
  1099.     if (!end_of_file)
  1100.         set_frame ();
  1101.     
  1102. }
  1103.  
  1104. /****************************************************************************
  1105. *    set_frame ()                                                            *
  1106. *    Select the next logical frame in two-up or four-up mode.  If it is        *
  1107. *    the first frame of a physical page, the generate the %%Page                *
  1108. ****************************************************************************/
  1109.  
  1110. void set_frame ()
  1111. {
  1112.     if (frame == 0  ||  bookwork)
  1113.     {    if (book || reverse_order)        /*    mark byte position of %%Page: for psfdoub  */
  1114.         {    pg_loc[npg_loc++] = ftell (output_fp);
  1115.         }
  1116.         fprintf (output_fp, "%%%%Page: ? %d\n", ++physical_page);
  1117.         if (bookwork == 0)                    /* psfdoub will re-insert these */
  1118.         {    fprintf (output_fp, "/pg save def\n");
  1119.             if (landscape)
  1120.                 fprintf (output_fp, "90 rotate 0 %d translate\n", -real_width);
  1121.             fprintf (output_fp, "%.5f %.5f scale\n", scale_x, scale_y);
  1122.         }
  1123.         findfont();
  1124.     }
  1125.  
  1126.     set_y_coord ();
  1127.  
  1128.     if (max_frame > 1  &&  bookwork == 0)
  1129.         fprintf (output_fp, "%d %d translate\n", dx_home[frame], dy_home[frame]);
  1130.  
  1131.     if (frame == 0  &&  cross)
  1132.         draw_cross();
  1133.  
  1134.     if (max_frame > 1)
  1135.     {    fprintf (output_fp, "gsave\n");
  1136.         set_clip_path (0, 0, p->width, p->height);
  1137.     }
  1138. }
  1139.  
  1140.  
  1141. /****************************************************************************
  1142. *    set_y_coord                                                                *
  1143. *    position next line to the top of a logical page.                        *
  1144. *****************************************************************************/
  1145.  
  1146. void set_y_coord ()
  1147. {
  1148.     y_coord = p->height - y_top_offset - point_size;
  1149. }
  1150.  
  1151. /****************************************************************************
  1152. *    put_top                                                                    *
  1153. *    put a header line at the top of the page                                *
  1154. *****************************************************************************/
  1155.  
  1156. void put_top ()
  1157. {    int    save_attr, save_point, nc;
  1158.     char    fmt[50], *hd;
  1159.     
  1160.     save_attr = print_attribute;
  1161.     save_point = point_size;
  1162.     print_attribute = BOLD;
  1163.     point_size = save_point_size;
  1164.  
  1165.     hd = (header == 1) ? fname : header_text;
  1166.     nc = n_chars - 33;
  1167.     if (nc < strlen (hd))
  1168.         nc = strlen (hd) + 3;
  1169.     sprintf (fmt, "(%%-%ds%%3d     %%s)show\n", nc);
  1170.  
  1171.     findfont();
  1172.     moveto (0, y_coord, 1);
  1173.     fprintf (output_fp, fmt, hd, page_number + 1, now);
  1174.     y_coord -= point_size * 2;
  1175.     x_coord = 0;
  1176.     print_attribute = save_attr;
  1177.     point_size = save_point;
  1178.     findfont();
  1179. }
  1180.  
  1181. /****************************************************************************
  1182. *    process_file()                                                            *
  1183. *    Read the file, look for escape sequences, put text in postscript form    *
  1184. ****************************************************************************/
  1185.  
  1186. void process_file ()
  1187. {    int        char_type, char_count, i, set_page, esc_type;
  1188.     char    *strchr ();
  1189.     int        previous_attribute;
  1190.     int        lcount = 0;
  1191.     unsigned char    *xln;
  1192.  
  1193.     set_page = 0;
  1194.     i = remove_beginning;
  1195.     while (i--  &&  fgets (line, LONG_STR, input_fp))
  1196.         ;
  1197.     if (i >= 0)
  1198.     {    showpage (1);
  1199.         return;
  1200.     }
  1201.  
  1202.     if (setjmp (eof_env))
  1203.     {    return;
  1204.     }
  1205.  
  1206. #ifdef PSFFILTER
  1207.     /*    psffilter already has a first line,  psf does not */
  1208.     do
  1209. #else
  1210.     while (fgets (line, LONG_STR, input_fp) != NULL)
  1211. #endif
  1212.     {
  1213.         if (*line == CTLD_EOJ)        /* printing postscript code: ^D at end    */
  1214.             break;                    /* assume it is end of file also        */
  1215.  
  1216.         if (lcount++ == 0)
  1217.         {    if ((i = tscan (line, "ta=")) >= 0)
  1218.             {    tab_size = atoi (line + i + 3);
  1219.             }
  1220.         }
  1221.  
  1222.         if (need_xlate)                /*    translate character set? */
  1223.         {    xln = (unsigned char *) line;
  1224.             while (*xln)
  1225.             {    i = *xln;
  1226.                 *xln++ = xlate[i];
  1227.             }
  1228.         }
  1229.  
  1230.         if ((c = strchr (line, '\f')) != NULL)
  1231.         {    if (c == line)
  1232.             {    line_number = 32000;
  1233.                 c = line + 1;
  1234.             }
  1235.             else
  1236.             {    *c = 0;
  1237.                 set_page = 1;
  1238.                 c = line;
  1239.             }
  1240.             is_a_formfeed = 1;
  1241.         }
  1242.         else
  1243.             c = line;
  1244.  
  1245.         if (line_number >= lines_on_page * 10)
  1246.         {    page_number++;
  1247.             showpage (0);
  1248.             line_number = 10;
  1249.             if (header)
  1250.             {    put_top();
  1251.                 line_number += 20;
  1252.             }
  1253.         }
  1254.         else
  1255.             line_number += 10;
  1256.  
  1257.         char_type = char_count = 0;
  1258.  
  1259.         /*    for empty lines, don't generate a real moveto - but to call
  1260.             to ensure that check for page overflow is done.
  1261.         */
  1262.         if (*c == '\n')
  1263.             moveto (x_coord, y_coord, 0);        /*    don't gen moveto    */
  1264.         else
  1265.             moveto (x_coord, y_coord, 1);        /*    do gen moveto        */
  1266.  
  1267.         while (*c  && *c != '\n')
  1268.         {    if (char_type == 0)
  1269.             {    if (fputc ('(', output_fp) == EOF)
  1270.                     output_trouble (2);
  1271.             }
  1272.             switch ((int) *c)
  1273.             {
  1274.             case ESCAPE:
  1275.                 previous_attribute = print_attribute;
  1276.                 esc_type = *(++c);
  1277.                 if (escape_sequence (esc_type) == 0)
  1278.                 {    switch (esc_type)
  1279.                     {
  1280.                     case 'u':
  1281.                         SHOWU (output_fp, point_size);
  1282.                         break;
  1283.  
  1284.                     default:
  1285.                         if (char_type  &&  (previous_attribute & UNDERLINE))
  1286.                             SHOWU (output_fp, point_size);
  1287.                         else
  1288.                         {    if (fputs (")show\n", output_fp) == EOF)
  1289.                                 output_trouble (2);
  1290.                         }
  1291.                         if (esc_type == '+'  ||  esc_type == '-')
  1292.                         {    /*    check for +/- 1/2 line feed        */
  1293.                             if (esc_type == '+')
  1294.                                 y_coord -= point_size / 2;
  1295.                             else
  1296.                                 y_coord += point_size / 2;
  1297.                             moveto (x_coord, y_coord, 1);
  1298.                             char_type = -1;
  1299.                             c++;
  1300.                             if (*c != '\n')
  1301.                             {    if (fputc ('(', output_fp) == EOF)
  1302.                                     output_trouble (2);
  1303.                             }
  1304.                             continue;
  1305.                         }
  1306.                         else
  1307.                             findfont ();
  1308.                     }
  1309.                     char_type = 0;
  1310.                 }
  1311.                 break;
  1312.  
  1313.             default:
  1314.                 if (*c == '\t')
  1315.                 {    fputc (' ', output_fp);
  1316.                     while (++char_count % tab_size)
  1317.                     {    if (fputc (' ', output_fp) == EOF)
  1318.                             output_trouble (2);
  1319.                     }
  1320.                 }
  1321.                 else
  1322.                 {    if (strchr ("\r\b\\()", *c) != NULL)
  1323.                     if (fputc ('\\', output_fp) == EOF)
  1324.                         output_trouble (2);
  1325.                     if (fputc (*c, output_fp) == EOF)
  1326.                         output_trouble (2);
  1327.                     char_count++;
  1328.                 }
  1329.                 char_type = 1;
  1330.                 break;
  1331.             }
  1332.             c++;
  1333.         }
  1334.         if (char_type == 1)
  1335.         {    if (print_attribute & UNDERLINE)
  1336.                 SHOWU (output_fp, point_size);
  1337.             else
  1338.             {    if (fputs (")show\n", output_fp) == EOF)
  1339.                     output_trouble (2);
  1340.             }
  1341.         }
  1342.  
  1343.         y_coord -= point_size;
  1344.         x_coord = 0;
  1345.         if (set_page)
  1346.         {    line_number = 32000;
  1347.             set_page = 0;
  1348.         }
  1349. #ifdef PSFFILTER
  1350.     } while (fgets (line, LONG_STR, input_fp) != NULL);
  1351. #else
  1352.     }
  1353. #endif
  1354.     if (end_of_file == 0)
  1355.         showpage (1);
  1356. }
  1357.  
  1358. /****************************************************************************
  1359. *    escape_sequence ()                                                        *
  1360. *    If an escape sequence (esc,char) is found, mark which type of font        *
  1361. ****************************************************************************/
  1362.  
  1363. int escape_sequence (which)
  1364. int    which;
  1365. {    char    s[10];
  1366.  
  1367.     switch (which)
  1368.     {
  1369.     case 'I':
  1370.         print_attribute |= ITALICS;
  1371.         break;
  1372.  
  1373.     case 'i':
  1374.         print_attribute &= ~ITALICS;
  1375.         break;
  1376.  
  1377.     case 'B':
  1378.         print_attribute |= BOLD;
  1379.         break;
  1380.  
  1381.     case 'b':
  1382.         print_attribute &= ~BOLD;
  1383.         break;
  1384.  
  1385.     case 'U':
  1386.         print_attribute |= UNDERLINE;
  1387.         break;
  1388.  
  1389.     case 'u':
  1390.         print_attribute &= ~UNDERLINE;
  1391.         break;
  1392.  
  1393.     case 'F':
  1394.         s[0] = *(++c);
  1395.         s[1] = '\0';
  1396.         font_number = xtoi ((int) *s);        
  1397.         if (font_number > (font_count / 4))
  1398.             font_number = (font_count / 4) - 1;
  1399.         break;
  1400.  
  1401.     case 'f':
  1402.         font_number = default_font_number;
  1403.         break;
  1404.  
  1405.     case 'P':
  1406.         s[0] = *(++c);
  1407.         s[1] = *(++c);
  1408.         s[2] = '\0';
  1409.         point_size = atoi (s);
  1410.         break;
  1411.  
  1412.     case 'p':
  1413.         point_size = default_point_size;
  1414.         break;
  1415.  
  1416.     case '+':
  1417.     case '-':
  1418.         break;
  1419.  
  1420.     default:
  1421.         return (-1);
  1422.         ;
  1423.     }
  1424.     return (0);
  1425. }
  1426.  
  1427. /****************************************************************************
  1428. *    moveto ()                                                                *
  1429. *    Generate a postscript     x y moveto    statememt                        *
  1430. ****************************************************************************/
  1431.  
  1432. void moveto (x, y, do_move)
  1433. int    x;
  1434. int    y;
  1435. int do_move;            /*    1 = gen moveto     0 = dont gen moveto    */
  1436. {
  1437.     /*    ensure that the current line can fit on the page - including the
  1438.         1/4 line needed for the decenders
  1439.     */
  1440.  
  1441.     if (line_number > lines_on_page * 10  ||  y < (p->bot_marg + point_size / 3))
  1442.     {    if (line_number < lines_on_page * 10)
  1443.             page_number++;
  1444.         showpage (0);
  1445.         if (header)
  1446.         {    put_top();
  1447.             line_number += 20;
  1448.         }
  1449.         y = y_coord;
  1450.         x = x_coord;
  1451.     }
  1452.  
  1453.     if (do_move)
  1454.         fprintf (output_fp, "%d %d mv ", x + x_left_offset, y);
  1455. }
  1456.  
  1457. /****************************************************************************
  1458. *    findfont ()                                                                *
  1459. *    generate a findfont statement                                            *
  1460. ****************************************************************************/
  1461.  
  1462. void findfont ()
  1463. {    int    this;
  1464.  
  1465.     /*    remove reference to UNDERLINE.  Underline is not a font.    */
  1466.  
  1467.     this = (font_number * 4) + (print_attribute & 0x03);
  1468.     fonts_used[this] = 1;
  1469.     fprintf (output_fp, "/%s findfont %d scalefont setfont\n", fonts[this], point_size);
  1470. }
  1471.  
  1472. /****************************************************************************
  1473. *    start_file ()                                                            *
  1474. *    Generate things that are appropriate for beginning of file processing    *
  1475. ****************************************************************************/
  1476.  
  1477. void start_file ()
  1478. {
  1479.     end_of_file = 0;
  1480.     line_number = 0;
  1481.     print_attribute = 0;
  1482.     page_number = 0;
  1483.     frame = 0;
  1484.     set_frame ();
  1485.     if (header)
  1486.     {    put_top();
  1487.         line_number += 20;
  1488.     }
  1489. }
  1490.  
  1491.  
  1492. /****************************************************************************
  1493. *    terminate_printer ()                                                    *
  1494. *    Generate things that are appropriate wrap-up after all files printed    *
  1495. *    For double sided printing (book == 1), generate byte offset info.        *
  1496. ****************************************************************************/
  1497.  
  1498. void terminate_printer ()
  1499. {    int    i, used;
  1500.     long    psfptr;
  1501.  
  1502.     if (book || reverse_order)
  1503.     {    pg_loc[npg_loc++] = ftell (output_fp);
  1504.     }
  1505.     fprintf (output_fp, "%%%%Trailer\n");
  1506.     for (used = i = 0;  i < font_count;  i++)
  1507.     {    if (fonts_used[i])
  1508.         {    used = 1;
  1509.             break;
  1510.         }
  1511.     }
  1512.     if (used)
  1513.     {    fprintf (output_fp, "%%%%DocumentFonts:");
  1514.         for (i = 0;  i < font_count;  i ++)
  1515.         {    if (fonts_used[i])
  1516.                 fprintf (output_fp, " %s", fonts[i]);
  1517.         }
  1518.         fprintf (output_fp, "\n");
  1519.     }
  1520.  
  1521.     fprintf (output_fp, "%%%%Pages: %d\n", physical_page);
  1522.  
  1523.     if (book || reverse_order)            /*    print statistics for psfdoub  */
  1524.     {    psfptr = ftell (output_fp);
  1525.         fprintf (output_fp, "%%PsfScale: %.5f %.5f scale\n", scale_x, scale_y);
  1526.         fprintf (output_fp, "%%PsfMargin: %d %d %d %d %d\n", 
  1527.                         max_frame, landscape, real_width, p->height, p->width);
  1528.         for (i = 0;  i < 4;  i++)
  1529.             fprintf (output_fp, "%%PsfHome: %d %d %d\n",  i, dx_home[i], dy_home[i]);
  1530.         for (i = 0;  i < npg_loc-1;  i++)
  1531.             fprintf (output_fp, "%%PsfPg: %d %d\n",  i, pg_loc[i]);
  1532.         fprintf (output_fp, "%%PsfPg: 9999 %d\n", pg_loc[npg_loc-1]);
  1533.         fprintf (output_fp, "%%PsfPtr: %d\n", psfptr);
  1534.     }
  1535.     fprintf (output_fp, "%c", CTLD_EOJ);        /* CTL/D = end job */
  1536. }
  1537.  
  1538. /****************************************************************************
  1539. *    draw_cross ()                                                            *
  1540. *    Draw horizontal and vertical separation lines between pages 2/4-up        *
  1541. ****************************************************************************/
  1542.  
  1543. void draw_cross ()
  1544. {    int     p_w, p_h;
  1545.  
  1546.     if (max_frame > 1)
  1547.     {    p_w = p->width;
  1548.         p_h = p->height;
  1549.         if (max_frame == 4)
  1550.         {    set_clip_path (0, -p_h, p_w * 2, p_h);
  1551.             fprintf (output_fp,"gsave %d %d moveto\n", p_w, p_h);
  1552.             fprintf (output_fp,"%d %d lineto\n", p_w, -p_h);
  1553.             fprintf (output_fp,"%d %d moveto\n", 0, 0);
  1554.             fprintf (output_fp,"%d %d lineto\n", p_w * 2, 0);
  1555.             fprintf (output_fp,"%s\n", "stroke grestore");
  1556.         }
  1557.         else
  1558.         {    set_clip_path (0, 0, p_w * 2+ 1, p_h + 1);
  1559.             fprintf (output_fp,"gsave %d %d moveto\n", p_w, p_h);
  1560.             fprintf (output_fp,"%d %d lineto\n", p_w, 0);
  1561.             fprintf (output_fp,"%s\n", "stroke grestore");
  1562.         }
  1563.     }
  1564. }
  1565.  
  1566. /****************************************************************************
  1567. *    set_clip_path                                                            *
  1568. ****************************************************************************/
  1569.  
  1570. void set_clip_path (x1, y1, x2, y2)
  1571. int    x1, y1, x2, y2;
  1572. {
  1573.     x1--; y1--; x2++; y2++;
  1574.  
  1575.     fprintf (output_fp, "newpath\n");
  1576.     fprintf (output_fp,"%d %d moveto\n", x1, y1);
  1577.     fprintf (output_fp,"%d %d lineto\n", x1, y2);
  1578.     fprintf (output_fp,"%d %d lineto\n", x2, y2);
  1579.     fprintf (output_fp,"%d %d lineto\n", x2, y1);
  1580.     fprintf (output_fp,"%s\n", "closepath clip");
  1581. }
  1582.  
  1583. /****************************************************************************
  1584. *    output_book ()                                                            *
  1585. *    Send file "double sided print" mode.  Used to make a "book".            *
  1586. ****************************************************************************/
  1587.  
  1588. void output_book (bookfile)
  1589. char    *bookfile;
  1590. {    char    opts[50];
  1591.  
  1592.     if (book == 0  &&  reverse_order == 0)
  1593.         return;
  1594.  
  1595. #ifdef HOPPER
  1596.  
  1597.     if (nslots > 1  ||  reverse_order)
  1598.     {    if (output_fp != stdout)
  1599.         {    fflush (output_fp);
  1600.             fclose (output_fp);
  1601.  
  1602.             sprintf (opts, "%s %s", reverse_requested ? "-v" : "",
  1603.                                      book ? "-3" : "");
  1604.  
  1605. #if defined(MSDOS)  ||  defined(__MSDOS__)
  1606.             sprintf (line, "%s %s -u %s %s", PSFDOUB, opts, defref, bookfile);
  1607. #else
  1608.             sprintf (line, "%s/%s %s -u %s %s", BINDIR, PSFDOUB, opts, defref, bookfile);
  1609. #endif
  1610.             system (line);
  1611.             unlink (bookfile);
  1612.         }
  1613.     }
  1614.  
  1615.  
  1616. #else    /*    not HOPPER    */
  1617.     if (reverse_order)
  1618.     {    if (output_fp != stdout)
  1619.         {    fflush (output_fp);
  1620.             fclose (output_fp);
  1621.         
  1622.             sprintf (opts, "%s", reverse_requested ? "-v" : "");
  1623.  
  1624. #if defined(MSDOS)  ||  defined(__MSDOS__)
  1625.             sprintf (line, "%s %s -u %s %s", PSFDOUB, opts, defref, bookfile);
  1626. #else
  1627.             sprintf (line, "%s/%s %s -u %s %s", BINDIR, PSFDOUB, opts, defref, bookfile);
  1628. #endif
  1629.             system (line);
  1630.             unlink (bookfile);
  1631.         }
  1632.     }    
  1633.  
  1634.  
  1635. #endif    /* HOPPER */
  1636. }
  1637.  
  1638.  
  1639. /************************************************************************
  1640. *        tscan (s,t)                                                        *        
  1641. *    look for string t in s. return -1 if t does not exits in s else        *
  1642. *    return array position of first character match                        *
  1643. ************************************************************************/
  1644.  
  1645. int tscan (s, t)
  1646. char     s[], t[];
  1647. {
  1648.     int    i, j, k;
  1649.     for (i = 0;  s[i] != '\0';  i++)
  1650.     {    for (j = i, k=0;  t[k] != '\0'  &&  s[j] == t[k];  j++, k++)
  1651.             ;
  1652.         if (t[k] == '\0')
  1653.             return (i);
  1654.     }
  1655.     return (-1);
  1656. }
  1657.  
  1658. void get_time (t)                /*    get current time of */
  1659. char    *t;
  1660. {
  1661.     long    n_time, time ();
  1662.     char    *x_time, *cc, *strchr();
  1663.  
  1664.     n_time = time (0);            /* get time */
  1665.     x_time = ctime (&n_time);    /* convert ascii */
  1666.     if ((cc = strchr (x_time, '\n')) != NULL)
  1667.         *cc = '\0';
  1668.     strcpy (t, x_time);
  1669. }
  1670.  
  1671. int compare (a,b)                /*    case insensitive compare */
  1672. char    *a, *b;
  1673. {    int    aa, bb;
  1674.  
  1675.     while (*a)
  1676.     {    aa = *a++;
  1677.         bb = *b++;
  1678.         if (UCCHAR (aa)  !=  UCCHAR (bb))
  1679.             return (UCCHAR(aa) - UCCHAR(bb));
  1680.     }
  1681.     return (UCCHAR (*a) - UCCHAR (*b));
  1682. }
  1683.  
  1684. int partial_compare (a,b)            /*    case insensitive compare */
  1685. char    *a, *b;                        /*    if all parts of 'a' are successful */
  1686. {    int    aa, bb;
  1687.  
  1688.     while (*a)
  1689.     {    aa = *a++;
  1690.         bb = *b++;
  1691.         if (UCCHAR (aa)  !=  UCCHAR (bb))
  1692.             return (UCCHAR(aa) - UCCHAR(bb));
  1693.     }
  1694.     return (0);
  1695. }
  1696.  
  1697. int comparen (a,b, n)            /* case insensitive compare with count limit */
  1698. char    *a, *b;
  1699. int        n;
  1700. {    int    aa, bb;
  1701.  
  1702.     while (*a &&  n--)
  1703.     {    aa = *a++;
  1704.         bb = *b++;
  1705.         if (UCCHAR (aa)  !=  UCCHAR (bb))
  1706.             return (UCCHAR(aa) - UCCHAR(bb));
  1707.     }
  1708.     if (n <= 0)
  1709.         return (0);
  1710.     return (UCCHAR (*a) - UCCHAR (*b));
  1711. }
  1712.  
  1713. int endcompare (a,b)            /* compare end of a with b */
  1714. char    *a, *b;
  1715. {
  1716.     int    na, nb;
  1717.     
  1718.     na = strlen (a);
  1719.     nb = strlen (b);
  1720.     if (na > nb)
  1721.         a += na - nb;
  1722.     return (strcmp (a,b));
  1723. }
  1724.  
  1725.  
  1726. void trim (s)                    /*    trim trailing blanks  and \n */
  1727. char    *s;
  1728. {    int many;
  1729.  
  1730.     for (many = strlen (s) - 1;  many >= 0;  many--)
  1731.     {    if (isgraph (s[many]))
  1732.             break;
  1733.         else
  1734.             s[many] = '\0';
  1735.     }
  1736. }
  1737.  
  1738. void bad_file()
  1739. {
  1740.     fprintf (stderr, "Bad %s file\n", defref);
  1741.     exit (1);
  1742. }
  1743.  
  1744. int xtoi (c)                    /*    hex character to integer     */
  1745. int c;                            /*    any letter is a 'hex' digit */
  1746. {
  1747.     char xc[2];
  1748.     int     rv;
  1749.     
  1750.     if (isupper (c))
  1751.         xc[0] = tolower (c);
  1752.     else
  1753.         xc[0] = c;
  1754.     xc[1] = '\0';
  1755.     
  1756.     rv = tscan (ascii_hex, xc);
  1757.     if (rv >= 0)
  1758.         return (rv);
  1759.     return (0);
  1760. }
  1761.  
  1762.  
  1763. /********************************************************
  1764. *    catch ()                                            *
  1765. *    Catch SIGINT from lpd                                *
  1766. ********************************************************/
  1767.  
  1768. void catch (signo)
  1769. int    signo;
  1770. {
  1771.         fprintf (output_fp, "%c", CTLD_EOJ);
  1772.         exit (0);
  1773. }
  1774.  
  1775. void output_trouble (rc)
  1776. int    rc;
  1777. {
  1778. #ifndef PSFFILTER
  1779.     fprintf (stderr, "Cannot write to output file\n");
  1780. #endif
  1781.     exit (rc);
  1782. }
  1783. /************************************************************************
  1784. *    replacement_fonts()                                                    *
  1785. *    get language-specific fonts and translation vectors.                *
  1786. *    Reads only the %%PsfStart -to- %%PsfEnd code.  The file is is left    *
  1787. *    positioned at the first postscript code that prologue() will copy    *
  1788. *    to the output.                                                        *
  1789. ************************************************************************/
  1790.  
  1791. void replacement_fonts ()
  1792. {    int        found, i, fn, xold, xnew;
  1793.     char    line[201];
  1794.     char    *ln, *x, *fname;
  1795.  
  1796.     if (pdef == NULL)
  1797.         return;
  1798.     found = 0;
  1799.     while (fgets (line, 200, pdef))        /*    skip printer name     */
  1800.     {    if (strncmp (line, "%%PsfStart", 10) == 0)
  1801.         {    found = 1;
  1802.             break;
  1803.         }
  1804.     }
  1805.     if (found)
  1806.     {    while (fgets (line, 200, pdef))            /*    read fonts, translate */
  1807.         {    if (strncmp (line, "%%PsfEnd", 8) == 0)
  1808.                 break;
  1809.             if (strncmp (line, "%%font",  6) == 0)
  1810.             {    fn = xtoi (line[6]) * 4;
  1811.                 if (fn >= font_count)
  1812.                     font_count = fn + 4;
  1813.                 trim (line);
  1814.                 ln = malloc (strlen (line) - 6);
  1815.                 strcpy (ln, line + 7);
  1816.                 fonts_have[fn] = 1;
  1817.                 fonts[fn++] = strtok (ln, " \t");
  1818.                 for (i = 1;  i < 4;  i++)
  1819.                 {    fonts_have[fn] = 1;
  1820.                     fonts[fn++] = strtok (NULL, " \t");
  1821.                 }
  1822.             }
  1823.             else if (strncmp (line, "%%translate",  11) == 0)
  1824.             {    x = strtok (line + 11, " \t");
  1825.                 do
  1826.                 {    xold = otoi (x) % 256;
  1827.                     xnew = otoi (x+4) % 256;
  1828.                     xlate[xold] = xnew;
  1829.                 } while (x = strtok (NULL, " \t"));
  1830.                 need_xlate = 1;
  1831.             }
  1832.             else if (strncmp (line, "%%copy", 6) == 0)
  1833.             {    fname = strtok (line + 6, " \t");
  1834.                 if (fname)
  1835.                     strcpy (copyfile, fname);
  1836.             }
  1837.         }
  1838.     }
  1839.     else
  1840.     {    fclose (pdef);
  1841.         pdef = NULL;
  1842.     }
  1843.     return;
  1844. }
  1845.  
  1846. /****************************************************************************
  1847. *    octal to integer                                                        *
  1848. ****************************************************************************/
  1849. int    otoi (s)
  1850. char    *s;
  1851. {
  1852.     int        v, p, quit;
  1853.  
  1854.     v = 0;
  1855.     while (*s == ' ')
  1856.         s++;
  1857.     quit = 0;
  1858.     while (*s)
  1859.     {    switch (*s)
  1860.         {
  1861.         case '0':    p = 0;  break;
  1862.         case '1':    p = 1;  break;
  1863.         case '2':    p = 2;  break;
  1864.         case '3':    p = 3;  break;
  1865.         case '4':    p = 4;  break;
  1866.         case '5':    p = 5;  break;
  1867.         case '6':    p = 6;  break;
  1868.         case '7':    p = 7;  break;
  1869.         default:    quit = 1;
  1870.         }
  1871.         if (quit)
  1872.             break;
  1873.         v = (v << 3) + p;
  1874.         s++;
  1875.     }
  1876.     return (v);
  1877. }
  1878.  
  1879. /****************************************************************************
  1880. *    usage ()                                                                *
  1881. ****************************************************************************/
  1882.  
  1883. #ifdef PSFFILTER
  1884.  
  1885. void usage ()
  1886. {    exit (1);
  1887. }
  1888. void size_display ()
  1889. {    exit (1);
  1890. }
  1891.  
  1892. #else    /* not PSFFILTER */
  1893.  
  1894. static char *usage_text[] =
  1895. {
  1896.     "Usage: %s [-1|2|4] [-b n] [-c n] [-d] [-f n] [-g type ] [-h]\n",
  1897.     "           [-H text] [-i n] [-l n] [-m n] [-n] [-p n] [-R n]",
  1898.     "           [-r n] [-s] [-t n] [-u fil] [-w] [-x] file ...",
  1899.     "where:",
  1900.     "   -1|2|4  print 1,2,4 up (default=1)",
  1901.     "   -b n    paper bin n",
  1902.     "   -c n    print columns",
  1903.     "   -d      double sided",
  1904.     "   -f n    font number (def=0:Courier)",
  1905.     "   -g type letter legal a4 b5",
  1906.     "   -h      file name header",
  1907.     "   -H text text header",
  1908.     "   -i n    indent left margin points",
  1909.     "   -l n    print lines per page",
  1910.     "   -L n    lines per page",
  1911.     "   -m n    top margin points",
  1912.     "   -n      portrait (narrow) format",
  1913.     "   -p n    point size n",
  1914.     "   -R n    remove lines from beginning",
  1915.     "   -r n    remove lines between pages",
  1916.     "   -s      show page stats",
  1917.     "   -t n    tabs to n (default=8)",
  1918.     "   -u fil  use this file as psfprint.def",
  1919.     "   -v      reverse page order",
  1920.     "   -w      landscape (wide) format",
  1921.     "   -x      draw cross (2/4-up page)",
  1922.     "   file..  name of files (or stdin)",
  1923.     "   output: stdout",
  1924.     ""
  1925. } ;
  1926.  
  1927. #define TOPCOUNT 4
  1928.  
  1929. void usage ()
  1930. {    int        i, many, n, ff;
  1931.  
  1932.     fprintf (stderr, usage_text[0], pgmname);
  1933.     for (i = 1;  i < TOPCOUNT; i++)
  1934.         fprintf (stderr, "%s\n", usage_text[i]);
  1935.  
  1936.     many = sizeof (usage_text)/sizeof (char *) - TOPCOUNT;
  1937.     
  1938.     for (i = 0;  i < many/2;  i++)
  1939.         fprintf (stderr, "%-38s %-38s\n", usage_text[i+TOPCOUNT], usage_text[i+many/2+TOPCOUNT]);
  1940.  
  1941.     fprintf (stderr,"Fonts selection with -f n (number or name)\n");
  1942.     many = ff = 0;
  1943.     for (i = 0;  i < font_count/4;  i++)
  1944.     {    if (fonts_have[i*4])
  1945.         {    fprintf (stderr, " %c %-22s", ascii_hex[i], fonts[i*4]);
  1946.             many++;
  1947.             if ((ff = many % 3)  == 0)
  1948.                 fprintf (stderr, "\n");
  1949.         }
  1950.     }
  1951.     if (ff)
  1952.         fprintf (stderr, "\n");
  1953.  
  1954.     fprintf (stderr, "Paper type/size selection with -g type\n");
  1955.     many = 0;
  1956.     for (i = 0;  page_types[i].paper_name[0] != '\0';  i++)
  1957.     {    n = strlen (page_types[i].paper_name);
  1958.         if (many + n > 75)
  1959.         {    many = 0;
  1960.             fprintf (stderr,"\n");
  1961.             ff = 0;
  1962.         }
  1963.         else ff = 1;
  1964.         many += n + 3;
  1965.         fprintf (stderr,"   %s", page_types[i].paper_name);
  1966.     }
  1967.     if (ff)
  1968.         fprintf (stderr, "\n");
  1969.     exit (1);
  1970. }
  1971.  
  1972. /************************************************************************
  1973. *    size_display ()                                                        *
  1974. *    print a table of point size, page size, line count, column count    *
  1975. ************************************************************************/
  1976.  
  1977. void size_display ()
  1978. {
  1979.     int    point_size, ps, nominal_high, nominal_wide, i;
  1980.     int    n_chars, n_lines;
  1981.     double    char_width;
  1982.     char    *which;
  1983.     
  1984.     fprintf (stderr, "%22s", "point size: ");
  1985.     for (point_size = 6;  point_size < 17;  point_size += 2)
  1986.         fprintf (stderr, " %5d   ", point_size);
  1987.     fprintf (stderr, "\n%-22s", " ");
  1988.     for (point_size = 6;  point_size < 17;  point_size += 2)
  1989.         fprintf (stderr, "  lin col");
  1990.     fprintf (stderr, "\n%-22s", "---- Page Layout ----");
  1991.     for (point_size = 6;  point_size < 17;  point_size += 2)
  1992.         fprintf (stderr, "  --- ---");
  1993.     fprintf (stderr, "\n");
  1994.     for (ps = 0;  page_types[ps].paper_name[0];  ps++)
  1995.     {    for (i = 0;  i < 2;  i++)
  1996.         {    if (i == 0)
  1997.             {    nominal_high = page_types[ps].y_size;
  1998.                 nominal_wide = page_types[ps].x_size;
  1999.                 which = "portrait";
  2000.             }
  2001.             else
  2002.             {    nominal_high = page_types[ps].x_size;
  2003.                 nominal_wide = page_types[ps].y_size;
  2004.                 which = "landscape";
  2005.             }
  2006.             fprintf (stderr, "%10.10s %9s: ", page_types[ps].paper_name, which);
  2007.             for (point_size = 6;  point_size < 17;  point_size += 2)
  2008.             {    char_width = point_size / 12.0 * NOMINAL_CWIDE;
  2009.                 n_chars = ceil ((double) nominal_wide / (double) char_width);
  2010.                 n_lines = (double) nominal_high / (double) point_size;
  2011.                 fprintf (stderr, " %4d%4d", n_lines, n_chars);
  2012.             }
  2013.             fprintf (stderr, "\n");
  2014.         }
  2015.     }
  2016.     exit (1);
  2017. }
  2018. #endif /* PSFFILTER */
  2019.