OSDN Git Service

code clean.
[putex/putex.git] / src / dvisourc / dvianal.c
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
4
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.
9
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.
14
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
18    02110-1301 USA.  */
19
20
21 /**********************************************************************
22 *
23 * DVI to PS convertor for Adobe Type 1 (ATM compatible) fonts
24 * This is the part that actually converts DVI commands to PS
25 *
26 **********************************************************************/
27
28 #include "dvipsone.h"
29
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 */
32
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) */
38
39 int stinx;        /* stack index - to avoid overflow */ 
40 int maxstinx;     /* max stack index seen  - not used here */
41
42 long currentpagestart;    /* 95/Aug/27 */
43
44 /* int escapecode[14] = {'b', 't', 'n', 'v', 'f', 'r'}; */
45
46 char *escapecode = "btnvfr";  /* special codes for 8, 9, 10, 12, and 13 */
47
48 /* we don't have to worry about sign extension here - no need for short int */
49
50 static unsigned int ureadtwo (FILE *input)
51 {
52   return (getc(input) << 8) | getc(input);
53 }
54
55 static unsigned long ureadthree (FILE *input)
56 {
57   int c, d, e;
58   c = getc(input);
59   d = getc(input);
60   e = getc(input);
61   return ((((unsigned long) c << 8) | d) << 8) | e;
62 }
63
64 static unsigned long ureadfour (FILE *input)
65 {
66   int c, d, e, f;
67   c = getc(input);
68   d = getc(input);
69   e = getc(input);
70   f = getc(input);
71   return ((((((unsigned long) c << 8) | (unsigned long) d) << 8) | e) << 8) | f;
72 }
73
74 /* we do have to worry about sign extension here - use short int if needed */
75
76 static int sreadone (FILE *input)
77 {
78   int c;
79
80   c = getc(input);
81   if (c > 127)
82     return (c - 256);
83   else
84     return c;
85 }
86
87 /* possible compiler optimization bug worked around 98/Feb/8 */
88
89 static int sreadtwo (FILE *input)
90 {
91   int c, d;
92   c = getc(input);
93   d = getc(input);
94   if (c > 127) c = c - 256;
95   return c << 8 | d;
96 }
97
98 static long sreadthree (FILE *input)
99 {
100   int c, d, e;
101   c = getc(input);
102   d = getc(input);
103   e = getc(input);
104   if (c > 127) c = c - 256;
105   return ((((long) c << 8) | d) << 8) | e;
106 }
107
108 static long sreadfour (FILE *input)
109 {
110   int c, d, e, f;
111   c = getc(input);
112   d = getc(input);
113   e = getc(input);
114   f = getc(input);
115   return ((((((long) c << 8) | (long) d) << 8) | e) << 8) | f;
116 }
117
118 /* don't need to optimize `push pop' since doesn't happen ever? */
119
120 void do_push(FILE *output, FILE *input)
121 {
122   int c;
123
124   if (skipflag == 0)
125   {
126     stinx++;
127
128     if (stinx % 64 == 0)    /* see if stack is getting full */
129     {
130       PSputs(" pushstack\n", output);
131       showcount = 0;
132       return;
133     }
134
135     c = getc(input);
136
137     if (c == (int) push && ((stinx + 1) % 64 != 0))
138     {
139       stinx++;
140       PSputs(" U", output); /* u u */
141     }
142     else
143     {
144       (void) ungetc(c, input);
145       PSputs(" u", output);   /* statepush */
146     }
147     showcount = 0;
148   }
149 }
150
151 /* Are we sure the `O' = `o o' works when at edge of 64 size stack ? */
152
153 void do_pop(FILE *output, FILE *input)
154 {
155   int c;
156
157   if (skipflag == 0)
158   {
159     if (stinx % 64 == 0)    /* time to retrieve saved stack ? */
160     {
161       stinx--;
162       PSputs(" popstack\n", output);
163       showcount = 0; 
164       return;
165     }
166
167     stinx--;
168     c = getc(input);
169
170     if (c == (int) pop && (stinx % 64 != 0))
171     {
172       stinx--;
173       PSputs(" O", output);   /* o o */
174     }
175     else
176     {
177       if (c == (int) push)
178       {
179         stinx++;
180         PSputs(" M", output);
181       }   /* o u - OK if M defined as `o u' */
182       else
183       {
184         (void) ungetc(c, input);
185         PSputs(" o", output); /* statepop */
186       }
187     }
188     showcount = 0;
189   }
190 }
191
192 void complain_char_code(unsigned long c)
193 {
194   sprintf(logline, " Character code %lu > 255\n", c);
195   showline(logline, 1);
196 }
197
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 */
200
201 void normal_char (FILE *output, FILE *input, int c)
202 {
203   int d;
204
205   if (skipflag == 0)
206   {
207     if (showcount > MAXSHOWONLINE)    /* too much on one line ? */
208     {
209       PSputc('\n', output);
210       showcount = 0;  /* first go to new line */
211     } 
212     PSputc('(', output);
213   }
214
215   while (c < 128 || c == (int) set1)    /* changed ! */
216   {
217     if (c == (int) set1)
218       c = getc(input); /* new ! read next byte */
219
220     if (skipflag == 0)
221     {
222       if (bRemapControl || bRemapFont)
223       {
224         if (c < MAXREMAP)
225           c = remaptable[c];
226 #if MAXREMAP < 128
227         else if (c == 32)
228           c = 195;
229         else if (c == 127)
230           c = 196;
231 #endif
232       }
233 /* NOTE: this must match corresponding code in DVIPSLOG.C */
234       else if (bRemapSpace && c <= 32)  /* 1995/Oct/17 */
235       {
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;
241       }
242
243       if (c < 32 || c >= 127 || c == 37)
244       {
245         if (c <= 13 && c >= 8 && c != 11 && bForwardFlag != 0)
246         {
247 /* use special escape \b \t \n ... \f \r for 8 ... 13 1993/Sep/29 */
248           PSputc('\\', output);
249           PSputc(escapecode[c - 8], output);
250         }
251         else if (bBackWardFlag == 1) /* compatibility with old ALW */
252         {
253           d = getc(input); (void) ungetc(d, input); /* peek  */
254
255           if ((d >= 32 && d <= 127) || d == (int) set1)
256           {
257 //            fprintf(output, "\\%03o", c);  /* just to be safe */
258             sprintf(logline, "\\%03o", c);  /* just to be safe */
259           }
260           else
261           {
262             sprintf(logline, "\\%o", c);
263           }
264           
265           PSputs(logline, output);
266         }
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 */
272           }
273           else {
274             sprintf(logline, "\\%o", c);
275           }
276           PSputs(logline, output);
277         }
278       }
279       else /* not control characters */
280       {
281         if (c == '\\' || c == '(' || c == ')')
282         {
283           PSputc('\\', output);
284         }
285
286         PSputc(c, output);
287       }
288     }
289
290     c = getc(input);    /* get the next byte in DVI file */
291
292     if (c < 0)
293       break;   /* trap EOF - avoid loop */
294   } /* end of while (c < 128 ... ) loop */
295
296 /* analyze next DVI command to see whether can combine with above */
297   if (skipflag != 0)
298     (void) ungetc(c, input);
299   else
300   {
301     if (c == (int) w0)
302     {
303       PSputs(")S", output);
304     }
305     else if (c == (int) x0)
306     {
307       PSputs(")T", output);
308     }
309     else
310     {
311       PSputs(")s", output);
312       (void) ungetc(c, input);  /* can't use it, put it back */
313     }
314
315     showcount++;
316   }
317 /*  also need to increase h by total width */
318 /*  fprintf(output, "currentpoint pop /h exch def\n"); */
319 }
320
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 */
325
326 /* separated out 1995/June/30 */  /* third arg is `s' or `p' */
327
328 void do_charsub (FILE *output, unsigned long c, char code)
329 {
330   if (skipflag == 0)
331   {
332     if (bRemapControl || bRemapFont)
333     {
334       if (c < MAXREMAP)
335         c = remaptable[c];
336
337 #if MAXREMAP < 128
338       else if (c == 32)
339         c = 195;
340       else if (c == 127)
341         c = 196;
342 #endif
343     }
344     else if (bRemapSpace && c <= 32)
345     {
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;
351     }
352
353     if (c >= 256)
354     {
355       complain_char_code(c);
356       return;       /* ignore it - should never happen */
357     }
358
359     PSputc('(', output); 
360
361     if (c < 32 || c >= 127 || c == 37)
362     {
363       if (c <= 13 && c >= 8 && c != 11 && bForwardFlag != 0)
364       {
365         /* use special escape \b \t \n ... \f \r for 8 ... 13 1993/Sep/29 */
366         PSputc('\\', output);
367         PSputc(escapecode[c - 8], output);
368       }
369       else if (bBackWardFlag == 1)  /* compatibility with old ALW */
370       {
371         sprintf(logline, "\\%03o", (unsigned int) c);
372         PSputs(logline, output);
373       }
374       else  /* following not always safe for old ALW ... */
375       {
376         sprintf(logline, "\\%o", (unsigned int) c);
377         PSputs(logline, output);
378       }
379     }
380     else
381     {
382       if (c == '\\' || c == '(' || c == ')')
383       {
384         PSputc('\\', output);
385       }
386
387       PSputc((unsigned int) c, output);
388     }
389
390     PSputc(')', output); 
391     PSputc(code, output); /* 'p' or 's' */
392     showcount++;
393   }
394 }
395
396 /* could be more efficient here if we ever see several in a row OK */
397 /* model on "normal_char" if needed OK */
398     
399 void do_set1(FILE *output, FILE *input)
400 {
401   if (skipflag == 0)
402   {
403     normal_char(output, input, (int) set1);
404   }
405   else
406     (void) getc(input);
407
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 */
411 }
412
413 void do_set2(FILE *output, FILE *input)
414 {
415   do_charsub(output, ureadtwo(input), 's');
416 }
417
418 void do_set3(FILE *output, FILE *input)
419 {
420   do_charsub(output, ureadthree(input), 's');
421 }
422
423 void do_set4(FILE *output, FILE *input)
424 {
425   do_charsub(output, ureadfour(input), 's');
426 }
427
428 /* set character c and DO NOT increase h by width of character */
429
430 void do_put1(FILE *output, FILE *input)
431 {
432   do_charsub(output, getc(input), 'p');
433 }
434
435 void do_put2(FILE *output, FILE *input)
436 {
437   do_charsub(output, ureadtwo(input), 'p');
438 }
439
440 void do_put3(FILE *output, FILE *input)
441 {
442   do_charsub(output, ureadthree(input), 'p');
443 }
444
445 void do_put4(FILE *output, FILE *input)
446 {
447   do_charsub(output, ureadfour(input), 'p');
448 }
449
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 */
453
454 void do_common_rule (FILE *output, FILE *input, char *s)
455 {
456   long a, b; /* height, width */
457
458   a = sreadfour(input);
459   b = sreadfour(input);
460
461   if (skipflag == 0)
462   {
463     if (nMinRule != 0 && a > 0)
464     {
465       /* Make sure we don't get zero width rules in PDF output... */
466       /* ... compensate for truncating down instead of rounding in pdf */
467       if (a < nMinRule)
468         a = nMinRule;
469       else if (a > nMinRule)
470         a = a + nMinRule / 2;
471     }
472
473     if (bRuleColor)
474     {
475       if (! freshflag)
476         PSputc('\n', output);
477
478       sprintf(logline, "%lg %lg %lg rgb ", rule_red, rule_green, rule_blue);
479       PSputs(logline, output);
480       freshflag = 0;
481     }
482     else
483     {
484       if (bTextColor)
485       {
486         if (! freshflag) PSputc('\n', output);
487         PSputs("black ", output);
488         freshflag = 0;
489       }
490     }
491
492     /* some silly nonsense about using a height = -2^31 in set_rule */
493     if (bDVICopyReduce && -a == 2147483648L)
494     {
495       /* need to do nothing for pr, no output, no motion */
496       if (strcmp (s, "sr") == 0)
497       {
498         if (! freshflag)
499           PSputc('\n', output);
500
501 #ifdef ALLOWSCALE
502         if (outscaleflag)
503         {
504           sprintf(logline, "%.9lg r", (double) b / outscale);
505         }
506         else
507 #endif
508         {
509           sprintf(logline, "%ld r", b); /* setrule => right */
510         }
511
512         PSputs(logline, output);
513         freshflag = 0;
514       }
515     }
516     else
517     {
518       if (! freshflag)
519         PSputc('\n', output);
520
521 #ifdef ALLOWSCALE
522       if (outscaleflag)
523       {
524         sprintf(logline, "%.9lg %.9lg %s",
525             (double) a / outscale, (double) b / outscale, s);
526       }
527       else
528 #endif
529       {
530         sprintf(logline, "%ld %ld %s", a, b, s); /* setrule or putrule */
531       }
532
533       PSputs(logline, output);
534       freshflag = 0;
535     }
536
537     if (bTextColor)
538     {
539       if (! freshflag)
540         PSputc('\n', output);
541
542       sprintf(logline, "%lg %lg %lg rgb ", text_red, text_green, text_blue);
543       PSputs(logline, output);
544       freshflag = 0;
545     }
546     else
547     {
548       if (bRuleColor)
549       {
550         if (! freshflag) PSputc('\n', output);
551         PSputs("black ", output);
552         freshflag = 0;
553       }
554     }
555
556     showcount = 0;
557   }
558 }
559
560 void do_set_rule(FILE *output, FILE *input)
561 {
562   do_common_rule (output, input, "sr");
563 }
564
565 void do_put_rule(FILE *output, FILE *input)
566 {
567   do_common_rule (output, input, "pr");
568 }
569
570 /* write TeX /counter's */
571 char *show_counters(char *s)
572 {
573   int k;
574   int kmax = 0;
575
576   sprintf(s, "%ld", counter[0]); /* *always* write first one */
577   s += strlen(s);
578
579   for (k = 10-1; k > 0; k--)
580   {
581     if (counter[k] != 0)
582     {
583       kmax = k;
584       break;
585     }
586   }
587
588   for (k = 1; k <= kmax; k++) /* write others if non-zero */
589   {
590     sprintf(s, " %ld", counter[k]);
591     s += strlen(s);
592   }
593
594   return s;
595 }
596
597 /*** code for working way into back end of file looking for post ***/
598
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 */
602
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 ! */
605
606 /* search for post at end of file */
607 long goto_post(FILE *input)
608 {
609   unsigned long n;
610   int c, d, e, f, k, i, j, count;
611   int buffer[BUFSIZE];
612   long nlen;
613
614   if (fseek(input, - (long) BUFSIZE, SEEK_END) < 0)
615   {
616     rewind(input);      /* possibly because file shorter than BUFSIZE ? */
617   }
618
619   for (j = 0; j < NUMSTEPS; j++) /* let's not go on forever ! */
620   {
621     for (k = 0; k < BUFSIZE; k++)
622     {
623       buffer[k] =  getc(input);
624     }
625
626     k = BUFSIZE - 1;
627
628     while (k > 10)
629     {
630       count=0;            /* count MAGIC codes seen */
631
632       for (i = k; i >= 5; i--)    /* need at least seq of four */
633       {
634         if (buffer[i] == MAGIC)
635         {
636           count++;
637
638           if (count == 4)
639             break;
640         }
641         else
642           count = 0;
643       }
644
645       k = i;
646
647       if (count == 4)    /* found sequence of four */
648       {
649         for (i = k; i >= 5; i--)   /* but there can be many more */
650           if (buffer[i] != MAGIC)
651             break;
652
653         k = i;             /* first non MAGIC - ID_BYTE ? */
654
655         if (buffer[k] != MAGIC) /* did see end of MAGIC stuff */
656         {
657           if (buffer[k-5] == (int) post_post)
658           { 
659             k = k - 5;    /* step back to post_post */
660             c = buffer[k+1];
661             d = buffer[k+2];
662             e = buffer[k+3];
663             f = buffer[k+4];
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);
667
668             if (c != (int) post)
669             {
670               showline("ERROR: Unable to find pointer to POST", 1);
671               giveup(5);
672               return 0;
673             }
674             else
675             {
676               if (traceflag)
677               {
678                 sprintf(logline, "Found POST at %ld\n", n);
679                 showline(logline, 0);
680               }
681
682               return n;   /* seem to be in good shape */
683             }
684           }
685         }
686       }
687     }
688
689     if (fseek(input, - (long) (BUFSIZE * 2 - 10), SEEK_CUR) != 0)
690     {
691       break;
692     }
693   }
694
695   sprintf(logline, "ERROR: Can't find proper ending of DVI file `%s'\n",
696       filenamex);
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);
702   giveup(5);
703
704   return 0;
705 }
706
707 void insert_blank(FILE *output, long page)
708 {
709   PSputs("dvidict begin\n", output);
710
711   if (newbopflag)
712   {
713     sprintf(logline, "%ld %ld bop eop end ",
714        counter[0], page);
715     PSputs(logline, output);
716   }
717   else
718   {
719     PSputs("bp ep end ", output);
720   }
721
722   PSputs("% blank page\n", output);
723 }
724
725 void do_counter_comment (FILE *output)
726 {
727   char *s;
728
729   s = logline;
730   strcpy(s, "% [");
731   s += strlen(s);
732   s = show_counters(s);
733   strcat(s, "]");
734   PSputs(logline, output);
735 }
736
737 /* beginning of page */
738 void do_bop(FILE *output, FILE *input)
739 {
740   int k;
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 */
745
746   if (skiptoend != 0)
747   {
748     goto_post(input);
749     skiptoend = 0;
750     return;
751   }
752
753   /*  Normally bRepeatMode == 0 */
754   if (nRepeatCount > 1)
755   {
756     if (nRepeatIndex == 0)
757       currentpagestart = ftell(input) - 1;  /* right at bop */
758     else
759       pagenumber--;            /* compensate */
760   }
761
762   pagenumber++;       /* DVI page count from start of job */
763
764   if (reverseflag)
765     page = dvi_t - pagenumber + 1;
766   else
767     page = pagenumber;
768
769   stinx = 0;
770   ff = -1; 
771   pagetpic = 0;
772   complainedaboutj=0;
773
774   if (bCarryColor == 0)
775     colorindex=0;
776
777   if (bCarryColor && bColorUsed)
778   {
779     RestoreColorStack(page);
780   }
781
782   clipstackindex = 0;     /* reset push pop stack 98/Sep/12 */
783   CTMstackindex= 0;   /* reset CTM stack pointer in dvispeci.c */
784
785   for (k = 0; k < 10; k++)
786     counter[k] = sreadfour(input); 
787
788   previous = sreadfour(input);
789   showcount = 0;
790
791   if (countzeroflag != 0)
792     pageno = counter[0];
793   else
794     pageno = (long) page;
795
796   skipflag = skip_this_page(pageno);
797
798   if (skipflag != 0)
799     firstpage = -1;
800   else if (skipflag == 0)  /* page in valid range */
801   {
802     if (oddpageflag != 0)   /* if printing only odd pages */
803     {
804       if ((counter[0] & 1) == 0) /* seen even numbered page */
805       {
806         if (firstpage != 0)
807           insert_blank(output, page);    /* matching blank */
808
809         skipflag++; 
810       }
811
812       firstpage = 0;      
813     }
814
815     if (evenpageflag != 0)  /* if printing only even pages */
816     {
817       if ((counter[0] & 1) == 1) /* seen odd numbered page */
818       {
819         if (firstpage != 0)
820           insert_blank(output, page);  /* matching blank */
821
822         skipflag++;
823       }
824
825       firstpage = 0;
826     }
827   }
828
829   if (skipflag != 0) /* skipping this page */
830   {
831     if (reverseflag != 0)
832     {
833       if (previous > 0)
834         fseek(input, previous, SEEK_SET);
835       else
836         finish = -1; 
837     }
838
839     return;
840   }
841   else  /* not skipping this page */
842   {
843     if (verboseflag)
844     { 
845       showline("[", 0);
846       show_counters(logline);
847       showline(logline, 0); 
848     } 
849     else
850     {
851       showline(".", 0);
852     }
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)
860     {
861       PSputs("%%Page: ", output);
862
863       if (bUseCounters)
864       {
865         sprintf(logline, "%ld-%ld %ld\n",
866           counter[1], counter[2], numpages+1);  /* 1996/Jan/20 */
867       }
868       else
869       {
870         sprintf(logline, "%ld %ld\n", counter[0], numpages+1);
871       }
872
873       PSputs(logline, output);
874     }
875
876     PSputs("dvidict begin ", output);
877
878     if (evenoddoff != 0)
879     {
880       if ((counter[0] & 1) == 1) /* seen odd numbered page */
881       {
882         xoffset = xoffseto;
883         yoffset = yoffseto;
884       }
885       else /* seen even numbered page */
886       {
887         xoffset = xoffsete;
888         yoffset = yoffsete;
889       }
890
891       sprintf(logline, 
892         "/xoffset %lg def /yoffset %lg def\n", xoffset, yoffset);
893       PSputs(logline, output);
894     }
895
896     PSputc('\n', output);   // always start new line for this
897
898     if (newbopflag)
899     {
900       sprintf(logline, "%ld %ld bop ", counter[0], numpages+1);
901       PSputs(logline, output);
902     }
903     else
904       PSputs("bp ", output);
905
906     if (stripcomment == 0)
907       do_counter_comment (output);
908
909     if (bBackGroundFlag && bBackUsed)
910     {
911       if (BackColors[page].A != -1.0 ||
912         BackColors[page].B != -1.0 ||
913         BackColors[page].C != -1.0)
914       {
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 */
922       }
923     }
924
925     /* now pop color pushed at bottom of previous page (restored stack up above) */
926     if (bColorUsed && (colorindex > 0))
927     {
928       doColorPop(page); 
929       doColorSet(output, 2); /* bop - in dvispeci.c */
930     }
931     else
932     {
933       PSputc('\n', output); /* omission slightly risky ... */
934     }
935   }
936 /*  maybe also do "structuring conventions" stuff ? */
937 }
938
939 /* end of page */
940 void do_eop(FILE *output, FILE *input)
941 {
942   int c;
943
944   if (bAbort)
945     abortjob();
946
947   if (abortflag)
948     return;
949
950   showcount = 0;
951
952   if (colorindex > 0)
953     checkColorStack(output);
954
955   if (clipstackindex > 0)
956     doClipBoxPopAll(output);
957
958   if (skipflag == 0)
959   {
960     if (CTMstackindex != 0)
961       checkCTM(output);
962
963     PSputc('\n', output); // always start new line
964
965     if (newbopflag)
966       PSputs("eop ", output);
967     else
968       PSputs("ep ", output);
969
970     if (stripcomment == 0)
971       do_counter_comment(output);
972
973     PSputc('\n', output);
974     PSputs("end", output);
975
976     if (stripcomment == 0)
977       PSputs(" % dvidict", output);
978
979     PSputc('\n', output);
980
981     /* %%PageTrailer comments highly optional ... */
982     if (bOptionalDSC)
983     {
984       if (stripcomment == 0)
985       {
986         PSputs("%%PageTrailer\n", output);
987       }
988     }
989
990     if (verboseflag)
991       showline("] ", 0);
992
993     numpages++;   /* update number of pages actually processed */
994   }
995
996   if (output != NULL && ferror(output))
997   {
998     showline("\n", 0);
999     showline("ERROR in output file", 1);
1000     perrormod((outputfile != NULL) ? outputfile : "");
1001     giveup(7);
1002     return;
1003   }
1004
1005   /*  Normally bRepeatMode == 0 */
1006   if (nRepeatCount > 1)
1007   {
1008     nRepeatIndex++;
1009
1010     if (nRepeatIndex == nRepeatCount)
1011       nRepeatIndex = 0;
1012     else
1013     {
1014       fseek (input, currentpagestart, SEEK_SET);
1015       return;
1016     }
1017   }
1018
1019   skipflag = 0;
1020
1021   if (reverseflag != 0) /* go back if reading in reverse */
1022   {
1023     if (previous > 0)
1024       fseek(input, previous, SEEK_SET);
1025     else
1026       finish = -1;
1027   }
1028
1029   if (textures != 0)
1030     (void) ureadfour(input); /* skip over length code */
1031
1032   /*  may also want to check whether length is something reasonable ? */
1033   c = getc(input); (void) ungetc(c, input);   /* peek ahead */
1034
1035   if (c >= 0 && c <= 127)
1036   {
1037     sprintf(logline, " invalid code (%d)\n", c);
1038     showline(logline, 1);
1039     finish = -1;
1040   }
1041 }
1042
1043 /* rare */
1044 void do_right1(FILE *output, FILE *input)
1045 {
1046   int b;
1047
1048   b = sreadone(input);
1049
1050   if (skipflag == 0)
1051   {
1052     if (! freshflag)
1053       PSputc('\n', output);
1054
1055 #ifdef ALLOWSCALE
1056     if (outscaleflag)
1057     {
1058       sprintf(logline, "%.9lg r", (double) b / outscale);
1059     }
1060     else
1061 #endif
1062     {
1063       sprintf(logline, "%d r", b); /* right */
1064     }
1065
1066     PSputs(logline, output);
1067     freshflag = 0;
1068     showcount = 0;
1069 /*  h = h + b; */
1070   }
1071 }
1072
1073 void do_right2(FILE *output, FILE *input)
1074 {
1075   int b;
1076
1077   b = sreadtwo(input);
1078
1079   if (skipflag == 0)
1080   {
1081     if (! freshflag)
1082       PSputc('\n', output);
1083
1084 #ifdef ALLOWSCALE
1085     if (outscaleflag)
1086     {
1087       sprintf(logline, "%.9lg r", (double) b / outscale);
1088     }
1089     else
1090 #endif
1091     {
1092       sprintf(logline, "%d r", b);  /* right */
1093     }
1094
1095     PSputs(logline, output);
1096     freshflag = 0;
1097     showcount = 0;
1098 /*  h = h + b; */
1099   }
1100
1101
1102 void do_rightsub(FILE *output, long b)
1103 {
1104   if (skipflag == 0)
1105   {
1106     if (! freshflag)
1107       PSputc('\n', output);
1108
1109 #ifdef ALLOWSCALE
1110     if (outscaleflag)
1111     {
1112       sprintf(logline, "%.9lg r", (double) b / outscale);
1113     }
1114     else
1115 #endif
1116     {
1117       sprintf(logline, "%ld r", b); /* right */
1118     }
1119
1120     PSputs(logline, output);
1121     freshflag = 0;
1122     showcount = 0;
1123 /*  h = h + b; */
1124   }
1125 }
1126
1127 void do_right3(FILE *output, FILE *input)
1128 {
1129   do_rightsub(output, sreadthree(input));
1130 }
1131
1132 void do_right4(FILE *output, FILE *input)
1133 {
1134   do_rightsub(output, sreadfour(input));
1135 }
1136
1137 void do_w0(FILE * output)
1138 {
1139   if (skipflag == 0)
1140   {
1141     PSputs(" w", output); /* wright */
1142     showcount = 0;
1143 /*    h = h + w; */
1144   }
1145 }
1146
1147 /* rare */
1148 void do_w1(FILE *output, FILE *input)
1149 {
1150   long w; /* trial */
1151
1152   w = sreadone(input);
1153
1154   if (skipflag == 0)
1155   {
1156     if (! freshflag)
1157       PSputc('\n', output);
1158
1159 #ifdef ALLOWSCALE
1160     if (outscaleflag)
1161     {
1162       sprintf(logline, "%.9lg W", (double) w / outscale);
1163     }
1164     else
1165 #endif
1166     {
1167       sprintf(logline, "%ld W", w); /* wsetright */
1168     }
1169
1170     PSputs(logline, output);
1171     freshflag = 0;
1172     showcount = 0;
1173 /*  h = h + w; */
1174   }
1175 }
1176
1177 void do_w2(FILE *output, FILE *input)
1178 {
1179   long w; /* trial */
1180
1181   w = sreadtwo(input);
1182
1183   if (skipflag == 0)
1184   {
1185     if (! freshflag)
1186       PSputc('\n', output);
1187
1188 #ifdef ALLOWSCALE
1189     if (outscaleflag)
1190     {
1191       sprintf(logline, "%.9lg W", (double) w / outscale);
1192     }
1193     else
1194 #endif
1195     {
1196       sprintf(logline, "%ld W", w); /* wsetright */
1197     }
1198
1199     PSputs(logline, output);
1200     freshflag = 0;
1201     showcount = 0;
1202 /*  h = h + w; */
1203   }
1204 }
1205
1206 void do_wsub(FILE *output, long w)
1207 {
1208   if (skipflag == 0)
1209   {
1210     if (! freshflag)
1211       PSputc('\n', output);
1212
1213 #ifdef ALLOWSCALE
1214     if (outscaleflag)
1215     {
1216       sprintf(logline, "%.9lg W", (double) w / outscale);
1217     }
1218     else
1219 #endif
1220     {
1221       sprintf(logline, "%ld W", w); /* wsetright */
1222     }
1223
1224     PSputs(logline, output);
1225     freshflag = 0;
1226     showcount = 0;
1227 /*  h = h + w; */
1228   }
1229 }
1230
1231 void do_w3(FILE *output, FILE *input)
1232 {
1233   do_wsub(output, sreadthree(input));
1234 }
1235
1236 void do_w4(FILE *output, FILE *input)
1237 {
1238   do_wsub(output, sreadfour(input));
1239 }
1240
1241 void do_x0(FILE *output)
1242 {
1243   if (skipflag == 0)
1244   {
1245     PSputs(" x", output); /* xright */
1246     showcount = 0;
1247 /*    h = h + x; */
1248   }
1249 }
1250
1251 /* rare */
1252 void do_x1(FILE *output, FILE *input)
1253 {
1254   long x; /* trial */
1255
1256   x = sreadone(input);
1257
1258   if (skipflag == 0)
1259   {
1260     if (! freshflag)
1261       PSputc('\n', output);
1262
1263 #ifdef ALLOWSCALE
1264     if (outscaleflag)
1265     {
1266       sprintf(logline, "%.9lg X", (double) x / outscale);
1267     }
1268     else
1269 #endif
1270     {
1271       sprintf(logline, "%ld X", x); /*  xsetright */
1272     }
1273
1274     PSputs(logline, output);
1275     freshflag = 0;
1276     showcount = 0;
1277 /*  h = h + x; */
1278   }
1279 }
1280
1281 void do_x2(FILE *output, FILE *input)
1282 {
1283   long x; /* trial */
1284
1285   x = sreadtwo(input);
1286
1287   if (skipflag == 0)
1288   {
1289     if (! freshflag)
1290       PSputc('\n', output);
1291
1292 #ifdef ALLOWSCALE
1293     if (outscaleflag)
1294     {
1295       sprintf(logline, "%.9lg X", (double) x / outscale);
1296     }
1297     else
1298 #endif
1299     {
1300       sprintf(logline, "%ld X", x); /* xsetright */
1301     }
1302
1303     PSputs(logline, output);
1304     freshflag = 0;
1305     showcount = 0;
1306 /*  h = h + x; */
1307   }
1308 }
1309
1310 void do_xsub(FILE *output, long x)
1311 {
1312   if (skipflag == 0)
1313   {
1314     if (! freshflag)
1315       PSputc('\n', output);
1316
1317 #ifdef ALLOWSCALE
1318     if (outscaleflag)
1319     {
1320       sprintf(logline, "%.9lg X", (double) x / outscale);
1321     }
1322     else
1323 #endif
1324     {
1325       sprintf(logline, "%ld X", x); /* xsetright */
1326     }
1327
1328     PSputs(logline, output);
1329     freshflag = 0;
1330     showcount = 0;
1331 /*  h = h + x; */
1332   }
1333 }
1334
1335 void do_x3(FILE *output, FILE *input)
1336 {
1337   do_xsub(output, sreadthree(input));
1338 }
1339
1340 void do_x4(FILE *output, FILE *input)
1341 {
1342   do_xsub(output, sreadfour(input));
1343 }
1344
1345 /* rare */
1346 void do_down1(FILE *output, FILE *input)
1347 {
1348   int a;
1349
1350   a = sreadone(input);
1351
1352   if (skipflag == 0)
1353   {
1354     if (! freshflag)
1355       PSputc('\n', output);
1356
1357 #ifdef ALLOWSCALE
1358     if (outscaleflag)
1359     {
1360       sprintf(logline, "%.9lg d", (double) a / outscale);
1361     }
1362     else
1363 #endif
1364     {
1365       sprintf(logline, "%d d", a); /* down */
1366     }
1367
1368     PSputs(logline, output);
1369     freshflag = 0;
1370     showcount = 0;
1371 /*  v = v + a; */
1372   }
1373 }
1374
1375 /* rare */
1376 void do_down2(FILE *output, FILE *input)
1377 {
1378   int a;
1379
1380   a = sreadtwo(input);
1381
1382   if (skipflag == 0)
1383   {
1384     if (! freshflag)
1385       PSputc('\n', output);
1386
1387 #ifdef ALLOWSCALE
1388     if (outscaleflag)
1389     {
1390       sprintf(logline, "%.9lg d", (double) a / outscale);
1391     }
1392     else
1393 #endif
1394     {
1395       sprintf(logline, "%d d", a); /* down */
1396     }
1397
1398     PSputs(logline, output);
1399     freshflag = 0;
1400     showcount = 0;
1401 /*  v = v + a; */
1402   }
1403 }
1404
1405 void do_downsub(FILE *output, long a)
1406 {
1407   if (skipflag == 0)
1408   {
1409     if (! freshflag)
1410       PSputc('\n', output);
1411
1412 #ifdef ALLOWSCALE
1413     if (outscaleflag)
1414     {
1415       sprintf(logline, "%.9lg d", (double) a / outscale);
1416     }
1417     else
1418 #endif
1419     {
1420       sprintf(logline, "%ld d", a); /* down */
1421     }
1422
1423     PSputs(logline, output);
1424     freshflag = 0;
1425     showcount = 0;
1426 /*  v = v + a; */
1427   }
1428 }
1429
1430 void do_down3(FILE *output, FILE *input)
1431 {
1432   do_downsub(output, sreadthree(input));
1433 }
1434
1435 void do_down4(FILE *output, FILE *input)
1436 {
1437   do_downsub(output, sreadfour(input));
1438 }
1439
1440 void do_y0(FILE *output)
1441 {
1442   if (skipflag == 0)
1443   {
1444     PSputs(" y", output);
1445     showcount = 0;
1446 /*    v = v + y; */
1447   }
1448 }
1449
1450 /* rare */
1451 void do_y1(FILE *output, FILE *input)
1452 {
1453   long y; /* trial */
1454
1455   y = sreadone(input);
1456
1457   if (skipflag == 0)
1458   {
1459     if (! freshflag)
1460       PSputc('\n', output);
1461
1462 #ifdef ALLOWSCALE
1463     if (outscaleflag)
1464     {
1465       sprintf(logline, "%.9lg Y", (double) y / outscale);
1466     }
1467     else
1468 #endif
1469     {
1470       sprintf(logline, "%ld Y", y); /* ysetdown */
1471     }
1472
1473     PSputs(logline, output);
1474     freshflag = 0;
1475     showcount = 0;
1476 /*  v = v + y; */
1477   }
1478 }
1479
1480 void do_y2(FILE *output, FILE *input)
1481 {
1482   long y; /* trial */
1483
1484   y = sreadtwo(input);
1485
1486   if (skipflag == 0)
1487   {
1488     if (! freshflag)
1489       PSputc('\n', output);
1490
1491 #ifdef ALLOWSCALE
1492     if (outscaleflag)
1493     {
1494       sprintf(logline, "%.9lg Y", (double) y / outscale);
1495     }
1496     else
1497 #endif
1498     {
1499       sprintf(logline, "%ld Y", y); /*  ysetdown */
1500     }
1501
1502     PSputs(logline, output);
1503     freshflag = 0;
1504     showcount = 0;
1505 /*  v = v + y; */
1506   }
1507 }
1508
1509 void do_ysub(FILE *output, long y)
1510 {
1511   if (skipflag == 0)
1512   {
1513     if (! freshflag)
1514       PSputc('\n', output);
1515
1516 #ifdef ALLOWSCALE
1517     if (outscaleflag)
1518     {
1519       sprintf(logline, "%.9lg Y", (double) y / outscale);
1520     }
1521     else
1522 #endif
1523     {
1524       sprintf(logline, "%ld Y", y); /* ysetdown */
1525     }
1526
1527     PSputs(logline, output);
1528     freshflag = 0;
1529     showcount = 0;
1530 /*  v = v + y; */
1531   }
1532 }
1533
1534 void do_y3(FILE *output, FILE *input)
1535 {
1536   do_ysub(output, sreadthree(input));
1537 }
1538
1539 /* not used */
1540 void do_y4(FILE *output, FILE *input)
1541 {
1542   do_ysub(output, sreadfour(input));
1543
1544
1545 void do_z0(FILE *output)
1546 {
1547   if (skipflag == 0)
1548   {
1549     PSputs(" z", output);
1550     showcount = 0;
1551 /*    v = v + z; */
1552   }
1553 }
1554
1555 /* rare */
1556 void do_z1(FILE *output, FILE *input)
1557 {
1558   long z; /* trial */
1559
1560   z = sreadone(input);
1561
1562   if (skipflag == 0)
1563   {
1564     if (! freshflag)
1565       PSputc('\n', output);
1566
1567 #ifdef ALLOWSCALE
1568     if (outscaleflag)
1569     {
1570       sprintf(logline, "%.9lg Z", (double) z / outscale);
1571     }
1572     else
1573 #endif
1574     {
1575       sprintf(logline, "%ld Z", z); /* zsetdown */
1576     }
1577
1578     PSputs(logline, output);
1579     freshflag = 0;
1580     showcount = 0;
1581 /*  v = v + z; */
1582   }
1583 }
1584
1585 void do_z2(FILE *output, FILE *input)
1586 {
1587   long z; /* trial */
1588
1589   z = sreadtwo(input);
1590
1591   if (skipflag == 0)
1592   {
1593     if (! freshflag)
1594       PSputc('\n', output);
1595
1596 #ifdef ALLOWSCALE
1597     if (outscaleflag)
1598     {
1599       sprintf(logline, "%.9lg Z", (double) z / outscale);
1600     }
1601     else
1602 #endif
1603     {
1604       sprintf(logline, "%ld Z", z); /* zsetdown */
1605     }
1606
1607     PSputs(logline, output);
1608     freshflag = 0;
1609     showcount = 0;
1610 /*  v = v + z; */
1611   }
1612 }
1613
1614 void do_zsub(FILE *output, long z)
1615 {
1616   if (skipflag == 0)
1617   {
1618     if (! freshflag)
1619       PSputc('\n', output);
1620
1621 #ifdef ALLOWSCALE
1622     if (outscaleflag)
1623     {
1624       sprintf(logline, "%.9lg Z", (double) z / outscale);
1625     }
1626     else
1627 #endif
1628     {
1629       sprintf(logline, "%ld Z", z); /* zsetdown */
1630     }
1631
1632     PSputs(logline, output);
1633     freshflag = 0;
1634     showcount = 0;
1635 /*  v = v + z; */
1636   }
1637 }
1638
1639 void do_z3(FILE *output, FILE *input)
1640 {
1641   do_zsub(output, sreadthree(input));
1642 }
1643
1644 void do_z4(FILE *output, FILE *input)
1645 {
1646   do_zsub(output, sreadfour(input));
1647 }
1648
1649 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
1650
1651 void complain_font_code(unsigned long fs)
1652 {
1653   sprintf(logline, " Bad font code %lu (> %u)\n", fs, MAXFONTNUMBERS-1);
1654   showline(logline, 1);
1655 }
1656 /* switching to other font */
1657 void switch_font(FILE *output, int fs)
1658 {
1659   int fn;
1660
1661   if (fs < 0)
1662   {
1663     sprintf(logline, "Negative font number %d\n", fs);
1664     showline(logline, 1);
1665   }
1666
1667   if (fs >= MAXFONTNUMBERS)
1668     complain_font_code(fs);
1669
1670   ff = fs; /* set state */
1671
1672   if (skipflag == 0)
1673   {
1674     if (bShortFont != 0)
1675       fn = finx[ff];
1676     else
1677       fn = fs;
1678
1679     PSputc('\n', output);   // always on new line
1680     sprintf(logline, "f%d", fn);
1681     PSputs(logline, output);
1682   }
1683
1684   showcount = 0;
1685 }
1686 /* switch fonts */
1687 void do_fnt1(FILE *output, FILE *input)
1688 {
1689   unsigned int fs;
1690
1691   fs = getc(input);
1692   switch_font(output, (int) fs);
1693 }
1694 /* switch fonts */
1695 void do_fnt2(FILE *output, FILE *input)
1696 {
1697   unsigned int fs;
1698
1699   fs = ureadtwo(input);
1700
1701   if (fs >= MAXFONTNUMBERS)
1702   {
1703     complain_font_code (fs);
1704     fs = MAXFONTNUMBERS - 1;
1705   }
1706
1707   switch_font(output, (int) fs);
1708 }
1709
1710 void do_fntsub(FILE *output, unsigned long fs)
1711 {
1712   if (fs >= MAXFONTNUMBERS)
1713   {
1714     complain_font_code (fs);
1715     fs = MAXFONTNUMBERS-1;
1716   }
1717
1718   switch_font(output, (int) fs);
1719 }
1720 /* switch fonts */
1721 void do_fnt3(FILE *output, FILE *input)
1722 {
1723   do_fntsub(output, ureadthree(input));
1724 }
1725
1726 /* switch fonts */
1727 void do_fnt4(FILE *output, FILE *input)
1728 {
1729   long fs;
1730
1731   fs = sreadfour(input);
1732
1733   if (fs < 0)
1734   {
1735     sprintf(logline, "Font code %ld < 0\n", fs);
1736     showline(logline, 1);
1737     fs = 0;
1738   }
1739
1740   do_fntsub(output, (unsigned long) fs);
1741 }
1742
1743 void do_xxxi (FILE *output, FILE *input, unsigned int n)
1744 {
1745 /*  int c; */
1746   unsigned int k;
1747
1748   if (skipflag)
1749   {
1750     if (bCarryColor)
1751       prereadspecial(input, n);
1752     else for(k = 0; k < n; k++)
1753       (void) getc(input);
1754   }
1755   else
1756     readspecial(output, input, (unsigned long) n);
1757
1758   showcount = 0;
1759 }
1760 /* for /special */
1761 void do_xxx1 (FILE *output, FILE *input)
1762 {
1763   unsigned n;
1764
1765   n = getc(input);
1766   do_xxxi(output, input, n);
1767 }
1768
1769 /* for /special */
1770 void do_xxx2 (FILE *output, FILE *input)
1771 {
1772   unsigned int n;
1773
1774   n = ureadtwo(input);
1775   do_xxxi(output, input, n);
1776 }
1777
1778 void do_xxxl (FILE *output, FILE *input, unsigned long n)
1779 {
1780   unsigned long k;
1781
1782   if (skipflag)
1783   {
1784     if (bCarryColor)
1785       prereadspecial(input, n);
1786     else for(k = 0; k < n; k++) (void) getc(input);
1787   }
1788   else
1789     readspecial(output, input, n);
1790
1791   showcount = 0;
1792 }
1793
1794 void do_xxx3 (FILE *output, FILE *input)
1795 {
1796   unsigned long n;
1797
1798   n = ureadthree(input);
1799   do_xxxl(output, input, n);
1800 }
1801
1802 void do_xxx4 (FILE *output, FILE *input)
1803 {
1804   unsigned long n;
1805
1806   n = ureadfour(input);
1807   do_xxxl(output, input, n);
1808 }
1809
1810 /* need to do this even if skipping pages */
1811
1812 /* nothing much should actually happen here !!! */
1813
1814 void fnt_def (FILE *output, FILE *input, unsigned int k)
1815 {
1816   unsigned int na, nl, i;
1817   int f, newfont = 1;
1818   char namebuffer[FNAMELEN];
1819   char *fp;
1820
1821   if (finx[k] != BLANKFONT)
1822   {
1823     newfont = 0;
1824     f = finx[k];
1825   }
1826   else
1827   {
1828     f = fnext;
1829
1830     if (finx[k] != (short) f)
1831     {
1832       showline(" ERROR: Inconsistency between passes\n", 1);
1833       errcount(0);
1834     }
1835
1836     fnext++;
1837   }
1838
1839   for (k = 0; k < 12; k++)
1840     (void) getc(input);
1841
1842   na = getc(input);
1843   nl = getc(input);
1844
1845   if (newfont == 0)
1846   {
1847     for (i = 0; i < na + nl; i++)
1848       (void) getc(input);
1849   }
1850   else
1851   {
1852     sprintf(logline, " ERROR: Redefining font %d\n", f);
1853     showline(logline, 1);
1854 /*    fp = fontname[f]; */
1855     fp = namebuffer;
1856
1857     if (na + nl >= sizeof(namebuffer)-1)
1858     {
1859       sprintf(logline, "Font name too long: %d (> %d) ",
1860           na + nl, sizeof(namebuffer)-1);
1861       showline(logline, 1);
1862       showline("\n", 0);
1863       errcount(0);
1864       tellwhere(input, 1);
1865
1866       for (i = 0; i < na + nl; i++)
1867         (void) getc(input);
1868     }
1869     else
1870     {
1871       for (i = 0; i < na + nl; i++)
1872         *fp++ = (char) getc(input);
1873     }
1874
1875     *fp++ = '\0';
1876
1877     if (fontname[f] != NULL)
1878       free(fontname[f]);
1879
1880     fontname[f] = zstrdup(namebuffer);
1881     fontsubflag[f] = -1; /* all this goes to extract */
1882   }
1883 }
1884
1885 /* define font */
1886 void do_fnt_def1 (FILE *output, FILE *input)
1887 {
1888   unsigned int k;
1889
1890   k = getc(input);
1891   fnt_def(output, input, k);
1892 }
1893 /* define font */
1894 void do_fnt_def2 (FILE *output, FILE *input)
1895 {
1896   unsigned int k;
1897
1898   k = ureadtwo(input);
1899
1900   if (k >= MAXFONTNUMBERS)
1901   {
1902     complain_font_code (k);
1903     k = MAXFONTNUMBERS-1;
1904   }
1905
1906   fnt_def(output, input, (unsigned int) k);
1907 }
1908
1909 void do_fnt_defsub (FILE *output, FILE *input, unsigned long k)
1910 {
1911   if (k >= MAXFONTNUMBERS)
1912   {
1913     complain_font_code (k);
1914     k = MAXFONTNUMBERS-1;
1915   }
1916
1917   fnt_def(output, input, (unsigned int) k);
1918 }
1919
1920 /* define font */
1921 void do_fnt_def3 (FILE *output, FILE *input)
1922 {
1923   do_fnt_defsub(output, input, ureadthree(input));
1924 }
1925
1926 /* define font */
1927 void do_fnt_def4(FILE *output, FILE *input)
1928 {
1929   long k;
1930
1931   k = sreadfour(input);
1932
1933   if (k < 0)
1934   {
1935     sprintf(logline, "Font code %ld < 0\n", k);
1936     showline(logline, 1);
1937     k = 0;
1938   }
1939
1940   do_fnt_defsub(output, input, (unsigned long) k);
1941 }
1942
1943 /* need to do this even if skipping pages */
1944 /* doesn't do output */
1945 void do_pre (FILE *output, FILE *input)
1946 {
1947   unsigned int k, j;
1948
1949   (void) getc(input);
1950
1951   for (j = 0; j < 12; j++)
1952     (void) getc(input);
1953
1954   k = getc(input);
1955
1956   for (j = 0; j < k; j++)
1957     (void) getc(input);
1958
1959   if (textures != 0)
1960     (void) ureadfour(input); /* skip over length code */
1961 }
1962
1963 /* need to do this even if skipping pages */
1964 /* doesn't do output */
1965 void do_post (FILE *output, FILE *input)
1966 {
1967   int k;
1968
1969   previous = sreadfour(input);  /* was ureadfour ... */
1970
1971   if (traceflag)
1972     showline("Hit POST!\n", 0);
1973
1974   for (k = 0; k < 12; k++)
1975     (void) getc(input);
1976
1977   for (k = 0; k < 8; k++)
1978     (void) getc(input);
1979
1980   for (k = 0; k < 4; k++)
1981     (void) getc(input);
1982
1983   if (reverseflag == 0)
1984     finish = -1;
1985
1986   if (reverseflag != 0)
1987     fseek(input, previous, SEEK_SET); /* 98/Jul/20 ??? */
1988 }
1989
1990 /* only in reverse ? */
1991 void do_post_post (FILE *output, FILE *input)
1992 {
1993   unsigned long previous;
1994   unsigned int id;
1995
1996   if (traceflag)
1997     showline("Hit POSTPOST!\n", 0);  /* never ? */
1998
1999   previous = ureadfour(input);
2000   id = getc(input);
2001
2002   if (reverseflag != 0)
2003     fseek(input, previous, SEEK_SET); /* go to POST? */
2004   else
2005   {
2006     PSputs("% This is really the end !\n", output); // never!
2007   }
2008
2009   if (reverseflag == 0)
2010     finish = -1;  /* 98/Jul/20 */
2011
2012   showcount = 0;
2013 }
2014
2015 // main entry point to this part of the program
2016 // lastflag indicates last in set of copies of same page
2017
2018 int scan_dvi_file (FILE *output, FILE *input, int lastflag)
2019 {
2020   int c, fs;
2021   long filptr;
2022
2023 #ifdef DEBUGGING
2024   if (output == NULL)
2025   {
2026     sprintf(logline, " NULL %s file\n", "output"); /* debug */
2027     showline(logline, 1);
2028   }
2029
2030   if (input == NULL)
2031   {
2032     sprintf(logline, " NULL %s file\n", "input"); /* debug */
2033     showline(logline, 1);
2034   }
2035 #endif
2036
2037   if (countzeroflag)
2038     resetpagerangehit (0);
2039
2040   numpages = 0;   /* number of pages actually processed */
2041   firstpage = -1;   /* flag for two sided printing case */
2042
2043   if (textures != 0)
2044     fseek(input, dvistart, SEEK_SET);
2045
2046   if (reverseflag != 0)
2047     skiptoend = -1;
2048   else
2049     skiptoend = 0;
2050
2051   pagenumber = 0;     /* value from earlier scan already used */
2052
2053   finish = 0;
2054   stinx = 0;
2055
2056   if (nRepeatCount > 1)
2057     nRepeatIndex = 0;
2058
2059   for ( ; ; )
2060   {
2061     c = getc(input);
2062
2063     if (c == EOF)
2064     {
2065       sprintf(logline, " Unexpected EOF (%s)\n", "scandvi");
2066       showline(logline, 1);
2067
2068       {
2069         long current = ftell(input);
2070         sprintf(logline, " at byte %d\n", current);
2071         showline(logline, 1);
2072       }
2073
2074       finish = -1;
2075       break;
2076     }
2077
2078     if (c < 128)
2079     {
2080       normal_char(output, input, c);
2081     }
2082     else if (c >= 171 && c <= 234)
2083     {
2084       fs = (c - 171);
2085       switch_font(output, fs);
2086     }
2087     else
2088     {
2089       switch(c)
2090       {
2091         case set1:
2092           do_set1(output, input);
2093           break;
2094
2095         case set2:
2096           do_set2(output, input);
2097           break;
2098
2099         case set3:
2100           do_set3(output, input);
2101           break;
2102
2103         case set4:
2104           do_set4(output, input);
2105           break;
2106
2107         case set_rule:
2108           do_set_rule(output, input);
2109           break;
2110
2111         case put1:
2112           do_put1(output, input);
2113           break;
2114
2115         case put2:
2116           do_put2(output, input);
2117           break;
2118
2119         case put3:
2120           do_put3(output, input);
2121           break;
2122
2123         case put4:
2124           do_put4(output, input);
2125           break;
2126
2127         case put_rule:
2128           do_put_rule(output, input);
2129           break;
2130
2131         case nop:
2132           break;
2133
2134         case bop:
2135           do_bop(output, input);
2136           break;
2137
2138         case eop:
2139           do_eop(output, input);
2140           break;
2141
2142         case push:
2143           do_push(output, input);
2144           break;
2145
2146         case pop:
2147           do_pop(output, input);
2148           break;
2149
2150         case right1:
2151           do_right1(output, input);
2152           break;
2153
2154         case right2:
2155           do_right2(output, input);
2156           break;
2157
2158         case right3:
2159           do_right3(output, input);
2160           break;
2161
2162         case right4:
2163           do_right4(output, input);
2164           break;
2165
2166         case w0:
2167           do_w0(output);
2168           break;
2169
2170         case w1:
2171           do_w1(output, input);
2172           break;
2173
2174         case w2:
2175           do_w2(output, input);
2176           break;
2177
2178         case w3:
2179           do_w3(output, input);
2180           break;
2181
2182         case w4:
2183           do_w4(output, input);
2184           break;
2185
2186         case x0:
2187           do_x0(output);
2188           break;
2189
2190         case x1:
2191           do_x1(output, input);
2192           break;
2193
2194         case x2:
2195           do_x2(output, input);
2196           break;
2197
2198         case x3:
2199           do_x3(output, input);
2200           break;
2201
2202         case x4:
2203           do_x4(output, input);
2204           break;
2205
2206         case down1:
2207           do_down1(output, input);
2208           break;
2209
2210         case down2:
2211           do_down2(output, input);
2212           break;
2213
2214         case down3:
2215           do_down3(output, input);
2216           break;
2217
2218         case down4:
2219           do_down4(output, input);
2220           break;
2221
2222         case y0:
2223           do_y0(output);
2224           break;
2225
2226         case y1:
2227           do_y1(output, input);
2228           break;
2229
2230         case y2:
2231           do_y2(output, input);
2232           break;
2233
2234         case y3:
2235           do_y3(output, input);
2236           break;
2237
2238         case y4:
2239           do_y4(output, input);
2240           break;
2241
2242         case z0:
2243           do_z0(output);
2244           break;
2245
2246         case z1:
2247           do_z1(output, input);
2248           break;
2249
2250         case z2:
2251           do_z2(output, input);
2252           break;
2253
2254         case z3:
2255           do_z3(output, input);
2256           break;
2257
2258         case z4:
2259           do_z4(output, input);
2260           break;
2261
2262         case fnt1:
2263           do_fnt1(output, input);
2264           break;
2265
2266         case fnt2:
2267           do_fnt2(output, input);
2268           break;
2269
2270         case fnt3:
2271           do_fnt3(output, input);
2272           break;
2273
2274         case fnt4:
2275           do_fnt4(output, input);
2276           break;
2277
2278         case xxx1:
2279           do_xxx1(output, input);
2280           break;
2281
2282         case xxx2:
2283           do_xxx2(output, input);
2284           break;
2285
2286         case xxx3:
2287           do_xxx3(output, input);
2288           break;
2289
2290         case xxx4:
2291           do_xxx4(output, input);
2292           break;
2293
2294         case fnt_def1:
2295           do_fnt_def1(output, input);
2296           break;
2297
2298         case fnt_def2:
2299           do_fnt_def2(output, input);
2300           break;
2301
2302         case fnt_def3:
2303           do_fnt_def3(output, input);
2304           break;
2305
2306         case fnt_def4:
2307           do_fnt_def4(output, input);
2308           break;
2309
2310         case post:
2311           do_post(output, input);
2312           break;
2313
2314         case pre:
2315           do_pre(output, input);
2316           break;
2317
2318         case post_post:
2319           do_post_post(output, input);
2320           break;
2321   
2322         default:
2323         {
2324           finish = -1;
2325           sprintf(logline, " ERROR: Unrecognized DVI command: %d", c);
2326           showline(logline, 1);
2327           filptr = ftell(input);
2328
2329           if (filptr > 0)
2330           {
2331             sprintf(logline, " at byte %ld in DVI file", filptr - 1);
2332             showline(logline, 0);
2333           }
2334
2335           errcount(0);
2336         }
2337
2338         break;
2339       }
2340     }
2341
2342     if (c < xxx1 || c > xxx4)
2343       freshflag = 0;
2344
2345     if (finish != 0)
2346       break;
2347
2348     if (bAbort)
2349       abortjob(); // fine grained
2350
2351     if (abortflag)
2352       break;
2353   }
2354
2355   if (abortflag)
2356     return -1;
2357
2358   if (verboseflag && lastflag)
2359   {
2360     char *s;
2361     showline("\n", 0);
2362     s = logline;
2363
2364     if (statisticsflag)
2365     {
2366       sprintf(s, "Max stack depth %d - ", dvi_s);
2367       s += strlen(s);
2368       sprintf(s, "%d font slot%s used - ",
2369         fnext, (fnext == 1) ? "" : "s");
2370       s += strlen(s);
2371     }
2372
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);
2377   }
2378
2379   return 0;
2380 }
2381
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
2447    again. */