home *** CD-ROM | disk | FTP | other *** search
- /* ta=4 */
- /****************************************************************************
- * p s f . c v2.0 *
- * *
- * Postscript filter *
- * *
- * Print text files to postscript printer. Allow 1-up, 2-up and 4-up *
- * pages. Provisions are made to allow font selection by imbedded *
- * escape sequences - to allow printing of man pages. The escape sequence *
- * generated by "pnf" and "pmf" are compatible with psf. *
- * *
- * Copyright: 1989-Feb, Tony Field. tony@ajfcal *
- * *
- * The orginal underline algorithm (/showunderline) was provided by *
- * Anders Thulin mcvax!helios!ath@uunet.uucp *
- ****************************************************************************/
-
- /* NOTE: tabstop=4 */
-
- /* Note: if you want psf to ignore any text that is already in postscript
- format, then possibly modify function "process_file()" to
- do the detection and copy the input file to stdout.
-
- I haven't checked this out in detail, but it looks reasonable.
- Maybe a command line option should be used to enable/disable
- detection of postscript text (it is nice to be able to print
- out postscript code)?
- */
-
- /* NOTES: re: -d option: double sided print.
-
- Double sided print requires two scans over the data. The first
- scan generates postscript output in normal (non-double sided) form.
- A second scan examines the postscript and re-orders the output
- to the printer. The second pass is always done by the "psd" filter.
-
- Psf generates extra information to make it easy for psd to work.
- It simply constructs pointers to each of the %%Page: beginning
- in the print file. (see function terminate_printer()) Psd
- uses the pointers to "skip about" the file while it does the
- actual page layout.
-
- If the target printer has two paper hoppers (i.e. #define HOPPER is
- defined and "nslots > 2") then psf creates a temp file and system("psd
- fname") is called to immediately generate the double sided output.
- The user does not have to manually invoke psd.
-
- If HOPPER is not defined or nslots <= 1, psf simply creates an
- appropriate output file and the user must manually invoke psd to
- print the file.
-
- Double sided print is forced into this routine. It would have been
- simple except for the fact that 2-up "book" format is supported.
- The excuse for this strategy is, of course, to minimize the amount
- of file processing overhead when double sided printing is done.
-
- If the double sided printing is for 8.5x5.5 inch paper printed
- two-up, then psf carefully forgets (in function set_frame())
- to put in page scale, rotation, and translation information.
- The psd filter reads the page layout and carefully re-inserts
- these when appropriate. If 2-up "books" are made, each logical
- page becomes a separate page on the output temp file.
- */
-
- #include <stdio.h>
- #include <math.h>
- #include <time.h>
- #include "patchlevel.h"
- #include "psf.h"
-
- /* BINDIR is used to locate double sided printer "psd".
- psd is called in function output_book ()
- You may wish to remove the reference to "BINDIR" in output_book().
- */
-
- #ifndef BINDIR
- #define BINDIR "\0"
- #endif
-
- /* set up the mechanism for underline display */
-
- #ifndef FONTINFO
- #define SHOWU(fp,ps) fprintf (fp, ") %d showuline\n", ps)
- #else
- #define SHOWU(fp,ps) fputs (") showunderline\n", fp)
- #endif
-
- #define MAX_PAGES 500 /* max pages in a book */
- #define LONG_STR 1000 /* long buffer line */
-
- #define min(x,y) ((x) < (y) ? (x) : (y))
- #define max(x,y) ((x) > (y) ? (x) : (y))
-
- /* default font with and height - assumes Courier fixed pitch */
-
- #define NOMINAL_CWIDE 7.2 /* point width for Courier 12-point */
- #define NOMINAL_POINTS 12 /* standard 12-point for printing */
-
- #define NORMAL 0x00 /* bitset for print_attributes */
- #define ITALICS 0x01
- #define BOLD 0x02
- #define UNDERLINE 0x04 /* must be 0x04. underline is not a font */
-
- /* Paper physical dimensions. Each paper size supported must be described.
- If the paper print areas specified are incorrect, you must modify them.
- The default paper sizes are coded into psf and are set for a NEC LC890
- printer. These defaults are overridden in the "psfprint.def" printer
- definition file.
-
- All text work must preserve the physical margins and scale the
- drawing area to reflect the 1-up, 2-up or 4-up magnification.
-
-
- "paper_name" is the name used on the command line with the -g option
- to select the paper size: eg -g legal
-
- "paper_tray" is the command that is necessary to select the
- specified paper size. For example, if the "legal" sized paper is in
- the "alternate print tray", the postscript commands necessary to
- switch paper tray and to select the legal size must be specified in
- the "paper_tray" structure element.
- */
-
- typedef struct /* measurement in point */
- { char paper_name[60]; /* name of paper size (for command line) */
- char paper_tray[200]; /* postscript operator to select this tray */
- int width; /* portrait point width of paper */
- int height; /* portrait point height of paper */
- int lx, ly, ux, uy;
- int left_marg; /* margin widths (unprintable area) */
- int bot_marg; /* " */
- int right_marg; /* " */
- int top_marg; /* " */
- int x_size; /* generated by psf. */
- int y_size; /* size after correction for line count */
- int n_lines; /* " */
- int n_chars; /* " */
- } measure;
-
- measure *p; /* working set of parameters (points to something below) */
-
- /* standard paper sizes in portrait layout (NEC LC890) */
- /* These are defaults and are overridden in psfprint.def. */
-
- measure page_types[30] =
- { { "letter",
- "statusdict begin lettertray end",
- 612, 792, 18, 15, 593, 777
- },
- { "legal",
- "statusdict begin legaltray end",
- 612, 1008, 18, 15, 593, 993
- },
- { "a4",
- "statusdict begin a4tray end",
- 595, 842, 18, 15, 578, 827
- },
- { "b5",
- "statusdict begin b5tray end",
- 516, 729, 18, 15, 497, 712
- },
- { "", /* end of paper list */
- "",
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- }
- };
-
- char slots[4][100] =
- { "statusdict begin 1 setpapertray end",
- "statusdict begin 2 setpapertray end",
- "",
- ""
- } ;
- int nslots = 2;
-
-
- /* Current information about page. Where are we, etc.
- */
-
- int y_top_offset; /* offsets for each frame */
- int x_left_offset;
- int dx_home[4]; /* page frame home (0,0) translations */
- int dy_home[4];
-
- int x,y; /* current x,y coordinate */
- double scale_x, scale_y; /* scale factors for 2-up, 4-up printing */
- int real_width;
-
- long *pg_loc; /* double side print byte ptr to %%Page: */
- int npg_loc; /* number of elements in pg_loc[] */
-
- int book = 0; /* book format: double sided */
- int bookwork = 0; /* book format, 2-up print */
- int lines_on_page = 60; /* user print lines on page */
- int lines_total = 0; /* total number of lines for scale purposes */
- int chars_on_line = 80; /* default number of chars on line */
- int landscape = 0; /* 1 = landscape, 0 = portrait layout */
- int header = 0; /* 1 = print header at top of each page */
- int cross = 0; /* 1 = print cross on 4-up pages */
- int line_number = 0; /* current logical line number on page */
- int tab_size = 8; /* space translation for tabs. */
- int font_number = 0; /* one of the valid fonts in the printer */
- int point_size = 12; /* can be changed with the -p option */
- int x_user_offset = 0; /* offsets specified buy user */
- int y_user_offset = 0; /* points from physical page edge. */
- int set_paper_tray = 0; /* user has set paper tray selection */
- int set_line_count = 0; /* print line count on page */
- int set_total_count = 0; /* total line count on page */
- int set_point_size = 0; /* point size */
- int set_char_count = 0; /* characters on a line */
- int set_paper_bin = 0; /* paper bin (not page size) */
- char header_text[100]; /* header line text */
-
- int print_attribute = 0; /* such as BOLD, UNDERLINE, ITALICS */
- int default_font_number; /* set with -f option, or 0 */
- int default_point_size; /* assumes value due to -p option */
- int y_coord = 0; /* current logical page y-coordinate, points*/
- int x_coord = 0; /* current logical page x-coordinate, points*/
- int page_number; /* current page number for this file */
- int physical_page = 0; /* postscript physical page for multi-up */
-
-
- char fname[100];
- char now[50]; /* time of day for page headers */
-
-
- /* to select a font, use 4 * font_number + print_attribute as index.
- e.g. If font_number = 1 for Helvetica,
- and print_attribute = 0x02 for BOLD
-
- then the actual font selected is fonts[4 * 1 + 2]
- = Helvetica-Bold
-
- The various print attributes can be OR'ed together:
- fonts [4 * 1 + ITALICS | BOLD]
-
- The following are default fonts - and are overridden in psfprint.def.
- */
-
- #define NFONTS 40 /* 4 variations * 9 font families */
- char *fonts[NFONTS] =
- {
- "Courier", "Courier-Oblique", "Courier-Bold", "Courier-BoldOblique",
- "Helvetica", "Helvetica-Oblique", "Helvetica-Bold", "Helvetica-BoldOblique",
- "Times-Roman", "Times-Italic", "Times-Bold", "Times-BoldItalic",
- "AvantGarde-Book", "AvantGarde-BookOblique", "AvantGarde-Demi", "AvantGarde-DemiOblique",
- "Bookman-Light", "Bookman-LightItalic", "Bookman-Demi", "Bookman-DemiItalic",
- "NewCenturySchlbk-Roman", "NewCenturySchlbk-Italic", "NewCenturySchlbk-Bold", "NewCenturySchlbk-BoldItalic",
- "Palatino-Roman", "Palatino-Italic", "Palatino-Bold", "Palatino-BoldItalic",
- "Helvetica-Narrow", "Helvetica-Narrow-Oblique", "Helvetica-Narrow-Bold", "Helvetica-Narrow-BoldOblique",
- "Garamond-Light", "Garamond-LightItalic", "Garamond-Bold", "Garamond-BoldItalic",
- "ZapfChancery-MediumItalic","ZapfChancery-MediumItalic","ZapfChancery-MediumItalic","ZapfChancery-MediumItalic"
- } ;
-
- int fonts_used[NFONTS];
- int fonts_have[NFONTS];
-
- int max_frame = 1; /* max number of frames in use */
- int frame = -1; /* current frame in use */
-
- FILE *input_fp, *output_fp;
-
- /* input line and input line pointer */
- unsigned char *c;
- unsigned char line[LONG_STR + 1];
-
- char *pgmname;
-
- char *malloc();
-
- main (argc, argv)
- int argc;
- char *argv[];
- { int c, i, j;
- extern char *optarg;
- extern int optind;
- FILE *pdef;
-
- /* see if there is a psfprint.def printer definition file. If so,
- use those parameters, rather than the hard-coded defaults.
- */
-
- if ((pdef = fopen (PDEF, "r")) != NULL)
- { nslots = 0;
- fgets (line, 100, pdef);
- for (i = 0; i < 28; i++)
- { if (fgets (page_types[i].paper_name, 59, pdef) == NULL)
- break;
- trim (page_types[i].paper_name);
- if (strncmp (page_types[i].paper_name, "*fonts", 6) == 0)
- {
- for (j = 0; j < NFONTS; j++)
- fonts_have[j] = 0;
- page_types[i].paper_name[0] = '\0';
- while (fgets (line, 90, pdef) != NULL)
- { trim (line);
- if (*line == '*')
- break;
- for (j = 0; j < NFONTS; j++)
- { if (comp (fonts[j], line) == 0)
- { fonts_have[j] = 1;
- break;
- }
- }
- }
- if (strncmp (line, "*slots", 6) == 0)
- { while (fgets (line, 90, pdef) != NULL)
- { trim (line);
- if (strncmp (line, "*eof", 4) == 0)
- break;
- if (*line)
- {
- strcpy (slots[nslots], line);
- if (++nslots > 3)
- break;
- }
- }
- }
- break; /* end of file */
- }
- if (fgets (page_types[i].paper_tray, 199, pdef) == NULL)
- bad_file();
- trim (page_types[i].paper_tray);
- if (fgets (line, 100, pdef) == NULL)
- bad_file();
- trim (line);
- sscanf (line, "%d%d%d%d%d%d",
- &page_types[i].width,
- &page_types[i].height,
- &page_types[i].lx,
- &page_types[i].ly,
- &page_types[i].ux,
- &page_types[i].uy);
-
- }
- page_types[i].paper_name[0] = '\0';
- fclose (pdef);
- }
- else
- { for (i = 0; i < NFONTS; i++)
- fonts_have[i] = 1;
- fonts_have[8] = 0;
- }
-
- for (i = 0; page_types[i].paper_name[0]; i++)
- { page_types[i].left_marg = page_types[i].lx;
- page_types[i].bot_marg = page_types[i].ly;
- page_types[i].top_marg = (page_types[i].height - 1) - page_types[i].uy;
- page_types[i].right_marg = (page_types[i].width - 1) - page_types[i].ux;
-
- page_types[i].x_size = page_types[i].ux - page_types[i].lx + 1;
- page_types[i].y_size = page_types[i].uy - page_types[i].ly + 1;
- }
-
- pgmname = argv[0];
- p = &page_types[0]; /* default to letter size paper */
- *header_text = '\0';
- scale_x = 1.0;
- scale_y = 1.0;
- if (strcmp (argv[1], "-") == 0 || strcmp (argv[1], "--") == 0)
- usage();
- while ((c = getopt(argc, argv, "124xhnwdi:m:b:c:g:H:l:L:f:t:p:-?")) != -1)
- { switch (c)
- {
- case '1':
- max_frame = 1;
- scale_x = 1.0;
- scale_y = 1.0;
- break;
-
- case '2':
- landscape = 1;
- max_frame = 2;
- scale_x = 0.647;
- scale_y = 0.772;
- break;
-
- case '4':
- max_frame = 4;
- scale_x = 0.5;
- scale_y = 0.5;
- break;
-
- case 'b':
- if ((set_paper_bin = atoi (optarg)) > nslots)
- { if (nslots = 0)
- fprintf (stderr, "%s: no alternate bins permitted for this printer\n", nslots);
- else
- fprintf (stderr, "%s: paper bin greater than %d\n", pgmname, nslots);
- exit (1);
- }
- break;
-
- case 'c':
- chars_on_line = atoi (optarg);
- set_char_count = 1;
- break;
-
- case 'd':
- book = 1;
- break;
-
- case 'f':
- if (*optarg > '9')
- { for (i = 0; i < NFONTS; i += 4)
- { if (compare (optarg, fonts[i]) == 0)
- { font_number = i / 4;
- break;
- }
- }
- if (i >= NFONTS)
- font_number = 0;
- }
- else
- {
- font_number = atoi (optarg);
- if (font_number > (NFONTS / 4))
- font_number = 0;
- }
- break;
-
- case 'g':
- p = NULL;
- for (i = 0; page_types[i].paper_name[0]; i++)
- { if (compare (optarg, page_types[i].paper_name) == 0)
- { p = &page_types[i];
- break;
- }
- }
- if (p == NULL)
- usage ();
- set_paper_tray = 1;
- break;
-
- case 'l':
- lines_on_page = atoi (optarg);
- set_line_count = 1;
- break;
-
- case 'L':
- lines_total = atoi (optarg);
- set_total_count = 1;
- break;
-
- case 'h':
- header = 1;
- break;
-
- case 'H':
- header = 2;
- strcpy (header_text, optarg);
- break;
-
- case 'i':
- x_user_offset = atoi (optarg);
- break;
-
- case 'm':
- y_user_offset = atoi (optarg);
- break;
-
- case 'n':
- landscape = 0;
- break;
-
- case 'p':
- point_size = atoi (optarg);
- set_point_size = 1;
- break;
-
- case 't':
- tab_size = atoi (optarg);
- break;
-
- case 'w':
- landscape = 1;
- break;
-
- case 'x':
- cross = 1;
- break;
-
- default: usage ();
- break;
- }
- }
-
- if (font_number * 4 > NFONTS)
- { fprintf (stderr,"Font number invalid....\n");
- usage ();
- }
-
- if (header)
- lines_on_page += 2;
-
- #ifdef HOPPER
- if (book && nslots > 1)
- {
- if ((output_fp = fopen ("1psbook2.d34", "w")) == NULL)
- { fprintf (stderr, "%s: cannot create work file\n", pgmname);
- exit (1);
- }
- }
- else
- #endif
- output_fp = stdout;
-
- if (book)
- { if ((pg_loc = (long *) malloc (sizeof (long) * MAX_PAGES)) == NULL)
- { fprintf (stderr, "%s: cannot allocate enough memory\n", pgmname);
- exit (1);
- }
- npg_loc = 0;
- }
-
- for (i = 0; i < NFONTS; i++)
- fonts_used[i] = 0;
-
- page_number = -1;
- line_number = 32000;
- default_point_size = point_size;
- default_font_number = font_number;
- bookwork = book && landscape && (max_frame == 2);
- *fname = 0;
-
- get_time (now);
- scale_factors ();
- prologue (output_fp);
- if (optind >= argc)
- { if (header == 1)
- header = 0;
- start_file ();
- input_fp = stdin;
- process_file ();
- terminate_file ();
- }
- else for ( ; optind < argc; optind++)
- { i = strlen (argv[optind]);
- if (i > 38)
- i -= 38;
- else
- i = 0;
- strcpy (fname, argv[optind] + i);
- if ((input_fp = fopen (argv[optind], "r")) == NULL)
- { fprintf (stderr, "Unknown file: %s\n", argv[optind]);
- continue;
- }
- start_file ();
- process_file ();
- terminate_file ();
- fclose (input_fp);
- }
- terminate_printer ();
-
- if (book)
- output_book ();
-
- exit (0);
- }
-
- /****************************************************************************
- * scale_factors () *
- * Compute the x and y scale factors. If the print is for landscape, *
- * adjust the paper size matrix (p->...) to reflect landscape rather *
- * than portrait. *
- ****************************************************************************/
-
- /* scale factors are calculated from:
-
- unprintable size + scale factor * print size = total paper size
-
- total paper size - unprintable size
- scale factor = --------------------------------------
- print size
- */
-
- scale_factors ()
- { int wide; /* width needed for char count */
- int high; /* points needed for line count */
- int i;
- double char_width, scale;
-
- /* determine default number of characters and lines based upon
- Courier 12 point, 10 pitch font, portrait layout
- */
-
- char_width = NOMINAL_CWIDE; /* in points */
- real_width = p->width; /* for initial axis translate only */
-
- p->n_chars = ceil ((double) p->x_size / NOMINAL_CWIDE);
- p->n_lines = p->y_size / NOMINAL_POINTS;
-
- /* set line count relative to portrait measure */
-
- if (set_total_count == 0)
- lines_total = p->n_lines;
-
- if (set_line_count == 0)
- lines_on_page = p->n_lines;
-
- if (lines_total < lines_on_page)
- { if (set_total_count)
- lines_on_page = lines_total;
- else
- lines_total = lines_on_page;
- }
-
- /* if landscape, then switch the height and width dimensions */
-
- if (landscape)
- {
- i = p->height; p->height = p->width; p->width = i;
- i = p->left_marg; p->left_marg = p->bot_marg; p->bot_marg = i;
- i = p->top_marg; p->top_marg = p->right_marg; p->right_marg = i;
- i = p->lx; p->lx = p->ly; p->ly = i;
- i = p->ux; p->ux = p->uy; p->uy = i;
- i = p->x_size; p->x_size = p->y_size; p->y_size = i;
-
- if (max_frame == 1)
- { scale = (double) p->y_size / (double) p->x_size;
- p->n_chars = ceil ((double) p->n_chars * scale * scale);
- }
- }
- if (set_char_count == 0)
- chars_on_line = p->n_chars;
-
- if (set_point_size)
- { scale = (double) point_size / (double) NOMINAL_POINTS;
- lines_total = p->y_size / point_size;
- if (set_char_count == 0)
- { chars_on_line /= scale;
- char_width *= scale;
- }
- }
- else if (set_line_count || set_total_count)
- {
- if (set_char_count == 0)
- { scale = (double) lines_total / (double) p->n_lines;
- chars_on_line = ceil ((double) chars_on_line * scale);
- }
- }
-
- /* Ideally, we wish to use a decender value of 0.5 line.
- This is yieds a scale factor of 1.0 for Courier in default
- portrait mode. Hopefully, this is not a problem with
- other fonts.
- */
- high = ceil ((double) point_size * ((double) lines_total + 0.51));
- wide = ceil (chars_on_line * char_width);
-
- x_user_offset = max (0, x_user_offset - p->left_marg);
- y_user_offset = max (0, y_user_offset - p->top_marg );
-
- switch (max_frame)
- {
- case 1:
- scale_x = (double) (p->x_size) / (double) wide;
- scale_y = (double) (p->y_size) / (double) high;
- x_left_offset = (int) ceil ((double) (p->left_marg + x_user_offset) / scale_x);
- y_top_offset = (int) ceil ((double) (p->top_marg + y_user_offset) / scale_y);
- dx_home[0] = 0;
- dy_home[0] = 0;
- p->height = ceil ((double) p->height / scale_y);
- p->width = ceil ((double) p->width / scale_x);
- p->bot_marg = ceil ((double) p->bot_marg / scale_y);
- break;
-
- case 2:
- scale_x = (double) (p->width - 2 * p->left_marg - 2 * p->right_marg)
- / (double) (2 * wide);
- scale_y = (double) (p->y_size) / (double) high;
-
- /* point offsets for margins account for physical "forbidden" area */
-
- x_left_offset = (int) ceil ((double) p->left_marg / scale_x);
- y_top_offset = (int) ceil ((double) p->top_marg / scale_y);
-
- /* page origin translation vectors */
-
- p->height = ceil ((double) p->height / scale_y);
- p->width = ceil ((double) p->width / (scale_x * 2.0));
- p->bot_marg = ceil ((double) p->bot_marg / scale_y);
- dx_home[0] = 0;
- dy_home[0] = 0;
- dx_home[1] = p->width;
- dy_home[1] = 0;
- break;
-
- case 4:
- scale_x = (double) (p->width - 2 * p->left_marg - 2 * p->right_marg)
- / (double) (2 * wide);
- scale_y = (double) (p->height - 2 * p->top_marg - 2 * p->bot_marg)
- / (double) (2 * high);
-
- /* point offsets for margins account for physical "forbidden" area */
-
- x_left_offset = (int) ceil ((double) p->left_marg / scale_x);
- y_top_offset = (int) ceil ((double) p->top_marg / scale_y);
-
- /* page origin tranlsation vectors */
-
- p->height = ceil ((double) p->height / (scale_y * 2.0));
- p->width = ceil ((double) p->width / (scale_x * 2.0));
- p->bot_marg = ceil ((double) p->bot_marg / scale_y);
- dx_home[0] = 0;
- dy_home[0] = p->height;
- dx_home[1] = 0;
- dy_home[1] = -p->height;
- dx_home[2] = p->width;
- dy_home[2] = p->height;
- dx_home[3] = 0;
- dy_home[3] = -p->height;
- break;
-
- default: ;
- }
-
- if (max_frame > 1)
- { x_left_offset += x_user_offset;
- y_top_offset += y_user_offset;
- }
-
- #ifdef DEBUG
- printf ("%%!PS-Adobe-\n");
- printf ("%% lines =%d/%d/%d chars = %d/%d\n", lines_total, set_line_count,set_total_count, chars_on_line, set_char_count);
- printf ("%% height = %d / %d\n", p->height, high);
- printf ("%% width = %d / %d\n", p->width, wide);
- printf ("%% (lx,ly) = (%d,%d)\n", p->lx, p->ly);
- printf ("%% (ux,uy) = (%d,%d)\n", p->ux, p->uy);
- printf ("%% left_marg = %d\n", p->left_marg);
- printf ("%% right_marg = %d\n", p->right_marg);
- printf ("%% top_marg = %d\n", p->top_marg);
- printf ("%% bot_marg = %d\n", p->bot_marg);
- printf ("%% y_size = %d\n", p->y_size);
- printf ("%% x_size = %d\n", p->x_size);
- printf ("%% scale_x = %f scale_y = %f\n", scale_x, scale_y);
- printf ("%% offset (lx,ty) = (%d,%d)\n", x_left_offset, y_top_offset);
- printf ("%% home = %d %d %d %d\n",dy_home[0], dy_home[1], dy_home[2],dy_home[3]);
- #endif
- }
-
-
- /****************************************************************************
- * prologue () *
- * generate the require postscript-conformant prologue *
- ****************************************************************************/
-
- prologue ()
- { char *getlogin();
- int i;
-
- if (book)
- fprintf (output_fp, "%%Book file: psf-to-psd\n");
- else
- fprintf (output_fp, "%%!PS-Adobe-\n");
- fprintf (output_fp, "%%%%Creator: %s\n", getlogin());
- fprintf (output_fp, "%%%%CreationDate: %s\n", now);
- fprintf (output_fp, "%%%%DocumentFonts: (atend)\n");
- fprintf (output_fp, "%%%%Pages: (atend)\n");
- fprintf (output_fp, "%%%%EndComments\n");
-
- #ifndef FONTINFO
- /* The red book (pg 93) indicates that the FontInfo dictionary
- "MAY" contain the /UnderlinePosition and /UnderlineThickness
- This is the case for all Adobe fonts. External non-Adobe fonts may
- not have these values.
-
- usage: (text to underline) <pointsize> showuline
- where: <pointsize> is current text point size.
-
- eg: (text to underline) 12 showuline
- */
- fprintf (output_fp, "%s%s%s%s%s%s%s%s%s%s",
- "/showuline {\n",
- " /CurPointSize exch def\n",
- " dup stringwidth pop\n",
- " gsave\n",
- " currentfont /FontInfo get dup\n",
- " /UnderlinePosition get CurPointSize mul 1000 div 0 exch rmoveto exch 0 rlineto\n",
- " /UnderlineThickness get CurPointSize mul 1000 div setlinewidth stroke\n",
- " grestore\n",
- " show\n",
- "} def\n");
-
- #else
- /* showunderline: without FontInfo: underline is 2 points below base
- compliments of Anders Thulin
- mcvax!helios!ath@uunet.uucp (Anders Thulin)
-
- usage: (text to underline) showunderline
- */
- fprintf (output_fp, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
- "/showunderline {\n",
- " /str exch def\n",
- " /dy 0 def\n",
- " currentpoint\n",
- " str show\n",
- " moveto\n",
- " /dy -2 def\n",
- " currentpoint\n",
- " dy add\n",
- " moveto\n",
- " str stringwidth\n",
- " rlineto \n",
- " currentpoint\n",
- " stroke\n",
- " moveto\n",
- " currentpoint\n",
- " dy sub\n",
- " moveto\n",
- "} def\n");
- #endif
-
- fprintf (output_fp, "%%%%EndProlog\n");
-
- if (set_paper_tray)
- fprintf (output_fp, "%s\n", p->paper_tray);
-
- if (set_paper_bin)
- fprintf (output_fp, "%s\n", slots[set_paper_bin - 1]);
- }
-
- /****************************************************************************
- * new_page () *
- * Generate a new page. Send out required rotation,scale information *
- * This is the "prologue" to a page (not the end of the previous) *
- ****************************************************************************/
-
- new_page ()
- {
- }
-
-
- /****************************************************************************
- * showpage () *
- * Generate a real "showpage" if we have really finished generating a *
- * physical page. If we are processing 2 or 4 up, then generate *
- * coordinate "translates" if we really haven't finished all possible *
- * page frames of the page. *
- ****************************************************************************/
-
- showpage (end_of_file)
- int end_of_file;
- {
- line_number = 0;
-
- if (++frame >= max_frame || end_of_file)
- { if (bookwork == 0) /* psd will re-insert this */
- fprintf (output_fp, "showpage pg restore\n");
- frame = 0;
- }
- if (!end_of_file)
- set_frame ();
- }
-
- /****************************************************************************
- * set_frame () *
- * Select the next logical frame in two-up or four-up mode. If it is *
- * the first frame of a physical page, the generate the %%Page *
- ****************************************************************************/
-
- set_frame ()
- {
- if (frame == 0 || bookwork)
- {
- if (book) /* mark byte position of %%Page: for psd */
- { pg_loc[npg_loc++] = ftell (output_fp);
- }
- fprintf (output_fp, "%%%%Page: ? %d\n", ++physical_page);
- if (bookwork == 0) /* psd will re-insert these */
- { fprintf (output_fp, "/pg save def\n");
- if (landscape)
- fprintf (output_fp, "90 rotate 0 %d translate\n", -real_width);
- fprintf (output_fp, "%.5f %.5f scale\n", scale_x, scale_y);
- }
- findfont();
- }
- set_y_coord ();
-
- if (max_frame > 1 && bookwork == 0)
- fprintf (output_fp, "%d %d translate\n", dx_home[frame], dy_home[frame]);
-
- if (frame == 0 && cross)
- draw_cross();
-
- }
-
-
- /****************************************************************************
- * set_y_coord *
- * position next line to the top of a logical page. *
- *****************************************************************************/
-
- set_y_coord ()
- {
- y_coord = p->height - y_top_offset - point_size;
- }
-
- /****************************************************************************
- * put_top *
- * put a header line at the top of the page *
- *****************************************************************************/
-
- put_top ()
- {
- int save_attr, save_point;
-
- save_attr = print_attribute;
- save_point = point_size;
- print_attribute = BOLD;
- point_size = 12;
-
- findfont();
- moveto (0, y_coord, 1);
- if (header == 1)
- fprintf (output_fp, "(%-40s %3d %s)show\n", fname, page_number + 1, now);
- else
- fprintf (output_fp, "(%-40s %3d %s)show\n", header_text, page_number + 1, now);
- y_coord -= point_size * 2;
- x_coord = 0;
- print_attribute = save_attr;
- point_size = save_point;
- findfont();
- }
-
- /****************************************************************************
- * process_file() *
- * Read the file, look for escape sequences, put text in postscript form *
- ****************************************************************************/
-
- process_file ()
- {
- int char_type, char_count, i, set_page, esc_type;
- char *strchr ();
- int previous_attribute;
- int lcount = 0;
-
- set_page = 0;
- while (fgets (line, LONG_STR, input_fp) != NULL)
- {
- if (lcount++ == 0)
- { if ((i = tscan (line, "ta=")) >= 0)
- { tab_size = atoi (line + i + 3);
- }
- /* we could also test here to see if the file is already
- in postscript format and simply copy out the file
- to stdout - however, we couldn't print postscript source.
- By choice, detection of postscript is left to "psdetect"
- in the back-end spooler.
-
- e.g. print postscript source with:
-
- psf thisfile.ps | lp
-
- will work even if psf is working in the print spooler.
- */
- }
- if ((c = (unsigned char *) strchr (line, '\f')) != NULL)
- {
- if (c == line)
- { line_number = 32000;
- c = line + 1;
- }
- else
- { *c = 0;
- set_page = 1;
- c = line;
- }
- }
- else
- c = line;
-
- if (line_number >= lines_on_page * 10)
- { page_number++;
- showpage (0);
- line_number = 10;
- if (header)
- {
- put_top();
- line_number += 20;
- }
- }
- else
- line_number += 10;
-
- char_type = char_count = 0;
-
- /* for empty lines, don't generate a real moveto - but to call
- to ensure that check for page overflow is done.
- */
- if (*c == '\n')
- moveto (x_coord, y_coord, 0); /* don't gen moveto */
- else
- moveto (x_coord, y_coord, 1); /* do gen moveto */
-
- while (*c && *c != '\n')
- {
- if (char_type == 0)
- fputc ('(', output_fp);
-
- switch ((int) *c)
- {
- case ESCAPE:
- previous_attribute = print_attribute;
- esc_type = *(++c);
- if (escape_sequence (esc_type) == 0)
- {
- switch (esc_type)
- {
- case 'u':
- SHOWU (output_fp, point_size);
- break;
-
-
- default:
- if (char_type && (previous_attribute & UNDERLINE))
- SHOWU (output_fp, point_size);
- /*
- else
- if (c == line + 1 && (esc_type == '+' || esc_type == '-'))
- ;
- */
- else
- fputs (")show\n", output_fp);
-
- if (esc_type == '+' || esc_type == '-')
-
- /* check for +/- 1/2 line feed */
-
- {
- if (esc_type == '+')
- y_coord -= point_size / 2;
- else
- y_coord += point_size / 2;
-
- moveto (x_coord, y_coord, 1);
- char_type = -1;
- c++;
- if (*c != '\n')
- fputc ('(', output_fp);
- continue;
- }
- else
- findfont (output_fp);
- }
- char_type = 0;
- }
- break;
-
- default:
- if (*c == '\t')
- {
- fputc (' ', output_fp);
- while (++char_count % tab_size)
- fputc (' ', output_fp);
- }
- else
- { if (strchr ("\r\b\\()", *c) != NULL)
- fputc ('\\', output_fp);
- fputc (*c, output_fp);
- char_count++;
- }
- char_type = 1;
- break;
- }
- c++;
- }
- if (char_type == 1)
- { if (print_attribute & UNDERLINE)
- SHOWU (output_fp, point_size);
- else
- fputs (")show\n", output_fp);
- }
-
- y_coord -= point_size;
- x_coord = 0;
- if (set_page)
- { line_number = 32000;
- set_page = 0;
- }
- }
- }
-
- /****************************************************************************
- * escape_sequence () *
- * If an escape sequence (esc,char) is found, mark which type of font *
- ****************************************************************************/
-
- int escape_sequence (which)
- int which;
- { unsigned char s[10];
-
- switch (which)
- {
- case 'I':
- print_attribute |= ITALICS;
- break;
-
- case 'i':
- print_attribute &= ~ITALICS;
- break;
-
- case 'B':
- print_attribute |= BOLD;
- break;
-
- case 'b':
- print_attribute &= ~BOLD;
- break;
-
- case 'U':
- print_attribute |= UNDERLINE;
- break;
-
- case 'u':
- print_attribute &= ~UNDERLINE;
- break;
-
- case 'F':
- s[0] = *(++c);
- s[1] = '\0';
- font_number = atoi (s);
- if (font_number > (NFONTS / 4))
- font_number = (NFONTS / 4) - 1;
- break;
-
- case 'f':
- font_number = default_font_number;
- break;
-
- case 'P':
- s[0] = *(++c);
- s[1] = *(++c);
- s[2] = '\0';
- point_size = atoi (s);
- break;
-
- case 'p':
- point_size = default_point_size;
- break;
-
- case '+':
- case '-':
- break;
-
- default:
- return (-1);
- ;
- }
- return (0);
- }
-
- /****************************************************************************
- * moveto () *
- * Generate a postscript x y moveto statememt *
- ****************************************************************************/
-
- moveto (x, y, do_move)
- int x;
- int y;
- int do_move; /* 1 = gen moveto 0 = dont gen moveto */
- {
- /* ensure that the current line can fit on the page - including the
- 1/4 line needed for the decenders
- */
-
- if (line_number > lines_on_page * 10 || y < (p->bot_marg + point_size / 3))
- {
- showpage (0);
- if (header)
- {
- put_top();
- line_number += 20;
- }
- y = y_coord;
- x = x_coord;
- }
-
- if (do_move)
- fprintf (output_fp, "%d %d moveto\n", x + x_left_offset, y);
- }
-
- /****************************************************************************
- * findfont () *
- * generate a findfont statement *
- ****************************************************************************/
-
- findfont ()
- { int this;
-
- /* remove reference to UNDERLINE. Underline is not a font. */
-
- this = (font_number * 4) + (print_attribute & 0x03);
- fonts_used[this] = 1;
- fprintf (output_fp, "/%s findfont %d scalefont setfont\n", fonts[this], point_size);
- }
-
- /****************************************************************************
- * start_file () *
- * Generate things that are appropriate for beginning of file processing *
- ****************************************************************************/
-
- start_file ()
- {
- line_number = 0;
- print_attribute = 0;
- page_number = 0;
- frame = -1;
- showpage (0);
- if (header)
- {
- put_top();
- line_number += 20;
- }
- }
-
- /****************************************************************************
- * terminate_file () *
- * Generate things that are appropriate for end of file processing *
- ****************************************************************************/
-
- terminate_file ()
- {
- showpage (1);
- }
-
-
- /****************************************************************************
- * terminate_printer () *
- * Generate things that are appropriate wrap-up after all files printed *
- * For double sided printing (book == 1), generate byte offset info. *
- ****************************************************************************/
-
- terminate_printer ()
- { int i, used;
- long psfptr;
-
- if (book)
- { pg_loc[npg_loc++] = ftell (output_fp);
- }
- fprintf (output_fp, "%%%%Trailer\n");
- for (used = i = 0; i < NFONTS; i++)
- { if (fonts_used[i])
- { used = 1;
- break;
- }
- }
- if (used)
- { fprintf (output_fp, "%%%%DocumentFonts:");
- for (i = 0; i < NFONTS; i ++)
- { if (fonts_used[i])
- fprintf (output_fp, " %s", fonts[i]);
- }
- fprintf (output_fp, "\n");
- }
-
- fprintf (output_fp, "%%%%Pages: %d\n", physical_page);
-
- if (book) /* print statistics for psd */
- {
- psfptr = ftell (output_fp);
- fprintf (output_fp, "%%PsfScale: %.5f %.5f scale\n", scale_x, scale_y);
- fprintf (output_fp, "%%PsfMargin: %d %d %d %d %d\n",
- max_frame, landscape, real_width, p->height, p->width);
- for (i = 0; i < 4; i++)
- fprintf (output_fp, "%%PsfHome: %d %d %d\n", i, dx_home[i], dy_home[i]);
- for (i = 0; i < npg_loc-1; i++)
- fprintf (output_fp, "%%PsfPg: %d %d\n", i, pg_loc[i]);
- fprintf (output_fp, "%%PsfPg: 9999 %d\n", pg_loc[npg_loc-1]);
- fprintf (output_fp, "%%PsfPtr: %d\n", psfptr);
- }
- fprintf (output_fp, "%c", 0x04); /* CTL/D = end job */
- }
-
- /****************************************************************************
- * draw_cross () *
- * Draw horizontal and vertical separation lines between pages 4-up *
- ****************************************************************************/
-
- draw_cross ()
- { int p_w, p_h;
-
- if (max_frame == 4)
- { p_w = p->width;
- p_h = p->height;
- fprintf (output_fp,"%d %d moveto\n", p_w, p_h);
- fprintf (output_fp,"%d %d lineto\n", p_w, -p_h);
- fprintf (output_fp,"%d %d moveto\n", 0, 0);
- fprintf (output_fp,"%d %d lineto\n", p_w * 2, 0);
- fprintf (output_fp,"%s\n", "stroke");
- }
- }
-
- /****************************************************************************
- * output_book () *
- * Send file "double sided print" mode. Used to make a "book". *
- * Will pause the printer to ask for stack re-feed *
- ****************************************************************************/
-
- output_book ()
- {
- #ifdef HOPPER
- if (nslots > 1)
- {
- fflush (output_fp);
- fclose (output_fp);
- strcpy (line, BINDIR);
- if (*line)
- strcat (line, "/");
- strcat (line, "psd -3 1psbook2.d34");
- system (line);
- unlink ("1psbook2.d34");
- }
- #endif
- }
-
- static char *usage_text[] =
- { "Usage: psf [-1|2|4] [-b n] [-c n] [-d] [-f n] [-g type ] [-h] [-H text]",
- " [-i n] [-l n] [-m n] [-n] [-p n] [-t n] [-w] [-x] file...",
- "where:",
- " -1|2|4 print 1,2,4 up (default=1)",
- " -b n paper bin n",
- " -c n print columns",
- " -d double sided",
- " -f n font number (def=0:Courier)",
- " -g type letter legal a4 b5",
- " -h file name header",
- " -H text text header",
- " -i n indent left margin points",
- " -l n print lines per page",
- " -L n lines per page",
- " -m n top margin points",
- " -n portrait (narrow) format",
- " -p n point size n",
- " -t n tabs to n (default=8)",
- " -w landscape (wide) format",
- " -x draw cross (4-up page)",
- " file.. name of files (or stdin)",
- " output: stdout",
- ""
- } ;
-
- usage ()
- { int i, many, n, ff;
-
- for (i = 0; i < 3; i++)
- fprintf (stderr, "%s\n", usage_text[i]);
-
- many = sizeof (usage_text)/sizeof (char *) - 3;
-
- for (i = 0; i < many/2; i++)
- fprintf (stderr, "%-38s %-38s\n", usage_text[i+3], usage_text[i+many/2+3]);
-
- fprintf (stderr,"Fonts selection with -f n (number or name)\n");
- many = 0;
- for (i = 0; i < NFONTS/4; i++)
- { if (fonts_have[i*4])
- { fprintf (stderr, "%2d %-18s", i, fonts[i*4]);
- many++;
- if ((ff = many % 3) == 0)
- fprintf (stderr, "\n");
- }
- }
- if (ff)
- fprintf (stderr, "\n");
-
- fprintf (stderr, "Paper type/size selection with -g type\n");
- many = 0;
- for (i = 0; page_types[i].paper_name[0] != '\0'; i++)
- { n = strlen (page_types[i].paper_name);
- if (many + n > 75)
- { many = 0;
- fprintf (stderr,"\n");
- ff = 0;
- }
- else ff = 1;
- many += n + 3;
- fprintf (stderr," %s", page_types[i].paper_name);
- }
- if (ff)
- fprintf (stderr, "\n");
- exit (0);
- }
-
- /************************************************
- * tscan (s,t) *
- * char s[],t[]; *
- * *
- * Index function as defined in K&R *
- * Look for string t in s *
- * *
- * return -1 if t does not exits in s *
- * else return array position of first *
- * character match *
- ************************************************/
-
-
- tscan (s, t)
- char s[], t[];
- {
- int i, j, k;
- for (i = 0; s[i] != '\0'; i++)
- { for (j = i, k=0; t[k] != '\0' && s[j] == t[k]; j++, k++)
- ;
- if (t[k] == '\0')
- return (i);
- }
- return (-1);
- }
-
- get_time (t)
- char *t;
- {
- long n_time, time ();
- char *x_time, *cc, *strchr();
-
- n_time = time (0); /* get time */
- x_time = ctime (&n_time); /* convert ascii */
- if ((cc = strchr (x_time, '\n')) != NULL)
- *cc = '\0';
- strcpy (t, x_time);
- }
-
- compare (a,b)
- char *a, *b;
- { int aa, bb;
-
- while (*a && *b)
- { aa = *a++;
- bb = *b++;
- if (toupper (aa) != toupper (bb))
- return (aa - bb);
- }
- return (0);
- }
-
- comp (a,b)
- char *a, *b;
- { int aa, bb;
-
- while (*a && *b)
- { aa = *a++;
- bb = *b++;
- if (toupper (aa) != toupper (bb))
- return (aa - bb);
- }
- if (*a == '\0' && *b == '\n')
- return (0);
- return (*a - *b);
- }
-
- trim (s)
- char *s;
- {
- while (*s)
- { if (*s < ' ')
- { *s = 0;
- break;
- }
- s++;
- }
- }
-
- bad_file()
- {
- fprintf (stderr, "Bad %s file\n", PDEF);
- exit (1);
- }
-