home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3403 / dvibook.c next >
Encoding:
C/C++ Source or Header  |  1991-05-23  |  18.8 KB  |  872 lines

  1. /*
  2.  * Copyright (c) 1987, 1989 University of Maryland
  3.  * Department of Computer Science.  All rights reserved.
  4.  * Permission to copy for any purpose is hereby granted
  5.  * so long as this copyright notice remains intact.
  6.  */
  7.  
  8. #ifndef lint
  9. static char rcsid[] = "$Header: /usr/src/local/tex/local/mctex/dvi/RCS/dviselect.c,v 3.1 89/08/22 17:16:13 chris Exp $";
  10. #endif
  11.  
  12. /*
  13.  * DVI page rearrangement program
  14.  *
  15.  * Reads DVI version 2 files and rearranges pages into signatures,
  16.  * writing a new DVI file.
  17.  */
  18.  
  19. #include "libtex/types.h"
  20. #include "libtex/dviclass.h"
  21. #include "libtex/dvicodes.h"
  22. #include "libtex/error.h"
  23. #include "libtex/fio.h"
  24. #include "libtex/gripes.h"
  25. #include "libtex/search.h"
  26. #include <stdio.h>
  27. #include <ctype.h>
  28. #include "libtex/seek.h"
  29.  
  30. #define white(x) ((x) == ' ' || (x) == '\t' || (x) == ',')
  31.  
  32. #define MAXDVIPAGES 1000 /* max (absolute) pages in DVI file */
  33.  
  34. char  *ProgName;
  35. extern char *optarg;
  36. extern int   optind;
  37.  
  38. /* Globals */
  39. char    serrbuf[BUFSIZ];    /* buffer for stderr */
  40.  
  41. /*
  42.  * We will try to keep output lines shorter than MAXCOL characters.
  43.  */
  44. #define MAXCOL    75
  45.  
  46. /*
  47.  * We use the following structure to keep track of fonts we have seen.
  48.  * The final DVI file lists only the fonts it uses.
  49.  */
  50. struct fontinfo {
  51.     i32    fi_newindex;    /* font number in output file */
  52.     int    fi_reallyused;    /* true => used on a page we copied */
  53.     i32    fi_checksum;    /* the checksum */
  54.     i32    fi_mag;        /* the magnification */
  55.     i32    fi_designsize;    /* the design size */
  56.     short    fi_n1;        /* the name header length */
  57.     short    fi_n2;        /* the name body length */
  58.     char    *fi_name;    /* the name itself */
  59. };
  60.  
  61. int     Signature;              /* #pages per signature (multiple of 4) */
  62.  
  63. int    SFlag;            /* true => -s, silent operation */
  64.  
  65. struct    search *FontFinder;    /* maps from input indicies to fontinfo */
  66. i32    NextOutputFontIndex;    /* generates output indicies */
  67. i32    CurrentFontIndex;    /* current (old) index in input */
  68. i32    OutputFontIndex;    /* current (new) index in ouput */
  69.  
  70. char    *DVIFileName;        /* name of input DVI file */
  71. FILE    *inf;            /* the input file itself */
  72. FILE    *outf;            /* the output DVI file */
  73.  
  74. long    StartOfPage[MAXDVIPAGES];    /* The file positions of the
  75.                        input pages */
  76.  
  77. long    StartOfLastPage;    /* The file position just before we
  78.                    started the last page */
  79. long    CurrentPosition;    /* The current position of the file */
  80.  
  81. int    UseThisPage;        /* true => current page is selected */
  82.  
  83. i32    InputPageNumber;    /* current absolute page in old DVI file */
  84. int    NumberOfOutputPages;    /* number of pages in new DVI file */
  85.  
  86. i32    Numerator;        /* numerator from DVI file */
  87. i32    Denominator;        /* denominator from DVI file */
  88. i32    DVIMag;            /* magnification from DVI file */
  89.  
  90. i32    Count[10];        /* the 10 \count variables */
  91.  
  92. /* save some string space: we use this a lot */
  93. char    writeerr[] = "error writing DVI file";
  94.  
  95. char    *malloc(), *realloc();
  96. /*
  97.  * You may get lint warnings about sprintf's return value.
  98.  * Older versions of 4BSD have `char *sprintf()'.  ANSI and
  99.  * SysV use `int sprintf()'; so ignore the warnings.
  100.  */
  101.  
  102. /*
  103.  * Lint gets somewhat confused over putc.
  104.  */
  105. #ifdef lint
  106. #undef putc
  107. #ifdef ultrix /* grr */
  108. #define putc(c, f) fputc((char)(c), f)
  109. #else
  110. #define putc(c, f) fputc((int)(c), f)
  111. #endif
  112. #endif
  113.  
  114. /*
  115.  * Print a message to stderr, with an optional leading space, and handling
  116.  * long line wraps.
  117.  */
  118. message(space, str, len)
  119.     int space;
  120.     register char *str;
  121.     register int len;
  122. {
  123.     static int beenhere;
  124.     static int col;
  125.  
  126.     if (!beenhere)
  127.         space = 0, beenhere++;
  128.     if (len == 0)
  129.         len = strlen(str);
  130.     col += len;
  131.     if (space) {
  132.         if (col >= MAXCOL)
  133.             (void) putc('\n', stderr), col = len;
  134.         else
  135.             (void) putc(' ', stderr), col++;
  136.     }
  137.     while (--len >= 0)
  138.         (void) putc(*str++, stderr);
  139.     (void) fflush(stderr);
  140. }
  141.  
  142. /*
  143.  * Start a page (process a DVI_BOP).
  144.  */
  145. BeginPage()
  146. {
  147.     register i32 *i;
  148.  
  149.     OutputFontIndex = -1;    /* new page requires respecifying font */
  150.     for (i = Count; i < &Count[10]; i++)
  151.         fGetLong(inf, *i);
  152.     (void) GetLong(inf);    /* previous page pointer */
  153.  
  154.     if (!UseThisPage)
  155.         return;
  156.  
  157.     putbyte(outf, DVI_BOP);
  158.     for (i = Count; i < &Count[10]; i++)
  159.         PutLong(outf, *i);
  160.     PutLong(outf, StartOfLastPage);
  161.     if (ferror(outf))
  162.         error(1, -1, writeerr);
  163.  
  164.     StartOfLastPage = CurrentPosition;
  165.     CurrentPosition += 45;    /* we just wrote this much */
  166.  
  167.     if (!SFlag) {        /* write nice page usage messages */
  168.         register int z = 0;
  169.         register int mlen = 0;
  170.         char msg[80];
  171.  
  172.         (void) sprintf(msg, "[%ld", (long)Count[0]);
  173.         mlen = strlen(msg);
  174.         for (i = &Count[1]; i < &Count[10]; i++) {
  175.             if (*i == 0) {
  176.                 z++;
  177.                 continue;
  178.             }
  179.             while (--z >= 0)
  180.                 msg[mlen++] = '.', msg[mlen++] = '0';
  181.             z = 0;
  182.             (void) sprintf(msg + mlen, ".%ld", (long)*i);
  183.             mlen += strlen(msg + mlen);
  184.         }
  185.         message(1, msg, mlen);
  186.     }
  187. }
  188.  
  189. /*
  190.  * End a page (process a DVI_EOP).
  191.  */
  192. EndPage()
  193. {
  194.  
  195.     if (!UseThisPage)
  196.         return;
  197.     if (!SFlag)
  198.         message(0, "]", 1);
  199.     putbyte(outf, DVI_EOP);
  200.     if (ferror(outf))
  201.         error(1, -1, writeerr);
  202.     CurrentPosition++;
  203.     NumberOfOutputPages++;
  204. }
  205.  
  206. /*
  207.  * For each of the fonts used in the new DVI file, write out a definition.
  208.  */
  209. /* ARGSUSED */
  210. void
  211. PostAmbleFontEnumerator(addr, key)
  212.     char *addr;
  213.     i32 key;
  214. {
  215.  
  216.     if (((struct fontinfo *)addr)->fi_reallyused)
  217.         WriteFont((struct fontinfo *)addr);
  218. }
  219.  
  220. HandlePostAmble()
  221. {
  222.     register i32 c;
  223.  
  224.     (void) GetLong(inf);    /* previous page pointer */
  225.     if (GetLong(inf) != Numerator)
  226.         GripeMismatchedValue("numerator");
  227.     if (GetLong(inf) != Denominator)
  228.         GripeMismatchedValue("denominator");
  229.     if (GetLong(inf) != DVIMag)
  230.         GripeMismatchedValue("\\magnification");
  231.  
  232.     putbyte(outf, DVI_POST);
  233.     PutLong(outf, StartOfLastPage);
  234.     PutLong(outf, Numerator);
  235.     PutLong(outf, Denominator);
  236.     PutLong(outf, DVIMag);
  237.     c = GetLong(inf);
  238.     PutLong(outf, c);    /* tallest page height */
  239.     c = GetLong(inf);
  240.     PutLong(outf, c);    /* widest page width */
  241.     c = GetWord(inf);
  242.     PutWord(outf, c);    /* DVI stack size */
  243.     PutWord(outf, NumberOfOutputPages);
  244.     StartOfLastPage = CurrentPosition;    /* point at post */
  245.     CurrentPosition += 29;    /* count all those `put's */
  246. #ifdef notdef
  247.     (void) GetWord(inf);    /* skip original number of pages */
  248. #endif
  249.  
  250.     /*
  251.      * just ignore all the incoming font definitions; we are done with
  252.      * input file 
  253.      */
  254.  
  255.     /*
  256.      * run through the FontFinder table and dump definitions for the
  257.      * fonts we have used. 
  258.      */
  259.     SEnumerate(FontFinder, PostAmbleFontEnumerator);
  260.  
  261.     putbyte(outf, DVI_POSTPOST);
  262.     PutLong(outf, StartOfLastPage);    /* actually start of postamble */
  263.     putbyte(outf, DVI_VERSION);
  264.     putbyte(outf, DVI_FILLER);
  265.     putbyte(outf, DVI_FILLER);
  266.     putbyte(outf, DVI_FILLER);
  267.     putbyte(outf, DVI_FILLER);
  268.     CurrentPosition += 10;
  269.     while (CurrentPosition & 3) {
  270.         putbyte(outf, DVI_FILLER);
  271.         CurrentPosition++;
  272.     }
  273.     if (ferror(outf))
  274.         error(1, -1, writeerr);
  275. }
  276.  
  277. /*
  278.  * Write a font definition to the output file
  279.  */
  280. WriteFont(fi)
  281.     register struct fontinfo *fi;
  282. {
  283.     register int l;
  284.     register char *s;
  285.  
  286.     if (fi->fi_newindex < 256) {
  287.         putbyte(outf, DVI_FNTDEF1);
  288.         putbyte(outf, fi->fi_newindex);
  289.         CurrentPosition += 2;
  290.     } else if (fi->fi_newindex < 65536) {
  291.         putbyte(outf, DVI_FNTDEF2);
  292.         PutWord(outf, fi->fi_newindex);
  293.         CurrentPosition += 3;
  294.     } else if (fi->fi_newindex < 16777216) {
  295.         putbyte(outf, DVI_FNTDEF3);
  296.         Put3Byte(outf, fi->fi_newindex);
  297.         CurrentPosition += 4;
  298.     } else {
  299.         putbyte(outf, DVI_FNTDEF4);
  300.         PutLong(outf, fi->fi_newindex);
  301.         CurrentPosition += 5;
  302.     }
  303.     PutLong(outf, fi->fi_checksum);
  304.     PutLong(outf, fi->fi_mag);
  305.     PutLong(outf, fi->fi_designsize);
  306.     putbyte(outf, fi->fi_n1);
  307.     putbyte(outf, fi->fi_n2);
  308.     l = fi->fi_n1 + fi->fi_n2;
  309.     CurrentPosition += 14 + l;
  310.     s = fi->fi_name;
  311.     while (--l >= 0)
  312.         putbyte(outf, *s++);
  313. }
  314.  
  315. /*
  316.  * Handle the preamble.  Someday we should update the comment field.
  317.  */
  318. HandlePreAmble()
  319. {
  320.     register int n, c;
  321.  
  322.     c = getc(inf);
  323.     if (c == EOF)
  324.         GripeUnexpectedDVIEOF();
  325.     if (c != DVI_PRE)
  326.         GripeMissingOp("PRE");
  327.     if (getc(inf) != DVI_VERSION)
  328.         error(1, 0, "%s is not a DVI version %d file",
  329.             DVIFileName, DVI_VERSION);
  330.     Numerator = GetLong(inf);
  331.     Denominator = GetLong(inf);
  332.     DVIMag = GetLong(inf);
  333.     putbyte(outf, DVI_PRE);
  334.     putbyte(outf, DVI_VERSION);
  335.     PutLong(outf, Numerator);
  336.     PutLong(outf, Denominator);
  337.     PutLong(outf, DVIMag);
  338.  
  339.     n = UnSign8(GetByte(inf));
  340.     CurrentPosition = 15 + n;    /* well, almost */
  341.     putbyte(outf, n);
  342.     while (--n >= 0) {
  343.         c = GetByte(inf);
  344.         putbyte(outf, c);
  345.     }
  346. }
  347.  
  348. main(argc, argv)
  349.     int argc;
  350.     register char **argv;
  351. {
  352.     register int c;
  353.     register char *s;
  354.     char *outname = NULL;
  355.  
  356.     Signature = 0;
  357.  
  358.     ProgName = *argv;
  359.     setbuf(stderr, serrbuf);
  360.  
  361.     while ((c = getopt(argc, argv, "i:o:s:q")) != EOF) {
  362.         switch (c) {
  363.  
  364.         case 'q':    /* silent */
  365.             SFlag++;
  366.             break;
  367.  
  368.         case 'i':
  369.             if (DVIFileName != NULL)
  370.                 goto usage;
  371.             DVIFileName = optarg;
  372.             break;
  373.  
  374.         case 'o':
  375.             if (outname != NULL)
  376.                 goto usage;
  377.             outname = optarg;
  378.             break;
  379.  
  380.         case 's':
  381.             if (Signature != 0)
  382.                 goto usage;
  383.             Signature = atoi(optarg);
  384.             if (Signature <= 0)
  385.                error(1, -1, "-s parameter must be > 0");
  386.             if (Signature % 4 != 0)
  387.                error(1, -1,
  388.                  "-s parameter must be a multiple of 4");
  389.             break;
  390.  
  391.         case '?':
  392. usage:
  393.             (void) fprintf(stderr, "\
  394. Usage: %s [-s signature] [-q] [-i infile] [-o outfile] [infile [outfile]]\n",
  395.                 ProgName);
  396.             (void) fflush(stderr);
  397.             exit(1);
  398.         }
  399.     }
  400.  
  401.     while (optind < argc) {
  402.         s = argv[optind++];
  403.         c = *s;
  404.         if (DVIFileName == NULL)
  405.             DVIFileName = s;
  406.         else if (outname == NULL)
  407.             outname = s;
  408.         else
  409.             goto usage;
  410.     }
  411.     if (DVIFileName == NULL) {
  412.         DVIFileName = "`stdin'";
  413.         inf = stdin;
  414.     } else if ((inf = fopen(DVIFileName, "r")) == 0)
  415.         error(1, -1, "cannot read %s", DVIFileName);
  416.     if (outname == NULL)
  417.         outf = stdout;
  418.     else if ((outf = fopen(outname, "w")) == 0)
  419.         error(1, -1, "cannot write %s", outname);
  420.  
  421.     if ((FontFinder = SCreate(sizeof(struct fontinfo))) == 0)
  422.         error(1, 0, "cannot create font finder (out of memory?)");
  423.  
  424.     /* copy inf to TEMP file if not seekable */
  425.     if ((inf = SeekFile(inf)) == NULL) {
  426.             error(1, 0, "can't seek file");
  427.     }
  428.     InputPageNumber = 0;
  429.     StartOfLastPage = -1;
  430.     HandlePreAmble();
  431.     ScanDVIFile();
  432.     HandleDVIFile();
  433.     HandlePostAmble();
  434.     if (!SFlag)
  435.         (void) fprintf(stderr, "\nWrote %d page%s, %ld bytes\n",
  436.             NumberOfOutputPages, NumberOfOutputPages == 1 ? "" : "s",
  437.             (long)CurrentPosition);
  438.     exit(0);
  439.     /* NOTREACHED */
  440. }
  441.  
  442. /*
  443.  * Handle a font definition.
  444.  */
  445. HandleFontDef(index)
  446.     i32 index;
  447. {
  448.     register struct fontinfo *fi;
  449.     register int i;
  450.     register char *s;
  451.     int def = S_CREATE | S_EXCL;
  452.  
  453.     if (!UseThisPage) {
  454.         if ((fi = (struct fontinfo *)SSearch(FontFinder, index, &def)) == 0)
  455.             if (def & S_COLL)
  456.                 error(1, 0, "font %ld already defined", (long)index);
  457.             else
  458.                 error(1, 0, "cannot stash font %ld (out of memory?)",
  459.                     (long)index);
  460.         fi->fi_reallyused = 0;
  461.         fi->fi_checksum = GetLong(inf);
  462.         fi->fi_mag = GetLong(inf);
  463.         fi->fi_designsize = GetLong(inf);
  464.         fi->fi_n1 = UnSign8(GetByte(inf));
  465.         fi->fi_n2 = UnSign8(GetByte(inf));
  466.         i = fi->fi_n1 + fi->fi_n2;
  467.         if ((s = malloc((unsigned)i)) == 0)
  468.             GripeOutOfMemory(i, "font name");
  469.         fi->fi_name = s;
  470.         while (--i >= 0)
  471.             *s++ = GetByte(inf);
  472.     } else {
  473.             (void) GetLong(inf);
  474.             (void) GetLong(inf);
  475.             (void) GetLong(inf);
  476.         i = UnSign8(GetByte(inf));
  477.         i += UnSign8(GetByte(inf));
  478.         while (--i >= 0)
  479.             (void) GetByte(inf);
  480.     }
  481. }
  482.  
  483. /*
  484.  * Handle a \special.
  485.  */
  486. HandleSpecial(c, l, p)
  487.     int c;
  488.     register int l;
  489.     register i32 p;
  490. {
  491.     register int i;
  492.  
  493.     if (UseThisPage) {
  494.         putbyte(outf, c);
  495.         switch (l) {
  496.  
  497.         case DPL_UNS1:
  498.             putbyte(outf, p);
  499.             CurrentPosition += 2;
  500.             break;
  501.  
  502.         case DPL_UNS2:
  503.             PutWord(outf, p);
  504.             CurrentPosition += 3;
  505.             break;
  506.  
  507.         case DPL_UNS3:
  508.             Put3Byte(outf, p);
  509.             CurrentPosition += 4;
  510.             break;
  511.  
  512.         case DPL_SGN4:
  513.             PutLong(outf, p);
  514.             CurrentPosition += 5;
  515.             break;
  516.  
  517.         default:
  518.             panic("HandleSpecial l=%d", l);
  519.             /* NOTREACHED */
  520.         }
  521.         CurrentPosition += p;
  522.         while (--p >= 0) {
  523.             i = getc(inf);
  524.             putbyte(outf, i);
  525.         }
  526.         if (feof(inf))
  527.             GripeUnexpectedDVIEOF();
  528.         if (ferror(outf))
  529.             error(1, -1, writeerr);
  530.     } else
  531.         while (--p >= 0)
  532.             (void) getc(inf);
  533. }
  534.  
  535. ReallyUseFont()
  536. {
  537.     register struct fontinfo *fi;
  538.     int look = S_LOOKUP;
  539.  
  540.     fi = (struct fontinfo *)SSearch(FontFinder, CurrentFontIndex, &look);
  541.     if (fi == NULL)
  542.         error(1, 0, "DVI file requested font %ld without defining it",
  543.             (long)CurrentFontIndex);
  544.     if (fi->fi_reallyused == 0) {
  545.         fi->fi_reallyused++;
  546.         fi->fi_newindex = NextOutputFontIndex++;
  547.         WriteFont(fi);
  548.     }
  549.     if (fi->fi_newindex != OutputFontIndex) {
  550.         PutFontSelector(fi->fi_newindex);
  551.         OutputFontIndex = fi->fi_newindex;
  552.     }
  553. }
  554.  
  555. /*
  556.  * Write a font selection command to the output file
  557.  */
  558. PutFontSelector(index)
  559.     i32 index;
  560. {
  561.  
  562.     if (index < 64) {
  563.         putbyte(outf, index + DVI_FNTNUM0);
  564.         CurrentPosition++;
  565.     } else if (index < 256) {
  566.         putbyte(outf, DVI_FNT1);
  567.         putbyte(outf, index);
  568.         CurrentPosition += 2;
  569.     } else if (index < 65536) {
  570.         putbyte(outf, DVI_FNT2);
  571.         PutWord(outf, index);
  572.         CurrentPosition += 3;
  573.     } else if (index < 16777216) {
  574.         putbyte(outf, DVI_FNT3);
  575.         Put3Byte(outf, index);
  576.         CurrentPosition += 4;
  577.     } else {
  578.         putbyte(outf, DVI_FNT4);
  579.         PutLong(outf, index);
  580.         CurrentPosition += 5;
  581.     }
  582. }
  583.  
  584. /*
  585.  * The following table describes the length (in bytes) of each of the DVI
  586.  * commands that we can simply copy, starting with DVI_SET1 (128).
  587.  */
  588. char    oplen[128] = {
  589.     0, 0, 0, 0,        /* DVI_SET1 .. DVI_SET4 */
  590.     9,            /* DVI_SETRULE */
  591.     0, 0, 0, 0,        /* DVI_PUT1 .. DVI_PUT4 */
  592.     9,            /* DVI_PUTRULE */
  593.     1,            /* DVI_NOP */
  594.     0,            /* DVI_BOP */
  595.     0,            /* DVI_EOP */
  596.     1,            /* DVI_PUSH */
  597.     1,            /* DVI_POP */
  598.     2, 3, 4, 5,        /* DVI_RIGHT1 .. DVI_RIGHT4 */
  599.     1,            /* DVI_W0 */
  600.     2, 3, 4, 5,        /* DVI_W1 .. DVI_W4 */
  601.     1,            /* DVI_X0 */
  602.     2, 3, 4, 5,        /* DVI_X1 .. DVI_X4 */
  603.     2, 3, 4, 5,        /* DVI_DOWN1 .. DVI_DOWN4 */
  604.     1,            /* DVI_Y0 */
  605.     2, 3, 4, 5,        /* DVI_Y1 .. DVI_Y4 */
  606.     1,            /* DVI_Z0 */
  607.     2, 3, 4, 5,        /* DVI_Z1 .. DVI_Z4 */
  608.     0,            /* DVI_FNTNUM0 (171) */
  609.     0, 0, 0, 0, 0, 0, 0, 0,    /* 172 .. 179 */
  610.     0, 0, 0, 0, 0, 0, 0, 0,    /* 180 .. 187 */
  611.     0, 0, 0, 0, 0, 0, 0, 0,    /* 188 .. 195 */
  612.     0, 0, 0, 0, 0, 0, 0, 0,    /* 196 .. 203 */
  613.     0, 0, 0, 0, 0, 0, 0, 0,    /* 204 .. 211 */
  614.     0, 0, 0, 0, 0, 0, 0, 0,    /* 212 .. 219 */
  615.     0, 0, 0, 0, 0, 0, 0, 0,    /* 220 .. 227 */
  616.     0, 0, 0, 0, 0, 0, 0,    /* 228 .. 234 */
  617.     0, 0, 0, 0,        /* DVI_FNT1 .. DVI_FNT4 */
  618.     0, 0, 0, 0,        /* DVI_XXX1 .. DVI_XXX4 */
  619.     0, 0, 0, 0,        /* DVI_FNTDEF1 .. DVI_FNTDEF4 */
  620.     0,            /* DVI_PRE */
  621.     0,            /* DVI_POST */
  622.     0,            /* DVI_POSTPOST */
  623.     0, 0, 0, 0, 0, 0,    /* 250 .. 255 */
  624. };
  625.  
  626. /*
  627.  * Here we scan the input DVI file and record pointers to the pages.
  628.  */
  629. ScanDVIFile()
  630. {
  631.     UseThisPage = 0;
  632.  
  633.     StartOfPage[InputPageNumber] = ftell(inf);
  634.     while (HandlePage()) {  /* scan DVI file */
  635.             StartOfPage[++InputPageNumber] = ftell(inf);
  636.     }
  637. }
  638.  
  639. /*
  640.  * Here we read the input DVI file and write relevant pages to the
  641.  * output DVI file. We also keep track of font changes, handle font
  642.  * definitions, and perform some other housekeeping.
  643.  */
  644. HandleDVIFile()
  645. {
  646.         int CurrentPage, ActualPage, MaxPage;
  647.  
  648.     UseThisPage = 1;
  649.  
  650.     MaxPage = InputPageNumber + (4-InputPageNumber%4)%4;
  651.  
  652.     if (!Signature)
  653.             Signature = MaxPage;
  654.     for (CurrentPage = 0; CurrentPage < MaxPage; CurrentPage++) {
  655.             ActualPage = CurrentPage - CurrentPage%Signature;
  656.             switch (CurrentPage%4) {
  657.         case 0:
  658.         case 3:
  659.            ActualPage += Signature-1-(CurrentPage%Signature)/2;
  660.            break;
  661.         case 1:
  662.         case 2:
  663.            ActualPage += (CurrentPage%Signature)/2;
  664.            break;
  665.         }
  666.             if (ActualPage < InputPageNumber) {
  667.                 if (fseek(inf, StartOfPage[ActualPage], 0) == -1)
  668.                        error(1, -1,
  669.                      "can't seek page %d", ActualPage+1);
  670.                 HandlePage();
  671.         } else
  672.                         PutEmptyPage();
  673.     }
  674.     if (fseek(inf, StartOfPage[InputPageNumber]+1, 0) == -1)
  675.             error(1, -1, "can't seek last page");
  676. }
  677.  
  678. int
  679. HandlePage()
  680. {
  681.     register int c, l;
  682.     register i32 p;
  683.     register int CurrentFontOK = 0;
  684.     int doingpage = 0;
  685.  
  686.     /* Only way out is via "return" statement */
  687.     for (;;) {
  688.         c = getc(inf);    /* getc() returns unsigned values */
  689.         if (DVI_IsChar(c)) {
  690.             /*
  691.              * Copy chars, note font usage, but ignore if
  692.              * page is not interesting.
  693.              */
  694.             if (!UseThisPage)
  695.                 continue;
  696.             if (!CurrentFontOK) {
  697.                 ReallyUseFont();
  698.                 CurrentFontOK++;
  699.             }
  700.             putbyte(outf, c);
  701.             CurrentPosition++;
  702.             continue;
  703.         }
  704.         if (DVI_IsFont(c)) {    /* note font change */
  705.             CurrentFontIndex = c - DVI_FNTNUM0;
  706.             CurrentFontOK = 0;
  707.             continue;
  708.         }
  709.         if (c == EOF)
  710.             GripeUnexpectedDVIEOF();
  711.         if ((l = (oplen - 128)[c]) != 0) {    /* simple copy */
  712.             if (!UseThisPage) {
  713.                 while (--l > 0)
  714.                     (void) getc(inf);
  715.                 continue;
  716.             }
  717.             CurrentPosition += l;
  718.             putbyte(outf, c);
  719.             while (--l > 0) {
  720.                 c = getc(inf);
  721.                 putbyte(outf, c);
  722.             }
  723.             if (ferror(outf))
  724.                 error(1, -1, writeerr);
  725.             continue;
  726.         }
  727.         if ((l = DVI_OpLen(c)) != 0) {
  728.             /*
  729.              * Handle other generics.
  730.              * N.B.: there should only be unsigned parameters
  731.              * here (save SGN4), for commands with negative
  732.              * parameters have been taken care of above.
  733.              */
  734.             switch (l) {
  735.  
  736.             case DPL_UNS1:
  737.                 p = getc(inf);
  738.                 break;
  739.  
  740.             case DPL_UNS2:
  741.                 fGetWord(inf, p);
  742.                 break;
  743.  
  744.             case DPL_UNS3:
  745.                 fGet3Byte(inf, p);
  746.                 break;
  747.  
  748.             case DPL_SGN4:
  749.                 fGetLong(inf, p);
  750.                 break;
  751.  
  752.             default:
  753.                 panic("HandleDVIFile l=%d", l);
  754.             }
  755.  
  756.             /*
  757.              * Now that we have the parameter, perform the
  758.              * command.
  759.              */
  760.             switch (DVI_DT(c)) {
  761.  
  762.             case DT_SET:
  763.             case DT_PUT:
  764.                 if (!UseThisPage)
  765.                     continue;
  766.                 if (!CurrentFontOK) {
  767.                     ReallyUseFont();
  768.                     CurrentFontOK++;
  769.                 }
  770.                 putbyte(outf, c);
  771.                 switch (l) {
  772.  
  773.                 case DPL_UNS1:
  774.                     putbyte(outf, p);
  775.                     CurrentPosition += 2;
  776.                     continue;
  777.  
  778.                 case DPL_UNS2:
  779.                     PutWord(outf, p);
  780.                     CurrentPosition += 3;
  781.                     continue;
  782.  
  783.                 case DPL_UNS3:
  784.                     Put3Byte(outf, p);
  785.                     CurrentPosition += 4;
  786.                     continue;
  787.  
  788.                 case DPL_SGN4:
  789.                     PutLong(outf, p);
  790.                     CurrentPosition += 5;
  791.                     continue;
  792.                 }
  793.  
  794.             case DT_FNT:
  795.                 CurrentFontIndex = p;
  796.                 CurrentFontOK = 0;
  797.                 continue;
  798.  
  799.             case DT_XXX:
  800.                 HandleSpecial(c, l, p);
  801.                 continue;
  802.  
  803.             case DT_FNTDEF:
  804.                 HandleFontDef(p);
  805.                 continue;
  806.  
  807.             default:
  808.                 panic("HandleDVIFile DVI_DT(%d)=%d",
  809.                       c, DVI_DT(c));
  810.             }
  811.             continue;
  812.         }
  813.  
  814.         switch (c) {    /* handle the few remaining cases */
  815.  
  816.         case DVI_BOP:
  817.             if (doingpage)
  818.                 GripeUnexpectedOp("BOP (during page)");
  819.             BeginPage();
  820.             doingpage = 1;
  821.             break;
  822.  
  823.         case DVI_EOP:
  824.             if (!doingpage)
  825.                 GripeUnexpectedOp("EOP (outside page)");
  826.             EndPage();
  827.             doingpage = 0;
  828.             return(1);
  829.  
  830.         case DVI_PRE:
  831.             GripeUnexpectedOp("PRE");
  832.             /* NOTREACHED */
  833.  
  834.         case DVI_POST:
  835.             if (doingpage)
  836.                 GripeUnexpectedOp("POST (inside page)");
  837.             return(0);
  838.  
  839.         case DVI_POSTPOST:
  840.             GripeUnexpectedOp("POSTPOST");
  841.             /* NOTREACHED */
  842.  
  843.         default:
  844.             GripeUndefinedOp(c);
  845.             /* NOTREACHED */
  846.         }
  847.     }
  848. }
  849.  
  850. /* write an empty page to fill out space */
  851. PutEmptyPage()
  852. {
  853.         int i;
  854.  
  855.     putbyte(outf, DVI_BOP);
  856.     PutLong(outf, -1L);
  857.     for (i = 1; i < 10; i++)     /* set all sub counts to 0 */
  858.         PutLong(outf, 0L);
  859.     PutLong(outf, StartOfLastPage);
  860.     putbyte(outf, DVI_EOP);
  861.     if (!SFlag) {        /* write nice page usage messages */
  862.         char *msg = "[*]";
  863.         message(1, msg, strlen(msg));
  864.     }
  865.     if (ferror(outf))
  866.         error(1, -1, writeerr);
  867.  
  868.     StartOfLastPage = CurrentPosition;
  869.     CurrentPosition += 46;    /* we just wrote this much */
  870.     NumberOfOutputPages++;
  871. }
  872.