1 /* Copyright 1990,1991,1992,1993,1994,1995,1996,1997,1998,1999 Y&Y, Inc.
2 Copyright 2007 TeX Users Group
3 Copyright 2014 Clerk Ma
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 /**********************************************************************
23 * DVI to PS convertor for Adobe Type 1 (ATM compatible) fonts
24 * This is the part that actually converts DVI commands to PS
26 **********************************************************************/
30 /* NOTE: S = s w, T = s x, W = w<n>, X = x<n>, Y = y<n>, Z = z<n> */
31 /* bp = bop, ep = eop, pr = put_rule, sr = set_rule */
33 int firstpage = 0; /* non-zero when nothing has been output yet */
34 /* int evenlast = 0; */ /* last non-skipped page was even */
35 /* int oddlast = 0; */ /* last non-skipped page was odd */
36 int skiptoend = 0; /* non-zero => still need to skip to last page */
37 int finish = 0; /* non-zero => have hit end of DVI file */
38 int showcount = 0; /* on when last sent out "set" or "put" */
39 int freshflag = 0; /* on after fresh line is started (\n) */
41 int stinx; /* stack index - to avoid overflow */
42 int maxstinx; /* max stack index seen - not used here */
44 long currentpagestart; /* 95/Aug/27 */
46 /* int escapecode[14] = {'b', 't', 'n', 'v', 'f', 'r'}; */
48 char *escapecode = "btnvfr"; /* special codes for 8, 9, 10, 12, and 13 */
50 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
52 /* we don't have to worry about sign extension here - no need for short int */
54 /* static unsigned int ureadone (FILE *input) {
58 static unsigned int ureadtwo (FILE *input)
60 return (getc(input) << 8) | getc(input);
63 static unsigned long ureadthree (FILE *input)
69 return ((((unsigned long) c << 8) | d) << 8) | e;
72 static unsigned long ureadfour (FILE *input)
79 return ((((((unsigned long) c << 8) | (unsigned long) d) << 8) | e) << 8) | f;
82 /* we do have to worry about sign extension here - use short int if needed */
84 static int sreadone (FILE *input)
96 static int sreadtwo (FILE *input)
99 /* return (getc(input) << 8) | getc(input); */ /* 1995/Nov/15 */
100 /* result = (getc(input) << 8) | getc(input); */
101 result = ((short int) getc(input) << 8) | (short int) getc(input);
106 /* possible compiler optimization bug worked around 98/Feb/8 */
108 static int sreadtwo (FILE *input)
113 if (c > 127) c = c - 256;
117 static long sreadthree (FILE *input)
123 if (c > 127) c = c - 256;
124 return ((((long) c << 8) | d) << 8) | e;
127 static long sreadfour (FILE *input)
134 return ((((((long) c << 8) | (long) d) << 8) | e) << 8) | f;
137 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
139 /* don't need to optimize `push pop' since doesn't happen ever? */
141 void do_push(FILE *output, FILE *input)
149 if (stinx % 64 == 0) /* see if stack is getting full */
151 PSputs(" pushstack\n", output);
158 if (c == (int) push && ((stinx + 1) % 64 != 0))
161 PSputs(" U", output); /* u u */
165 (void) ungetc(c, input);
166 PSputs(" u", output); /* statepush */
172 /* Are we sure the `O' = `o o' works when at edge of 64 size stack ? */
174 void do_pop(FILE *output, FILE *input)
180 if (stinx % 64 == 0) /* time to retrieve saved stack ? */
183 PSputs(" popstack\n", output);
191 if (c == (int) pop && (stinx % 64 != 0))
194 PSputs(" O", output); /* o o */
201 PSputs(" M", output);
202 } /* o u - OK if M defined as `o u' */
205 (void) ungetc(c, input);
206 PSputs(" o", output); /* statepop */
213 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
215 void complaincharcode(unsigned long c) /* 1993/Dec/11 */
217 sprintf(logline, " Character code %lu > 255\n", c);
218 showline(logline, 1);
221 /* come here either with character code 0 - 127 --- or from set1 */
222 /* in the case of set1 we need to read the next byte, which likely is > 127 */
224 void normalchar (FILE *output, FILE *input, int c)
230 if (showcount > MAXSHOWONLINE) /* too much on one line ? */
232 PSputc('\n', output);
233 showcount = 0; /* first go to new line */
238 while (c < 128 || c == (int) set1) /* changed ! */
241 c = getc(input); /* new ! read next byte */
245 if (bRemapControl || bRemapFont)
256 /* NOTE: this must match corresponding code in DVIPSLOG.C */
257 else if (bRemapSpace && c <= 32) /* 1995/Oct/17 */
259 if (c == 32) c = 195; /* not 160 */
260 else if (c == 13) c = 176; /* 1996/June/4 */
261 else if (c == 10) c = 173; /* 1996/June/4 */
262 else if (c == 9) c = 170; /* 1996/June/4 */
263 else if (c == 0) c = 161;
265 /* if (c < 32 || c >= 127) { */ /* control characters */
266 /* added test for percent 1992/Dec/21 to avoid % in string ... */
267 if (c < 32 || c >= 127 || c == 37) { /* control chars and % */
268 /* if (bForwardFlag != 0 && c <= 13 && c >= 8 && c != 11) */
269 if (c <= 13 && c >= 8 && c != 11 && bForwardFlag != 0) {
270 /* use special escape \b \t \n ... \f \r for 8 ... 13 1993/Sep/29 */
271 PSputc('\\', output);
272 PSputc(escapecode[c-8], output);
274 /* if (backwardflag == 1) */ /* backward compatible with old ALW */
275 else if (bBackWardFlag == 1) { /* compatibility with old ALW */
276 d = getc(input); (void) ungetc(d, input); /* peek */
277 if ((d >= 32 && d <= 127) || d == (int) set1) {
278 // fprintf(output, "\\%03o", c); /* just to be safe */
279 sprintf(logline, "\\%03o", c); /* just to be safe */
282 sprintf(logline, "\\%o", c);
284 PSputs(logline, output);
286 else { /* following not always safe for old ALW ... */
287 d = getc(input); (void) ungetc(d, input); /* peek */
288 if ((d >= '0' && d <= '7') || d == (int) set1) {
289 // fprintf(output, "\\%03o", c); /* just to be safe */
290 sprintf(logline, "\\%03o", c); /* just to be safe */
293 sprintf(logline, "\\%o", c);
295 PSputs(logline, output);
298 else { /* not control characters */
299 if (c == '\\' || c == '(' || c == ')')
301 // putc('\\', output);
302 PSputc('\\', output);
304 /* if (c == '%') fprintf(output, "\045"); */
305 /* else putc(c, output); */
310 c = getc(input); /* get the next byte in DVI file */
311 if (c < 0) break; /* trap EOF - avoid loop */
312 } /* end of while (c < 128 ... ) loop */
314 /* analyze next DVI command to see whether can combine with above */
315 if (skipflag != 0) (void) ungetc(c, input);
318 // fputs(")S", output);
319 PSputs(")S", output);
321 else if (c == (int) x0) {
322 // fputs(")T", output);
323 PSputs(")T", output);
326 // fputs(")s", output);
327 PSputs(")s", output);
328 (void) ungetc(c, input); /* can't use it, put it back */
332 /* also need to increase h by total width */
333 /* fprintf(output, "currentpoint pop /h exch def\n"); */
336 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
338 /* Following need *not* be efficient since it is rarely used */
339 /* Put single character - called by put1/put2/put3/put4 */
340 /* Set single character - also called by set2/set3/set4 */
341 /* duplicates a lot of code form normalchar() above */
343 /* separated out 1995/June/30 */ /* third arg is `s' or `p' */
345 void do_charsub (FILE *output, unsigned long c, char code)
349 /* if (bRemapControl && c < MAXREMAP) c = remaptable[c]; */
350 if (bRemapControl || bRemapFont)
352 if (c < MAXREMAP) c = remaptable[c];
354 else if (c == 32) c = 195;
355 else if (c == 127) c = 196;
358 else if (bRemapSpace && c <= 32) { /* 1995/Oct/17 */
359 if (c == 32) c = 195; /* not 160 */
360 else if (c == 13) c = 176; /* 1996/June/4 */
361 else if (c == 10) c = 173; /* 1996/June/4 */
362 else if (c == 9) c = 170; /* 1996/June/4 */
363 else if (c == 0) c = 161;
367 return; /* ignore it - should never happen */
370 showline("Setting char %d without font", c);
371 tellwhere(1); errcount(0);
373 // putc('(', output);
375 /* the following code copied from normachar() --- 1995/June/30 */
376 /* if (bRemapControl && c < MAXREMAP)
377 c = remaptable[c]; */ /* 1994/Jun/20 */
378 /* if (c < 32 || c >= 127) */
379 if (c < 32 || c >= 127 || c == 37) { /* 1995/June/30 fix */
380 /* fprintf(output, "(\\%o)p", c); */ /* put1 */
381 if (c <= 13 && c >= 8 && c != 11 && bForwardFlag != 0) {
382 /* use special escape \b \t \n ... \f \r for 8 ... 13 1993/Sep/29 */
383 // putc('\\', output);
384 PSputc('\\', output);
385 // putc(escapecode[c-8], output);
386 PSputc(escapecode[c-8], output);
388 else if (bBackWardFlag == 1) { /* compatibility with old ALW */
389 sprintf(logline, "\\%03o", (unsigned int) c);
390 PSputs(logline, output);
392 else { /* following not always safe for old ALW ... */
393 sprintf(logline, "\\%o", (unsigned int) c);
394 PSputs(logline, output);
397 /* else fprintf(output, "(%c)p", c); */ /* 1995/June/30 fixed */
399 if (c == '\\' || c == '(' || c == ')') {
400 // putc('\\', output);
401 PSputc('\\', output);
403 /* if (c == '%') fprintf(output, "\045"); */
404 /* else putc(c, output); */
405 // putc((unsigned int) c, output);
406 PSputc((unsigned int) c, output);
408 // putc(')', output);
410 // putc(code, output); /* 'p' or 's' */
411 PSputc(code, output); /* 'p' or 's' */
416 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
418 /* could be more efficient here if we ever see several in a row OK */
419 /* model on "normalchar" if needed OK */
421 void do_set1(FILE *output, FILE *input)
425 normalchar(output, input, (int) set1);
430 /* read following byte and throw it away */
431 /* set character c and increase h by width of character */
432 /* used (normally only) for characters in range 128 to 255 */
435 void do_set2(FILE *output, FILE *input)
437 do_charsub(output, ureadtwo(input), 's');
440 void do_set3(FILE *output, FILE *input)
442 do_charsub(output, ureadthree(input), 's');
445 void do_set4(FILE *output, FILE *input)
447 do_charsub(output, ureadfour(input), 's');
450 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
452 /* set character c and DO NOT increase h by width of character */
454 void do_put1(FILE *output, FILE *input)
456 do_charsub(output, getc(input), 'p');
459 void do_put2(FILE *output, FILE *input)
461 do_charsub(output, ureadtwo(input), 'p');
464 void do_put3(FILE *output, FILE *input)
466 do_charsub(output, ureadthree(input), 'p');
469 void do_put4(FILE *output, FILE *input)
471 do_charsub(output, ureadfour(input), 'p');
474 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
476 /* For PDF problems we adjust height of horizontal rule 95/Oct/15 */
477 /* but we don't adjust the position of the rule ... and */
478 /* if we were to adjust width of vertical rules we'd need to adjust position */
480 void do_common_rule (FILE *output, FILE *input, char *s)
482 long a, b; /* height, width */
484 a = sreadfour(input);
485 b = sreadfour(input);
489 if (nMinRule != 0 && a > 0) /* 1995/Oct/10 */
491 /* Make sure we don't get zero width rules in PDF output... */
492 /* ... compensate for truncating down instead of rounding in pdf */
495 else if (a > nMinRule)
496 a = a + nMinRule / 2;
502 PSputc('\n', output);
504 sprintf(logline, "%lg %lg %lg rgb ", rulered, rulegreen, ruleblue);
505 PSputs(logline, output);
511 if (! freshflag) PSputc('\n', output);
512 PSputs("black ", output);
516 /* some silly nonsense about using a height = -2^31 in set_rule */
517 /* if (bDVICopyReduce && -a == 2147483648L) a = 0; */ /* 1995/Sep/16 */
518 if (bDVICopyReduce && -a == 2147483648L) /* 1995/Sep/16 */
520 /* need to do nothing for pr, no output, no motion */
521 if (strcmp (s, "sr") == 0)
523 if (! freshflag) PSputc('\n', output);
527 sprintf(logline, "%.9lg r", (double) b / outscale);
532 sprintf(logline, "%ld r", b); /* setrule => right */
534 PSputs(logline, output);
540 if (! freshflag) PSputc('\n', output);
544 sprintf(logline, "%.9lg %.9lg %s",
545 (double) a / outscale, (double) b / outscale, s);
550 sprintf(logline, "%ld %ld %s", a, b, s); /* setrule or putrule */
552 PSputs(logline, output);
558 if (! freshflag) PSputc('\n', output);
559 sprintf(logline, "%lg %lg %lg rgb ", textred, textgreen, textblue);/* 1993/Oct/22 */
560 PSputs(logline, output);
566 if (! freshflag) PSputc('\n', output);
567 PSputs("black ", output);
574 void do_set_rule(FILE *output, FILE *input)
576 do_common_rule (output, input, "sr");
579 void do_put_rule(FILE *output, FILE *input)
581 do_common_rule (output, input, "pr");
584 /* write TeX /counter's */
585 char *showcounters(char *s)
590 sprintf(s, "%ld", counter[0]); /* *always* write first one */
593 for (k = 10-1; k > 0; k--)
602 for (k = 1; k <= kmax; k++) /* write others if non-zero */
604 sprintf(s, " %ld", counter[k]);
611 /*** code for working way into back end of file looking for post ***/
613 #define BUFSIZE 128 /* buffer size to read in at one time */
614 #define NUMSTEPS 32 /* number of buffers to try from end of file */
615 #define MAGIC 223 /* magic code used by TeX at end of DVI file */
617 /* This does some things to work around possible crap at end of file */
618 /* The way to loose is get garbage at end that comes from other DVI file ! */
620 /* search for post at end of file */
621 long gotopost(FILE *input)
624 int c, d, e, f, k, i, j, count;
628 if (fseek(input, - (long) BUFSIZE, SEEK_END) < 0)
630 rewind(input); /* possibly because file shorter than BUFSIZE ? */
633 for (j=0; j < NUMSTEPS; j++) /* let's not go on forever ! */
635 for (k = 0; k < BUFSIZE; k++)
637 buffer[k] = getc(input);
644 count=0; /* count MAGIC codes seen */
646 for (i = k; i >= 5; i--) /* need at least seq of four */
648 if (buffer[i] == MAGIC)
661 if (count == 4) { /* found sequence of four */
662 for (i = k; i >= 5; i--) /* but there can be many more */
663 if (buffer[i] != MAGIC) break;
664 k = i; /* first non MAGIC - ID_BYTE ? */
665 if (buffer[k] != MAGIC) { /* did see end of MAGIC stuff */
666 if (buffer[k-5] == (int) post_post) { /* is it valid ? */
667 /* if (buffer[k] != ID_BYTE) {
669 "File is DVI version %d - program designed for %d\n",
673 k = k - 5; /* step back to post_post */
674 c = buffer[k+1]; d = buffer[k+2];
675 e = buffer[k+3]; f = buffer[k+4];
676 n = ((((((unsigned long) c << 8) | (unsigned long) d) << 8) | e) << 8) | f;
677 fseek(input, (long) n, SEEK_SET); /* go to post ! */
678 c = getc(input); (void) ungetc(c, input);
679 if (c != (int) post) { /* check it ! */
680 showline("ERROR: Unable to find pointer to POST", 1);
686 sprintf(logline, "Found POST at %ld\n", n);
687 showline(logline, 0);
689 return n; /* seem to be in good shape */
695 if (fseek(input, - (long) (BUFSIZE * 2 - 10), SEEK_CUR) != 0) {
696 /* showline("Can't find proper ending of DVI file", 1); */
702 sprintf(logline, "ERROR: Can't find proper ending of DVI file `%s'\n",
704 showline(logline, 1);
705 fseek(input, 0, SEEK_END);
706 nlen = ftell(input); /* get length of file 99/Mar/21 */
707 sprintf(logline, "Searched near end of file of %ld bytes\n", nlen);
708 showline(logline, 0);
713 void insertblank(FILE *output, long page)
715 PSputs("dvidict begin\n", output);
719 sprintf(logline, "%ld %ld bop eop end ",
720 counter[0], page); /* 1995/Mar/25 */
721 PSputs(logline, output);
725 PSputs("bp ep end ", output);
728 PSputs("% blank page\n", output);
731 void docountercomment (FILE *output)
740 PSputs(logline, output);
743 /* beginning of page */
744 void do_bop(FILE *output, FILE *input)
747 long pageno; /* page number logical or physical */
748 long page; /* always dvi page count from start of file */
749 double xoffset, yoffset; /* 1992/July/11 */
750 COLORSPEC SavedColor; /* 1999/Apr/06 */
760 /* Normally bRepeatMode == 0 */ /* 1995/Aug/27 */
761 if (nRepeatCount > 1)
763 if (nRepeatIndex == 0) /* first time */
764 currentpagestart = ftell(input)-1; /* right at bop */
766 pagenumber--; /* compensate */
769 pagenumber++; /* DVI page count from start of job */
772 page = dvi_t - pagenumber + 1;
776 stinx = 0; /* reset stack counter */
777 /* h = 0; v = 0; w = 0; x = 0; y = 0; z = 0; */
778 ff = -1; /* undefined font */
779 /* fnt = finx[0]; */ /* just in case - not clear could be -1 ! */
780 /* currentfont = fontchar[0]; */ /* ? */
781 /* reset_stack(); */ /* empty the stack */
782 pagetpic = 0; /* 1992/Nov/17 */
783 complainedaboutj=0; /* 1993/Oct/17 */
785 if (bCarryColor == 0)
786 colorindex=0; /* reset color stack index */
788 if (bCarryColor && bColorUsed) { /* 98/Jul/18 */
789 RestoreColorStack(page); /* right page number ? */
790 /* if (colorindex > 0) {
792 doColorSet(output, -1);
793 } */ /* done down below */
796 clipstackindex = 0; /* reset push pop stack 98/Sep/12 */
798 CTMstackindex= 0; /* reset CTM stack pointer in dvispeci.c */
800 for (k = 0; k < 10; k++) counter[k] = sreadfour(input);
801 previous = sreadfour(input);
805 /* if (reverseflag) page = dvi_t - pagenumber + 1;
806 else page = pagenumber; */ /* already done */
808 if (countzeroflag != 0) pageno = counter[0];
809 /* else pageno = (long) pagenumber; */
810 else pageno = (long) page; /* 1993/Aug/28 */
812 skipflag = skip_this_page(pageno);
813 /* following is the logic for two-sided printing */
814 /* if (skipflag != 0) evenlast = 1; oddlast = 1; */
815 if (skipflag != 0) firstpage = -1; /* reset for next group */
816 else if (skipflag == 0) { /* page in valid range */
817 if (oddpageflag != 0) { /* if printing only odd pages */
818 if ((counter[0] & 1) == 0) { /* seen even numbered page */
820 insertblank(output, page); /* matching blank */
825 if (evenpageflag != 0) { /* if printing only even pages */
826 if ((counter[0] & 1) == 1) { /* seen odd numbered page */
828 insertblank(output, page); /* matching blank */
834 if (skipflag != 0) { /* skipping this page */
835 if (reverseflag != 0) {
836 if (previous > 0) fseek(input, previous, SEEK_SET);
841 else { /* not skipping this page */
843 // putc('[', stdout);
844 // if (logfileflag) putc('[', logfile);
846 showcounters(logline);
847 showline(logline, 0);
848 // if (logfileflag) showcounters(logfile);
851 // putc('.', stdout);
852 // if (logfileflag) putc('.', logfile);
855 /* note: first item after Page: is a page label - here counter[0] */
856 /* (or counter[1]-counter[2]) 1996/Jan/28 */
857 /* note: first item after Page: need not be a number */
858 /* note: second item after Page: is sequential page number */
859 /* An experiment 1995/Aug/27 */
860 /* page = numpages + 1; */
861 if (stripcomment == 0) {
862 // fputs("%%Page: ", output);
863 PSputs("%%Page: ", output);
865 sprintf(logline, "%ld-%ld %ld\n",
866 counter[1], counter[2], numpages+1); /* 1996/Jan/20 */
869 sprintf(logline, "%ld %ld\n", counter[0], numpages+1);
871 PSputs(logline, output);
873 // fputs("dvidict begin ", output);
874 PSputs("dvidict begin ", output);
875 if (evenoddoff != 0) {
876 if ((counter[0] & 1) == 1) { /* seen odd numbered page */
877 xoffset = xoffseto; yoffset = yoffseto;
879 else { /* seen even numbered page */
880 xoffset = xoffsete; yoffset = yoffsete;
883 "/xoffset %lg def /yoffset %lg def\n", xoffset, yoffset);
884 PSputs(logline, output);
886 PSputc('\n', output); // always start new line for this
888 sprintf(logline, "%ld %ld bop ", counter[0], numpages+1);
889 PSputs(logline, output);
891 else PSputs("bp ", output);
893 if (stripcomment == 0) docountercomment (output);
895 /* sure use of pageno ??? is OK even with countzeroflag ??? use page instead ??? */
896 if (bBackGroundFlag && bBackUsed) { /* 98/Jun/30 */
897 if (BackColors[page].A != -1.0 ||
898 BackColors[page].B != -1.0 ||
899 BackColors[page].C != -1.0) {
900 // putc('\n', output);
901 PSputc('\n', output);
902 // fputs("gsave clippath ", output);
903 PSputs("gsave clippath ", output);
904 SavedColor = CurrColor; /* save around following */
905 CurrColor = BackColors[page];
906 doColorSet(output, 3); /* background - in dvispeci.c */
907 // fputs("fill grestore ", output);
908 PSputs("fill grestore ", output);
909 CurrColor = SavedColor; /* restore after 99/Apr/06 */
910 /* putc('\n', output); */
911 /* CurrColor.A = CurrColor.B = CurrColor.C = 0.0F;
912 CurrColor.D = 0.0F; */ /* initial color on page ? */
915 /* now pop color pushed at bottom of previous page (restored stack up above) */
916 if (bColorUsed && (colorindex > 0)) { /* 98/Feb/14 */
918 doColorSet(output, 2); /* bop - in dvispeci.c */
921 PSputc('\n', output); /* omission slightly risky ... */
922 // freshflag = 1; // maybe not, keep blank line in PS
926 /* maybe also do "structuring conventions" stuff ? */
930 void do_eop(FILE *output, FILE *input)
935 if (bAbort) abortjob(); /* 1992/Nov/24 */
936 if (abortflag) return;
938 /* check_stack(pageno); */ /* check that stack is empty */
942 if (colorindex > 0) checkColorStack(output); /* 1996/Nov/3 */
943 /* do this only if color was used ??? */
944 if (bCarryColor && bColorUsed) {
945 /* doColorPush(); *//* NO - do in dvipslog.c */
946 /* UGH! This only makes sense if we page sequentially */
949 if (clipstackindex > 0)
950 doClipBoxPopAll(output);
954 if (CTMstackindex != 0)
955 checkCTM(output); /* 1996/Nov/3 */
957 PSputc('\n', output); // always start new line
960 PSputs("eop ", output);
962 PSputs("ep ", output);
964 if (stripcomment == 0)
965 docountercomment(output);
967 PSputc('\n', output);
968 PSputs("end", output);
970 if (stripcomment == 0)
971 PSputs(" % dvidict", output);
973 PSputc('\n', output);
974 /* %%PageTrailer comments highly optional ... */
975 if (bOptionalDSC) { /* 1994/Mar/3 */
976 if (stripcomment == 0) {
977 // fputs("%%PageTrailer\n", output);
978 PSputs("%%PageTrailer\n", output);
981 if (verboseflag) showline("] ", 0);
983 /* maybe also do "structuring conventions" stuff ? */
984 numpages++; /* update number of pages actually processed */
986 // if (ferror(output) != 0)
987 if (output != NULL && ferror(output)) {
989 // sprintf(logline, " ERROR in output file %s\n", outputfile);
990 showline("ERROR in output file", 1);
991 perrormod((outputfile != NULL) ? outputfile : "");
996 /* Normally bRepeatMode == 0 */ /* 1995/Aug/27 */
997 if (nRepeatCount > 1) {
999 if (nRepeatIndex == nRepeatCount) nRepeatIndex = 0;
1001 fseek (input, currentpagestart, SEEK_SET);
1008 if (reverseflag != 0) { /* go back if reading in reverse */
1009 if (previous > 0) fseek(input, previous, SEEK_SET);
1012 if (textures != 0) (void) ureadfour(input); /* skip over length code */
1013 /* may also want to check whether length is something reasonable ? */
1014 c = getc(input); (void) ungetc(c, input); /* peek ahead */
1015 /* here we expect to see bop, nop or fnt_def's ONLY */
1016 /* if (c >= 0 && c <= 127) {
1017 showline( "Invalid code %d between EOP and BOP\n", c);
1022 if (c >= 0 && c <= 127) { /* this should normally not happen: */
1023 sprintf(logline, " invalid code (%d)\n", c); /* DEBUG */
1024 showline(logline, 1);
1029 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
1032 void do_right1(FILE *output, FILE *input)
1036 b = sreadone(input);
1040 if (! freshflag) PSputc('\n', output);
1044 sprintf(logline, "%.9lg r", (double) b / outscale);
1049 sprintf(logline, "%d r", b); /* right */
1052 PSputs(logline, output);
1059 void do_right2(FILE *output, FILE *input)
1063 b = sreadtwo(input);
1067 if (! freshflag) PSputc('\n', output);
1071 sprintf(logline, "%.9lg r", (double) b / outscale);
1076 sprintf(logline, "%d r", b); /* right */
1079 PSputs(logline, output);
1086 void do_rightsub(FILE *output, long b)
1090 if (! freshflag) PSputc('\n', output);
1094 sprintf(logline, "%.9lg r", (double) b / outscale);
1099 sprintf(logline, "%ld r", b); /* right */
1102 PSputs(logline, output);
1109 void do_right3(FILE *output, FILE *input)
1111 do_rightsub(output, sreadthree(input));
1114 void do_right4(FILE *output, FILE *input)
1116 do_rightsub(output, sreadfour(input));
1119 void do_w0(FILE * output)
1123 PSputs(" w", output); /* wright */
1130 void do_w1(FILE *output, FILE *input)
1134 w = sreadone(input);
1138 if (! freshflag) PSputc('\n', output);
1142 sprintf(logline, "%.9lg W", (double) w / outscale);
1147 sprintf(logline, "%ld W", w); /* wsetright */
1149 PSputs(logline, output);
1156 void do_w2(FILE *output, FILE *input)
1160 w = sreadtwo(input);
1164 if (! freshflag) PSputc('\n', output);
1168 sprintf(logline, "%.9lg W", (double) w / outscale);
1173 sprintf(logline, "%ld W", w); /* wsetright */
1176 PSputs(logline, output);
1183 void do_wsub(FILE *output, long w)
1187 if (! freshflag) PSputc('\n', output);
1191 sprintf(logline, "%.9lg W", (double) w / outscale);
1196 sprintf(logline, "%ld W", w); /* wsetright */
1199 PSputs(logline, output);
1206 void do_w3(FILE *output, FILE *input)
1208 do_wsub(output, sreadthree(input));
1211 void do_w4(FILE *output, FILE *input)
1213 do_wsub(output, sreadfour(input));
1216 void do_x0(FILE *output)
1220 PSputs(" x", output); /* xright */
1227 void do_x1(FILE *output, FILE *input)
1231 x = sreadone(input);
1235 if (! freshflag) PSputc('\n', output);
1239 sprintf(logline, "%.9lg X", (double) x / outscale);
1244 sprintf(logline, "%ld X", x); /* xsetright */
1247 PSputs(logline, output);
1254 void do_x2(FILE *output, FILE *input)
1258 x = sreadtwo(input);
1262 if (! freshflag) PSputc('\n', output);
1266 sprintf(logline, "%.9lg X", (double) x / outscale);
1271 sprintf(logline, "%ld X", x); /* xsetright */
1273 PSputs(logline, output);
1280 void do_xsub(FILE *output, long x)
1284 if (! freshflag) PSputc('\n', output);
1288 sprintf(logline, "%.9lg X", (double) x / outscale);
1293 sprintf(logline, "%ld X", x); /* xsetright */
1296 PSputs(logline, output);
1303 void do_x3(FILE *output, FILE *input)
1305 do_xsub(output, sreadthree(input));
1308 void do_x4(FILE *output, FILE *input)
1310 do_xsub(output, sreadfour(input));
1314 void do_down1(FILE *output, FILE *input)
1318 a = sreadone(input);
1322 if (! freshflag) PSputc('\n', output);
1326 sprintf(logline, "%.9lg d", (double) a / outscale);
1331 sprintf(logline, "%d d", a); /* down */
1334 PSputs(logline, output);
1342 void do_down2(FILE *output, FILE *input)
1346 a = sreadtwo(input);
1350 if (! freshflag) PSputc('\n', output);
1354 sprintf(logline, "%.9lg d", (double) a / outscale);
1359 sprintf(logline, "%d d", a); /* down */
1362 PSputs(logline, output);
1369 void do_downsub(FILE *output, long a)
1373 if (! freshflag) PSputc('\n', output);
1377 sprintf(logline, "%.9lg d", (double) a / outscale);
1382 sprintf(logline, "%ld d", a); /* down */
1385 PSputs(logline, output);
1392 void do_down3(FILE *output, FILE *input)
1394 do_downsub(output, sreadthree(input));
1397 void do_down4(FILE *output, FILE *input)
1399 do_downsub(output, sreadfour(input));
1402 void do_y0(FILE *output)
1406 PSputs(" y", output);
1413 void do_y1(FILE *output, FILE *input)
1417 y = sreadone(input);
1421 if (! freshflag) PSputc('\n', output);
1425 sprintf(logline, "%.9lg Y", (double) y / outscale);
1430 sprintf(logline, "%ld Y", y); /* ysetdown */
1433 PSputs(logline, output);
1440 void do_y2(FILE *output, FILE *input)
1444 y = sreadtwo(input);
1448 if (! freshflag) PSputc('\n', output);
1452 sprintf(logline, "%.9lg Y", (double) y / outscale);
1457 sprintf(logline, "%ld Y", y); /* ysetdown */
1459 PSputs(logline, output);
1466 void do_ysub(FILE *output, long y)
1470 if (! freshflag) PSputc('\n', output);
1474 sprintf(logline, "%.9lg Y", (double) y / outscale);
1479 sprintf(logline, "%ld Y", y); /* ysetdown */
1482 PSputs(logline, output);
1489 void do_y3(FILE *output, FILE *input)
1491 do_ysub(output, sreadthree(input));
1495 void do_y4(FILE *output, FILE *input)
1497 do_ysub(output, sreadfour(input));
1500 void do_z0(FILE *output)
1504 PSputs(" z", output);
1511 void do_z1(FILE *output, FILE *input)
1515 z = sreadone(input);
1519 if (! freshflag) PSputc('\n', output);
1523 sprintf(logline, "%.9lg Z", (double) z / outscale);
1528 sprintf(logline, "%ld Z", z); /* zsetdown */
1531 PSputs(logline, output);
1538 void do_z2(FILE *output, FILE *input)
1542 z = sreadtwo(input);
1546 if (! freshflag) PSputc('\n', output);
1550 sprintf(logline, "%.9lg Z", (double) z / outscale);
1555 sprintf(logline, "%ld Z", z); /* zsetdown */
1558 PSputs(logline, output);
1565 void do_zsub(FILE *output, long z)
1569 if (! freshflag) PSputc('\n', output);
1573 sprintf(logline, "%.9lg Z", (double) z / outscale);
1578 sprintf(logline, "%ld Z", z); /* zsetdown */
1581 PSputs(logline, output);
1588 void do_z3(FILE *output, FILE *input)
1590 do_zsub(output, sreadthree(input));
1593 void do_z4(FILE *output, FILE *input)
1595 do_zsub(output, sreadfour(input));
1598 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
1600 void complainfontcode(unsigned long fs)
1602 sprintf(logline, " Bad font code %lu (> %u)\n", fs, MAXFONTNUMBERS-1);
1603 showline(logline, 1);
1605 /* switching to other font */
1606 void switchfont(FILE *output, int fs)
1612 sprintf(logline, "Negative font number %d\n", fs);
1613 showline(logline, 1);
1616 if (fs >= MAXFONTNUMBERS)
1617 complainfontcode(fs);
1619 ff = fs; /* set state */
1623 if (bShortFont != 0)
1628 PSputc('\n', output); // always on new line
1629 sprintf(logline, "f%d", fn);
1630 PSputs(logline, output);
1633 /* if (fnt < 0) fnt = 0; */ /* for safety sake */
1637 void do_fnt1(FILE *output, FILE *input)
1642 switchfont(output, (int) fs);
1645 void do_fnt2(FILE *output, FILE *input)
1649 fs = ureadtwo(input);
1651 if (fs >= MAXFONTNUMBERS)
1653 complainfontcode (fs);
1654 fs = MAXFONTNUMBERS-1;
1657 switchfont(output, (int) fs);
1660 void do_fntsub(FILE *output, unsigned long fs)
1662 if (fs >= MAXFONTNUMBERS)
1664 complainfontcode (fs);
1665 fs = MAXFONTNUMBERS-1;
1667 switchfont(output, (int) fs);
1670 void do_fnt3(FILE *output, FILE *input)
1672 do_fntsub(output, ureadthree(input));
1676 void do_fnt4(FILE *output, FILE *input)
1680 fs = sreadfour(input);
1684 sprintf(logline, "Font code %ld < 0\n", fs);
1685 showline(logline, 1);
1689 do_fntsub(output, (unsigned long) fs);
1692 /**************************************************************************/
1694 void do_xxxi (FILE *output, FILE *input, unsigned int n)
1702 prereadspecial(input, n);
1703 else for(k = 0; k < n; k++) (void) getc(input);
1706 readspecial(output, input, (unsigned long) n);
1711 void do_xxx1 (FILE *output, FILE *input)
1716 do_xxxi(output, input, n);
1720 void do_xxx2 (FILE *output, FILE *input)
1724 n = ureadtwo(input);
1725 do_xxxi(output, input, n);
1728 void do_xxxl (FILE *output, FILE *input, unsigned long n)
1735 prereadspecial(input, n);
1736 else for(k = 0; k < n; k++) (void) getc(input);
1739 readspecial(output, input, n);
1744 void do_xxx3 (FILE *output, FILE *input)
1748 n = ureadthree(input);
1749 do_xxxl(output, input, n);
1752 void do_xxx4 (FILE *output, FILE *input)
1756 n = ureadfour(input);
1757 do_xxxl(output, input, n);
1760 /**************************************************************************/
1762 /* need to do this even if skipping pages */
1764 /* nothing much should actually happen here !!! */
1766 void fnt_def (FILE *output, FILE *input, unsigned int k)
1768 unsigned int na, nl, i;
1770 char namebuffer[FNAMELEN];
1773 if (finx[k] != BLANKFONT)
1782 if (finx[k] != (short) f)
1784 showline(" ERROR: Inconsistency between passes\n", 1);
1791 for (k = 0; k < 12; k++)
1799 for (i = 0; i < na + nl; i++)
1804 sprintf(logline, " ERROR: Redefining font %d\n", f);
1805 showline(logline, 1);
1806 /* fp = fontname[f]; */
1809 if (na + nl >= sizeof(namebuffer)-1)
1811 sprintf(logline, "Font name too long: %d (> %d) ",
1812 na + nl, sizeof(namebuffer)-1);
1813 showline(logline, 1);
1816 tellwhere(input, 1);
1818 for (i = 0; i < na + nl; i++)
1823 for (i = 0; i < na + nl; i++)
1824 *fp++ = (char) getc(input);
1829 if (fontname[f] != NULL)
1832 fontname[f] = zstrdup(namebuffer);
1833 fontsubflag[f] = -1; /* all this goes to extract */
1838 void do_fnt_def1 (FILE *output, FILE *input)
1843 fnt_def(output, input, k);
1846 void do_fnt_def2 (FILE *output, FILE *input)
1850 k = ureadtwo(input);
1852 if (k >= MAXFONTNUMBERS)
1854 complainfontcode (k);
1855 k = MAXFONTNUMBERS-1;
1858 fnt_def(output, input, (unsigned int) k);
1861 void do_fnt_defsub (FILE *output, FILE *input, unsigned long k)
1863 if (k >= MAXFONTNUMBERS)
1865 complainfontcode (k);
1866 k = MAXFONTNUMBERS-1;
1869 fnt_def(output, input, (unsigned int) k);
1873 void do_fnt_def3 (FILE *output, FILE *input)
1875 do_fnt_defsub(output, input, ureadthree(input));
1879 void do_fnt_def4(FILE *output, FILE *input)
1883 k = sreadfour(input);
1887 sprintf(logline, "Font code %ld < 0\n", k);
1888 showline(logline, 1);
1892 do_fnt_defsub(output, input, (unsigned long) k);
1895 /* need to do this even if skipping pages */
1896 /* doesn't do output */
1897 void do_pre (FILE *output, FILE *input)
1903 for (j = 0; j < 12; j++)
1908 for (j = 0; j < k; j++)
1912 (void) ureadfour(input); /* skip over length code */
1915 /* need to do this even if skipping pages */
1916 /* doesn't do output */
1917 void do_post (FILE *output, FILE *input)
1921 previous = sreadfour(input); /* was ureadfour ... */
1924 showline("Hit POST!\n", 0);
1926 for (k = 0; k < 12; k++)
1929 for (k = 0; k < 8; k++)
1932 for (k = 0; k < 4; k++)
1935 if (reverseflag == 0)
1938 if (reverseflag != 0)
1939 fseek(input, previous, SEEK_SET); /* 98/Jul/20 ??? */
1942 /* only in reverse ? */
1943 void do_post_post (FILE *output, FILE *input)
1945 unsigned long previous;
1949 showline("Hit POSTPOST!\n", 0); /* never ? */
1951 previous = ureadfour(input);
1954 if (reverseflag != 0)
1955 fseek(input, previous, SEEK_SET); /* go to POST? */
1958 PSputs("% This is really the end !\n", output); // never!
1961 if (reverseflag == 0)
1962 finish = -1; /* 98/Jul/20 */
1967 // main entry point to this part of the program
1968 // lastflag indicates last in set of copies of same page
1970 int scandvifile (FILE *output, FILE *input, int lastflag)
1978 sprintf(logline, " NULL %s file\n", "output"); /* debug */
1979 showline(logline, 1);
1984 sprintf(logline, " NULL %s file\n", "input"); /* debug */
1985 showline(logline, 1);
1990 resetpagerangehit (0);
1992 numpages = 0; /* number of pages actually processed */
1993 firstpage = -1; /* flag for two sided printing case */
1994 /* evenlast = -1; oddlast = -1; */
1997 fseek(input, dvistart, SEEK_SET);
1999 if (reverseflag != 0)
2004 pagenumber = 0; /* value from earlier scan already used */
2007 stinx = 0; /* maxstinx = 0; */ /* redundant, hopefully */
2008 /* if (reverseflag != 0) pageorder = -1; else pageorder = +1; */
2010 /* if (wanthistogram != 0) for(k = 0; k < 256; k++) histogram[k] = 0; */
2012 if (nRepeatCount > 1)
2013 nRepeatIndex = 0; /* 95/Aug/27 */
2016 /* if (output == NULL) showline("NULL output file\n", 1); */
2021 sprintf(logline, " Unexpected EOF (%s)\n", "scandvi");
2022 showline(logline, 1);
2025 long current = ftell(input);
2026 sprintf(logline, " at byte %d\n", current);
2027 showline(logline, 1);
2031 /* increase error count here ? */
2032 break; /* NEW ??? */
2038 normalchar(output, input, c);
2040 else if (c >= 171 && c <= 234)
2043 switchfont(output, fs);
2050 do_set1(output, input);
2054 do_set2(output, input);
2058 do_set3(output, input);
2062 do_set4(output, input);
2066 do_set_rule(output, input);
2070 do_put1(output, input);
2074 do_put2(output, input);
2078 do_put3(output, input);
2082 do_put4(output, input);
2086 do_put_rule(output, input);
2093 do_bop(output, input);
2097 do_eop(output, input);
2101 do_push(output, input);
2105 do_pop(output, input);
2109 do_right1(output, input);
2113 do_right2(output, input);
2117 do_right3(output, input);
2121 do_right4(output, input);
2129 do_w1(output, input);
2133 do_w2(output, input);
2137 do_w3(output, input);
2141 do_w4(output, input);
2149 do_x1(output, input);
2153 do_x2(output, input);
2157 do_x3(output, input);
2161 do_x4(output, input);
2165 do_down1(output, input);
2169 do_down2(output, input);
2173 do_down3(output, input);
2177 do_down4(output, input);
2185 do_y1(output, input);
2189 do_y2(output, input);
2193 do_y3(output, input);
2197 do_y4(output, input);
2205 do_z1(output, input);
2209 do_z2(output, input);
2213 do_z3(output, input);
2217 do_z4(output, input);
2221 do_fnt1(output, input);
2225 do_fnt2(output, input);
2229 do_fnt3(output, input);
2233 do_fnt4(output, input);
2237 do_xxx1(output, input);
2241 do_xxx2(output, input);
2245 do_xxx3(output, input);
2249 do_xxx4(output, input);
2253 do_fnt_def1(output, input);
2257 do_fnt_def2(output, input);
2261 do_fnt_def3(output, input);
2265 do_fnt_def4(output, input);
2269 do_post(output, input);
2273 do_pre(output, input);
2277 do_post_post(output, input);
2283 sprintf(logline, " ERROR: Unrecognized DVI command: %d", c);
2284 showline(logline, 1);
2285 filptr = ftell(input);
2289 sprintf(logline, " at byte %ld in DVI file", filptr-1);
2290 showline(logline, 0);
2299 if (c < xxx1 || c > xxx4)
2300 freshflag = 0; // 99/Dec/19
2306 abortjob(); // fine grained
2309 break; // in DLL version
2315 if (verboseflag && lastflag)
2323 sprintf(s, "Max stack depth %d - ", dvi_s);
2325 sprintf(s, "%d font slot%s used - ",
2326 fnext, (fnext == 1) ? "" : "s"); /* 1994/Feb/1 */
2329 // we have a problem if there are more than 65535 pages
2330 sprintf(s, "DVI file contains %d page%s\n", dvi_t,
2331 (dvi_t == 1) ? "" : "s"); /* 1994/Feb/1 */
2332 showline(logline, 0);
2337 /* deal with CMINCH */ /* deal with MANFNT */
2339 /* add in PostScript 2.0 structuring convention bullshit */
2341 /* can use either box or line to draw rules - don't need both */
2343 /* combine /font9 def and /f9 def ? what ? */
2345 /* reduce size of scanfile to allow optimize */
2347 /* deal with other page formats ? A4 ? portrait ? */
2349 /* precompute the scale factor used on each BOP - don't recompute it */
2351 /* quick way to get fonts: go to end of file - NOT NEEDED */
2353 /* alternate way of specifying pages (actual pages versus counter[0] ? */
2354 /* OK use upper case B and E instead of lower case b and e */
2356 /* maybe control how much goes on one output line ? */
2357 /* presently somewhat kludgy in allowing MAXSHOWONLINE items */
2358 /* rather count character columns and check before output if it will fit */
2360 /* avoid bind def in some cases to allow redefinition via special ? */
2362 /* may need to align lower left of rule to underlying grid... */
2363 /* do tests with rules spaced along page to see effect */
2365 /* shorten code for set_rule and put_rule and bp and ep */
2366 /* set up scale constant to use at top of page */
2367 /* improve mf & set font */
2369 /* should bop include "dvidict begin" and eop include "end" ? */
2370 /* but watch out, fnt_def1 and xxx1 can appear between eop and bop */
2372 /* further compression coding to exploit common sequences ? */
2373 /* d u u u - s o y u - s o o o o - s o o u - s o o o o o */
2374 /* exploit - o u - o o u u - sequences ? - u o already is absent */
2375 /* o o => O, u u => U, o u => K, d u => D */
2376 /* s o y u => M, s o z u => N */
2377 /* also helps make undecypherable ! have under control of flag ? */
2378 /* write as post-processing rules ? use output line buffer ? */
2379 /* also s o y u <n> r is common pattern with fixed <n> */
2381 /* note also common patterns like r(char)s and r(char)S */
2383 /* keep convention that lower case letters are straight DVI command trans */
2384 /* while upper case letters are combinations of sorts */
2386 /* access w, x, y, z off stack (i.e. keep in stack not register) ? */
2388 /* consider sequences of set1 commands - treat like normalchar ? */
2390 /* check on fonthit even when font switch on page that is not printed ? */
2392 /* check on redundant operations that dvipslog already does anyway */
2394 /* for set1 and put1, use number, not string! then use =string ? */
2396 /* check that nothing but nop and font defs happen between eop and bop ? */
2398 /* Implement %%PageTable: ? */
2400 /* avoid shortening octal codes for old interpretors maybe */
2402 /* try and avoid actually giving up if at all possible */
2404 /* when print even pages only, print a blank at first if last page is odd */
2405 /* when print odd pages only, print a blank at first if first is even */
2407 /* when stack gets too deep insert a savestack - and matching restorestack */
2409 /* bRemapSpace remaps 32 => 195, 13 to 176, 10 => 173, 9 => 170, 0 => 161 */
2410 /* Rational is that text fonts reencoded to TeX 'n ANSI do not use 0 */
2411 /* or 9 or 10, and from now on text fonts will not use 13 for fl, */
2412 /* and TeX does not use 32 in text fonts */
2413 /* But math fonts do use 0, 9, 10, 13 and 32 */
2414 /* but math fonts always have the repetition of 0 - 32 higher up */
2415 /* And for some versions of Acrobat it may be best not to do this */
2416 /* for example transfer material to clipboard is null terminated */
2417 /* 9 is treated as tab, 10 as newline, 13 ignored and 32 ignored */
2419 /* Bytes 250 and 251 are used for left to right typesetting. For instance,
2420 what follows is the definition of these commands in omega:
2422 250. Begin a (possibly recursive) reflected segment.
2423 251. End a (possibly recursive) reflected segment.
2425 When a DVI-IVD driver encounters a \\{begin\_reflect} command, it should
2426 skim ahead (as previously described) until finding the matching
2427 \\{end\_reflect}; these will be properly nested with respect to each
2428 other and with respect to \\{push} and \\{pop}. After skimming has
2429 located a segment of material to be reflected, that segment should be
2430 re-scanned and obeyed in mirror-image mode as described earlier. The
2431 reflected segment might recursively involve
2432 $\\{begin\_reflect}/\\{end\_reflect}$ pairs that need to be reflected