/* * Copyright (c) 1987, 1989 University of Maryland * Department of Computer Science. All rights reserved. * Permission to copy for any purpose is hereby granted * so long as this copyright notice remains intact. */ #ifndef lint 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 $"; #endif /* * DVI page rearrangement program * * Reads DVI version 2 files and rearranges pages, * writing a new DVI file. */ #include "libtex/types.h" #include "libtex/dviclass.h" #include "libtex/dvicodes.h" #include "libtex/error.h" #include "libtex/fio.h" #include "libtex/gripes.h" #include "libtex/search.h" #include #include #include "libtex/seek.h" #define white(x) ((x) == ' ' || (x) == '\t' || (x) == ',') #define MAXDVIPAGES 1000 /* max (absolute) pages in DVI file */ char *ProgName; extern char *optarg; extern int optind; /* Globals */ char serrbuf[BUFSIZ]; /* buffer for stderr */ /* * We will try to keep output lines shorter than MAXCOL characters. */ #define MAXCOL 75 /* * We use the following structure to keep track of fonts we have seen. * The final DVI file lists only the fonts it uses. */ struct fontinfo { i32 fi_newindex; /* font number in output file */ int fi_reallyused; /* true => used on a page we copied */ i32 fi_checksum; /* the checksum */ i32 fi_mag; /* the magnification */ i32 fi_designsize; /* the design size */ short fi_n1; /* the name header length */ short fi_n2; /* the name body length */ char *fi_name; /* the name itself */ }; i32 Width; /* width of page */ i32 Height; /* height of page */ i32 Magnification; /* Magnification of pages */ int Modulo; /* page spec modulo */ struct pagespec *PageSpecs; /* page specification list */ int SFlag; /* true => -s, silent operation */ struct search *FontFinder; /* maps from input indicies to fontinfo */ i32 NextOutputFontIndex; /* generates output indicies */ i32 CurrentFontIndex; /* current (old) index in input */ i32 OutputFontIndex; /* current (new) index in ouput */ char *DVIFileName; /* name of input DVI file */ FILE *inf; /* the input file itself */ FILE *outf; /* the output DVI file */ long StartOfPage[MAXDVIPAGES]; /* The file positions of the input pages */ long StartOfLastPage; /* The file position just before we started the last page */ long CurrentPosition; /* The current position of the file */ int UseThisPage; /* true => current page is selected */ i32 InputPageNumber; /* current absolute page in old DVI file */ int NumberOfOutputPages; /* number of pages in new DVI file */ i32 Numerator; /* numerator from DVI file */ i32 Denominator; /* denominator from DVI file */ i32 DVIMag; /* magnification from DVI file */ i32 Count[10]; /* the 10 \count variables */ /* save some string space: we use this a lot */ char writeerr[] = "error writing DVI file"; char *malloc(), *realloc(); /* * You may get lint warnings about sprintf's return value. * Older versions of 4BSD have `char *sprintf()'. ANSI and * SysV use `int sprintf()'; so ignore the warnings. */ /* * Lint gets somewhat confused over putc. */ #ifdef lint #undef putc #ifdef ultrix /* grr */ #define putc(c, f) fputc((char)(c), f) #else #define putc(c, f) fputc((int)(c), f) #endif #endif void specusage() { error(1, -1, "page specification error:\n\ = [modulo:][mag@]\n\ = [-]pageno[(xoff,yoff)][,spec|+spec]\n\ modulo>=1, 0<=pageno 0x40000000L) error(1, -1, "arithmetic overflow in dimension") ; sf = sf % den ; v += (sf * num * 2 + den) / (2 * den) ; return (v) ; } struct pagespec { int reversed, pageno, add; i32 xoff, yoff; struct pagespec *next; }; struct pagespec *newspec() { struct pagespec *temp = (struct pagespec *)malloc(sizeof(struct pagespec)); temp->reversed = temp->pageno = temp->add = 0; temp->xoff = temp->yoff = 0; temp->next = NULL; return (temp); } int parseint(sp) char **sp; { char *s = *sp; int n = 0, neg = 0; if (*s == '-') { neg = 1; s++; } for (; isdigit(*s); s++) n = n*10 + (*s-'0'); if (*sp == s) specusage(); *sp = s; return (neg ? -n : n); } i32 parsedimen(sp) char **sp; { i32 whole = 0; int num = 0, den = 1, neg = 0; i32 fac = 0L; char *s = *sp; if (*s == '-') { neg = 1; *sp = ++s; } for (; isdigit(*s); s++) whole = whole*10 + (*s-'0'); if (*s == '.') { *sp = ++s; for (; isdigit(*s); s++) { if (den < 10000) { /* limit precision for scale to work */ num = num*10 + (*s-'0'); den *= 10; } } } if (*sp == s) specusage(); *sp = s; /* * Allowed units are `in', `cm', `mm', `pt', `sp', `cc', `dd', and `pc'; * must be in lower case. */ if (*s == 'c' && s[1] == 'm') { /* centimeters need to be scaled by 72.27 * 216 / 2.54, or 1 864 680 */ fac = 1864680L ; s += 2; } else if (*s == 'p' && s[1] == 't') { /* real points need to be scaled by 65536 */ fac = 65536L ; s += 2; } else if (*s == 'p' && s[1] == 'c') { /* picas need to be scaled by 65536 * 12, or 786 432 */ fac = 786432L ; s += 2; } else if (*s == 'm' && s[1] == 'm') { /* millimeters need to be scaled by 72.27 * 216 / 25.4, or 186 468 */ fac = 186468L ; s += 2; } else if (*s == 's' && s[1] == 'p') { /* scaled points are already taken care of; simply round */ fac = 1L ; s += 2; } else if (*s == 'b' && s[1] == 'p') { /* big points need to be scaled by 72.27 * 65536 / 72, or 65782 */ fac = 65782L ; s += 2; } else if (*s == 'd' && s[1] == 'd') { /* didot points need to be scaled by 65536 * 1238 / 1157, or 70124 */ fac = 70124L ; s += 2; } else if (*s == 'c' && s[1] == 'c') { /* cicero need to be scaled by 65536 * 1238 / 1157 * 12, or 841 489 */ fac = 841489L ; s += 2; } else if (*s == 'i' && s[1] == 'n') { /* inches need to be scaled by 72.27 * 65536, or 4 736 286 */ fac = 4736286L ; s += 2; } else if (*s == 'w') { fac = Width; s++; } else if (*s == 'h') { fac = Height; s++; } whole = scale(whole, num, den, fac) ; *sp = s; return (neg ? -whole : whole); } struct pagespec *ParseSpecs(str, make) char *str; int make; { char *t; struct pagespec *head, *tail; int other = 0; int num = -1; struct pagespec spare; if (make) head = tail = newspec(); else head = tail = &spare; while (*str) { if (isdigit(*str)) { num = parseint(&str); } else { switch (*str++) { case ':': if (other || head != tail || num < 1) specusage(); Modulo = num; num = -1; break; case '@': if (other || head != tail || num < 1) specusage(); Magnification = num; num = -1; break; case '-': tail->reversed = !tail->reversed; other = 1; break; case '(': tail->xoff += parsedimen(&str); if (*str++ != ',') specusage(); tail->yoff += parsedimen(&str); if (*str++ != ')') specusage(); other = 1; break; case '+': tail->add = 1; case ',': if (num < 0 || num >= Modulo) specusage(); tail->pageno = num; if (make) { tail->next = newspec(); tail = tail->next; } num = -1; other = 1; break; default: specusage(); } } } if (num >= Modulo) specusage(); else if (num >= 0) tail->pageno = num; return (head); } i32 singledimen(str) char *str; { i32 num = parsedimen(&str); if (*str) return (0); return (num); } /* * Print a message to stderr, with an optional leading space, and handling * long line wraps. */ message(space, str, len) int space; register char *str; register int len; { static int beenhere; static int col; if (!beenhere) space = 0, beenhere++; if (len == 0) len = strlen(str); col += len; if (space) { if (col >= MAXCOL) (void) putc('\n', stderr), col = len; else (void) putc(' ', stderr), col++; } while (--len >= 0) (void) putc(*str++, stderr); (void) fflush(stderr); } /* * Start a page (process a DVI_BOP). */ BeginPage(really) int really; { register i32 *i; OutputFontIndex = -1; /* new page requires respecifying font */ for (i = Count; i < &Count[10]; i++) fGetLong(inf, *i); (void) GetLong(inf); /* previous page pointer */ if (!UseThisPage || !really) return; putbyte(outf, DVI_BOP); for (i = Count; i < &Count[10]; i++) PutLong(outf, *i); PutLong(outf, StartOfLastPage); if (ferror(outf)) error(1, -1, writeerr); StartOfLastPage = CurrentPosition; CurrentPosition += 45; /* we just wrote this much */ if (!SFlag) { /* write nice page usage messages */ register int z = 0; register int mlen = 0; char msg[80]; (void) sprintf(msg, "[%ld", (long)Count[0]); mlen = strlen(msg); for (i = &Count[1]; i < &Count[10]; i++) { if (*i == 0) { z++; continue; } while (--z >= 0) msg[mlen++] = '.', msg[mlen++] = '0'; z = 0; (void) sprintf(msg + mlen, ".%ld", (long)*i); mlen += strlen(msg + mlen); } message(1, msg, mlen); } } /* * End a page (process a DVI_EOP). */ EndPage(really) int really; { if (!UseThisPage || !really) return; if (!SFlag) message(0, "]", 1); putbyte(outf, DVI_EOP); if (ferror(outf)) error(1, -1, writeerr); CurrentPosition++; NumberOfOutputPages++; } /* * For each of the fonts used in the new DVI file, write out a definition. */ /* ARGSUSED */ void PostAmbleFontEnumerator(addr, key) char *addr; i32 key; { if (((struct fontinfo *)addr)->fi_reallyused) WriteFont((struct fontinfo *)addr); } HandlePostAmble() { register i32 c; (void) GetLong(inf); /* previous page pointer */ if (GetLong(inf) != Numerator) GripeMismatchedValue("numerator"); if (GetLong(inf) != Denominator) GripeMismatchedValue("denominator"); if (GetLong(inf) * Magnification / 1000 != DVIMag) GripeMismatchedValue("\\magnification"); putbyte(outf, DVI_POST); PutLong(outf, StartOfLastPage); PutLong(outf, Numerator); PutLong(outf, Denominator); PutLong(outf, DVIMag); c = GetLong(inf); PutLong(outf, c); /* tallest page height */ c = GetLong(inf); PutLong(outf, c); /* widest page width */ c = GetWord(inf)+1; PutWord(outf, c); /* DVI stack size */ PutWord(outf, NumberOfOutputPages); StartOfLastPage = CurrentPosition; /* point at post */ CurrentPosition += 29; /* count all those `put's */ #ifdef notdef (void) GetWord(inf); /* skip original number of pages */ #endif /* * just ignore all the incoming font definitions; we are done with * input file */ /* * run through the FontFinder table and dump definitions for the * fonts we have used. */ SEnumerate(FontFinder, PostAmbleFontEnumerator); putbyte(outf, DVI_POSTPOST); PutLong(outf, StartOfLastPage); /* actually start of postamble */ putbyte(outf, DVI_VERSION); putbyte(outf, DVI_FILLER); putbyte(outf, DVI_FILLER); putbyte(outf, DVI_FILLER); putbyte(outf, DVI_FILLER); CurrentPosition += 10; while (CurrentPosition & 3) { putbyte(outf, DVI_FILLER); CurrentPosition++; } if (ferror(outf)) error(1, -1, writeerr); } /* * Write a font definition to the output file */ WriteFont(fi) register struct fontinfo *fi; { register int l; register char *s; if (fi->fi_newindex < 256) { putbyte(outf, DVI_FNTDEF1); putbyte(outf, fi->fi_newindex); CurrentPosition += 2; } else if (fi->fi_newindex < 65536) { putbyte(outf, DVI_FNTDEF2); PutWord(outf, fi->fi_newindex); CurrentPosition += 3; } else if (fi->fi_newindex < 16777216) { putbyte(outf, DVI_FNTDEF3); Put3Byte(outf, fi->fi_newindex); CurrentPosition += 4; } else { putbyte(outf, DVI_FNTDEF4); PutLong(outf, fi->fi_newindex); CurrentPosition += 5; } PutLong(outf, fi->fi_checksum); PutLong(outf, fi->fi_mag); PutLong(outf, fi->fi_designsize); putbyte(outf, fi->fi_n1); putbyte(outf, fi->fi_n2); l = fi->fi_n1 + fi->fi_n2; CurrentPosition += 14 + l; s = fi->fi_name; while (--l >= 0) putbyte(outf, *s++); } /* * Handle the preamble. Someday we should update the comment field. */ HandlePreAmble() { register int n, c; c = getc(inf); if (c == EOF) GripeUnexpectedDVIEOF(); if (c != DVI_PRE) GripeMissingOp("PRE"); if (getc(inf) != DVI_VERSION) error(1, 0, "%s is not a DVI version %d file", DVIFileName, DVI_VERSION); Numerator = GetLong(inf); Denominator = GetLong(inf); DVIMag = GetLong(inf) * Magnification / 1000; putbyte(outf, DVI_PRE); putbyte(outf, DVI_VERSION); PutLong(outf, Numerator); PutLong(outf, Denominator); PutLong(outf, DVIMag); n = UnSign8(GetByte(inf)); CurrentPosition = 15 + n; /* well, almost */ putbyte(outf, n); while (--n >= 0) { c = GetByte(inf); putbyte(outf, c); } } main(argc, argv) int argc; register char **argv; { register int c; register char *s; char *outname = NULL; char *specstring = NULL; Width = 0; Height = 0; Magnification = 1000; Modulo = 1; ProgName = *argv; setbuf(stderr, serrbuf); while ((c = getopt(argc, argv, "i:o:w:h:q")) != EOF) { switch (c) { case 'q': /* silent */ SFlag++; break; case 'i': if (DVIFileName != NULL) goto usage; DVIFileName = optarg; break; case 'o': if (outname != NULL) goto usage; outname = optarg; break; case 'w': if (Width != 0) goto usage; Width = singledimen(optarg); if (Width <= 0) error(1, -1, "-w parameter must be > 0"); break; case 'h': if (Height != 0) goto usage; Height = singledimen(optarg); if (Height <= 0) error(1, -1, "-h parameter must be > 0"); break; case '?': usage: (void) fprintf(stderr, "\ Usage: %s [-q] [-i infile] [-o outfile] [-w width] [-h height] [infile [outfile]]\n", ProgName); (void) fflush(stderr); exit(1); } } while (optind < argc) { s = argv[optind++]; c = *s; if (specstring == NULL) (void) ParseSpecs((specstring = s), 0); else if (DVIFileName == NULL) DVIFileName = s; else if (outname == NULL) outname = s; else goto usage; } if (specstring == NULL) goto usage; if (DVIFileName == NULL) { DVIFileName = "`stdin'"; inf = stdin; } else if ((inf = fopen(DVIFileName, "r")) == 0) error(1, -1, "cannot read %s", DVIFileName); if (outname == NULL) outf = stdout; else if ((outf = fopen(outname, "w")) == 0) error(1, -1, "cannot write %s", outname); if ((FontFinder = SCreate(sizeof(struct fontinfo))) == 0) error(1, 0, "cannot create font finder (out of memory?)"); /* copy inf to TEMP file if not seekable */ if ((inf = SeekFile(inf)) == NULL) { error(1, 0, "can't seek file"); } InputPageNumber = 0; StartOfLastPage = -1; HandlePreAmble(); ScanDVIFile(); if (fseek(inf, 16L, 1) == -1) error(1, -1, "can't seek postamble"); if (Height == 0) /* get height from postamble */ Height = GetLong(inf); else (void) GetLong(inf); /* ignore height */ if (Width == 0) /* get width from postamble */ Width = GetLong(inf); PageSpecs = ParseSpecs(specstring, 1); HandleDVIFile(); HandlePostAmble(); if (!SFlag) (void) fprintf(stderr, "\nWrote %d page%s, %ld bytes\n", NumberOfOutputPages, NumberOfOutputPages == 1 ? "" : "s", (long)CurrentPosition); exit(0); /* NOTREACHED */ } /* * Handle a font definition. */ HandleFontDef(index) i32 index; { register struct fontinfo *fi; register int i; register char *s; int def = S_CREATE | S_EXCL; if (!UseThisPage) { if ((fi = (struct fontinfo *)SSearch(FontFinder, index, &def)) == 0) if (def & S_COLL) error(1, 0, "font %ld already defined", (long)index); else error(1, 0, "cannot stash font %ld (out of memory?)", (long)index); fi->fi_reallyused = 0; fi->fi_checksum = GetLong(inf); fi->fi_mag = GetLong(inf); fi->fi_designsize = GetLong(inf); fi->fi_n1 = UnSign8(GetByte(inf)); fi->fi_n2 = UnSign8(GetByte(inf)); i = fi->fi_n1 + fi->fi_n2; if ((s = malloc((unsigned)i)) == 0) GripeOutOfMemory(i, "font name"); fi->fi_name = s; while (--i >= 0) *s++ = GetByte(inf); } else { (void) GetLong(inf); (void) GetLong(inf); (void) GetLong(inf); i = UnSign8(GetByte(inf)); i += UnSign8(GetByte(inf)); while (--i >= 0) (void) GetByte(inf); } } /* * Handle a \special. */ HandleSpecial(c, l, p) int c; register int l; register i32 p; { register int i; if (UseThisPage) { putbyte(outf, c); switch (l) { case DPL_UNS1: putbyte(outf, p); CurrentPosition += 2; break; case DPL_UNS2: PutWord(outf, p); CurrentPosition += 3; break; case DPL_UNS3: Put3Byte(outf, p); CurrentPosition += 4; break; case DPL_SGN4: PutLong(outf, p); CurrentPosition += 5; break; default: panic("HandleSpecial l=%d", l); /* NOTREACHED */ } CurrentPosition += p; while (--p >= 0) { i = getc(inf); putbyte(outf, i); } if (feof(inf)) GripeUnexpectedDVIEOF(); if (ferror(outf)) error(1, -1, writeerr); } else while (--p >= 0) (void) getc(inf); } ReallyUseFont() { register struct fontinfo *fi; int look = S_LOOKUP; fi = (struct fontinfo *)SSearch(FontFinder, CurrentFontIndex, &look); if (fi == NULL) error(1, 0, "DVI file requested font %ld without defining it", (long)CurrentFontIndex); if (fi->fi_reallyused == 0) { fi->fi_reallyused++; fi->fi_newindex = NextOutputFontIndex++; WriteFont(fi); } if (fi->fi_newindex != OutputFontIndex) { PutFontSelector(fi->fi_newindex); OutputFontIndex = fi->fi_newindex; } } /* * Write a font selection command to the output file */ PutFontSelector(index) i32 index; { if (index < 64) { putbyte(outf, index + DVI_FNTNUM0); CurrentPosition++; } else if (index < 256) { putbyte(outf, DVI_FNT1); putbyte(outf, index); CurrentPosition += 2; } else if (index < 65536) { putbyte(outf, DVI_FNT2); PutWord(outf, index); CurrentPosition += 3; } else if (index < 16777216) { putbyte(outf, DVI_FNT3); Put3Byte(outf, index); CurrentPosition += 4; } else { putbyte(outf, DVI_FNT4); PutLong(outf, index); CurrentPosition += 5; } } /* * The following table describes the length (in bytes) of each of the DVI * commands that we can simply copy, starting with DVI_SET1 (128). */ char oplen[128] = { 0, 0, 0, 0, /* DVI_SET1 .. DVI_SET4 */ 9, /* DVI_SETRULE */ 0, 0, 0, 0, /* DVI_PUT1 .. DVI_PUT4 */ 9, /* DVI_PUTRULE */ 1, /* DVI_NOP */ 0, /* DVI_BOP */ 0, /* DVI_EOP */ 1, /* DVI_PUSH */ 1, /* DVI_POP */ 2, 3, 4, 5, /* DVI_RIGHT1 .. DVI_RIGHT4 */ 1, /* DVI_W0 */ 2, 3, 4, 5, /* DVI_W1 .. DVI_W4 */ 1, /* DVI_X0 */ 2, 3, 4, 5, /* DVI_X1 .. DVI_X4 */ 2, 3, 4, 5, /* DVI_DOWN1 .. DVI_DOWN4 */ 1, /* DVI_Y0 */ 2, 3, 4, 5, /* DVI_Y1 .. DVI_Y4 */ 1, /* DVI_Z0 */ 2, 3, 4, 5, /* DVI_Z1 .. DVI_Z4 */ 0, /* DVI_FNTNUM0 (171) */ 0, 0, 0, 0, 0, 0, 0, 0, /* 172 .. 179 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 180 .. 187 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 188 .. 195 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 196 .. 203 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 204 .. 211 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 212 .. 219 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 220 .. 227 */ 0, 0, 0, 0, 0, 0, 0, /* 228 .. 234 */ 0, 0, 0, 0, /* DVI_FNT1 .. DVI_FNT4 */ 0, 0, 0, 0, /* DVI_XXX1 .. DVI_XXX4 */ 0, 0, 0, 0, /* DVI_FNTDEF1 .. DVI_FNTDEF4 */ 0, /* DVI_PRE */ 0, /* DVI_POST */ 0, /* DVI_POSTPOST */ 0, 0, 0, 0, 0, 0, /* 250 .. 255 */ }; int HandlePage(first, last, hoffset, voffset) int first, last; i32 hoffset, voffset; { register int c, l; register i32 p; register int CurrentFontOK = 0; int doingpage = 0; /* Only way out is via "return" statement */ for (;;) { c = getc(inf); /* getc() returns unsigned values */ if (DVI_IsChar(c)) { /* * Copy chars, note font usage, but ignore if * page is not interesting. */ if (!UseThisPage) continue; if (!CurrentFontOK) { ReallyUseFont(); CurrentFontOK++; } putbyte(outf, c); CurrentPosition++; continue; } if (DVI_IsFont(c)) { /* note font change */ CurrentFontIndex = c - DVI_FNTNUM0; CurrentFontOK = 0; continue; } if (c == EOF) GripeUnexpectedDVIEOF(); if ((l = (oplen - 128)[c]) != 0) { /* simple copy */ if (!UseThisPage) { while (--l > 0) (void) getc(inf); continue; } CurrentPosition += l; putbyte(outf, c); while (--l > 0) { c = getc(inf); putbyte(outf, c); } if (ferror(outf)) error(1, -1, writeerr); continue; } if ((l = DVI_OpLen(c)) != 0) { /* * Handle other generics. * N.B.: there should only be unsigned parameters * here (save SGN4), for commands with negative * parameters have been taken care of above. */ switch (l) { case DPL_UNS1: p = getc(inf); break; case DPL_UNS2: fGetWord(inf, p); break; case DPL_UNS3: fGet3Byte(inf, p); break; case DPL_SGN4: fGetLong(inf, p); break; default: panic("HandleDVIFile l=%d", l); } /* * Now that we have the parameter, perform the * command. */ switch (DVI_DT(c)) { case DT_SET: case DT_PUT: if (!UseThisPage) continue; if (!CurrentFontOK) { ReallyUseFont(); CurrentFontOK++; } putbyte(outf, c); switch (l) { case DPL_UNS1: putbyte(outf, p); CurrentPosition += 2; continue; case DPL_UNS2: PutWord(outf, p); CurrentPosition += 3; continue; case DPL_UNS3: Put3Byte(outf, p); CurrentPosition += 4; continue; case DPL_SGN4: PutLong(outf, p); CurrentPosition += 5; continue; } case DT_FNT: CurrentFontIndex = p; CurrentFontOK = 0; continue; case DT_XXX: HandleSpecial(c, l, p); continue; case DT_FNTDEF: HandleFontDef(p); continue; default: panic("HandleDVIFile DVI_DT(%d)=%d", c, DVI_DT(c)); } continue; } switch (c) { /* handle the few remaining cases */ case DVI_BOP: if (doingpage) GripeUnexpectedOp("BOP (during page)"); BeginPage(first); if (UseThisPage) { if (!last) { putbyte(outf, DVI_PUSH); CurrentPosition++; } if (hoffset != 0) { putbyte(outf, DVI_RIGHT4) ; PutLong(outf, hoffset) ; CurrentPosition += 5; } if (voffset != 0) { putbyte(outf, DVI_DOWN4) ; PutLong(outf, voffset) ; CurrentPosition += 5; } } doingpage = 1; break; case DVI_EOP: if (!doingpage) GripeUnexpectedOp("EOP (outside page)"); if (!last && UseThisPage) { putbyte(outf, DVI_POP); CurrentPosition++; } EndPage(last); doingpage = 0; return(1); case DVI_PRE: GripeUnexpectedOp("PRE"); /* NOTREACHED */ case DVI_POST: if (doingpage) GripeUnexpectedOp("POST (inside page)"); return(0); case DVI_POSTPOST: GripeUnexpectedOp("POSTPOST"); /* NOTREACHED */ default: GripeUndefinedOp(c); /* NOTREACHED */ } } } /* write an empty page to fill out space */ PutEmptyPage() { int i; putbyte(outf, DVI_BOP); PutLong(outf, -1L); for (i = 1; i < 10; i++) /* set all sub counts to 0 */ PutLong(outf, 0L); PutLong(outf, StartOfLastPage); putbyte(outf, DVI_EOP); if (!SFlag) { /* write nice page usage messages */ char *msg = "[*]"; message(1, msg, strlen(msg)); } if (ferror(outf)) error(1, -1, writeerr); StartOfLastPage = CurrentPosition; CurrentPosition += 46; /* we just wrote this much */ NumberOfOutputPages++; } /* * Here we scan the input DVI file and record pointers to the pages. */ ScanDVIFile() { UseThisPage = 0; StartOfPage[InputPageNumber] = ftell(inf); while (HandlePage(0, 0, 0, 0)) { /* scan DVI file */ StartOfPage[++InputPageNumber] = ftell(inf); } } /* * Here we read the input DVI file and write relevant pages to the * output DVI file. We also keep track of font changes, handle font * definitions, and perform some other housekeeping. */ HandleDVIFile() { int CurrentPage, ActualPage, MaxPage; UseThisPage = 1; MaxPage = ((InputPageNumber+Modulo-1)/Modulo)*Modulo; for (CurrentPage = 0; CurrentPage < MaxPage; CurrentPage += Modulo) { int add_last = 0; struct pagespec *ps; for (ps = PageSpecs; ps != NULL; ps = ps->next) { int add_next = ps->add; if (ps->reversed) ActualPage = MaxPage-CurrentPage-Modulo+ps->pageno; else ActualPage = CurrentPage+ps->pageno; if (ActualPage < InputPageNumber) { if (fseek(inf, StartOfPage[ActualPage], 0) == -1) error(1, -1, "can't seek page %d", ActualPage+1); HandlePage(!add_last, !add_next, ps->xoff, ps->yoff); } else if (!add_last && !add_next) PutEmptyPage(); add_last = add_next; } } if (fseek(inf, StartOfPage[InputPageNumber]+1, 0) == -1) error(1, -1, "can't seek last page"); }