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 skiptoend = 0; /* non-zero => still need to skip to last page */
35 int finish = 0; /* non-zero => have hit end of DVI file */
36 int showcount = 0; /* on when last sent out "set" or "put" */
37 int freshflag = 0; /* on after fresh line is started (\n) */
39 int stinx; /* stack index - to avoid overflow */
40 int maxstinx; /* max stack index seen - not used here */
42 long currentpagestart; /* 95/Aug/27 */
44 /* int escapecode[14] = {'b', 't', 'n', 'v', 'f', 'r'}; */
46 char *escapecode = "btnvfr"; /* special codes for 8, 9, 10, 12, and 13 */
48 /* we don't have to worry about sign extension here - no need for short int */
50 static unsigned int ureadtwo (FILE *input)
52 return (getc(input) << 8) | getc(input);
55 static unsigned long ureadthree (FILE *input)
61 return ((((unsigned long) c << 8) | d) << 8) | e;
64 static unsigned long ureadfour (FILE *input)
71 return ((((((unsigned long) c << 8) | (unsigned long) d) << 8) | e) << 8) | f;
74 /* we do have to worry about sign extension here - use short int if needed */
76 static int sreadone (FILE *input)
87 /* possible compiler optimization bug worked around 98/Feb/8 */
89 static int sreadtwo (FILE *input)
94 if (c > 127) c = c - 256;
98 static long sreadthree (FILE *input)
104 if (c > 127) c = c - 256;
105 return ((((long) c << 8) | d) << 8) | e;
108 static long sreadfour (FILE *input)
115 return ((((((long) c << 8) | (long) d) << 8) | e) << 8) | f;
118 /* don't need to optimize `push pop' since doesn't happen ever? */
120 void do_push(FILE *output, FILE *input)
128 if (stinx % 64 == 0) /* see if stack is getting full */
130 PSputs(" pushstack\n", output);
137 if (c == (int) push && ((stinx + 1) % 64 != 0))
140 PSputs(" U", output); /* u u */
144 (void) ungetc(c, input);
145 PSputs(" u", output); /* statepush */
151 /* Are we sure the `O' = `o o' works when at edge of 64 size stack ? */
153 void do_pop(FILE *output, FILE *input)
159 if (stinx % 64 == 0) /* time to retrieve saved stack ? */
162 PSputs(" popstack\n", output);
170 if (c == (int) pop && (stinx % 64 != 0))
173 PSputs(" O", output); /* o o */
180 PSputs(" M", output);
181 } /* o u - OK if M defined as `o u' */
184 (void) ungetc(c, input);
185 PSputs(" o", output); /* statepop */
192 void complain_char_code(unsigned long c)
194 sprintf(logline, " Character code %lu > 255\n", c);
195 showline(logline, 1);
198 /* come here either with character code 0 - 127 --- or from set1 */
199 /* in the case of set1 we need to read the next byte, which likely is > 127 */
201 void normal_char (FILE *output, FILE *input, int c)
207 if (showcount > MAXSHOWONLINE) /* too much on one line ? */
209 PSputc('\n', output);
210 showcount = 0; /* first go to new line */
215 while (c < 128 || c == (int) set1) /* changed ! */
218 c = getc(input); /* new ! read next byte */
222 if (bRemapControl || bRemapFont)
233 /* NOTE: this must match corresponding code in DVIPSLOG.C */
234 else if (bRemapSpace && c <= 32) /* 1995/Oct/17 */
236 if (c == 32) c = 195; /* not 160 */
237 else if (c == 13) c = 176; /* 1996/June/4 */
238 else if (c == 10) c = 173; /* 1996/June/4 */
239 else if (c == 9) c = 170; /* 1996/June/4 */
240 else if (c == 0) c = 161;
243 if (c < 32 || c >= 127 || c == 37)
245 if (c <= 13 && c >= 8 && c != 11 && bForwardFlag != 0)
247 /* use special escape \b \t \n ... \f \r for 8 ... 13 1993/Sep/29 */
248 PSputc('\\', output);
249 PSputc(escapecode[c - 8], output);
251 else if (bBackWardFlag == 1) /* compatibility with old ALW */
253 d = getc(input); (void) ungetc(d, input); /* peek */
255 if ((d >= 32 && d <= 127) || d == (int) set1)
257 // fprintf(output, "\\%03o", c); /* just to be safe */
258 sprintf(logline, "\\%03o", c); /* just to be safe */
262 sprintf(logline, "\\%o", c);
265 PSputs(logline, output);
267 else { /* following not always safe for old ALW ... */
268 d = getc(input); (void) ungetc(d, input); /* peek */
269 if ((d >= '0' && d <= '7') || d == (int) set1) {
270 // fprintf(output, "\\%03o", c); /* just to be safe */
271 sprintf(logline, "\\%03o", c); /* just to be safe */
274 sprintf(logline, "\\%o", c);
276 PSputs(logline, output);
279 else /* not control characters */
281 if (c == '\\' || c == '(' || c == ')')
283 PSputc('\\', output);
290 c = getc(input); /* get the next byte in DVI file */
293 break; /* trap EOF - avoid loop */
294 } /* end of while (c < 128 ... ) loop */
296 /* analyze next DVI command to see whether can combine with above */
298 (void) ungetc(c, input);
303 PSputs(")S", output);
305 else if (c == (int) x0)
307 PSputs(")T", output);
311 PSputs(")s", output);
312 (void) ungetc(c, input); /* can't use it, put it back */
317 /* also need to increase h by total width */
318 /* fprintf(output, "currentpoint pop /h exch def\n"); */
321 /* Following need *not* be efficient since it is rarely used */
322 /* Put single character - called by put1/put2/put3/put4 */
323 /* Set single character - also called by set2/set3/set4 */
324 /* duplicates a lot of code form normal_char() above */
326 /* separated out 1995/June/30 */ /* third arg is `s' or `p' */
328 void do_charsub (FILE *output, unsigned long c, char code)
332 if (bRemapControl || bRemapFont)
344 else if (bRemapSpace && c <= 32)
346 if (c == 32) c = 195; /* not 160 */
347 else if (c == 13) c = 176; /* 1996/June/4 */
348 else if (c == 10) c = 173; /* 1996/June/4 */
349 else if (c == 9) c = 170; /* 1996/June/4 */
350 else if (c == 0) c = 161;
355 complain_char_code(c);
356 return; /* ignore it - should never happen */
361 if (c < 32 || c >= 127 || c == 37)
363 if (c <= 13 && c >= 8 && c != 11 && bForwardFlag != 0)
365 /* use special escape \b \t \n ... \f \r for 8 ... 13 1993/Sep/29 */
366 PSputc('\\', output);
367 PSputc(escapecode[c - 8], output);
369 else if (bBackWardFlag == 1) /* compatibility with old ALW */
371 sprintf(logline, "\\%03o", (unsigned int) c);
372 PSputs(logline, output);
374 else /* following not always safe for old ALW ... */
376 sprintf(logline, "\\%o", (unsigned int) c);
377 PSputs(logline, output);
382 if (c == '\\' || c == '(' || c == ')')
384 PSputc('\\', output);
387 PSputc((unsigned int) c, output);
391 PSputc(code, output); /* 'p' or 's' */
396 /* could be more efficient here if we ever see several in a row OK */
397 /* model on "normal_char" if needed OK */
399 void do_set1(FILE *output, FILE *input)
403 normal_char(output, input, (int) set1);
408 /* read following byte and throw it away */
409 /* set character c and increase h by width of character */
410 /* used (normally only) for characters in range 128 to 255 */
413 void do_set2(FILE *output, FILE *input)
415 do_charsub(output, ureadtwo(input), 's');
418 void do_set3(FILE *output, FILE *input)
420 do_charsub(output, ureadthree(input), 's');
423 void do_set4(FILE *output, FILE *input)
425 do_charsub(output, ureadfour(input), 's');
428 /* set character c and DO NOT increase h by width of character */
430 void do_put1(FILE *output, FILE *input)
432 do_charsub(output, getc(input), 'p');
435 void do_put2(FILE *output, FILE *input)
437 do_charsub(output, ureadtwo(input), 'p');
440 void do_put3(FILE *output, FILE *input)
442 do_charsub(output, ureadthree(input), 'p');
445 void do_put4(FILE *output, FILE *input)
447 do_charsub(output, ureadfour(input), 'p');
450 /* For PDF problems we adjust height of horizontal rule 95/Oct/15 */
451 /* but we don't adjust the position of the rule ... and */
452 /* if we were to adjust width of vertical rules we'd need to adjust position */
454 void do_common_rule (FILE *output, FILE *input, char *s)
456 long a, b; /* height, width */
458 a = sreadfour(input);
459 b = sreadfour(input);
463 if (nMinRule != 0 && a > 0)
465 /* Make sure we don't get zero width rules in PDF output... */
466 /* ... compensate for truncating down instead of rounding in pdf */
469 else if (a > nMinRule)
470 a = a + nMinRule / 2;
476 PSputc('\n', output);
478 sprintf(logline, "%lg %lg %lg rgb ", rule_red, rule_green, rule_blue);
479 PSputs(logline, output);
486 if (! freshflag) PSputc('\n', output);
487 PSputs("black ", output);
492 /* some silly nonsense about using a height = -2^31 in set_rule */
493 if (bDVICopyReduce && -a == 2147483648L)
495 /* need to do nothing for pr, no output, no motion */
496 if (strcmp (s, "sr") == 0)
499 PSputc('\n', output);
504 sprintf(logline, "%.9lg r", (double) b / outscale);
509 sprintf(logline, "%ld r", b); /* setrule => right */
512 PSputs(logline, output);
519 PSputc('\n', output);
524 sprintf(logline, "%.9lg %.9lg %s",
525 (double) a / outscale, (double) b / outscale, s);
530 sprintf(logline, "%ld %ld %s", a, b, s); /* setrule or putrule */
533 PSputs(logline, output);
540 PSputc('\n', output);
542 sprintf(logline, "%lg %lg %lg rgb ", text_red, text_green, text_blue);
543 PSputs(logline, output);
550 if (! freshflag) PSputc('\n', output);
551 PSputs("black ", output);
560 void do_set_rule(FILE *output, FILE *input)
562 do_common_rule (output, input, "sr");
565 void do_put_rule(FILE *output, FILE *input)
567 do_common_rule (output, input, "pr");
570 /* write TeX /counter's */
571 char *show_counters(char *s)
576 sprintf(s, "%ld", counter[0]); /* *always* write first one */
579 for (k = 10-1; k > 0; k--)
588 for (k = 1; k <= kmax; k++) /* write others if non-zero */
590 sprintf(s, " %ld", counter[k]);
597 /*** code for working way into back end of file looking for post ***/
599 #define BUFSIZE 128 /* buffer size to read in at one time */
600 #define NUMSTEPS 32 /* number of buffers to try from end of file */
601 #define MAGIC 223 /* magic code used by TeX at end of DVI file */
603 /* This does some things to work around possible crap at end of file */
604 /* The way to loose is get garbage at end that comes from other DVI file ! */
606 /* search for post at end of file */
607 long goto_post(FILE *input)
610 int c, d, e, f, k, i, j, count;
614 if (fseek(input, - (long) BUFSIZE, SEEK_END) < 0)
616 rewind(input); /* possibly because file shorter than BUFSIZE ? */
619 for (j = 0; j < NUMSTEPS; j++) /* let's not go on forever ! */
621 for (k = 0; k < BUFSIZE; k++)
623 buffer[k] = getc(input);
630 count=0; /* count MAGIC codes seen */
632 for (i = k; i >= 5; i--) /* need at least seq of four */
634 if (buffer[i] == MAGIC)
647 if (count == 4) /* found sequence of four */
649 for (i = k; i >= 5; i--) /* but there can be many more */
650 if (buffer[i] != MAGIC)
653 k = i; /* first non MAGIC - ID_BYTE ? */
655 if (buffer[k] != MAGIC) /* did see end of MAGIC stuff */
657 if (buffer[k-5] == (int) post_post)
659 k = k - 5; /* step back to post_post */
664 n = ((((((unsigned long) c << 8) | (unsigned long) d) << 8) | e) << 8) | f;
665 fseek(input, (long) n, SEEK_SET); /* go to post ! */
666 c = getc(input); (void) ungetc(c, input);
670 showline("ERROR: Unable to find pointer to POST", 1);
678 sprintf(logline, "Found POST at %ld\n", n);
679 showline(logline, 0);
682 return n; /* seem to be in good shape */
689 if (fseek(input, - (long) (BUFSIZE * 2 - 10), SEEK_CUR) != 0)
695 sprintf(logline, "ERROR: Can't find proper ending of DVI file `%s'\n",
697 showline(logline, 1);
698 fseek(input, 0, SEEK_END);
699 nlen = ftell(input); /* get length of file 99/Mar/21 */
700 sprintf(logline, "Searched near end of file of %ld bytes\n", nlen);
701 showline(logline, 0);
707 void insert_blank(FILE *output, long page)
709 PSputs("dvidict begin\n", output);
713 sprintf(logline, "%ld %ld bop eop end ",
715 PSputs(logline, output);
719 PSputs("bp ep end ", output);
722 PSputs("% blank page\n", output);
725 void do_counter_comment (FILE *output)
732 s = show_counters(s);
734 PSputs(logline, output);
737 /* beginning of page */
738 void do_bop(FILE *output, FILE *input)
741 long pageno; /* page number logical or physical */
742 long page; /* always dvi page count from start of file */
743 double xoffset, yoffset; /* 1992/July/11 */
744 COLORSPEC SavedColor; /* 1999/Apr/06 */
753 /* Normally bRepeatMode == 0 */
754 if (nRepeatCount > 1)
756 if (nRepeatIndex == 0)
757 currentpagestart = ftell(input) - 1; /* right at bop */
759 pagenumber--; /* compensate */
762 pagenumber++; /* DVI page count from start of job */
765 page = dvi_t - pagenumber + 1;
774 if (bCarryColor == 0)
777 if (bCarryColor && bColorUsed)
779 RestoreColorStack(page);
782 clipstackindex = 0; /* reset push pop stack 98/Sep/12 */
783 CTMstackindex= 0; /* reset CTM stack pointer in dvispeci.c */
785 for (k = 0; k < 10; k++)
786 counter[k] = sreadfour(input);
788 previous = sreadfour(input);
791 if (countzeroflag != 0)
794 pageno = (long) page;
796 skipflag = skip_this_page(pageno);
800 else if (skipflag == 0) /* page in valid range */
802 if (oddpageflag != 0) /* if printing only odd pages */
804 if ((counter[0] & 1) == 0) /* seen even numbered page */
807 insert_blank(output, page); /* matching blank */
815 if (evenpageflag != 0) /* if printing only even pages */
817 if ((counter[0] & 1) == 1) /* seen odd numbered page */
820 insert_blank(output, page); /* matching blank */
829 if (skipflag != 0) /* skipping this page */
831 if (reverseflag != 0)
834 fseek(input, previous, SEEK_SET);
841 else /* not skipping this page */
846 show_counters(logline);
847 showline(logline, 0);
853 /* note: first item after Page: is a page label - here counter[0] */
854 /* (or counter[1]-counter[2]) 1996/Jan/28 */
855 /* note: first item after Page: need not be a number */
856 /* note: second item after Page: is sequential page number */
857 /* An experiment 1995/Aug/27 */
858 /* page = numpages + 1; */
859 if (stripcomment == 0)
861 PSputs("%%Page: ", output);
865 sprintf(logline, "%ld-%ld %ld\n",
866 counter[1], counter[2], numpages+1); /* 1996/Jan/20 */
870 sprintf(logline, "%ld %ld\n", counter[0], numpages+1);
873 PSputs(logline, output);
876 PSputs("dvidict begin ", output);
880 if ((counter[0] & 1) == 1) /* seen odd numbered page */
885 else /* seen even numbered page */
892 "/xoffset %lg def /yoffset %lg def\n", xoffset, yoffset);
893 PSputs(logline, output);
896 PSputc('\n', output); // always start new line for this
900 sprintf(logline, "%ld %ld bop ", counter[0], numpages+1);
901 PSputs(logline, output);
904 PSputs("bp ", output);
906 if (stripcomment == 0)
907 do_counter_comment (output);
909 if (bBackGroundFlag && bBackUsed)
911 if (BackColors[page].A != -1.0 ||
912 BackColors[page].B != -1.0 ||
913 BackColors[page].C != -1.0)
915 PSputc('\n', output);
916 PSputs("gsave clippath ", output);
917 SavedColor = CurrColor; /* save around following */
918 CurrColor = BackColors[page];
919 doColorSet(output, 3); /* background - in dvispeci.c */
920 PSputs("fill grestore ", output);
921 CurrColor = SavedColor; /* restore after 99/Apr/06 */
925 /* now pop color pushed at bottom of previous page (restored stack up above) */
926 if (bColorUsed && (colorindex > 0))
929 doColorSet(output, 2); /* bop - in dvispeci.c */
933 PSputc('\n', output); /* omission slightly risky ... */
936 /* maybe also do "structuring conventions" stuff ? */
940 void do_eop(FILE *output, FILE *input)
953 checkColorStack(output);
955 if (clipstackindex > 0)
956 doClipBoxPopAll(output);
960 if (CTMstackindex != 0)
963 PSputc('\n', output); // always start new line
966 PSputs("eop ", output);
968 PSputs("ep ", output);
970 if (stripcomment == 0)
971 do_counter_comment(output);
973 PSputc('\n', output);
974 PSputs("end", output);
976 if (stripcomment == 0)
977 PSputs(" % dvidict", output);
979 PSputc('\n', output);
981 /* %%PageTrailer comments highly optional ... */
984 if (stripcomment == 0)
986 PSputs("%%PageTrailer\n", output);
993 numpages++; /* update number of pages actually processed */
996 if (output != NULL && ferror(output))
999 showline("ERROR in output file", 1);
1000 perrormod((outputfile != NULL) ? outputfile : "");
1005 /* Normally bRepeatMode == 0 */
1006 if (nRepeatCount > 1)
1010 if (nRepeatIndex == nRepeatCount)
1014 fseek (input, currentpagestart, SEEK_SET);
1021 if (reverseflag != 0) /* go back if reading in reverse */
1024 fseek(input, previous, SEEK_SET);
1030 (void) ureadfour(input); /* skip over length code */
1032 /* may also want to check whether length is something reasonable ? */
1033 c = getc(input); (void) ungetc(c, input); /* peek ahead */
1035 if (c >= 0 && c <= 127)
1037 sprintf(logline, " invalid code (%d)\n", c);
1038 showline(logline, 1);
1044 void do_right1(FILE *output, FILE *input)
1048 b = sreadone(input);
1053 PSputc('\n', output);
1058 sprintf(logline, "%.9lg r", (double) b / outscale);
1063 sprintf(logline, "%d r", b); /* right */
1066 PSputs(logline, output);
1073 void do_right2(FILE *output, FILE *input)
1077 b = sreadtwo(input);
1082 PSputc('\n', output);
1087 sprintf(logline, "%.9lg r", (double) b / outscale);
1092 sprintf(logline, "%d r", b); /* right */
1095 PSputs(logline, output);
1102 void do_rightsub(FILE *output, long b)
1107 PSputc('\n', output);
1112 sprintf(logline, "%.9lg r", (double) b / outscale);
1117 sprintf(logline, "%ld r", b); /* right */
1120 PSputs(logline, output);
1127 void do_right3(FILE *output, FILE *input)
1129 do_rightsub(output, sreadthree(input));
1132 void do_right4(FILE *output, FILE *input)
1134 do_rightsub(output, sreadfour(input));
1137 void do_w0(FILE * output)
1141 PSputs(" w", output); /* wright */
1148 void do_w1(FILE *output, FILE *input)
1152 w = sreadone(input);
1157 PSputc('\n', output);
1162 sprintf(logline, "%.9lg W", (double) w / outscale);
1167 sprintf(logline, "%ld W", w); /* wsetright */
1170 PSputs(logline, output);
1177 void do_w2(FILE *output, FILE *input)
1181 w = sreadtwo(input);
1186 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_wsub(FILE *output, long w)
1211 PSputc('\n', output);
1216 sprintf(logline, "%.9lg W", (double) w / outscale);
1221 sprintf(logline, "%ld W", w); /* wsetright */
1224 PSputs(logline, output);
1231 void do_w3(FILE *output, FILE *input)
1233 do_wsub(output, sreadthree(input));
1236 void do_w4(FILE *output, FILE *input)
1238 do_wsub(output, sreadfour(input));
1241 void do_x0(FILE *output)
1245 PSputs(" x", output); /* xright */
1252 void do_x1(FILE *output, FILE *input)
1256 x = sreadone(input);
1261 PSputc('\n', output);
1266 sprintf(logline, "%.9lg X", (double) x / outscale);
1271 sprintf(logline, "%ld X", x); /* xsetright */
1274 PSputs(logline, output);
1281 void do_x2(FILE *output, FILE *input)
1285 x = sreadtwo(input);
1290 PSputc('\n', output);
1295 sprintf(logline, "%.9lg X", (double) x / outscale);
1300 sprintf(logline, "%ld X", x); /* xsetright */
1303 PSputs(logline, output);
1310 void do_xsub(FILE *output, long x)
1315 PSputc('\n', output);
1320 sprintf(logline, "%.9lg X", (double) x / outscale);
1325 sprintf(logline, "%ld X", x); /* xsetright */
1328 PSputs(logline, output);
1335 void do_x3(FILE *output, FILE *input)
1337 do_xsub(output, sreadthree(input));
1340 void do_x4(FILE *output, FILE *input)
1342 do_xsub(output, sreadfour(input));
1346 void do_down1(FILE *output, FILE *input)
1350 a = sreadone(input);
1355 PSputc('\n', output);
1360 sprintf(logline, "%.9lg d", (double) a / outscale);
1365 sprintf(logline, "%d d", a); /* down */
1368 PSputs(logline, output);
1376 void do_down2(FILE *output, FILE *input)
1380 a = sreadtwo(input);
1385 PSputc('\n', output);
1390 sprintf(logline, "%.9lg d", (double) a / outscale);
1395 sprintf(logline, "%d d", a); /* down */
1398 PSputs(logline, output);
1405 void do_downsub(FILE *output, long a)
1410 PSputc('\n', output);
1415 sprintf(logline, "%.9lg d", (double) a / outscale);
1420 sprintf(logline, "%ld d", a); /* down */
1423 PSputs(logline, output);
1430 void do_down3(FILE *output, FILE *input)
1432 do_downsub(output, sreadthree(input));
1435 void do_down4(FILE *output, FILE *input)
1437 do_downsub(output, sreadfour(input));
1440 void do_y0(FILE *output)
1444 PSputs(" y", output);
1451 void do_y1(FILE *output, FILE *input)
1455 y = sreadone(input);
1460 PSputc('\n', output);
1465 sprintf(logline, "%.9lg Y", (double) y / outscale);
1470 sprintf(logline, "%ld Y", y); /* ysetdown */
1473 PSputs(logline, output);
1480 void do_y2(FILE *output, FILE *input)
1484 y = sreadtwo(input);
1489 PSputc('\n', output);
1494 sprintf(logline, "%.9lg Y", (double) y / outscale);
1499 sprintf(logline, "%ld Y", y); /* ysetdown */
1502 PSputs(logline, output);
1509 void do_ysub(FILE *output, long y)
1514 PSputc('\n', output);
1519 sprintf(logline, "%.9lg Y", (double) y / outscale);
1524 sprintf(logline, "%ld Y", y); /* ysetdown */
1527 PSputs(logline, output);
1534 void do_y3(FILE *output, FILE *input)
1536 do_ysub(output, sreadthree(input));
1540 void do_y4(FILE *output, FILE *input)
1542 do_ysub(output, sreadfour(input));
1545 void do_z0(FILE *output)
1549 PSputs(" z", output);
1556 void do_z1(FILE *output, FILE *input)
1560 z = sreadone(input);
1565 PSputc('\n', output);
1570 sprintf(logline, "%.9lg Z", (double) z / outscale);
1575 sprintf(logline, "%ld Z", z); /* zsetdown */
1578 PSputs(logline, output);
1585 void do_z2(FILE *output, FILE *input)
1589 z = sreadtwo(input);
1594 PSputc('\n', output);
1599 sprintf(logline, "%.9lg Z", (double) z / outscale);
1604 sprintf(logline, "%ld Z", z); /* zsetdown */
1607 PSputs(logline, output);
1614 void do_zsub(FILE *output, long z)
1619 PSputc('\n', output);
1624 sprintf(logline, "%.9lg Z", (double) z / outscale);
1629 sprintf(logline, "%ld Z", z); /* zsetdown */
1632 PSputs(logline, output);
1639 void do_z3(FILE *output, FILE *input)
1641 do_zsub(output, sreadthree(input));
1644 void do_z4(FILE *output, FILE *input)
1646 do_zsub(output, sreadfour(input));
1649 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
1651 void complain_font_code(unsigned long fs)
1653 sprintf(logline, " Bad font code %lu (> %u)\n", fs, MAXFONTNUMBERS-1);
1654 showline(logline, 1);
1656 /* switching to other font */
1657 void switch_font(FILE *output, int fs)
1663 sprintf(logline, "Negative font number %d\n", fs);
1664 showline(logline, 1);
1667 if (fs >= MAXFONTNUMBERS)
1668 complain_font_code(fs);
1670 ff = fs; /* set state */
1674 if (bShortFont != 0)
1679 PSputc('\n', output); // always on new line
1680 sprintf(logline, "f%d", fn);
1681 PSputs(logline, output);
1687 void do_fnt1(FILE *output, FILE *input)
1692 switch_font(output, (int) fs);
1695 void do_fnt2(FILE *output, FILE *input)
1699 fs = ureadtwo(input);
1701 if (fs >= MAXFONTNUMBERS)
1703 complain_font_code (fs);
1704 fs = MAXFONTNUMBERS - 1;
1707 switch_font(output, (int) fs);
1710 void do_fntsub(FILE *output, unsigned long fs)
1712 if (fs >= MAXFONTNUMBERS)
1714 complain_font_code (fs);
1715 fs = MAXFONTNUMBERS-1;
1718 switch_font(output, (int) fs);
1721 void do_fnt3(FILE *output, FILE *input)
1723 do_fntsub(output, ureadthree(input));
1727 void do_fnt4(FILE *output, FILE *input)
1731 fs = sreadfour(input);
1735 sprintf(logline, "Font code %ld < 0\n", fs);
1736 showline(logline, 1);
1740 do_fntsub(output, (unsigned long) fs);
1743 void do_xxxi (FILE *output, FILE *input, unsigned int n)
1751 prereadspecial(input, n);
1752 else for(k = 0; k < n; k++)
1756 readspecial(output, input, (unsigned long) n);
1761 void do_xxx1 (FILE *output, FILE *input)
1766 do_xxxi(output, input, n);
1770 void do_xxx2 (FILE *output, FILE *input)
1774 n = ureadtwo(input);
1775 do_xxxi(output, input, n);
1778 void do_xxxl (FILE *output, FILE *input, unsigned long n)
1785 prereadspecial(input, n);
1786 else for(k = 0; k < n; k++) (void) getc(input);
1789 readspecial(output, input, n);
1794 void do_xxx3 (FILE *output, FILE *input)
1798 n = ureadthree(input);
1799 do_xxxl(output, input, n);
1802 void do_xxx4 (FILE *output, FILE *input)
1806 n = ureadfour(input);
1807 do_xxxl(output, input, n);
1810 /* need to do this even if skipping pages */
1812 /* nothing much should actually happen here !!! */
1814 void fnt_def (FILE *output, FILE *input, unsigned int k)
1816 unsigned int na, nl, i;
1818 char namebuffer[FNAMELEN];
1821 if (finx[k] != BLANKFONT)
1830 if (finx[k] != (short) f)
1832 showline(" ERROR: Inconsistency between passes\n", 1);
1839 for (k = 0; k < 12; k++)
1847 for (i = 0; i < na + nl; i++)
1852 sprintf(logline, " ERROR: Redefining font %d\n", f);
1853 showline(logline, 1);
1854 /* fp = fontname[f]; */
1857 if (na + nl >= sizeof(namebuffer)-1)
1859 sprintf(logline, "Font name too long: %d (> %d) ",
1860 na + nl, sizeof(namebuffer)-1);
1861 showline(logline, 1);
1864 tellwhere(input, 1);
1866 for (i = 0; i < na + nl; i++)
1871 for (i = 0; i < na + nl; i++)
1872 *fp++ = (char) getc(input);
1877 if (fontname[f] != NULL)
1880 fontname[f] = zstrdup(namebuffer);
1881 fontsubflag[f] = -1; /* all this goes to extract */
1886 void do_fnt_def1 (FILE *output, FILE *input)
1891 fnt_def(output, input, k);
1894 void do_fnt_def2 (FILE *output, FILE *input)
1898 k = ureadtwo(input);
1900 if (k >= MAXFONTNUMBERS)
1902 complain_font_code (k);
1903 k = MAXFONTNUMBERS-1;
1906 fnt_def(output, input, (unsigned int) k);
1909 void do_fnt_defsub (FILE *output, FILE *input, unsigned long k)
1911 if (k >= MAXFONTNUMBERS)
1913 complain_font_code (k);
1914 k = MAXFONTNUMBERS-1;
1917 fnt_def(output, input, (unsigned int) k);
1921 void do_fnt_def3 (FILE *output, FILE *input)
1923 do_fnt_defsub(output, input, ureadthree(input));
1927 void do_fnt_def4(FILE *output, FILE *input)
1931 k = sreadfour(input);
1935 sprintf(logline, "Font code %ld < 0\n", k);
1936 showline(logline, 1);
1940 do_fnt_defsub(output, input, (unsigned long) k);
1943 /* need to do this even if skipping pages */
1944 /* doesn't do output */
1945 void do_pre (FILE *output, FILE *input)
1951 for (j = 0; j < 12; j++)
1956 for (j = 0; j < k; j++)
1960 (void) ureadfour(input); /* skip over length code */
1963 /* need to do this even if skipping pages */
1964 /* doesn't do output */
1965 void do_post (FILE *output, FILE *input)
1969 previous = sreadfour(input); /* was ureadfour ... */
1972 showline("Hit POST!\n", 0);
1974 for (k = 0; k < 12; k++)
1977 for (k = 0; k < 8; k++)
1980 for (k = 0; k < 4; k++)
1983 if (reverseflag == 0)
1986 if (reverseflag != 0)
1987 fseek(input, previous, SEEK_SET); /* 98/Jul/20 ??? */
1990 /* only in reverse ? */
1991 void do_post_post (FILE *output, FILE *input)
1993 unsigned long previous;
1997 showline("Hit POSTPOST!\n", 0); /* never ? */
1999 previous = ureadfour(input);
2002 if (reverseflag != 0)
2003 fseek(input, previous, SEEK_SET); /* go to POST? */
2006 PSputs("% This is really the end !\n", output); // never!
2009 if (reverseflag == 0)
2010 finish = -1; /* 98/Jul/20 */
2015 // main entry point to this part of the program
2016 // lastflag indicates last in set of copies of same page
2018 int scan_dvi_file (FILE *output, FILE *input, int lastflag)
2026 sprintf(logline, " NULL %s file\n", "output"); /* debug */
2027 showline(logline, 1);
2032 sprintf(logline, " NULL %s file\n", "input"); /* debug */
2033 showline(logline, 1);
2038 resetpagerangehit (0);
2040 numpages = 0; /* number of pages actually processed */
2041 firstpage = -1; /* flag for two sided printing case */
2044 fseek(input, dvistart, SEEK_SET);
2046 if (reverseflag != 0)
2051 pagenumber = 0; /* value from earlier scan already used */
2056 if (nRepeatCount > 1)
2065 sprintf(logline, " Unexpected EOF (%s)\n", "scandvi");
2066 showline(logline, 1);
2069 long current = ftell(input);
2070 sprintf(logline, " at byte %d\n", current);
2071 showline(logline, 1);
2080 normal_char(output, input, c);
2082 else if (c >= 171 && c <= 234)
2085 switch_font(output, fs);
2092 do_set1(output, input);
2096 do_set2(output, input);
2100 do_set3(output, input);
2104 do_set4(output, input);
2108 do_set_rule(output, input);
2112 do_put1(output, input);
2116 do_put2(output, input);
2120 do_put3(output, input);
2124 do_put4(output, input);
2128 do_put_rule(output, input);
2135 do_bop(output, input);
2139 do_eop(output, input);
2143 do_push(output, input);
2147 do_pop(output, input);
2151 do_right1(output, input);
2155 do_right2(output, input);
2159 do_right3(output, input);
2163 do_right4(output, input);
2171 do_w1(output, input);
2175 do_w2(output, input);
2179 do_w3(output, input);
2183 do_w4(output, input);
2191 do_x1(output, input);
2195 do_x2(output, input);
2199 do_x3(output, input);
2203 do_x4(output, input);
2207 do_down1(output, input);
2211 do_down2(output, input);
2215 do_down3(output, input);
2219 do_down4(output, input);
2227 do_y1(output, input);
2231 do_y2(output, input);
2235 do_y3(output, input);
2239 do_y4(output, input);
2247 do_z1(output, input);
2251 do_z2(output, input);
2255 do_z3(output, input);
2259 do_z4(output, input);
2263 do_fnt1(output, input);
2267 do_fnt2(output, input);
2271 do_fnt3(output, input);
2275 do_fnt4(output, input);
2279 do_xxx1(output, input);
2283 do_xxx2(output, input);
2287 do_xxx3(output, input);
2291 do_xxx4(output, input);
2295 do_fnt_def1(output, input);
2299 do_fnt_def2(output, input);
2303 do_fnt_def3(output, input);
2307 do_fnt_def4(output, input);
2311 do_post(output, input);
2315 do_pre(output, input);
2319 do_post_post(output, input);
2325 sprintf(logline, " ERROR: Unrecognized DVI command: %d", c);
2326 showline(logline, 1);
2327 filptr = ftell(input);
2331 sprintf(logline, " at byte %ld in DVI file", filptr - 1);
2332 showline(logline, 0);
2342 if (c < xxx1 || c > xxx4)
2349 abortjob(); // fine grained
2358 if (verboseflag && lastflag)
2366 sprintf(s, "Max stack depth %d - ", dvi_s);
2368 sprintf(s, "%d font slot%s used - ",
2369 fnext, (fnext == 1) ? "" : "s");
2373 // we have a problem if there are more than 65535 pages
2374 sprintf(s, "DVI file contains %d page%s\n", dvi_t,
2375 (dvi_t == 1) ? "" : "s");
2376 showline(logline, 0);
2382 /* deal with CMINCH */ /* deal with MANFNT */
2383 /* add in PostScript 2.0 structuring convention bullshit */
2384 /* can use either box or line to draw rules - don't need both */
2385 /* combine /font9 def and /f9 def ? what ? */
2386 /* reduce size of scanfile to allow optimize */
2387 /* deal with other page formats ? A4 ? portrait ? */
2388 /* precompute the scale factor used on each BOP - don't recompute it */
2389 /* quick way to get fonts: go to end of file - NOT NEEDED */
2390 /* alternate way of specifying pages (actual pages versus counter[0] ? */
2391 /* OK use upper case B and E instead of lower case b and e */
2392 /* maybe control how much goes on one output line ? */
2393 /* presently somewhat kludgy in allowing MAXSHOWONLINE items */
2394 /* rather count character columns and check before output if it will fit */
2395 /* avoid bind def in some cases to allow redefinition via special ? */
2396 /* may need to align lower left of rule to underlying grid... */
2397 /* do tests with rules spaced along page to see effect */
2398 /* shorten code for set_rule and put_rule and bp and ep */
2399 /* set up scale constant to use at top of page */
2400 /* improve mf & set font */
2401 /* should bop include "dvidict begin" and eop include "end" ? */
2402 /* but watch out, fnt_def1 and xxx1 can appear between eop and bop */
2403 /* further compression coding to exploit common sequences ? */
2404 /* d u u u - s o y u - s o o o o - s o o u - s o o o o o */
2405 /* exploit - o u - o o u u - sequences ? - u o already is absent */
2406 /* o o => O, u u => U, o u => K, d u => D */
2407 /* s o y u => M, s o z u => N */
2408 /* also helps make undecypherable ! have under control of flag ? */
2409 /* write as post-processing rules ? use output line buffer ? */
2410 /* also s o y u <n> r is common pattern with fixed <n> */
2411 /* note also common patterns like r(char)s and r(char)S */
2412 /* keep convention that lower case letters are straight DVI command trans */
2413 /* while upper case letters are combinations of sorts */
2414 /* access w, x, y, z off stack (i.e. keep in stack not register) ? */
2415 /* consider sequences of set1 commands - treat like normal_char ? */
2416 /* check on fonthit even when font switch on page that is not printed ? */
2417 /* check on redundant operations that dvipslog already does anyway */
2418 /* for set1 and put1, use number, not string! then use =string ? */
2419 /* check that nothing but nop and font defs happen between eop and bop ? */
2420 /* Implement %%PageTable: ? */
2421 /* avoid shortening octal codes for old interpretors maybe */
2422 /* try and avoid actually giving up if at all possible */
2423 /* when print even pages only, print a blank at first if last page is odd */
2424 /* when print odd pages only, print a blank at first if first is even */
2425 /* when stack gets too deep insert a savestack - and matching restorestack */
2426 /* bRemapSpace remaps 32 => 195, 13 to 176, 10 => 173, 9 => 170, 0 => 161 */
2427 /* Rational is that text fonts reencoded to TeX 'n ANSI do not use 0 */
2428 /* or 9 or 10, and from now on text fonts will not use 13 for fl, */
2429 /* and TeX does not use 32 in text fonts */
2430 /* But math fonts do use 0, 9, 10, 13 and 32 */
2431 /* but math fonts always have the repetition of 0 - 32 higher up */
2432 /* And for some versions of Acrobat it may be best not to do this */
2433 /* for example transfer material to clipboard is null terminated */
2434 /* 9 is treated as tab, 10 as newline, 13 ignored and 32 ignored */
2435 /* Bytes 250 and 251 are used for left to right typesetting. For instance,
2436 what follows is the definition of these commands in omega:
2437 250. Begin a (possibly recursive) reflected segment.
2438 251. End a (possibly recursive) reflected segment.
2439 When a DVI-IVD driver encounters a \\{begin\_reflect} command, it should
2440 skim ahead (as previously described) until finding the matching
2441 \\{end\_reflect}; these will be properly nested with respect to each
2442 other and with respect to \\{push} and \\{pop}. After skimming has
2443 located a segment of material to be reflected, that segment should be
2444 re-scanned and obeyed in mirror-image mode as described earlier. The
2445 reflected segment might recursively involve
2446 $\\{begin\_reflect}/\\{end\_reflect}$ pairs that need to be reflected