home *** CD-ROM | disk | FTP | other *** search
- /* ta=4 */
-
- /****************************************************************************
- * p s d . c v2.0 *
- * *
- * Filter a "single sided" document to become a "double sided document" *
- * *
- * Tony Field. tony@ajfcal *
- * *
- * The basic algorithm for "print_book()" was based on a routine written *
- * by Tom Neff (tneff@well.uucp) named "book" which printed 5.5x8.5 *
- * double sided on an HP LaserJet. *
- ****************************************************************************/
- /*
- A number of comments could be made about psd:
- 1. it does work.
- 2. it could work a lot better
- 3. output is minimally conforming to postscript
- 4. input is "similar to" postscript
-
- the psf-generated control information is assumed to be at the
- end of the postscript print file. The postscript file must contain
- a line like:
- %PsfPtr: 21118
-
- If the %PsPtr line is missing, then the file is NOT a book format.
- The format of this information is described in function read_control().
-
- psd does little to normal double sided print other than to change
- the order in which the pages are printed. It also adjusts the
- %%Pages: value to reflect the actual page count printed.
-
- psd re-inserts translation, rotation and scale information eliminated
- by psf if the double sided print is to make an 8.5x5.5 "book".
-
- Of course, a bunch of "very ugly" logic is needed for the "book"
- format to re-insert the postscript for page control - but it does work...
- */
-
- #include <stdio.h>
- #include <string.h>
-
- /* If books are made by generating two print files with the -s side count
- then set SIDECOUNT = 0 (i.e. no alternate paper hopper is available.
-
- If books are made by switching to the alternate print hopper for
- the second side, then set SIDECOUNT = 3 (i.e. second hopper is available
- */
-
- #define SIDECOUNT 0
-
- #define LONG_STR 1000
- #define MAX_PAGE 1000
-
- static int nsheets, nhalves;
- static int row;
- static int lpage, rpage;
-
- char slots[4][100] =
- { "statusdict begin 1 setpapertray end",
- "statusdict begin 2 setpapertray end",
- "",
- ""
- } ;
- int nslots = 2;
-
- char line[LONG_STR + 1];
- char scale[100];
- int max_frame;
- int landscape;
- int real_width;
- int height;
- int width;
- int dx_home[4];
- int dy_home[4];
- int npage;
- long pg_loc[MAX_PAGE];
- long trailer_loc;
- int phys_page;
- int side;
- int bookwork;
- int alternate_tray = 0;
- int second_side = 0;
-
- FILE *input_fp;
- FILE *output_fp;
-
- char *pgmname;
-
- main(argc, argv)
- int argc;
- char *argv[];
- { int c;
- extern char *optarg;
- extern int optind;
- FILE *pdef;
-
- side = SIDECOUNT; /* print size 1, 2, or both = 3 */
-
- if ((pdef = fopen (PDEF, "r")) != NULL)
- { nslots = 0;
- while (fgets (line, LONG_STR - 1, pdef) != NULL)
- { trim (line);
- 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;
- }
- }
- }
- }
- fclose (pdef);
- }
-
- pgmname = argv[0];
- if (argc > 1 && strcmp (argv[1], "-") == 0)
- usage ();
-
- while ((c = getopt(argc, argv, "123-")) != -1)
- { switch (c)
- {
- case '1':
- case '2':
- case '3':
- side = c - '0';
- break;
-
- default:
- usage ();
- }
- }
- if (side == 3 && nslots < 2)
- { fprintf (stderr, "Cannot use -3: only one output tray\n");
- exit (1);
- }
-
- if (side <= 0 || side >= 4)
- { fprintf (stderr, "Print side must be 1, 2, or 3\n");
- exit (1);
- }
- if (optind >= argc)
- usage ();
-
- output_fp = stdout;
-
- if ((input_fp = fopen(argv[optind], "r")) == NULL)
- {
- fprintf(stderr, "%s: Error opening %s!\n", pgmname, argv[1]);
- exit (1);
- }
- read_control (input_fp);
- get_prologue ();
- if (bookwork)
- print_book ();
- else
- print_double ();
- get_trailer ();
- exit (0);
- }
-
- /****************************************************************************
- * read_control() *
- * Read the control information at the end of the file for the page *
- * dimensions and byte address of the start of each page. *
- * Each of the parameter lines is a comment with the form %Psfxxxx: yyyy *
- ****************************************************************************/
-
- read_control (fp)
- FILE *fp;
- { char tail[100];
- int i, j;
- long atol(), psfloc;
-
- /* %PsfPtr: xxx --> xxx is the pointer to the first %Psf... line
- in the file. Seek to the indicated byte position to begin
- reading the Psf generated information which looks like:
-
- %%Trailer <--- (a)
- %%DocumentFonts: Courier
- %%Pages: 8
- %PsfScale: 0.63194 0.79558 scale <--- (b)
- %PsfMargin: 2 1 612 769 626
- %PsfHome: 0 0 0
- %PsfHome: 1 626 0
- %PsfHome: 2 0 0
- %PsfHome: 3 0 0
- %PsfPg: 0 405 <--- byte offsets to page
- %PsfPg: 1 3885
- %PsfPg: 2 7023
- ...
- %PsfPg: 9999 21072 <--- points to (a) above
- %PsfPtr: 21118 <--- points to (b) above
- <ctrl/d>
- */
- fseek (fp, -50L, 2);
- fread (tail, 50, 1, fp);
- if ((i = tscan (tail, "%PsfPtr:")) == -1)
- { fprintf (stderr, "%s: File is not in psf book format\n", pgmname);
- exit (1);
- }
- psfloc = atol (tail + i + 9); /* beginning of psf information */
- fseek (fp, psfloc, 0);
-
- fgets (scale, 99, fp);
- strcpy (tail, scale + 11); /* get rid of the %psf comment */
- strcpy (scale, tail);
-
- /* fetch psf data. */
- /* %PsfMargin: */
- fscanf (fp, "%s %d %d %d %d %d", tail,
- &max_frame, &landscape, &real_width, &height, &width);
-
- bookwork = max_frame == 2 && landscape;
- for (i = 0; i < 4; i++) /* %PsfHome: */
- fscanf (fp, "%s %d %d %d", tail, &j, &dx_home[i], &dy_home[i]);
-
- npage = 0; /* %PsfPg: */
- while (fscanf (fp, "%s %d %ld", tail, &i, &pg_loc[npage]) == 3)
- {
- if (i == 9999)
- { trailer_loc = pg_loc[npage];
- break;
- }
- npage++;
- }
- fseek (fp, 0L, 0);
- }
-
- /****************************************************************************
- * get_prologue() *
- * Read the prologue and pass it directly to the output *
- ****************************************************************************/
-
- get_prologue ()
- {
- fgets (line, LONG_STR, input_fp); /* skip the psf header */
- fprintf (output_fp, "%%!PS-Adobe-\n"); /* write a valid header */
- while (fgets (line, LONG_STR, input_fp) != NULL)
- { if (strncmp (line, "%%Page:", 7) == 0)
- break;
- fputs (line, output_fp);
- }
- }
-
- /****************************************************************************
- * get_trailer () *
- * Read the trailer and pass it to the output. Modify the page count to *
- * reflect the number of physical pages printed. *
- * Remove any reference to the %Psf... lines. *
- ****************************************************************************/
-
- get_trailer ()
- {
- if (phys_page == 0 || (bookwork && second_side))
- fprintf (output_fp, "showpage pg restore\n");
- if (alternate_tray == 2)
- fprintf (output_fp, "%s\n", slots[0]);
- fseek (input_fp, trailer_loc, 0);
- while (fgets (line, LONG_STR, input_fp) != NULL)
- { if (strncmp (line, "%%Pages:", 8) == 0)
- fprintf (output_fp, "%%%%Pages: %d\n", phys_page);
- else if (strncmp (line, "%Psf", 4) != 0)
- fputs (line, output_fp);
- }
- }
-
- /****************************************************************************
- * display_page() *
- * Send all ouput that belongs to a specific page. For 8.5x5.5 books, *
- * generate the scale, etc that was omitted by psf. Also enable the *
- * alternate tray if it to be used. *
- ****************************************************************************/
-
- display_page (pgno, n)
- int pgno;
- int n;
- { static need_showpage = 0;
-
- fseek (input_fp, pg_loc[pgno], 0);
- fgets (line, LONG_STR, input_fp);
- if (n == 0)
- {
- if ((phys_page && bookwork) || need_showpage)
- fprintf (output_fp, "showpage pg restore\n");
-
- if (alternate_tray == 1)
- { alternate_tray = 2;
- fprintf (output_fp, "%s\n", slots[1]);
- }
- fprintf (output_fp, "%%%%Page: ? %d\n", ++phys_page);
- if ((bookwork && max_frame == 2) || pgno >= npage)
- { fprintf (output_fp, "/pg save def\n");
- }
- need_showpage = pgno >= npage;
- }
-
- if (bookwork)
- { if (n == 0)
- {
- fprintf (output_fp, "90 rotate 0 %d translate\n", -real_width);
- fprintf (output_fp, "%s", scale);
- }
- fprintf (output_fp, "%d %d translate\n", dx_home[n], dy_home[n]);
- }
-
- if (pgno < npage)
- { while (fgets (line, LONG_STR, input_fp) != NULL)
- { if(strncmp (line, "%%", 2) == 0)
- break;
- fputs (line, output_fp);
- }
- }
- }
-
-
- /****************************************************************************
- * print_book() *
- * print_book() is based on Tom Neff's (tneff@well.uucp) "book" *
- * for the HP LaserJet *
- * Scan the text to ensure that the 8.5x.5.5 pages are constructed in *
- * such a way that a "book" is generated - simply staple in the middle . *
- ****************************************************************************/
-
- print_book ()
- { int done;
-
- nsheets = (npage+3)/4;
- nhalves = nsheets*4;
- phys_page = 0;
-
- if (side & 1)
- { for (rpage=0, lpage=nhalves-1; rpage < lpage; rpage+=2, lpage-=2)
- {
- display_page (lpage, 0);
- display_page (rpage, 1);
- }
- }
-
- if (side == 3)
- alternate_tray = 1;
-
- if ((side & 2) && nhalves > 1)
- { second_side = 1;
- for (rpage=nhalves/2, lpage=rpage-1; lpage >= 0; rpage+=2, lpage-=2)
- {
- display_page (lpage, 0);
- display_page (rpage, 1);
- }
- }
- }
-
- /****************************************************************************
- * print double() *
- * print double sided pages. first odd numbered, then even numbered. *
- ****************************************************************************/
-
- print_double()
- {
- nsheets = (npage+1)/2;
- phys_page = 0;
-
- if (side & 1)
- { for (rpage=0; rpage < nsheets; rpage++)
- {
- display_page (rpage * 2, 0);
- }
- }
-
- if (side == 3)
- alternate_tray = 1;
-
- if (side & 2 && npage > 1)
- { second_side = 1;
- for (rpage=nsheets - 1; rpage >= 0; rpage--)
- {
- display_page (rpage * 2 + 1, 0);
- }
- }
- }
-
-
- tscan (s, t) /* search for string t in s */
- 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);
- }
- usage ()
- {
- printf ("Usage: psd -n file\n");
- printf (" where: n = side number to print\n");
- printf (" -1 = print side 1 only\n");
- printf (" -2 = print side 2 only\n");
- printf (" -3 = print both sides in one pass\n");
- printf (" file = print this file\n");
- exit (0);
- }
-
- trim (s)
- char *s;
- {
- while (*s)
- { if (*s < ' ')
- { *s = 0;
- break;
- }
- s++;
- }
- }
-