OSDN Git Service

Added dvipsone.
[putex/putex.git] / src / dvisourc / dvipslog.c
1 /* Copyright 1990,1991,1992,1993,1994,1995,1996,1997,1998,1999 Y&Y, Inc.
2    Copyright 2007 TeX Users Group
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful, but
10    WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17    02110-1301 USA.  */
18
19 /**********************************************************************
20 *
21 * DVI analyzer to extract font and character usage
22 * part of DVIPSONE
23 *
24 **********************************************************************/
25
26 /* Revised 1999 June 13 to run in DLL form */
27
28 #ifdef _WINDOWS
29 #define NOCOMM
30 #define NOSOUND
31 #define NODRIVERS
32 #define STRICT
33 #include <windows.h>
34 #endif
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <malloc.h>
40 #include <setjmp.h>
41
42 #ifdef _WINDOWS
43 // We must define MYLIBAPI as __declspec(dllexport) before including
44 // dvipsone.h, then dvipsone.h will see that we have already
45 // defined MYLIBAPI and will not (re)define it as __declspec(dllimport)
46 #define MYLIBAPI __declspec(dllexport)
47 // #include "dvipsone.h"
48 #endif
49
50 #include "dvipsone.h"
51
52 #ifdef _WINDOWS
53 #pragma warning(disable:4100)   // unreferenced formal variable 
54 #endif
55
56 #pragma warning(disable:4127)   // conditional expression is constant
57
58 #pragma hdrstop
59
60 #include <io.h>                                 /* for _access */
61                                                                 /* for _findfirst, _findnext, _findclose */
62
63 /* #define DEBUGALIAS */
64
65 /* #define DEBUGCOLORSTACK */
66
67 /* #define DEBUGATM */
68
69 COLORSPEC CurrColor;
70
71 /* tables to store background color for each page on prescan 98/Jun/30 */
72
73 COLORSPEC *BackColors=NULL;
74
75 /* font k is to be used at mag * s / (1000 * d) times its normal size */
76
77 int fonthit[MAXFONTS];                  /* which fonts have been seen - NOT ACCESSED */
78
79 /* char *currentfont;    */                             /* pointer to current font */
80 char *currentfont;                              /* pointer to current font */
81
82 long pageno;    /* for convenience in error messages - may be logical page */
83
84 /* now for the scan of the DVI file for font character log generation */
85
86 /* now for the scan of the DVI file for PS output generation */
87
88 void reset_stack(void) {
89         stinx = 0;
90 }
91
92 void check_stack(int pageno) {
93         if (stinx != 0) {
94                 sprintf(logline,
95                         " ERROR: stack not empty at EOP: %d on page %d ",
96                                 stinx, pageno); /* pageno ? logical page */
97                 showline(logline, 1);
98                 tellwhere(input, 1);
99 /*              errcount(0); */
100 /*              giveup(3); */
101         }
102 }
103
104 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
105  
106 /* we don't have to worry about sign extension here - no need for short int */
107
108 /* static unsigned int ureadone (FILE *infile) {
109         return getc(infile);
110 } */
111
112 static unsigned int ureadtwo (FILE *infile) {
113         return (getc(infile) << 8) | getc(infile); 
114 }
115
116 static unsigned long ureadthree (FILE *infile) {
117         int c, d, e; 
118 /*      unsigned int c, d, e; */
119         c = getc(infile);       d = getc(infile);       e = getc(infile);
120         return ((((unsigned long) c << 8) | d) << 8) | e;
121 }
122
123 static unsigned long ureadfour (FILE *infile) {
124         int c, d, e, f;
125         c = getc(infile);       d = getc(infile);
126         e = getc(infile);       f = getc(infile);
127         return ((((((unsigned long) c << 8) | (unsigned long) d) << 8) | e) << 8) | f;
128 }
129
130 /* we do have to worry about sign extension here - use short int if needed */
131
132 /* static int sreadone (FILE *infile) {
133         int c;
134         c = getc(infile);
135         if (c > 127) return (c - 256);
136         else return c;
137 } */
138
139 #ifdef IGNORED
140 /* static short int sreadtwo (FILE *infile) { */        /* ??? */
141 static int sreadtwo (FILE *infile) {
142         short int result;
143 /*      return (getc(infile) << 8) | getc(infile); */   /* 1995/Nov/15 */
144 /*      result = (getc(infile) << 8) | getc(infile); */
145         result = ((short int) getc(infile) << 8) | (short int) getc(infile);
146         return result;
147 } /* needed now for code imported from dviextra.c readtfm etc */
148 #endif
149
150 /* avoid possible compiler optimization error */
151
152 static int sreadtwo (FILE *input) {                     /* experiment 98/Feb/7 */
153         int c, d;
154         c = getc(input);        d = getc(input);
155         if (c > 127) c = c - 256; 
156         return  (c << 8) | d;
157 }
158
159 /* static long sreadthree (FILE *infile) {
160         int c, d, e;
161         c = getc(infile);       d = getc(infile);       e = getc(infile);
162         if (c > 127) c = c - 256; 
163         return ((((long) c << 8) | d) << 8) | e;
164  } */
165
166 static long sreadfour (FILE *infile) {
167         int c, d, e, f;
168         c = getc(infile);       d = getc(infile);
169         e = getc(infile);       f = getc(infile);
170         return ((((((long) c << 8) | (long) d) << 8) | e) << 8) | f;
171
172
173 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
174
175 int MaxColor;           /* size of save area allocated for color stacks */
176 /* int MaxBack; */              /* size of save area allocated for background color */
177
178 COLORSPEC **ColorStacks=NULL;   /* array of saved color stacks, one per page */
179
180 /*      restore at start of page what was current at end of page-1 */
181 /*      called from dvianal.c */ /* page is physical DVI page from start of file */
182
183 void RestoreColorStack (int page) {
184         COLORSPEC *SavedStack;
185         int k;
186 /*      don't bother if color \special{...} was never used */
187         if (bCarryColor == 0 || bColorUsed == 0) return;
188         if (page >= MaxColor) return;                                   /* sanity check */
189         page--;                 /* restore what was saved at eop of *previous* */
190         if (page < 1) { /* nothing saved to restore at start of first page */
191                 colorindex = 0;
192                 return;
193         }
194         if (ColorStacks == NULL) return;                /* sanity check */
195 /*      GrabColor(); */
196         SavedStack = ColorStacks[page];
197         if (SavedStack == NULL) {
198                 sprintf(logline, " Bad Color Restore page %d (%d)",
199                                 page, MaxColor-1);
200                 showline(logline, 1);
201                 colorindex = 0;
202                 return;
203         }
204         colorindex = (int) (SavedStack[0].D + 0.5);     /* depth of saved stack */
205 #ifdef DEBUGCOLORSTACK
206         if (traceflag) {
207                 sprintf(logline, " RestoreColorStack from page-1 %d colorindex %d\n",
208                                                         page, colorindex);
209                 showline(logline, 0);
210         }
211 #endif
212         if (colorindex > 0 && colorindex < MAXCOLORSTACK) {
213                 for (k = 0; k < colorindex; k++) ColorStack[k] = SavedStack[k+1];
214         }
215         else {
216                 sprintf(logline, " ERROR: colorindex %d", colorindex);  /* BUG */
217                 showline(logline, 1);
218         }
219 /*      ReleaseColor(); */
220 }
221
222 /*      Save at end of page for start of page+1 */
223 /*      called from logdo_eop dvipslog.c */ /* page is DVI page from start of file */
224
225 void SaveColorStack (int page, int colorindex) {
226         COLORSPEC *SavedStack;
227         int k;
228 /*      if (bCarryColor == 0 || bColorUsed == 0) return; */
229         if (bCarryColor == 0) return;
230 /*      if (page < 0 || page >= MaxColor) return; */
231 /*      GrabColor(); */
232         if (ColorStacks == NULL) return;                /* sanity check */
233         if (ColorStacks[page] != NULL) {
234                 sprintf(logline, " Bad Color Save page %d (%d) %08x",
235                                 page, MaxColor, ColorStacks[page]);
236                 showline(logline, 1);
237 /*              free(lpColor[page]); */
238         }
239 #ifdef DEBUGCOLORSTACK
240         if (traceflag) {
241                 sprintf(logline, " SaveColorStack page %d colorindex %d\n",
242                                 page, colorindex);
243                 showline(logline, 0);
244         }
245 #endif
246         if (colorindex == 0) return;            /* nothing to save ??? */
247         SavedStack = (COLORSPEC *) malloc ((colorindex+1) * sizeof(COLORSPEC));
248         ColorStacks[page] = SavedStack;
249         SavedStack[0].A = SavedStack[0].B = SavedStack[0].C = 0.0F;
250         SavedStack[0].D = (float) colorindex;
251         for (k = 0; k < colorindex; k++) SavedStack[k+1] = ColorStack[k];
252 /*      ReleaseColor(); */
253 }
254
255 /* format of allocated area is count followed by stack dump */
256
257 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
258
259 void logdo_push(void) {
260         if (skipflag == 0) {
261                 stinx++;
262                 if (stinx > maxstinx) maxstinx = stinx;
263 /*              if (stinx >= maxstack - 1) {
264                         showline(" WARNING: The stack will overflow\n", 1);
265                         errcount(0);
266                 } */
267         }
268 }
269
270 void logdo_pop(void) {
271         if (skipflag == 0)  {
272                 stinx--;
273                 if (stinx < 0) {
274                         sprintf(logline,
275                                          " ERROR: The stack will underflow on page %d ",
276                                          pageno);       /* pagenumber ??? logical page */
277                         showline(logline, 1);
278                         tellwhere(input, 1);
279 /*                      errcount(0); */
280                 }
281         }
282 }
283
284 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
285
286 void invalidset(int c) {
287         sprintf(logline, " ERROR: Setting char %d without font on page %d ",
288                         c, pageno);     /* pagenumber ??? logical page */
289         showline(logline, 1);
290         tellwhere(input, 1);
291 /*      errcount(0); */
292 }
293
294 /* common subroutine for set2 set3 set4 --- which should not occur */
295
296 void logdo_setsub(unsigned long c) {
297         if (skipflag == 0) {
298 /*              if (ff < 0) invalidset((int) c); */
299                 if (ff == BLANKFONT) invalidset((int) c);
300                 else if (c < 256) {
301 /*                      if (bRemapControl && c < MAXREMAP) c = remaptable[c]; */
302                         if (bRemapControl || bRemapFont) {
303                                 if (c < MAXREMAP) c = remaptable[c];
304 #if MAXREMAP < 128
305                                 else if (c == 32) c = 195;
306                                 else if (c == 127) c = 196;
307 #endif
308                         }
309 /* NOTE: this must match corresponding code in DVIANAL.C */
310                         else if (bRemapSpace && c <= 32) {                      /* 1995/Oct/17 */
311                                 if (c == 32) c = 195;           /* not 160 */
312                                 else if (c == 13) c = 176;      /* 1996/June/4 */
313                                 else if (c == 10) c = 173;      /* 1996/June/4 */
314                                 else if (c == 9) c = 170;       /* 1996/June/4 */
315                                 else if (c == 0) c = 161;
316                         }
317                         currentfont[c] = 1;
318                 }
319         }
320 }
321
322 /* For speed we keep the set1 case separate since it occurs often */
323
324 void logdo_set1(FILE *infile) {
325         unsigned int c;
326 /*      c = ureadone(infile); */
327         c = getc(infile);
328         if (skipflag == 0) {
329 /*              if (ff < 0) invalidset((int) c); */
330                 if (ff == BLANKFONT) invalidset((int) c);
331                 else {
332 /*                      if (bRemapControl && c < MAXREMAP) c = remaptable[c]; */
333                         if (bRemapControl || bRemapFont) {
334                                 if (c < MAXREMAP) c = remaptable[c];
335 #if MAXREMAP < 128
336                                 else if (c == 32) c = 195;
337                                 else if (c == 127) c = 196;
338 #endif
339                         }
340                         else if (bRemapSpace && c <= 32) {                      /* 1995/Oct/17 */
341                                 if (c == 32) c = 195;           /* not 160 */
342                                 else if (c == 13) c = 176;      /* 1996/June/4 */
343                                 else if (c == 10) c = 173;      /* 1996/June/4 */
344                                 else if (c == 9) c = 170;       /* 1996/June/4 */
345                                 else if (c == 0) c = 161;
346                         }
347                         currentfont[c] = 1;
348                 }
349         }
350 }
351
352 /* simplified 95/Oct/17 by using logo_setsub for logdo_set2 */
353
354 void logdo_set2(FILE *infile) {
355         logdo_setsub(ureadtwo(infile));
356 }
357
358 #ifdef IGNORED
359 void logdo_set2(FILE *infile) {
360         unsigned int c;
361         c = ureadtwo(infile);
362         if (skipflag == 0) {
363 /*              if (ff < 0) invalidset((int) c); */
364                 if (ff == BLANKFONT) invalidset((int) c);
365                 else if (c < 256) {
366 /*                      if (bRemapControl && c < MAXREMAP) c = remaptable[c]; */
367                         if (bRemapControl || bRemapFont) {
368                                 if (c < MAXREMAP) c = remaptable[c];
369 #if MAXREMAP < 128
370                                 else if (c == 32) c = 195;
371                                 else if (c == 127) c = 196;
372 #endif
373                         }
374                         else if (bRemapSpace && c <= 32) {                      /* 1995/Oct/17 */
375                                 if (c == 32) c = 195;           /* not 160 */
376                                 else if (c == 13) c = 176;      /* 1996/June/4 */
377                                 else if (c == 10) c = 173;      /* 1996/June/4 */
378                                 else if (c == 9) c = 170;       /* 1996/June/4 */
379                                 else if (c == 0) c = 161;
380                         }
381                         currentfont[c] = 1;
382                 }
383         }
384 }
385 #endif
386
387 void logdo_set3(FILE *infile) {
388         logdo_setsub(ureadthree(infile));
389 }
390
391 void logdo_set4(FILE *infile) {
392         logdo_setsub(ureadfour(infile));
393 }
394
395 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
396
397 /* common subroutine for put2, put3, pu4 --- which should not occur */
398
399 void logdo_putsub(unsigned long c) {
400         if (skipflag == 0) {
401 /*              if (ff < 0) invalidset((int) c); */
402                 if (ff == BLANKFONT) invalidset((int) c);
403                 else if (c < 256) {
404 /*                      if (bRemapControl && c < MAXREMAP) c = remaptable[c]; */
405                         if (bRemapControl || bRemapFont) {
406                                 if (c < MAXREMAP) c = remaptable[c];
407 #if MAXREMAP < 128
408                                 else if (c == 32) c = 195;
409                                 else if (c == 127) c = 196;
410 #endif
411                         }
412                         else if (bRemapSpace && c <= 32) {                      /* 1995/Oct/17 */
413                                 if (c == 32) c = 195;           /* not 160 */
414                                 else if (c == 13) c = 176;      /* 1996/June/4 */
415                                 else if (c == 10) c = 173;      /* 1996/June/4 */
416                                 else if (c == 9) c = 170;       /* 1996/June/4 */
417                                 else if (c == 0) c = 161;
418                         }
419                         currentfont[c] = 1;
420                 }
421         }
422 }
423
424 /* For speed we keep the set1 case separate since it occurs sometimes */
425
426 void logdo_put1(FILE *infile) {
427         unsigned int c;
428 /*      c = ureadone(infile); */
429         c = getc(infile);
430         if (skipflag == 0) {
431 /*              if (ff < 0) invalidset((int) c); */
432                 if (ff == BLANKFONT) invalidset((int) c);
433                 else {
434 /*                      if (bRemapControl && c < MAXREMAP) c = remaptable[c]; */
435                         if (bRemapControl || bRemapFont) {
436                                 if (c < MAXREMAP) c = remaptable[c];
437 #if MAXREMAP < 128
438                                 else if (c == 32) c = 195;
439                                 else if (c == 127) c = 196;
440 #endif
441                         }
442                         else if (bRemapSpace && c <= 32) {                      /* 1995/Oct/17 */
443                                 if (c == 32) c = 195;           /* not 160 */
444                                 else if (c == 13) c = 176;      /* 1996/June/4 */
445                                 else if (c == 10) c = 173;      /* 1996/June/4 */
446                                 else if (c == 9) c = 170;       /* 1996/June/4 */
447                                 else if (c == 0) c = 161;
448                         }
449                         currentfont[c] = 1;
450                 }
451         }
452 }
453
454 /* simplified 95/Oct/17 by using logo_putsub for logdo_put2 */
455
456 void logdo_put2(FILE *infile) {
457         logdo_putsub(ureadtwo(infile));
458 }
459
460 #ifdef IGNORED
461 void logdo_put2(FILE *infile) {
462         unsigned int c;
463         c = ureadtwo(infile);
464         if (skipflag == 0) {
465 /*              if (ff < 0) invalidset((int) c); */
466                 if (ff == BLANKFONT) invalidset((int) c);
467                 else if (c < 256) {
468 /*                      if (bRemapControl && c < MAXREMAP) c = remaptable[c]; */
469                         if (bRemapControl || bRemapFont) {
470                                 if (c < MAXREMAP) c = remaptable[c];
471 #if MAXREMAP < 128
472                                 else if (c == 32) c = 195;
473                                 else if (c == 127) c = 196;
474 #endif
475                         }
476                         else if (bRemapSpace && c <= 32) {                      /* 1995/Oct/17 */
477                                 if (c == 32) c = 195;           /* not 160 */
478                                 else if (c == 13) c = 176;      /* 1996/June/4 */
479                                 else if (c == 10) c = 173;      /* 1996/June/4 */
480                                 else if (c == 9) c = 170;       /* 1996/June/4 */
481                                 else if (c == 0) c = 161;
482                         }
483                         currentfont[c] = 1;
484                 }
485         }
486 }
487 #endif
488
489 void logdo_put3(FILE *infile) {
490         logdo_putsub(ureadthree(infile));
491 }
492
493 void logdo_put4(FILE *infile) {
494         logdo_putsub(ureadfour(infile));
495 }
496
497 void logdo_set_rule(FILE *infile) {
498         int k;
499         for (k=0; k < 8; k++) (void) getc(infile);
500 }
501
502 void logdo_put_rule(FILE *infile) {
503         int k;
504         for (k=0; k < 8; k++) (void) getc(infile);
505 }
506
507 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
508
509 /* int currentrange; */ /* range currently working in */
510 long currentpage;               /* page currently working in */
511 int prescanflag;                /* prescan is always forward */
512 int pagesequence;               /* count of ascending page sequence */
513
514 /* returns zero if page is to be printed */ /* non-zero if to be skipped */
515
516 int skipthispage(long pageno) {
517         int k;
518 /*      int hitrange=0; */
519 /*      int wantpage=0; */
520
521         if (rangeindex == 0) return 0;          /* easy, no page ranges specified! */
522
523         if (countzeroflag != 0) {
524                 if (prescanflag != 0 || reverseflag == 0) {
525 /* going forward, we remain in same page sequence if: */
526 /* (positive and ascending) or (negative and descending) */
527                         if (currentpage == -LINFINITY) ;        /* first time */
528                         else if (currentpage >= 0 && pageno >= 0 && pageno > currentpage) ;
529                         else if (currentpage <= 0 && pageno <= 0 && pageno < currentpage) ;
530                         else pagesequence++;
531                 }
532                 else if (reverseflag != 0) {
533 /* going backward, we remain in same page sequence if: */
534 /* (positive and descending) or (negative and ascending) */
535                         if (currentpage == -LINFINITY) ;        /* first time */
536                         else if (currentpage >= 0 && pageno >= 0 && pageno < currentpage) ;
537                         else if (currentpage <= 0 && pageno <= 0 && pageno > currentpage) ;
538                         else pagesequence--;
539                 }
540                 currentpage = pageno;                                           /* remember page number */
541         }
542
543         for (k = 0; k < rangeindex; k++) { 
544 /*              is current page in this page range ? */
545                 if ((pageno >= beginpages[k]) && (pageno <= endpages[k]))  {
546                         if (countzeroflag == 0) return 0;       /* easy, not using count[0] */
547                         if (pagerangeseq[k] < 0)                        /* no instance specified */
548                                 return 0;                                               /* means always print */
549                         if (pagerangeseq[k] == pagesequence) /* matches instance */
550                                 return 0;                                               /* OK, print it */
551                 }
552         }
553         return 1;                                               /* not inside any specified range */
554 }
555
556 void logdo_bop(FILE *infile) { /* beginning of page */
557         int k;
558         long current;                           /* ??? */
559
560         current = ftell(input) - 1;
561
562         pagenumber++;                   /* increment pages seen - going forward here */
563         reset_stack();                  /*      stinx = 0; */
564         ff = -1;                                /* undefined font */
565         fnt = finx[0];                  /* just in case - not clear could be -1 ! or 255 */
566 //      currentfont = fontchar;                                 /* just in case */
567         currentfont = fontchar[0];                              /* just in case ??? */
568
569         for(k=0; k < 10; k++) counter[k] = sreadfour(infile);
570
571         previous = sreadfour(infile);
572 /*      skipflag = 0; */
573         if (countzeroflag != 0) pageno = counter[0];
574         else pageno = (long) pagenumber;
575         skipflag = skipthispage(pageno);        /* figure out if skipped */
576 /*      if (beginpage != -LINFINITY && pageno < beginpage)      skipflag++;
577         if (endpage != LINFINITY && pageno > endpage) skipflag++;  */
578 /*      following is the logic for two-sided printing */
579         if (skipflag == 0) {
580                 if (oddpageflag != 0 && (counter[0] & 1) == 0) skipflag++;
581                 if (evenpageflag != 0 && (counter[0] & 1) == 1) skipflag++;
582         }
583 /*      what about first page ? */
584         if (bCarryColor) {
585                 if (colorindex > 0)                             /* avoid error on first page */
586                         doColorPop(pagenumber);         /* 98/Feb/15 to match ColorPush in eop */
587         }
588         if (bBackGroundFlag) {                          /* carry background color 99/Apr/05 */
589                 if (pagenumber > 0)                             /* avoid on first page */
590                         BackColors[pagenumber] = BackColors[pagenumber-1];
591 /*              else if (pagenumber == 0) {
592                         BackColors[0].A = BackColors[0].B =     BackColors[0].C = -1.0F;
593                         BackColors[0].D = -1.0F;
594                 } */
595         }
596 }
597
598 void logdo_eop(FILE *infile) { /* end of page */
599         int c;
600
601         if (bAbort) abortjob();                                 /* 1992/Nov/24 */
602         if (abortflag) return;
603         check_stack(pagenumber);
604         if (bCarryColor) {
605                 doColorPush(pagenumber);                                        /* 98/Feb/15 ??? */
606                 SaveColorStack(pagenumber, colorindex);         /* 98/Feb/19 ??? */
607         }
608         if (textures != 0) 
609                 (void) ureadfour(infile);       /* flush Textures length code */
610 /*      may want to check whether length is something reasonable ? */
611         c = getc(infile); (void) ungetc(c, infile);             /* peek ahead */
612 /*      here we expect to see bop, nop or fnt_def's ONLY */
613         if (c >= 0 && c <= 127) {
614                 sprintf(logline, " ERROR: Invalid DVI code (%d) between EOP and BOP ", c);
615                 showline(logline, 1);
616                 tellwhere(infile, 1);
617 /*              errcount(0); */
618                 finish = -1;
619         }
620         if (skipflag == 0)      numpages++;                             /* 94/Oct/12 */
621         skipflag = 0;
622 }
623
624 void logdo_right1(FILE *infile) { /* rare */
625         (void) getc(infile);
626 }
627
628 void logdo_right2(FILE *infile) {
629         (void) getc(infile); (void) getc(infile);
630
631
632 void logdo_right3(FILE *infile) {
633         (void) getc(infile); (void) getc(infile); (void) getc(infile);
634
635
636 void logdo_right4(FILE *infile) {
637         (void) getc(infile); (void) getc(infile); 
638         (void) getc(infile); (void) getc(infile);
639
640
641 void logdo_w0(void) {
642 }
643
644 void logdo_w1(FILE *infile) { /* rare */
645         (void) getc(infile); 
646 }
647
648 void logdo_w2(FILE *infile) {
649         (void) getc(infile); (void) getc(infile);
650
651
652 void logdo_w3(FILE *infile) {
653         (void) getc(infile); (void) getc(infile); (void) getc(infile);
654
655
656 void logdo_w4(FILE *infile) {
657         (void) getc(infile); (void) getc(infile); 
658         (void) getc(infile); (void) getc(infile);
659
660
661 void logdo_x0(void) {
662 }
663
664 void logdo_x1(FILE *infile) { /* rare */
665         (void) getc(infile);
666 }
667
668 void logdo_x2(FILE *infile) {
669         (void) getc(infile); (void) getc(infile);
670
671
672 void logdo_x3(FILE *infile) {
673         (void) getc(infile); (void) getc(infile); (void) getc(infile);
674 }
675
676 void logdo_x4(FILE *infile) {
677         (void) getc(infile); (void) getc(infile); 
678         (void) getc(infile); (void) getc(infile);
679 }
680
681 void logdo_down1(FILE *infile) { /* rare */
682         (void) getc(infile);
683 }
684
685 void logdo_down2(FILE *infile) { /* rare */
686         (void) getc(infile); (void) getc(infile);
687
688
689 void logdo_down3(FILE *infile) {
690         (void) getc(infile); (void) getc(infile); (void) getc(infile);
691 }
692
693 void logdo_down4(FILE *infile) {
694         (void) getc(infile); (void) getc(infile); 
695         (void) getc(infile); (void) getc(infile);
696
697
698 void logdo_y0(void) {
699 }
700
701 void logdo_y1(FILE *infile) { /* rare */
702         (void) getc(infile);
703 }
704
705 void logdo_y2(FILE *infile) {
706         (void) getc(infile); (void) getc(infile);
707
708
709 void logdo_y3(FILE *infile) {
710         (void) getc(infile); (void) getc(infile); (void) getc(infile);
711
712
713 void logdo_y4(FILE *infile) { /* not used */
714         (void) getc(infile); (void) getc(infile); 
715         (void) getc(infile); (void) getc(infile);
716
717
718 void logdo_z0(void) {
719 }
720
721 void logdo_z1(FILE *infile) {  /* rare */
722         (void) getc(infile);
723 }
724
725 void logdo_z2(FILE *infile) {
726         (void) getc(infile); (void) getc(infile);
727
728
729 void logdo_z3(FILE *infile) {
730         (void) getc(infile); (void) getc(infile); (void) getc(infile);
731
732
733 void logdo_z4(FILE *infile) {
734         (void) getc(infile); (void) getc(infile); 
735         (void) getc(infile); (void) getc(infile);
736
737
738 void logswitchfont(int fn, FILE *infile) { /* switching to other font */
739         int c;
740         ff = fn;                        /* set state */
741         fnt = finx[fn];
742 /*      if (fnt < 0) { */
743         if (fnt == BLANKFONT) {                                                         /* 93/Dec/11 */
744                 if (fn == 52) {
745                         c = getc(infile); (void) ungetc(c, infile);
746                         if (c == 171 + 52) {
747                                 sprintf(logline, 
748         " ERROR: Unexpected encounter of DVI trailer on page %d ", pagenumber);
749                                 showline(logline, 1);
750 /*                              errcount(0); */
751 /*                              finish = -1; */
752                                 giveup(9); 
753                                 return;
754                         }
755                 }
756                 sprintf(logline, " ERROR: switch to undefined font (%d) on page %d ",
757                                 fn, pagenumber);
758                 showline(logline, 1);
759                 tellwhere(infile, 1);
760 /*              errcount(0); */
761                 fnt = 0; 
762         }
763 //      currentfont = fontchar + MAXCHRS * fnt;
764         if (fontchar[fnt] == NULL) setupfontchar(fnt);
765         currentfont = fontchar[fnt]; 
766         fonthit[fnt] = 1;               /* even if skipflag != 0 ? */
767 }
768
769 void logdo_fnt1(FILE *infile) { /* switch fonts */
770         int fn;
771 /*      fn = ureadone(infile); */
772         fn = getc(infile);
773 /*      if (skipflag == 0) */
774         logswitchfont(fn, infile);
775 }
776
777 void logdo_fnt2(FILE *infile) { /* switch fonts */
778         unsigned int fn;
779         fn = ureadtwo(infile);
780 /*      if (skipflag == 0) */
781         if (fn >= MAXFONTNUMBERS) fn = MAXFONTNUMBERS-1;
782         logswitchfont((int) fn, infile);
783 }
784
785 void logdo_fntsub(unsigned long fn, FILE *infile) { /* switch fonts */
786 /*      if (skipflag == 0) */
787         if (fn >= MAXFONTNUMBERS) fn = MAXFONTNUMBERS-1;
788         logswitchfont((int) fn, infile);
789 }
790
791 void logdo_fnt3(FILE *infile) { /* switch fonts */
792 /*      unsigned long fn;
793         fn = ureadthree(infile); */
794         logdo_fntsub(ureadthree(infile), infile);
795 }
796
797 void logdo_fnt4(FILE *infile) { /* switch fonts */
798         long fn;
799         fn = sreadfour(infile);
800 /*      if (skipflag == 0) */
801         if (fn < 0) fn = 0;
802         logdo_fntsub((unsigned long) fn, infile);
803 }
804
805 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
806
807 void getheadername (FILE *infile) {     /* new version 95/Aug/30 */
808         char fname[FNAMELEN];                   /* buffer to get token into */
809         char *s;
810
811 /*      if (gettoken(infile, headerfile, FNAMELEN) == 0) {*/
812         if (gettoken(infile, fname, sizeof(fname)) == 0) {      /* FNAMELEN */
813                 showline(" Can't find header\n", 1);
814                 errcount(0); 
815                 return;
816         }
817
818 //      check whether this header file has already been listed 
819 //      if ((s = strstr(headerfile, fname)) != NULL) {
820         if (headerfile != NULL) {
821                 if ((s = strstr(headerfile, fname)) != NULL) {
822                         s += strlen(fname);
823                         if (*s == '\0' || *s == ',') {
824                                 return;
825                         }
826                 }
827         }
828
829 //      check whether there is enough space for the new name to add 
830 //      if (strlen(headerfile) + strlen(fname) + 2 >= sizeof(headerfile)) {
831 //              sprintf(logline, " No more space for HEADER (> %d)\n", sizeof(headerfile));
832 //              showline(logline, 1);
833 //              errcount(0);
834 //              return;
835 //      }
836
837         if (headerfile == NULL) {
838 //              nheaderlength = strlen(headerfile) + 2;
839                 nheaderlength = strlen(fname) + 2;
840                 headerfile = malloc(nheaderlength);
841                 if (headerfile == NULL) return;                 // allocation error - complain ???
842                 *headerfile = '\0';
843         }
844
845         while (strlen(headerfile) + strlen(fname) + 2 > (size_t) nheaderlength) {
846                 nheaderlength += strlen(fname) + 2;
847                 headerfile = realloc(headerfile, nheaderlength);
848         }
849         if (headerfile == NULL) return;         // allocation error - complain ???
850
851 //      add a comma separator, unless this is the first one 
852         if (*headerfile != '\0') {
853                 s = headerfile + strlen(headerfile);
854                 *s++ = ',';                                             // comma
855                 *s = '\0';                                              // not needed
856         }
857         else s = headerfile;                            // first time
858
859 //      finally: append the header file name  ...
860         strcpy(s, fname);
861 }
862
863 /* get name of file with DSC header comments */ /* only one allowed */
864
865 void getcustomname (FILE *infile) {
866 /*      int n=0; */
867
868         if (dscfile != NULL) {
869                 showline(" More than one DSCheader", 1);
870                 errcount(0);
871                 return;
872         }
873 /*      if (gettoken(infile, line, MAXLINE) == 0) { */
874         if (gettoken(infile, line, sizeof(line)) == 0) { /* MAXLINE */
875                 showline(" Can't find header\n", 1);
876                 errcount(0); 
877         }
878         else {
879                 dscfile = zstrdup(line);                /* remember single file name */
880         }
881 }
882
883 /* accumulate verbatim PS header text for prolog */
884
885  void getheadertext (FILE *infile) {            /* new 1993/Dec/29 */
886         char *headernew;
887         char *u;
888         int n;
889
890 /*      if (headertext == NULL) headernew = malloc (nspecial+2); else */
891 /*      first time around, headertext will be NULL, so it acts like malloc */
892         n = headertextlen + (int) nspecial + 2;
893 /*      headernew = realloc (headertext, n); */
894         headernew = realloc (headertext, n);
895         if (headernew == NULL) {
896                 showline(" Unable to allocate memory\n", 1);
897 /*              flushspecial(infile); */
898 /*              errcount(0); */
899 /*              return; */
900                 checkexit(1);                                                   /* 1995/July/15 */
901 //              more serious exit(1) ??? 
902         }
903         headertext = headernew;
904         u = headernew + headertextlen;
905         headertextlen = headertextlen + (int) nspecial + 1;
906         while (nspecial-- > 0) *u++ = (char) getc(infile);
907         *u++ = '\n'; *u++ = '\0';                               /* terminating linefeed and \0 */
908 }
909
910 /* accumulate command line args for DVIPSONE - passed through DVI file */
911
912 void getcommandspec (FILE *infile) {            // 99/Sept/6
913         char *commandnew;
914         char *u;
915         int n;
916
917 /*      first time around, commandspec will be NULL, so it acts like malloc */
918         n = commandspeclen + (int) nspecial + 2;
919         commandnew = realloc (commandspec, n);
920         if (commandnew == NULL) {
921                 showline(" Unable to allocate memory\n", 1);
922                 checkexit(1);
923         }
924         commandspec = commandnew;
925         u = commandnew + commandspeclen;
926         commandspeclen = commandspeclen + (int) nspecial + 1;
927         while (nspecial-- > 0) *u++ = (char) getc(infile);
928         *u++ = '\n'; *u++ = '\0';               // terminating linefeed and \0 
929  }
930
931 /* accumulate verbatim PS header text for prolog */
932
933 void getcustomtext (FILE *infile) {             /* new 1995/July/15 */
934         int c, n, needpercent=0;
935         char *customnew;
936         char *u;
937
938         c = getc(infile);       ungetc(c, infile);
939         if (c != '%') needpercent = 1;
940 /*      if (dsccustom == NULL) customnew = malloc (nspecial+2); else */
941 /*      first time around, dsccustom will be NULL, so it acts like malloc */
942         n = dsccustomlen + (int) nspecial + 2;
943         if (needpercent) n = n+2;
944 /*      customnew = realloc (dsccustom, n); */
945         customnew = realloc (dsccustom, n);
946         if (customnew == NULL) {
947                 showline(" Unable to allocate memory\n", 1);
948 /*              flushspecial(infile); */
949 /*              errcount(0); */
950 /*              return; */
951                 checkexit(1);                                                   /* 1995/July/15 */
952 //              more serious exit(1) ???
953         }
954         dsccustom = customnew;
955         u = customnew + dsccustomlen;
956         dsccustomlen = dsccustomlen + (int) nspecial + 1;
957         if (needpercent) {
958                 *u++ = '%';             *u++ = '%';
959                 dsccustomlen = dsccustomlen + 2;
960         }
961         while (nspecial-- > 0) *u++ = (char) getc(infile);
962         *u++ = '\n'; *u++ = '\0';                               /* terminating linefeed and \0 */
963 }
964
965 void getbbox (FILE *infile) {           /* Use for CropBox pdfmark not tested */
966 /*      Right now this is in PS coordinates, should be in TeX coordinates */
967         if (gettoken(infile, line, sizeof(line)) != 0) { /* MAXLINE */
968                 sscanf(line, "%d", &BBxll);
969         }
970         if (gettoken(infile, line, sizeof(line)) != 0) { /* MAXLINE */
971                 sscanf(line, "%d", &BByll);
972         }
973         if (gettoken(infile, line, sizeof(line)) != 0) { /* MAXLINE */
974                 sscanf(line, "%d", &BBxur);
975         }
976         if (gettoken(infile, line, sizeof(line)) != 0) { /* MAXLINE */
977                 sscanf(line, "%d", &BByur);
978         }
979
980
981 /* accumulate Keywords for DOCINFO pdfmark */
982
983 void getkeywords (FILE *infile) {               /* 1996/May/10 */
984         char *keywordsnew;
985         char *u;
986         int n, c;
987         int needcomma=0;                /* 0 or 2 if comma and space needed */
988
989 /*      if (headertext == NULL) headernew = malloc (nspecial+2); else */
990 /*      will add comma separator unless first, or comma or space already */
991         if (keywordslen == 0) needcomma = 0;
992         else {
993                 c = *(keywords + keywordslen - 1);
994                 if (c == ',' || c == ' ' || c == '\t') needcomma = 0;
995                 else needcomma = 2;
996         }
997 /*      n = keywordslen + (int) nspecial + 2; */        /* space for , and \0 */
998         n = keywordslen + (int) nspecial + needcomma + 1;       
999 /*      first time around, keywords will be NULL, so it acts like malloc(n) */
1000         keywordsnew = realloc (keywords, n);
1001         if (keywordsnew == NULL) {
1002                 showline(" Unable to allocate memory\n", 1);
1003 /*              flushspecial(infile); */
1004 /*              errcount(0); */
1005 /*              return; */
1006                 checkexit(1);                                                   /* 1995/July/15 */
1007 //              more serious exit(1) ???
1008         }
1009         keywords = keywordsnew;
1010         u = keywordsnew + keywordslen;
1011         if (needcomma > 0) {
1012                 *u++ = ',';                     /* add , if needed */
1013                 *u++ = ' ';                     /* add   if needed */
1014         }
1015         keywordslen = keywordslen + (int) nspecial + needcomma;
1016         while (nspecial-- > 0) *u++ = (char) getc(infile);
1017         *u++ = '\0';                            /* terminating \0 */
1018 }
1019
1020 // void getcommonstring (FILE *infile, char *newstring) 
1021 char *getcommonstring (FILE *infile) {
1022         char *u;
1023         char *newstring = malloc ((size_t) (nspecial+1));
1024         if (newstring == NULL) {
1025                 showline(" Unable to allocate memory\n", 1);
1026                 checkexit(1);
1027                 return NULL;
1028         }
1029         u = newstring;
1030         while (nspecial-- > 0) *u++ = (char) getc(infile);
1031         *u++ = '\0';                            /* terminating \0 */    
1032         return newstring;
1033 }
1034
1035 // unadvertized ability to change Creator fieldin DocInfo
1036
1037 void getcreator (FILE *infile) {
1038         if (creatorstring != NULL) return;      /* ignore all but first */
1039 //      creatorstring = malloc ((size_t) (nspecial+1));
1040 //      getcommonstring(infile, creatorstring);
1041         creatorstring = getcommonstring(infile);
1042 }
1043
1044 void gettitle (FILE *infile) {
1045         if (titlestring != NULL) return;        /* ignore all but first */
1046 //      titlestring = malloc ((size_t) (nspecial+1));
1047 //      getcommonstring(infile, titlestring);
1048         titlestring = getcommonstring(infile);
1049 }
1050
1051 void getsubject (FILE *infile) {
1052         if (subjectstring != NULL) return;      /* ignore all but first */
1053 //      subjectstring = malloc ((size_t) (nspecial+1));
1054 //      getcommonstring(infile, subjectstring);
1055         subjectstring = getcommonstring(infile);
1056 }
1057
1058 void getauthor (FILE *infile) {
1059         if (authorstring != NULL) return;       /* ignore all but first */
1060 //      authorstring = malloc ((size_t) (nspecial+1));
1061 //      getcommonstring(infile, authorstring);
1062         authorstring = getcommonstring(infile);
1063 }
1064
1065 void getbase (FILE *infile) {
1066         if (basestring != NULL) return; /* ignore all but first */
1067 //      basestring = malloc ((size_t) (nspecial+1));
1068 //      getcommonstring(infile, basestring);
1069         basestring = getcommonstring(infile);
1070 }
1071
1072 void getpagemode (FILE *infile) {
1073         if (pagemode != NULL) return;   /* ignore all but first */
1074 //      pagemode = malloc ((size_t) (nspecial+1));
1075 //      getcommonstring(infile, pagemode);
1076         pagemode = getcommonstring(infile);
1077 }
1078
1079 /* example \special{papersize=5.04in,3.751in} */
1080
1081 void getpapersize (FILE *infile) {
1082 //      if (strcmp(papersize,"") != 0) return;  /* ignore all but first */
1083         if (papersize != NULL) return;
1084 //      papersize = malloc ((size_t) (nspecial+1));
1085 //      getcommonstring(infile, papersize);
1086         papersize = getcommonstring(infile);
1087 }
1088
1089 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
1090
1091 int bComplainSpecial=1;
1092
1093 /* Attempt at \special{background rgb 0 0 1} support 98 June 30 */
1094
1095 void DoBackGround (FILE *infile, int c) {
1096         char *s;
1097         int n, m;
1098         int setcolor=0;
1099         COLORSPEC SavedColor;
1100
1101         if (bBackGroundFlag == 0) {
1102                 flushspecial(infile);
1103                 return;
1104         }
1105
1106         s = line + strlen(line);
1107         if (c > 0) *s++ = (char) c;                             /* stick in terminator */
1108         *s = '\0';                                                              /* just in case */
1109         (void) scanspecial(input, line, MAXLINE);
1110
1111         if (traceflag) {
1112                 sprintf(logline, "\n%s %c (%d) ", line, c, c);
1113                 showline(logline, 0);
1114         }
1115
1116 /*      if (c > 0) return; */                                   /* only do in prescan ! */
1117         s = line;
1118         if (*s == '\0') return;
1119         if (bKeepBlack) return;                                 /* 96/Nov/3 */
1120
1121         SavedColor = CurrColor;                                 /* 99/Apr/06 */
1122         if (strncmp(s, "rgb", 3) == 0) {
1123                 s += 3;
1124                 m = sscanf(s, "%g %g %g%n\n", &CurrColor.A, &CurrColor.B, &CurrColor.C, &n);
1125                 if (m == 3) {
1126                         CurrColor.D = -1.0F;
1127                         setcolor=1;
1128                         s += n;
1129                 }
1130                 else {
1131                         complainspecial(input);
1132                         return;
1133                 }
1134         }
1135         else if (strncmp(s, "cmyk", 4) == 0) {
1136                 s += 4;
1137                 m = sscanf(s, "%g %g %g %g%n",
1138                            &CurrColor.A, &CurrColor.B, &CurrColor.C, &CurrColor.D, &n);
1139                 if (m == 4) {
1140                         setcolor=1;
1141                         s += n;
1142                 }
1143                 else {
1144                         complainspecial(input);
1145                         return;
1146                 }
1147         }
1148         else if (strncmp(s, "gray", 4) == 0) {
1149                 s += 4;
1150                 m = sscanf(s, "%g%n", &CurrColor.A, &n);
1151                 if (m == 1) {
1152 /*                      CurrentC = CurrentB = CurrentA; CurrentD = -2.0F; */
1153                         CurrColor.C = CurrColor.B = CurrColor.A;
1154                         CurrColor.D = -2.0F;
1155                         setcolor = 1;
1156                         s += n;
1157                 }
1158                 else {
1159                         complainspecial(input);
1160                         return;
1161                 }
1162         }
1163         else if (_strnicmp(s, "black", 5) == 0) {
1164                 s += 5;
1165                 setcolor=1;
1166 /*              CurrentC = CurrentB = CurrentA = 0.0F; CurrentD = 1.0F; */
1167                 CurrColor.C = CurrColor.B = CurrColor.A = 0.0F;
1168                 CurrColor.D = 1.0F;             
1169         }
1170         else if (_strnicmp(s, "white", 5) == 0) {
1171                 s += 5;
1172                 setcolor=1;
1173 /*              CurrentC = CurrentB = CurrentA = 0.0F;
1174                 CurrentD = 0.0F; */
1175                 CurrColor.C = CurrColor.B = CurrColor.A = 0.0F;
1176                 CurrColor.D = 0.0F; 
1177         }
1178         else {
1179                 complainspecial(input); /* 1995/April/15 */
1180                 return;
1181         }
1182
1183         if (traceflag) {
1184                 sprintf(logline, " PAGENUMBER %d (%d %d) ", pagenumber, dvi_t, MaxColor);
1185                 showline(logline, 0);
1186         }
1187         
1188 /*      if (pagenumber < 0 || pagenumber >= dvi_t)  */
1189         if (pagenumber < 0 || pagenumber > dvi_t) {                     /* 99/Feb/21 */
1190                 sprintf(logline, " ERROR: bad page number %d\n", pagenumber);
1191                 showline(logline, 1);
1192                 return;
1193         }
1194
1195         if (traceflag) {
1196                 sprintf(logline, "\npage %d %g %g %g %g\n",
1197                            pagenumber, CurrColor.A, CurrColor.B, CurrColor.C,
1198                            CurrColor.D);
1199                 showline(logline, 0);
1200         }
1201         BackColors[pagenumber] = CurrColor;                     /* ??? */
1202         bBackUsed = 1;                          /* mark background color used */
1203         CurrColor = SavedColor;                                 /* 99/Apr/06 */
1204 }
1205
1206         
1207 #ifdef TPIC
1208
1209 /* TPIC commands */
1210
1211 /* char *tpiccommand[] = {
1212         "pa", "fp", "ip", "da", "dt", "sp", "pn", "ar", "ia", 
1213                 "sh", "wh", "bk", "tx", ""
1214 }; */
1215
1216 char *tpiccommands = "pa fp ip da dt sp pn ar ia sh wh bk tx";
1217
1218 #endif
1219
1220 /* Maybe check for TPIC specials only in selected page range ... */
1221 /* Hmm, may want to search for inserted figure files here and extract */
1222 /* DocumentNeededResources, DocumentFonts to save for writing in header ... */
1223 /* No, use IncludeResource: font ... and IncludeFont: ... ? */
1224 /* also check for \special{insertimage: ...} TIFF images re level2 96/Dec/20 */
1225 /* also check for \special{color ...} */
1226 /* also check for \special{background ...} 98/Jun/30 */
1227
1228 void logdo_com (FILE *infile) {
1229         int c;
1230 /*      int k=0; */
1231
1232         if (bIgnoreSpecials) {
1233                 flushspecial(infile);
1234                 return;
1235         }
1236         nspecialsav = nspecial;                         /* 99/Feb/21 */
1237         specstart = ftell(input);                       /* for complainspecial 99/Feb/21 */
1238         c = getc(infile);                                       /* peek ahead for ! */
1239         ungetc (c, infile);
1240         if (c == 0 && bFirstNull) {                     /* is first byte null ? 96/Aug/29 */
1241                 flushspecial(infile);
1242                 return;
1243         }
1244         if (c == '!') {
1245 /*              if (verbatimflag != 0) { */             /* flushed 97/Mar/9 */
1246                         c = getc(infile); nspecial--;
1247                         getheadertext(infile);
1248 /*              } */
1249                 flushspecial(infile);
1250                 return;
1251         }
1252 /*      c = getalphatoken(infile, line, MAXLINE); */
1253         c = getalphatoken(infile, line, sizeof(line)); /* MAXLINE */
1254 #ifdef TPIC
1255 /*      check whether maybe a TPIC \special */
1256         if (allowtpic != 0 && needtpic == 0 && (c == ' ' || c == 0)) {
1257 /*              while (strcmp(tpiccommand[k], "") != 0) {
1258                         if (strcmp(line, tpiccommand[k]) == 0) {
1259                                 needtpic++; break;
1260                         }
1261                         k++;
1262                 } */
1263                 if (strlen(line) == 2 && strstr(tpiccommands, line) != NULL)
1264                                 needtpic++; 
1265         }
1266 #endif
1267         if (c == ' ' || c == ':') {
1268                 if (strcmp(line, "color") == 0) {
1269                         doColor(NULL, input, c, 0);             /* no PS output */
1270                         bColorUsed = 1;         /* 98/Feb/14 */
1271                 }
1272                 else if (strcmp(line, "background") == 0) {
1273                         DoBackGround (infile, c);
1274 /*                      bColorUsed = 1; */ /* ? */
1275                 }
1276                 else if (strcmp(line, "landscape") == 0) {              /* 99/Apr/5 foils.cls */
1277                         bLandScape = ! bLandScape;                                      /* sets globally ! */
1278                 }
1279         }
1280 /*      check whether a special calling for a header or prolog file */
1281 /*      if(c == '=' && strcmp(line, "header") == 0) getheadername(infile); */
1282 /*      Separator is `=' */
1283         if(c == '=') {                                          /* extended 93/Dec/29 */
1284 /*              if (strcmp(line, "header") == 0) getheadername(infile); */
1285                 if (_strcmpi(line, "header") == 0) getheadername(infile);
1286 /*              else if (strcmp(line, "headertext") == 0) getheadertext(infile); */
1287                 else if (_strcmpi(line, "headertext") == 0) getheadertext(infile);
1288 /*              following added in 1995 July */
1289                 else if (strcmp(line, "DSCheader") == 0) getcustomname(infile);
1290                 else if (strcmp(line, "DSCtext") == 0) getcustomtext(infile);
1291                 else if (strcmp(line, "papersize") == 0) getpapersize(infile);
1292                 else if (strcmp(line, "DVIPSONE") == 0) getcommandspec(infile);
1293                 else if (strcmp(line, "DVIWindo") == 0) flushspecial(infile);
1294 /*              else complain ??? */
1295         }
1296 /*      else if (c == ':' && strcmp(line, "dvitops") == 0) { */
1297 /*      Separator is `:' */
1298         else if (c == ':') {
1299                 if (strcmp(line, "dvitops") == 0) {
1300 /*                      (void) getalphatoken(infile, line, MAXLINE); */
1301                         (void) getalphatoken(infile, line, sizeof(line)); /* MAXLINE */
1302                         if (strcmp(line, "prolog") == 0) getheadername(infile);
1303                 }
1304                 else if (strcmp(line, "PDF") == 0) {            /* 1996/July/4 */
1305                         c = getalphatoken(infile, line, sizeof(line));   /* MAXLINE */
1306                         if (c == ' ' || c == '=') {
1307                                 if (_strcmpi(line, "Keywords") == 0) getkeywords(infile);
1308                                 else if (strcmp(line, "BBox") == 0) getbbox(infile); 
1309                                 else if (_strcmpi(line, "Creator") == 0) getcreator(infile);
1310                                 else if (_strcmpi(line, "Title") == 0) gettitle(infile);
1311                                 else if (_strcmpi(line, "Subject") == 0) getsubject(infile);
1312                                 else if (_strcmpi(line, "Author") == 0) getauthor(infile);
1313                                 else if (_strcmpi(line, "Base") == 0) getbase(infile);
1314                                 else if (_strcmpi(line, "PageMode") == 0) getpagemode(infile);
1315                         }
1316                 }
1317 /*              check whether TIFF image inserted re level2 features 96/Dec/20 */
1318                 else if (strcmp(line, "insertimage") == 0)      bInsertImage++;
1319         }
1320         flushspecial(infile);
1321 }
1322
1323 void logdo_xxxi(FILE *infile, unsigned int n) {
1324 /*      unsigned int k; */
1325         nspecial = (long) n;
1326         logdo_com(infile);
1327 /*      for(k = 0; k < n; k++)  getc(infile); */
1328 }
1329
1330 void logdo_xxx1(FILE *infile) { /* for /special */
1331         unsigned int k;
1332         k = getc(infile);
1333         logdo_xxxi(infile, k);
1334 }
1335
1336 void logdo_xxx2(FILE *infile) { /* for /special */
1337         unsigned int k; 
1338         k = ureadtwo(infile);
1339         logdo_xxxi(infile, k);
1340 }
1341
1342 void logdo_xxxl(FILE *infile, unsigned long n) {
1343 /*      unsigned long k; */
1344         nspecial=(long) n;
1345         logdo_com(infile);
1346 /*      for(k = 0; k < n; k++)  getc(infile); */
1347 }
1348
1349 void logdo_xxx3(FILE *infile) { 
1350         logdo_xxxl(infile, ureadthree(infile));
1351 }
1352
1353 void logdo_xxx4(FILE *infile) { 
1354         logdo_xxxl(infile, ureadfour(infile));
1355 }
1356
1357 /* need to do this even if skipping pages */
1358
1359 void logfnt_def(FILE *infile, unsigned int k) {
1360         int fn;
1361         unsigned int na, nl, i;
1362         int newfont=1;          /* if this is a new one (not defined before) */
1363 //      char *tempfont;
1364         char *fp;
1365         char namebuffer[FNAMELEN];
1366
1367         if (finx[k] != BLANKFONT) {             /* seen this font before !!! */
1368                 sprintf(logline, " ERROR: Font %d being redefined ", k);
1369                 showline(logline, 1);
1370                 tellwhere(infile, 1);
1371 /*              errcount(0); */
1372                 newfont = 0;
1373                 fn = finx[k];
1374         }
1375         else {                          /* definition of font not seen before */
1376                 fn = fnext++;  /* grab next slot */
1377                 finx[k] = (short) fn;
1378                 if (fnext > maxfonts) {                 /* 94/May/23 */
1379                         sprintf(logline, " ERROR: More than %d fonts in use\n", maxfonts);
1380                         showline(logline, 1);
1381                         fnext--;
1382 /*                      errcount(0); */
1383                         checkexit(1);                   /* 1993/Dec/11 */
1384                 }
1385         }
1386         
1387         fc[fn] = ureadfour(infile);             /* read checksum (encoding info) */
1388 /*      (void) ureadfour(infile); */
1389         fs[fn] = ureadfour(infile);             /* read at size */
1390 /*      fd[fn] = ureadfour(infile); */  /* design size */
1391         (void) ureadfour(infile);               /* skip over design size */
1392         na = getc(infile);
1393         nl = getc(infile);
1394         if (newfont == 0) {     /* just skip over if already defined */
1395                 for (i = 0; i < na + nl; i++) (void) getc(infile);
1396                 return;
1397         }
1398 /*      fp = fontname[fn]; */
1399         fp = namebuffer;
1400         if (na + nl >= sizeof(namebuffer)-1) {  /* FNAMELEN */
1401                 sprintf(logline, " Font name too long: %d (> %d) ",
1402                                 na + nl, sizeof(namebuffer)-1);
1403                 showline(logline, 1);
1404                 showline("\n", 0);
1405 //              errcount(0);
1406                 tellwhere(infile, 1);
1407                 for (i = 0; i < na+nl; i++) (void) getc(infile);
1408         }
1409         else {
1410                 for (i = 0; i < na+nl; i++) *fp++ = (char) getc(infile);
1411         }
1412         *fp++ = '\0';
1413         if (fontname[fn] != NULL) free(fontname[fn]);
1414         fontname[fn] = zstrdup(namebuffer);
1415 /*      strcpy(subfontname[fn], ""); */         /* blank it out */
1416         if (subfontname[fn] != NULL) {          /* blank it out */
1417                 free(subfontname[fn]);
1418                 subfontname[fn] = NULL; 
1419         }
1420 //      strcpy(fontvector[fn], "");                     /* 1992/May/4 */
1421 //      *(fontvector + fn * MAXVECNAME) = '\0';                 /* blank it out */
1422         if (fontvector[fn] != NULL) {
1423                 free(fontvector[fn]);
1424                 fontvector[fn] = NULL;                  /* blank it out */
1425         }
1426         fontsubflag[fn] = -1;                           /* all this goes to extract now */
1427         fontproper[fn] = 0;                                     /* 1992/May/4 */
1428 /*      possibly determine whether we need to reencode *control* range ??? */
1429 /*      if (substitute != 0) fontsubflag[fn] = fontremap(fontname[fn]);
1430         if (uppercaseflag != 0) uppercase(font, fontname[fn]);  else */ 
1431 /*      strcpy(font, fontname[fn]); */          /* what for ??? */
1432 //      tempfont = fontchar[fn];                        /* reset character counts */
1433 //      tempfont = fontchar + MAXCHRS * fn;
1434 /*      for (i = 0; i < MAXCHRS; i++) tempfont[i] = 0;  */
1435 //      for (i = 0; i < MAXCHRS; i++) *tempfont++ = 0;          /* 1994/Feb/3 */
1436         if (fontchar[fn] == NULL) {
1437                 fontchar[fn] = (char *) malloc(MAXCHRS);
1438                 if (fontchar[fn] == NULL) {
1439                         showline(" Unable to allocate memory\n", 1);
1440                         checkexit(1);
1441                         return;
1442                 }
1443         }
1444         memset(fontchar[fn], 0, MAXCHRS);
1445 }
1446
1447 void logdo_fnt_def1(FILE *infile) { /* define font */
1448         unsigned int k;
1449 /*      k = ureadone(infile); */
1450         k = getc(infile);
1451         logfnt_def(infile, k);
1452 }
1453
1454 void logdo_fnt_def2(FILE *infile) { /* define font */
1455         unsigned int k;
1456         k = ureadtwo(infile);
1457         if (k >= MAXFONTNUMBERS) k = MAXFONTNUMBERS-1;
1458         logfnt_def(infile, k);
1459 }
1460
1461 void logdo_fnt_defsub(FILE *infile, unsigned long k) {
1462         if (k >= MAXFONTNUMBERS) k = MAXFONTNUMBERS-1;
1463         logfnt_def(infile, (unsigned int) k);
1464 }
1465
1466 void logdo_fnt_def3(FILE *infile) { /* define font */
1467 /*      unsigned long k;
1468         k = ureadthree(infile); */
1469         logdo_fnt_defsub(infile, ureadthree(infile));
1470 }
1471
1472 void logdo_fnt_def4(FILE *infile) { /* define font */
1473         long k;
1474         k = sreadfour(infile);
1475         if (k < 0) k = 0;
1476         logdo_fnt_defsub(infile, (unsigned long) k);
1477 }
1478
1479 /* need to do this even if skipping pages */
1480
1481 void logdo_pre(FILE *infile) {
1482         unsigned int i, k, j;
1483         int c;
1484         char *s;
1485         
1486 /*      i = ureadone(infile); */
1487         i = getc(infile);
1488         if (i < 1 || i > 3) {
1489                 showline("Not a valid DVI file ", 1);
1490                 giveup(3); 
1491                 return;
1492         }
1493         else if (i != ID_BYTE) {
1494                 sprintf(logline, "File is DVI version %d - *not* %d\n",
1495                         i, ID_BYTE);
1496                 showline(logline, 1);
1497                 errcount(0);
1498         }
1499         num = ureadfour(infile);
1500         den = ureadfour(infile);
1501         mag = ureadfour(infile);
1502 /*      k = ureadone(infile); */
1503         k = getc(infile);                                       /* bytes needed for TeX's comment */
1504 /*      s = comment; */                                         /* was to char comment[MAXCOMMENT] */
1505 //      if (strcmp(comment, "") != 0) {         /* free if still in use */
1506         if (comment != NULL) {          /* free if still in use */
1507                 free(comment);
1508 //              comment = "";
1509                 comment = NULL;
1510         }
1511         comment = malloc(k+1);
1512         if (comment == NULL) {
1513                 showline(" Unable to allocate memory\n", 1);
1514                 checkexit(1);
1515 //              more serious exit(1) ???
1516         }
1517         s = comment; 
1518 /*      if (traceflag) fprintf(stdout, "Comment:"); */
1519         c = getc(infile);                                       /* try and discard initial space */
1520         if (c == ' ') k--;                                      
1521         else (void) ungetc(c, infile);
1522         for (j=0; j < k; j++) { 
1523                 c = getc(infile); 
1524                 if (j < MAXCOMMENT)     *s++ = (char) c;
1525 /*              if (verboseflag) putc(c, stdout); */
1526         }
1527         *s++ = '\0';
1528         if (verboseflag) {
1529                 showline(comment, 0);
1530                 showline("\n", 0);
1531         }
1532         if (textures != 0) 
1533                 (void) ureadfour(infile);       /* flush length code */
1534 }
1535
1536 /* need to do this even if skipping pages */
1537
1538 void logdo_post(FILE *infile) {
1539 /*      int k; */
1540         previous = sreadfour(infile);   /* was ureadfour ... */
1541         num = ureadfour(infile);
1542         den = ureadfour(infile);
1543         mag = ureadfour(infile);
1544
1545         if (traceflag) {
1546                 sprintf(logline, " POST: previous %ld num %ld den %ld mag %ld\n",
1547                                                   previous, num, den, mag);
1548                 showline(logline, 0);
1549         }
1550 /* compare these with what was in preamble ? */
1551
1552         dvi_l = ureadfour(infile);                      /* max page height plus depth */
1553         dvi_u = ureadfour(infile);                      /* max page width */
1554         dvi_s = (int) ureadtwo(infile);         /* max stack depth */
1555         dvi_t = (int) ureadtwo(infile);         /* number bops limit 65535 */
1556         if (traceflag) {
1557                 sprintf(logline, "l %ld u %ld s %ld t %ld\n",
1558                                                   dvi_l, dvi_u, dvi_s, dvi_t);
1559                 showline(logline, 0);
1560         }
1561 /*      here l and u could be used for bbox info ? */
1562 /*      except: don't include headers and footers and other problems */ 
1563         finish = -1; 
1564 }
1565
1566 /* could do this even in forward mode to check on number of pages ? */
1567
1568 void logdo_post_post(FILE *infile) { /* only in reverse ? */
1569 /*      unsigned long q;         */
1570 /*      unsigned int i;          */
1571
1572         if (traceflag) showline("Hit POSTPOST!\n", 0);
1573
1574 /*      q = ureadfour(infile); */
1575         (void) ureadfour(infile);
1576 /*      i = ureadone(infile); */
1577         (void) getc(infile);
1578 /*      check ID_BYTE again ? */
1579 /*  followed by at least four 223's */
1580 /*      if (reverseflag != 0) fseek(infile, previous, SEEK_SET);
1581         else fputs("%% This is really the end !\n", output); */
1582 }
1583
1584 /* This version scans for Textures length code followed by pre & DVI code */
1585 /* could do something more fancy to get quickly to resource fork */
1586 /* should be fairly safe, unless initial length code is > 256 */
1587 /* Search for 3 or more zeros in a row, followed by dont-care (length) */
1588 /* - followed by pre and ID_BYTE */
1589
1590 int readovertext(FILE *infile) {
1591         int c, n;
1592
1593         c = getc(infile);
1594         for(;;) {
1595 /*              if ((c = getc(infile)) == 0) { */
1596                 if (c == 0) {
1597                         n = 1;
1598                         while ((c = getc(infile)) == 0) n++;
1599                         if (c == EOF) return 0;
1600                         if (n >= 3) {
1601                                 if((c = getc(infile)) == (int) pre) {
1602                                         (void) ungetc(c, infile);
1603                                         dvistart = ftell(infile);
1604                                         c = getc(infile);
1605                                         if ((c = getc(infile)) == ID_BYTE) {
1606                                                 if (fseek(infile, dvistart, SEEK_SET) != 0)
1607                                                         return 0;               /* seek error */
1608                                                 else return -1;         /* think we found it ! */
1609                                         }
1610                                 }
1611                         }
1612                 }
1613                 else if ((c = getc(infile)) == EOF) return 0;
1614         }       
1615 }
1616
1617 void resetpagerangehit (int flag) {
1618 /*      int k; */
1619 /*      for (k = 0; k < rangeindex; k++) pagerangehit[k] = 0; */        /* 1994/Jan/16 */
1620 /*      currentrange = -1; */
1621         currentpage = -LINFINITY;       /* indicate first time */
1622         prescanflag = flag;                     /* remember whether in prescan or not */
1623         if (prescanflag != 0 || reverseflag == 0)
1624                  pagesequence = 1;              /* 1994/Feb/16 */
1625 /* NOTE: don't reset page sequence instance if going in reverse order */
1626 }
1627
1628 /***************************************************************************/
1629
1630 void alloccolorsave (int npages) {
1631         int k;
1632
1633         if (ColorStacks != NULL) {
1634                 showline(" ERROR: color save stacks allocation\n", 1);
1635                 freecolorsave();
1636         }
1637 #ifdef DEBUGCOLORSTACK
1638         if (traceflag) {
1639                 sprintf(logline, "Allocating color save stack for %d pages\n", npages);
1640                 showline(logline, 0);
1641         }
1642 #endif
1643         if (npages == 0) npages = 1;
1644         ColorStacks = (COLORSPEC **) malloc((npages+1) * sizeof(COLORSPEC *));
1645         if (ColorStacks == NULL) {
1646                 showline(" Unable to allocate memory\n", 1);
1647                 checkexit(1);
1648 //              more serious exit(1) ???
1649         }
1650         for (k = 0; k <= npages; k++) ColorStacks[k] = NULL;
1651         MaxColor = npages+1;                    /* make note of size of allocation */
1652 }
1653
1654 void freecolorsave (void) {
1655         int k, npages = MaxColor;
1656         
1657         if (ColorStacks == NULL) return;
1658 #ifdef DEBUGCOLORSTACK
1659         if (traceflag) showline("Freeing Saved Color Stacks\n", 0);
1660 #endif
1661         for (k = 0; k < npages; k++) {
1662                 if (ColorStacks[k] != NULL) {
1663                         free(ColorStacks[k]);
1664                         ColorStacks[k] = NULL;
1665                 }
1666         }
1667         if (ColorStacks != NULL) {
1668                 free(ColorStacks);
1669                 ColorStacks = NULL;
1670         }
1671 }
1672
1673 #ifdef DEBUGCOLORSTACK
1674 void dumpcolorsave (void) {                     /* debugging only */
1675         int k, m, i, npages = MaxColor-1;
1676         COLORSPEC *ColorSaved;
1677
1678         if (ColorStacks == NULL) {
1679                 showline(" No saved color stacks to show\n", 1);
1680                 return;
1681         }
1682         sprintf(logline, " Saved color stacks for %d pages after prescan:\n", npages);
1683         showline(logline, 1);
1684 /*      for (k = 0; k < npages; k++) { */
1685         for (k = 1; k <= npages; k++) {
1686                 if (ColorStacks[k] != NULL) {
1687                         sprintf(logline, "For page %d:\n", k);
1688                         showline(logline, 1);
1689                         ColorSaved = ColorStacks[k];
1690                         m = (int) (ColorSaved[0].D + 0.5);
1691                         for (i = 1; i <= m; i++) {
1692                                 sprintf(logline, "%d\t%g\t%g\t%g\t%g\n", i,
1693                                            ColorSaved[i].A,  ColorSaved[i].B,
1694                                            ColorSaved[i].C,  ColorSaved[i].D);
1695                                 showline(logline, 1);
1696                         }
1697                 }
1698                 else {
1699                         sprintf(logline, " ERROR: ColorStack[%d] is NULL\n", k);
1700                         showline(logline, 1);
1701                 }
1702         }
1703 }
1704 #endif
1705
1706 void allocbackground (int npages) {
1707         int k;
1708         if (BackColors != NULL) {
1709                 showline(" ERROR: background allocation\n", 1);
1710                 freebackground();
1711         }
1712         if (npages == 0) npages = 1;
1713 /*      BackColors = (COLORSPEC *) malloc(npages * sizeof(COLORSPEC)); */
1714         BackColors = (COLORSPEC *) malloc((npages+1) * sizeof(COLORSPEC));
1715         if (BackColors == NULL) {
1716                 showline(" Unable to allocate memory\n", 1);
1717                 checkexit(1);
1718 //              more serious exit(1) ???
1719         }
1720 /*      for (k = 0; k < npages; k++) */
1721         for (k = 0; k <= npages; k++) {                 /* may not be needed */
1722                 BackColors[k].A = BackColors[k].B =     BackColors[k].C = -1.0F;
1723                 BackColors[k].D = -1.0F;
1724         }
1725 }
1726
1727 void freebackground (void) {
1728         if (BackColors != NULL) free(BackColors);
1729         BackColors = NULL;
1730 }
1731
1732 /***************************************************************************/
1733
1734 int scanlogfileaux(FILE *fp_in) {
1735         int c, k, fn;
1736 /*      long filptr; */
1737
1738 //      strcpy (headerfile, "");                                /* reset to no headers seen */
1739         if (headerfile != NULL) free(headerfile);
1740         headerfile = NULL;
1741         if (countzeroflag) resetpagerangehit (1);
1742
1743         numpages = 0;                   /* number of pages actually processed 94/Oct/12 */
1744         pagenumber = 0;                 /* pages seen in scan */
1745
1746         ff = -1;                                                /* redundant */
1747         for (k = 0; k < MAXFONTS; k++) fonthit[k] = 0;
1748 /*      for (k = 0; k < maxfonts; k++) fonthit[k] = 0; */ /* ah what the hell */
1749 //      currentfont = fontchar;                 /* just in case */
1750         currentfont = fontchar[0];              /* just in case ??? */
1751         fnext = 0;
1752         for (k = 0; k < MAXFONTNUMBERS; k++)    /* reset status to unused */
1753                 finx[k] = (short) BLANKFONT;
1754
1755 /*      Get dvi_t up front 98/Jun/30 */
1756         postposition = -1;
1757         bBackUsed=0;                    /* non-zero of \special{background ...} used */
1758         bColorUsed = 0;                 /* assume no color \special until ... 98/Feb/15 */
1759
1760         if (bCarryColor || bBackGroundFlag) {
1761                 postposition = gotopost(input); /* in dvianal.c */
1762                 (void) getc(input);                             /* absorb the post byte */
1763                 logdo_post(input);
1764                 rewind(input);
1765                 if (bCarryColor)
1766                         alloccolorsave(dvi_t);          /* allocated space for color table */
1767                 if (bBackGroundFlag)
1768                         allocbackground(dvi_t);         /* allocate background color table */
1769                 pagenumber = 0;
1770                 pageno = 0;
1771                 finish = 0;
1772         }
1773
1774         finish = 0;
1775         stinx = 0; maxstinx = 0;                /* redundant, hopefully */
1776         
1777         textures=0;                     /* start off by assuming normal DVI file */
1778         c = getc(fp_in);
1779         (void) ungetc(c, fp_in);
1780         if (c != (int) pre) {   /* not standard DVI file - can figure out ? */
1781                 if (readovertext(fp_in) == 0) {
1782                         if (strstr(fn_in, ".tex") != NULL) {                    /* 1994/Feb/24 */
1783                                 showline("Can't find DVI file ", 1);
1784                         }
1785                         else {
1786                                 showline("Not a valid DVI (or Textures) file ", 1);
1787                         }
1788                         input = NULL;  /* to stop at byte message ? */
1789                         giveup(3);
1790                         return -1;
1791                 }
1792                 else {
1793                         if (verboseflag) {
1794                                 showline("Textures DVI file - ", 0);
1795                         }
1796                         textures=1;
1797                 }
1798         }
1799
1800 /* in the above, may also want to look 100 bytes into the file for start */
1801 /* some Mac files come that way... */
1802
1803         for(;;) {
1804                 c = getc(fp_in);
1805                 if (c == EOF) {
1806                         sprintf(logline, " Unexpected EOF (%s)\n", "scanlogfile");
1807                         showline(logline, 1);
1808                         errcount(0);
1809                         finish = -1;
1810 /*                      giveup(13); */
1811                 }
1812                 if (c < 128) {
1813                         if (skipflag == 0) {
1814                                 if (ff < 0) invalidset((int) c);
1815                                 else {
1816 /*                                      if (bRemapControl && c < MAXREMAP) c = remaptable[c]; */
1817                                         if (bRemapControl || bRemapFont) {
1818                                                 if (c < MAXREMAP) c = remaptable[c];
1819 #if MAXREMAP < 128
1820                                                 else if (c == 32) c = 195;
1821                                                 else if (c == 127) c = 196;
1822 #endif
1823                                         }
1824                                         else if (bRemapSpace && c <= 32) {                      /* 1995/Oct/17 */
1825                                                 if (c == 32) c = 195;           /* not 160 */
1826                                                 else if (c == 13) c = 176;      /* 1996/June/4 */
1827                                                 else if (c == 10) c = 173;      /* 1996/June/4 */
1828                                                 else if (c == 9) c = 170;       /* 1996/June/4 */
1829                                                 else if (c == 0) c = 161;
1830                                         }
1831                                         currentfont[c]=1;
1832                                 }
1833                         }
1834                 }
1835                 else if (c >= 171 && c <= 234) { /*     switch to font (c - 171) */
1836                         fn = (c - 171);
1837                         logswitchfont(fn, fp_in);
1838                 }
1839                 else {
1840                         switch(c) {
1841                                 case set1: logdo_set1(fp_in); break;
1842                                 case set2: logdo_set2(fp_in); break;    /* silly */
1843                                 case set3: logdo_set3(fp_in); break;    /* silly */
1844                                 case set4: logdo_set4(fp_in); break;    /* silly */
1845                                 case set_rule: logdo_set_rule(fp_in); break;
1846                                 case put1: logdo_put1(fp_in); break ;
1847                                 case put2: logdo_put2(fp_in); break;    /* silly */
1848                                 case put3: logdo_put3(fp_in); break;    /* silly */
1849                                 case put4: logdo_put4(fp_in); break;    /* silly */
1850                                 case put_rule: logdo_put_rule(fp_in); break;    
1851                                 case nop: break;                        /* do nothing */
1852                                 case bop: logdo_bop(fp_in); break;
1853                                 case eop: logdo_eop(fp_in); break;
1854                                 case push: logdo_push(); break;
1855                                 case pop: logdo_pop(); break;
1856                                 case right1: logdo_right1(fp_in); break;
1857                                 case right2: logdo_right2(fp_in); break;  
1858                                 case right3: logdo_right3(fp_in); break; 
1859                                 case right4: logdo_right4(fp_in); break; 
1860                                 case w0: logdo_w0(); break;
1861                                 case w1: logdo_w1(fp_in); break;
1862                                 case w2: logdo_w2(fp_in); break; 
1863                                 case w3: logdo_w3(fp_in); break; 
1864                                 case w4: logdo_w4(fp_in); break;        /* not used ? */
1865                                 case x0: logdo_x0(); break;
1866                                 case x1: logdo_x1(fp_in); break;
1867                                 case x2: logdo_x2(fp_in); break; 
1868                                 case x3: logdo_x3(fp_in); break; 
1869                                 case x4: logdo_x4(fp_in); break;        /* not used ? */
1870                                 case down1: logdo_down1(fp_in); break;
1871                                 case down2: logdo_down2(fp_in); break; 
1872                                 case down3: logdo_down3(fp_in); break; 
1873                                 case down4: logdo_down4(fp_in); break; 
1874                                 case y0: logdo_y0(); break;
1875                                 case y1: logdo_y1(fp_in); break;
1876                                 case y2: logdo_y2(fp_in); break; 
1877                                 case y3: logdo_y3(fp_in); break; 
1878                                 case y4: logdo_y4(fp_in); break;        /* not used ? */
1879                                 case z0: logdo_z0(); break;
1880                                 case z1: logdo_z1(fp_in); break;
1881                                 case z2: logdo_z2(fp_in); break; 
1882                                 case z3: logdo_z3(fp_in); break; 
1883                                 case z4: logdo_z4(fp_in); break;        /* not used ? */
1884                                 case fnt1: logdo_fnt1(fp_in); break;
1885                                 case fnt2: logdo_fnt2(fp_in); break;    /* silly */
1886                                 case fnt3: logdo_fnt3(fp_in); break;    /* silly */
1887                                 case fnt4: logdo_fnt4(fp_in); break;    /* silly */
1888                                 case xxx1: logdo_xxx1(fp_in); break;
1889                                 case xxx2: logdo_xxx2(fp_in); break; /* not used ? */
1890                                 case xxx3: logdo_xxx3(fp_in); break; /* not used ? */
1891                                 case xxx4: logdo_xxx4(fp_in); break; 
1892                                 case fnt_def1: logdo_fnt_def1(fp_in); break;
1893                                 case fnt_def2: logdo_fnt_def2(fp_in); break;    /* silly */
1894                                 case fnt_def3: logdo_fnt_def3(fp_in); break;    /* silly */
1895                                 case fnt_def4: logdo_fnt_def4(fp_in); break;    /* silly */
1896                                 case post: logdo_post(fp_in); break;
1897                                 case pre: logdo_pre(fp_in); break;
1898                                 case post_post: logdo_post_post(fp_in); break;
1899         
1900                                 default: {
1901                                         sprintf(logline, 
1902                                                 " ERROR: Unrecognized DVI command: %d", c);
1903                                         showline(logline, 1);
1904                                         tellwhere(fp_in, 1);
1905 /*                                      errcount(0); */
1906                                         finish = -1;            /* ? */
1907 /*                                      giveup(7); */
1908                                  }
1909                                  break;
1910                         }
1911                 }
1912                 if (finish != 0) break;
1913                 if (bAbort) abortjob(); /* fine grained */
1914                 if (abortflag) break;
1915         }
1916 /*      if (maxstinx >= maxstack-1) {
1917                 showline( WARNING: The PS stack will probably overflow %d > %d\n",
1918                                 maxstinx, maxstack -1 );
1919                 errcount(0);
1920         }  */
1921         if (abortflag) return -1;
1922         return 0;
1923 }
1924
1925 /* main entry point, prescan DVI file font usage, \specials */
1926
1927 int scanlogfile (FILE *fp_in) {
1928         int c, d;
1929         input = fp_in;                  /* remember file handle */
1930
1931         if (traceflag) showline("Start PreScan DVI file\n", 0);
1932 /*      strcpy (headerfile, ""); */     /* reset to no headers seen */
1933         c = getc(fp_in);
1934         d = getc(fp_in);
1935         rewind(fp_in);
1936 //      we now forget about Textures files 99/July/14
1937         if (c != pre || d != ID_BYTE) {
1938                 sprintf(logline, " Not a proper DVI file `%s'\n",
1939                                 (filenamex != NULL) ? filenamex : "");
1940                 showline(logline, 1);
1941                 errcount(0);
1942                 return -1;
1943         }
1944         scanlogfileaux(fp_in);
1945 /*      if (showlogflag != 0) showlog(stdout); */
1946         if (bBackGroundFlag != 0 && bBackUsed == 0)
1947                 freebackground();                       /* not needed in this case */
1948         if (bCarryColor != 0 && bColorUsed == 0)
1949                 freecolorsave();                        /* not needed in this case */
1950         if (traceflag) showline("End PreScan DVI file\n", 0);
1951 #ifdef DEBUGCOLORSTACK
1952         if (traceflag) dumpcolorsave();
1953 #endif
1954         if (abortflag) return -1;
1955         return 0;
1956 }
1957
1958 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
1959
1960 /* Use `texfonts.map' in directory path TEXFONTS for aliasing */
1961
1962 #define FONTMAP
1963
1964 #ifdef FONTMAP
1965
1966 typedef struct map_element_struct {             /* list element key . value pair */
1967         char *key;
1968         char *value;
1969         struct map_element_struct *next;
1970 } map_element_type;
1971
1972 typedef map_element_type **map_type; 
1973
1974 /* **************************** auxiliary functions *********************** */
1975
1976 static void complain_mem (unsigned int size) {  /* out of memory */
1977         sprintf(logline, "Unable to honor request for %u bytes.\n", size);
1978         showline(logline, 1);
1979         checkexit(1);
1980 }
1981
1982 static void *xmalloc (unsigned int size) {
1983         void *new_mem = (void *) malloc (size);
1984         if (new_mem == NULL) complain_mem(size);
1985         return new_mem;
1986 }
1987
1988 static void *xrealloc (void *old_ptr, unsigned int size) {
1989         void *new_mem;
1990         if (old_ptr == NULL)
1991 /*              new_mem = xmalloc (size); *//* could just let realloc do this case? */
1992                 new_mem = malloc (size);        /* could just let realloc do this case? */
1993         else {
1994                 new_mem = (void *) realloc (old_ptr, size);
1995 /*              if (new_mem == NULL) complain_mem(size); */
1996         }
1997         if (new_mem == NULL) complain_mem(size);
1998         return new_mem;
1999 }
2000
2001 static char *xstrdup (char *s) {
2002         char *new_string = (char *) xmalloc (strlen (s) + 1);
2003         return strcpy (new_string, s);
2004 }
2005
2006 /* static char *concat3 (char *s1, char *s2, char *s3) {
2007         char *answer
2008                 = (char *) xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1);
2009         strcpy (answer, s1);
2010         strcat (answer, s2);
2011         strcat (answer, s3);
2012         return answer;
2013 } */    /* used by extend_filename only */
2014
2015 static void *xcalloc (unsigned int nelem, unsigned int elsize) {
2016         void *new_mem = (void *) calloc (nelem, elsize);
2017         if (new_mem == NULL) complain_mem (nelem * elsize);
2018         return new_mem;
2019 }
2020
2021 /*      Here we work only with suffix-free names - so this is silly */
2022
2023 /* static char *find_suffix (char *name) {
2024         char *dot_pos; 
2025         char *slash_pos; 
2026   
2027         dot_pos = strrchr (name, '.');
2028         if (dot_pos == NULL) return NULL;       
2029         if ((slash_pos = strrchr (name, '/')) != NULL) ;
2030         else if ((slash_pos = strrchr (name, '\\')) != NULL) ;  
2031         else if ((slash_pos = strrchr (name, ':')) != NULL) ;
2032         else slash_pos = name;
2033         if (dot_pos < slash_pos) return NULL;
2034         return dot_pos + 1;
2035 } */
2036
2037 /* static char *extend_filename (char *name, char *default_suffix) {
2038   char *suffix = find_suffix (name);
2039   char *new_s;
2040   if (suffix != NULL) return name;      
2041   new_s = concat3 (name, ".", default_suffix);
2042   return new_s;                                         
2043 } */
2044
2045 /* static char *remove_suffix (char *s) {
2046         char *ret;
2047         char *suffix = find_suffix (s);
2048   
2049         if (suffix == NULL) return NULL;
2050         suffix--;
2051         ret = (char *) xmalloc (suffix - s + 1);
2052         strncpy (ret, s, suffix - s);
2053         ret[suffix - s] = 0;
2054         return ret; 
2055 } */
2056
2057 /* only used by fontmap.c */ /* why not just use fgets on global line ? */
2058
2059 #define BLOCK_SIZE 40
2060
2061 static char *read_line (FILE *f) {
2062         int c;
2063         unsigned int limit = BLOCK_SIZE;
2064         unsigned int loc = 0;
2065         char *line;
2066
2067         line = (char *) xmalloc (limit);
2068   
2069         while ((c = getc (f)) != EOF && c != '\n') {
2070                 line[loc] = (char) c;
2071                 loc++;
2072                 if (loc == limit) {
2073                         limit += BLOCK_SIZE;
2074                         line = (char *) xrealloc (line, limit);
2075                 }
2076         }
2077   
2078         if (c != EOF) line[loc] = 0;            /* not EOF */
2079         else if (loc > 0) line[loc] = 0;        /* c == EOF, but line not empty */
2080         else {          /* c == EOF and nothing on the line --- at end of file.  */
2081                 free (line);
2082                 line = NULL;
2083         }
2084         return line;
2085 }
2086
2087 /* ************************************************************************* */
2088
2089 /* Fontname mapping.  We use a straightforward hash table. Should be prime? */
2090
2091 #define MAP_SIZE 307
2092
2093 /* The hash function.  We go for simplicity here.  */
2094
2095 static unsigned int map_hash (char *key) {
2096         unsigned int n = 0;
2097         char *s = key;
2098 /*      There are very few font names which are anagrams of each other
2099         so no point in weighting the characters.  */
2100         while (*s != 0) n += *s++;
2101         n %= MAP_SIZE;
2102 #ifdef DEBUGALIAS
2103         if (traceflag) {
2104                 sprintf(logline, "hash %u for %s\n", n, key);
2105                 showline(logline, 0);
2106         }
2107 #endif
2108         return n;
2109 }
2110
2111 /* Look up STR in MAP.  Return the corresponding `value' or NULL.  */
2112
2113 static char *map_lookup_str (map_type map, char *key) {
2114         unsigned int n = map_hash (key);
2115         map_element_type *p;
2116   
2117         for (p = map[n]; p != NULL; p = p->next) {
2118 #ifdef DEBUGALIAS
2119                 if (traceflag) {
2120                         sprintf(logline, "Trying %s against %s\n", key, p->key);
2121                         showline(logline, 0);
2122                 }
2123 #endif
2124                 if (strcmp (key, p->key) == 0) return p->value;
2125 #ifdef DEBUGALIAS
2126                 if (traceflag) {
2127                         sprintf(logline, "p->next %p\n", p->next);
2128                         showline(logline, 0);
2129                 }
2130 #endif
2131         }
2132 #ifdef DEBUGALIAS
2133         if (traceflag) {
2134                 sprintf(logline, " failed to find %s\n", key);
2135                 showline(logline, 0);
2136         }
2137 #endif
2138         return NULL;                                    /* failed to find it */
2139 }
2140
2141 #ifdef DEBUGALIAS
2142 static void map_show (map_type map) {   /* debugging tool */
2143         map_element_type *p;
2144         unsigned int n;
2145   
2146         for (n = 0; n < MAP_SIZE; n++) {
2147                 for (p = map[n]; p != NULL; p = p->next) {
2148                         sprintf(logline, "n %u key %s next %p\n", n, p->key, p->next);
2149                         showline(logline, 0);
2150                 }
2151         }
2152 }
2153 #endif
2154
2155 /*      Look up KEY in MAP; if it's not found, remove any suffix from KEY and
2156         try again.  Then paste key back into answer ... */
2157
2158 /* OK, the original KEY didn't work.  Let's check for the KEY without
2159     an extension -- perhaps they gave foobar.tfm, but the mapping only
2160     defines `foobar'.  */
2161
2162 /* Append the same suffix we took off, if necessary.  */
2163 /*      if (ret) ret = extend_filename (ret, suffix); */
2164
2165 char *map_lookup (map_type map, char *key) {
2166         char *ret = map_lookup_str(map, key);
2167 /*      char *suffix; */
2168   
2169 /*      lets assume we never have to deal with names that have extensions */
2170 /*      suffix = find_suffix (key); 
2171         if (!ret) {
2172                 if (suffix) {
2173                         char *base_key = remove_suffix (key);
2174                         ret = map_lookup_str(map, base_key);
2175                         free (base_key);
2176                 }
2177         }
2178         if (ret && suffix) ret = extend_filename (ret, suffix);  */
2179
2180         return ret;
2181 }
2182
2183 /* If KEY is not already in MAP, insert it and VALUE.  */
2184 /* This was a total mess!       Fixed 1994/March/18 */
2185
2186 static void map_insert (map_type map, char *key, char *value) {
2187         unsigned int n = map_hash (key);
2188         map_element_type **ptr = &map[n]; 
2189
2190         while (*ptr != NULL && !(strcmp(key, (*ptr)->key) == 0))  
2191                 ptr = &((*ptr)->next); 
2192
2193         if (*ptr == NULL) {
2194                 *ptr = (map_element_type *) xmalloc (sizeof(map_element_type));
2195                 (*ptr)->key = xstrdup (key);
2196                 (*ptr)->value = xstrdup (value);
2197                 (*ptr)->next = NULL;
2198         }
2199 }
2200
2201 /* Open and read the mapping file FILENAME, putting its entries into
2202    MAP. Comments begin with % and continue to the end of the line.  Each
2203    line of the file defines an entry: the first word is the real
2204    filename (e.g., `ptmr'), the second word is the alias (e.g.,
2205    `Times-Roman'), and any subsequent words are ignored.  .tfm is added
2206    if either the filename or the alias have no extension.  This is the
2207    same order as in Dvips' psfonts.map; unfortunately, we can't have TeX
2208    read that same file, since most of the real filenames start with an
2209    `r', because of the virtual fonts Dvips uses.  
2210    And what a load of bull! And who cares about DVIPS and VF files !*/
2211
2212 static void map_file_parse (map_type map, char *map_filename) {
2213         char *l;
2214         unsigned int map_lineno = 0;
2215         unsigned int entries = 0;
2216         FILE *f = fopen(map_filename, "r");
2217   
2218         if (f == NULL) {
2219                 sprintf(logline, " ERROR: Can't open %s\n", map_filename);
2220                 showline(logline, 1);
2221                 perrormod(map_filename);
2222                 return;
2223         }
2224
2225         while ((l = read_line(f)) != NULL) {
2226                 char *filename;
2227                 char *comment_loc;
2228
2229 /*              comment_loc = strrchr (l, '%'); */
2230                 comment_loc = strchr(l, '%');                                   /* 96/Aug/20 */
2231 /*              if (comment_loc == NULL) comment_loc = strrchr (l, ';'); */
2232                 if (comment_loc == NULL) comment_loc = strchr (l, ';');
2233       
2234 /*              Ignore anything after a % or ;  */
2235                 if (comment_loc)  *comment_loc = 0;
2236       
2237                 map_lineno++;
2238       
2239 /*              If we don't have any filename, that's ok, the line is blank.  */
2240                 filename = strtok (l, " \t");
2241                 if (filename) {
2242                         char *alias = strtok (NULL, " \t");
2243           
2244                         /* But if we have a filename and no alias, something's wrong.  */
2245                         if (alias == NULL || *alias == 0) {
2246                                 sprintf(logline,
2247                                         " font name `%s', but no alias (line %u in `%s').\n",
2248                                                 filename, map_lineno, map_filename);
2249                                 showline(logline, 1);
2250                         }
2251                         else {       /* We've got everything.  Insert the new entry.  */
2252                                 map_insert (map, alias, filename); /* alias is the key */
2253                                 entries++;
2254                         }
2255                 }
2256                 free (l);
2257         }
2258 /*      xfclose (f, map_filename); */
2259         fclose (f);
2260 #ifdef DEBUGALIAS
2261         if (traceflag) {
2262                 sprintf(logline, "%u entries\n", entries);
2263                 showline(logline, 0);
2264         }
2265 #endif
2266 }
2267
2268 /* Look for the file `texfonts.map' in each of the directories in
2269    TEXFONTS.  Entries in earlier files override later files.  */
2270
2271 /* uses _searchenv ? */
2272
2273 /* map_type map_create (char *envvar) { old version
2274         char filename[_MAX_PATH];
2275         map_type map;
2276       
2277         _searchenv ("texfonts.map", envvar, filename);
2278         if (*filename == '\0') return NULL;
2279
2280         map = (map_type) xcalloc (MAP_SIZE, sizeof (map_element_type *));
2281         map_file_parse (map, filename);
2282 #ifdef DEBUG
2283         if (traceflag) map_show(map);
2284 #endif
2285         return map;
2286 } */
2287
2288 /* Look for the file `texfonts.map' in each of the directories in
2289    TEXFONTS.  Entries in earlier files override later files.  */
2290
2291 /* void oursearchenv (char *mapname, char *envvar, char *pathname) { */
2292 void oursearchenv (char *mapname, char *searchpath, char *pathname) {
2293 /*      char *searchpath; */                                    /* 97/May/10 */
2294         int foundfile=0;                                                /* set, but not used ? */
2295 #ifndef SUBDIRSEARCH
2296         FILE *input;
2297         char *s;
2298 #endif
2299
2300 /*      searchpath = _getenv(envvar); */
2301 /*      searchpath = grabenv(envvar); */                /* 97/May/10 */
2302         if (searchpath == NULL) {                               /* 1996/July/30 */
2303                 *pathname = '\0';                                       /* failed env var lookup */
2304                 return;
2305         }                                                                               /* new sanity check */
2306 #ifdef SUBDIRSEARCH
2307         if (searchalongpath(mapname, searchpath, pathname, 0) != 0)
2308                 *pathname = '\0';
2309         else foundfile = 1;                                             /* 1994/Aug/18 */
2310 #else
2311         for (;;) {
2312                 if ((searchpath = nextpathname(pathname, searchpath)) == NULL) {
2313 /*                      foundfile = 0; */
2314                         break;
2315                 }
2316                 s = pathname + strlen(pathname) - 1;
2317                 if (*s != '\\' && *s != '/') strcat(pathname, "\\"); 
2318                 strcat(pathname, mapname);
2319                 if ((input = fopen(pathname, "r")) != NULL) {
2320                         foundfile = 1;
2321                         fclose (input);
2322                         break;
2323                 }
2324         }
2325 #endif
2326 }
2327
2328 /* Returns NULL if it failed for some reason */
2329
2330 /* map_type map_create (char *envvar) { */              /* 94/May/23 */
2331 map_type map_create (char *texfonts) {                  /* 97/May/10 */
2332         char pathname[_MAX_PATH];
2333         map_type map;
2334       
2335 #ifdef DEBUGALIAS
2336         if (traceflag) showline("Creating alias table\n", 0);
2337 #endif
2338 /*      oursearchenv ("texfonts.map", envvar, pathname); */
2339         oursearchenv ("texfonts.map", texfonts, pathname);
2340         if (*pathname == '\0') {
2341 #ifdef DEBUGALIAS
2342                 if (traceflag) {
2343                         sprintf(logline, "Could not find %s in\n", "texfonts.map", texfonts);
2344                         showline(logline, 0);
2345                 }
2346 #endif
2347                 return NULL;
2348         }
2349
2350         map = (map_type) xcalloc (MAP_SIZE, sizeof(map_element_type *));
2351         map_file_parse (map, pathname);
2352 #ifdef DEBUGALIAS
2353         if (traceflag) map_show(map);
2354 #endif
2355         return map;
2356 }
2357
2358 /* ************************************************************************* */
2359
2360 /*      if we didn't find the font, maybe its alias to be found in texfonts.map */
2361
2362 map_type fontmap = NULL;                        /* static - keep around once set */
2363
2364 /*      returns NULL if failed to find an alias */
2365
2366 char *alias (char *name) {  
2367 /*      static map_type fontmap = NULL; */      /* static - keep around once set */
2368         char *mapped_name;
2369       
2370         if (usefontmap == 0) return NULL;       /* failed to find it before */
2371 /*      Now fault in the mapping if necessary.  */
2372         if (fontmap == NULL) {
2373 /*              fontmap = map_create ("TEXFONTS"); */
2374                 fontmap = map_create (texfonts);                /* 97/May/10 */
2375                 if (fontmap == NULL) {          /* check if it worked */
2376                         usefontmap = 0;                 /* don't try this again */
2377                         return NULL;
2378                 }
2379         }
2380       
2381 /*      Now look for our filename in the mapping.  */
2382         mapped_name = map_lookup(fontmap, name);
2383         return mapped_name;                                             /* possibly NULL */
2384 }
2385
2386 /* ************************************************************** */
2387
2388 #endif
2389
2390 /***************************************************************************/
2391
2392 #ifndef SUBDIRSEARCH
2393
2394 /* Moved from DVIPSONE.C since DVIPSLOG.C module is much smaller */
2395
2396 /* Extract next pathname from a searchpath - and write into pathname */
2397 /* return NULL if there are no more pathnames, */
2398 /* otherwise returns pointer to NEXT pathname in searchpath */
2399 /* searchpath = pathname1;pathname2; ... ;pathnamen */
2400
2401 /* used for pfb search path and eps search path */
2402 /* this version also allows space as separator */
2403
2404 char *nextpathname(char *pathname, char *searchpath) {
2405         int n;
2406         char *s;
2407
2408         if (*searchpath == '\0') return NULL;   /* nothing left */
2409         else if (((s = strchr(searchpath, ';')) != NULL) ||
2410                      ((s = strchr(searchpath, ' ')) != NULL)) {
2411                 n = (s - searchpath);
2412                 if (n >= MAXPATHLEN) {
2413                         sprintf(logline, " Path too long %s\n", searchpath);
2414                         showline(logline, 1);
2415                         return NULL;
2416                 }
2417                 strncpy(pathname, searchpath, (unsigned int) n);
2418                 *(pathname + n) = '\0';                         /* terminate it */
2419                 return(s + 1);                                          /* next pathname or NULL */
2420         }
2421         else {
2422                 n = (int) strlen(searchpath);
2423                 if (n >= MAXPATHLEN) {
2424                         sprintf(logline, " Path too long %s\n", searchpath);
2425                         showline(logline, 1);
2426                         return NULL;
2427                 }
2428                 strcpy(pathname, searchpath);
2429                 return(searchpath + n);
2430         }
2431 }
2432
2433 #endif
2434
2435 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2436
2437 /* struct _find_t {
2438     char reserved[21];
2439     char attrib;
2440     unsigned wr_time;
2441     unsigned wr_date;
2442     long size;
2443     char name[13];
2444     }; */ /* 16 bit world --- in dos.h */
2445
2446 /* struct _finddata_t {
2447     unsigned    attrib;
2448     time_t      time_create;    -1 for FAT file systems 
2449     time_t      time_access;    -1 for FAT file systems 
2450     time_t      time_write;
2451     _fsize_t    size;
2452     char        name[260];
2453 }; */ /* 32 bit world --- in io.h */
2454
2455 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2456
2457 #ifdef SUBDIRSEARCH
2458
2459 /* Code to implement (possibly recursive) sub-directory search 94/Aug/18 */
2460
2461 #define ACCESSCODE 4
2462
2463 #define SEPARATOR "\\"
2464
2465 /* This is the (possibly recursive) sub-directory searching code */
2466
2467 /* We come in here with the directory name in pathname */
2468 /* Which is also where we plan to return the result when we are done */
2469 /* We search in this directory first, */
2470 /* and we search one level subdirectories (if it ended in \), */
2471 /* or recursively if the flag is set (when it ends in \\). */
2472 /* File name searched for is in filename */
2473 /* Returns zero if successful --- return non-zero if not found */
2474
2475 /*  struct _finddata_t c_file; */
2476 /*  _finddata_t structure *can* be reused, unlike _find_t 95/Jan/31 */
2477 /*  so save on stack space, by having one copy, not one per expand_subdir */
2478 /*  possibly allocate this in the caller of findsubpath ? not static ? */
2479
2480 int findsubpath (char *filename, char *pathname, int recurse) {
2481         char *s;
2482         int code;
2483         int ret;
2484 /*      struct _finddata_t c_file; */   
2485         static struct _finddata_t c_file;       /* structure can be reused (?) */
2486         long hFind;
2487 #endif
2488
2489         s = pathname + strlen(pathname);        /* remember the end of the dirpath */
2490         if (traceflag) {
2491                 sprintf(logline, " Entering findsubpath: %s %s %d\n",
2492                                 filename, pathname, recurse);
2493                 showline(logline, 0);
2494         }
2495
2496 /*      First try directly in this directory (may want this conditional) */
2497         strcat (pathname, SEPARATOR);           /* \ or / */
2498         strcat (pathname, filename);
2499
2500 /*      Try for match in this directory first - precedence over files in subdirs */
2501 /*      if (_access(pathname, ACCESSCODE) == 0) */              /* check for read access */
2502         code = _access(pathname, ACCESSCODE);
2503         if (code == 0) {
2504                 if (traceflag) {
2505                         sprintf(logline, " SUCCESS: %s\n", pathname);
2506                         showline(logline, 0);
2507                 }
2508                 return 0;                                               /* success */
2509         }
2510         if (traceflag) {                                        /* debugging */
2511 /*              code = _access(pathname, ACCESSCODE); */
2512                 sprintf(logline, " File %s Access %d\n", pathname, code);
2513                 showline(logline, 0);
2514         }
2515
2516         *s = '\0';                                              /* strip off the filename again */
2517 /*      no luck, so try and find subdirectories */
2518         strcat (pathname, SEPARATOR);   /* \ or / */
2519         strcat (pathname, "*.*");
2520 /*      if (_dos_findfirst (pathname, _A_NORMAL | _A_SUBDIR, &c_file) != 0) { */
2521 /*      if (_dos_findfirst (pathname,
2522                 _A_NORMAL | _A_SUBDIR | _A_RDONLY, &c_file) != 0)  */
2523         hFind = _findfirst (pathname, &c_file);
2524         if (hFind > 0)  ret = 0;                /* found something */
2525         else ret = -1;                                  /* did not find path ? */
2526 /*      ret = _dos_findfirst (pathname, _A_NORMAL | _A_SUBDIR | _A_RDONLY, &c_file); */
2527
2528         if (ret) {                                              /* nothing found ? */
2529                 if (badpathwarn++ == 0) {
2530                         sprintf(logline, "WARNING: bad path `%s' for `%s':\n", pathname, filename);
2531                         showline(logline, 1);
2532                         perrormod(filename);            /* debugging only ? bad path given */
2533                 }
2534                 return -1;                                      /* failure */
2535         }
2536         *s = '\0';                                              /* strip off the \*.* again */
2537 /*      Step through sub-directories */
2538         for (;;) {
2539 /*              Ignore all but sub-directories here - also ignore . and .. */
2540                 if ((c_file.attrib & _A_SUBDIR) == 0 || *c_file.name == '.') {
2541 /*                      if (_dos_findnext (&c_file) != 0) break; */
2542                         ret = _findnext (hFind, &c_file);       /* success == TRUE ??? */
2543 /*                      need to flip polarity of ret ? apparently not ... */
2544 /*                      ret = _dos_findnext (&c_file);  */      /* success == 0 */
2545
2546                         if (ret != 0) break;    /* give up, found nothing more */
2547                         continue;                               /* did find something else, go on */
2548                 }
2549 /*              extend pathname with subdir name */
2550                 strcat(pathname, SEPARATOR);
2551                 strcat(pathname, c_file.name);
2552                 if (traceflag) {
2553                         sprintf(logline, " Checking subdir: %s\n", pathname);
2554                         showline(logline, 0);
2555                 }
2556 /*              OK, now try for match in this directory */
2557                 if (recurse) {                                                  /* recursive version */
2558                         if (findsubpath(filename, pathname, recurse) == 0) {
2559                                 _findclose(hFind);
2560                                 hFind = 0;
2561                                 return 0;                                               /* succeeded */
2562                         }
2563                 }
2564                 else {                                                                  /* not recursive */
2565                         strcat (pathname, SEPARATOR);
2566                         strcat (pathname, filename);
2567                         if (traceflag) {
2568                                 sprintf(logline, " Checking file: %s\n", pathname);
2569                                 showline(logline, 0);
2570                         }
2571 /*                      if (_access(pathname, ACCESSCODE) == 0)   */
2572                         code = _access(pathname, ACCESSCODE);   /* check read access */
2573                         if (code == 0) { 
2574                                 if (traceflag) {
2575                                         sprintf(logline, " SUCCESS: %s\n", pathname);
2576                                         showline(logline, 0);
2577                                 }
2578                                 _findclose(hFind);
2579                                 hFind = 0;
2580                                 return 0;                                               /* success */
2581                         }
2582                         if (traceflag) {                                                        /* debugging */
2583 /*                              code = _access(pathname, ACCESSCODE); */
2584                                 sprintf(logline, " File %s Access %d\n", pathname, code);
2585                                 showline(logline, 0);
2586                         }
2587                 }
2588
2589 /*              No match in this directory, so continue */
2590                 *s = '\0';
2591                 if (traceflag) {
2592                         sprintf(logline, "Ready for dos_findnext: %s %s %d\n",
2593                                         filename, pathname, recurse);
2594                         showline(logline, 0);
2595                 }
2596 /*              if (_dos_findnext (&c_file) != 0) break; */
2597                 ret = _findnext (hFind, &c_file);               /* success == TRUE ??? */
2598 /*              need to flip polarity of ret ? apparently not ... */
2599 /*              ret = _dos_findnext (&c_file); */                       /* success == 0 */
2600
2601                 if (ret != 0) break;                                    /* found no more */
2602         }       /* end of for{;;} loop */
2603         if (hFind > 0) {
2604                 _findclose (hFind);
2605                 hFind = 0;
2606         }
2607         return -1;                                                                      /* failed */
2608 }
2609
2610 /* Our searchalongpath is (somewhat) analogous to DOS _searchenv */
2611 /* The name of the desired file is given in `filename' */
2612 /* The list of paths is given in `pathlist' */
2613 /* searchalongpath returns the full pathname of first match in `pathname' */
2614 /* (make sure there is enough space there!) */
2615 /* If the file is not found, then pathname contains "" */
2616 /* and it also returns non-zero if it fails. */
2617 /* It first searches in the current directory if currentflag > 0 */
2618 /* It also searches PFM subdirectories if currentflag < 0 97/June/1 */
2619 /* If a path in `pathlist' ends in \, then its sub-directories are searched, */
2620 /* (after the specified directory) */
2621 /* If a path in `pathlist' ends in \\, then this works recursively */
2622 /* (which may be slow and cause stack overflows ...) */
2623
2624 int searchalongpath (char *filename, char *pathlist, char *pathname, int current) {
2625 /*      struct _find_t c_file; *                        /* need to preserve across calls to DOS */
2626         char *s, *t, *u, *send;
2627         int c, n;
2628         int recurse;
2629 #ifdef DEBUGSEARCHPATH
2630         int code;
2631 #endif
2632         
2633         if (current > 0) {      /*      Try for exact match in current directory first ? */
2634                 strcpy(pathname, filename);
2635                 if (_access(pathname, ACCESSCODE) == 0) {       /* check for read access */
2636                         if (traceflag) {
2637                                 sprintf(logline, " File %s SUCCESS\n", pathname);
2638                                 showline(logline, 0);
2639                         }
2640                         return 0;                                                       /* success */
2641                 }
2642 #ifdef DEBUGSEARCHPATH
2643                 if (traceflag) {                                                        /* debugging */
2644                         code = _access(pathname, ACCESSCODE);
2645                         sprintf(logline, " File %s Access %d\n",
2646                                 pathname, _access(pathname, ACCESSCODE));
2647                         showline(logline, 0);
2648                 }
2649 #endif
2650         }
2651
2652 /*      Now step through paths in pathlist */
2653         s = pathlist;
2654         for (;;) {
2655                 if (*s == '\0') break;                          /* sanity check */
2656                 if ((t = strchr(s, ';')) == NULL)
2657                         t = s + strlen(s);                              /* if last path */
2658                 n = t - s;
2659                 strncpy(pathname, s, n);
2660                 u = pathname + n;
2661                 *u-- = '\0';                                            /* null terminate */
2662                 c = *u;                                                         /* check whether ends on \ */
2663                 if (c == '\\' || c == '/') {            /* yes it does -> subdir search */
2664                         *u-- = '\0';                                    /* remove it */
2665                         c = *u;                                                 /* check whether ends on \\ */
2666                         if (c == '\\' || c == '/') {    /* yes it does */
2667                                 *u-- = '\0';                            /* remove it */
2668                                 recurse = 1;                            /* recursive subdir search */
2669                         }
2670                         else recurse = 0;
2671                         if (traceflag) {
2672                                 sprintf(logline, " Trying subdir: %s\n", pathname);
2673                                 showline(logline, 0);
2674                         }
2675                         if (findsubpath (filename, pathname, recurse) == 0)
2676                                 return 0;       /* success */
2677                 }
2678                 else {                                                                  /* its just a directory */
2679                         send = pathname + strlen(pathname);     /* remember end for below */
2680                         strcat (pathname, SEPARATOR);           /* \ or / */
2681                         strcat (pathname, filename);
2682                         if (_access (pathname, ACCESSCODE) == 0) {
2683                                 if (traceflag) {
2684                                         sprintf(logline, " File %s SUCCESS\n", pathname);
2685                                         showline(logline, 0);
2686                                 }
2687                                 return 0;                                               /* success */
2688                         }
2689 #ifdef DEBUGSEARCHPATH
2690                         if (traceflag) {                                        /* debugging */
2691                                 code = _access(pathname, ACCESSCODE);
2692                                 sprintf(logline, " File %s Access %d\n",
2693                                         pathname, _access(pathname, ACCESSCODE));
2694                                 showline(logline, 0);
2695                         }
2696 #endif
2697                         if (current < 0) {      /* try in PFM sub-directory also 97/June/1 */
2698                                 *send = '\0';                                   /* snip off file name again */
2699                                 strcat (pathname, SEPARATOR);           /* \ or / */
2700                                 strcat (pathname, "PFM");                       /* splice in PFM */
2701                                 strcat (pathname, SEPARATOR);           /* \ or / */
2702                                 strcat (pathname, filename);
2703                                 if (_access (pathname, ACCESSCODE) == 0) {
2704                                         if (traceflag) {
2705                                                 sprintf(logline, " File %s SUCCESS\n", pathname);
2706                                                 showline(logline, 0);
2707                                         }
2708                                         return 0;                                               /* success */
2709                                 }
2710 #ifdef DEBUGSEARCHPATH
2711                                 if (traceflag) {                                        /* debugging */
2712                                         code = _access(pathname, ACCESSCODE);
2713                                         sprintf(logline, " File %s Access %d\n",
2714                                                    pathname, _access(pathname, ACCESSCODE));
2715                                         showline(logline, 0);
2716                                 }
2717 #endif
2718                         }
2719                 }
2720
2721                 s = t;                                          /* move on to next item in list */
2722                 if (*s == ';') s++;                     /* step over separator */
2723                 else break;                                     /* we ran off the end */
2724         }
2725         strcpy(pathname, "");                   /* failed to find it */
2726         return -1;
2727 }
2728
2729 /*      search for file in path list and open it if found */
2730 /*      return full path name in third arg unless third arg is NULL */
2731 /*      if third arg is NULL, a local temporary place is used for the name */
2732 /*      if current > 0, look in current directory first */
2733 /*      if current < 0, look in PFM sub directories also */
2734 //      only place we use _alloca ...
2735
2736 FILE *findandopen (char *filename, char *pathlist, char *pathname,
2737                 char *mode, int current) {
2738         FILE *file;
2739
2740         if (pathname == NULL) {
2741                 pathname = (char *) _alloca (FNAMELEN);
2742                 if (pathname == NULL) checkexit(1);
2743         }
2744         if (searchalongpath(filename, pathlist, pathname, current) == 0) {
2745                 file = fopen(pathname, mode);
2746                 return file;
2747         }
2748         else return NULL;
2749 }
2750
2751 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2752
2753 /* dviextra.c(5813) : fatal error C1001: internal compiler error */
2754 /*              (compiler file 'msc2.cpp', line 1011) */
2755
2756 /* dvipslog.c(2008) : fatal error C1001: internal compiler error
2757                 (compiler file 'msc2.cpp', line 1011) */
2758
2759 /* stuff for reading .afm files */
2760
2761 int readafm(char *font, FILE *fp_afm, long widths[]) {
2762         double fwidth;
2763         int chr, k=0;
2764
2765 /*      if (fp_afm == NULL) checkexit(5);        */
2766         (void) getrealline(fp_afm, line);
2767
2768         while (strstr(line, "StartCharMetrics") == NULL)  {
2769                 if(getrealline(fp_afm, line) == 0) {
2770                         sprintf(logline, 
2771                                 " Can't find CharMetrics in AFM file for %s\n", font);
2772                         showline(logline, 1);
2773                         errcount(0);
2774                         return 0;
2775                 }
2776
2777 /* could extract UniqueID, BBox and FontInfo stuff at this point */
2778         }
2779         (void) getrealline(fp_afm, line);
2780         while(strstr(line, "EndCharMetrics") == NULL) {
2781                 if(strstr(line, "EndCharMetrics") != NULL) break;
2782                 if (sscanf(line," C %d ; WX %lg", &chr, &fwidth) < 2) {
2783                         sprintf(logline, 
2784                                 " Parse error in line from AFM file for %s: %s", 
2785                                         font, line);
2786                         showline(logline, 1);
2787                         errcount(0);
2788                         return 0;
2789                 }
2790                 if (chr >= 0 && chr < MAXCHRS) {
2791                         if (chr > k) k = chr;
2792                         widths[chr] = (long) ((fwidth/1000.0) * 1048576.0 + 0.5);
2793                 }
2794                 (void) getrealline(fp_afm, line);
2795         }
2796         return k;
2797 }
2798
2799 /* moved here from dviextra.c */
2800
2801 /* stuff for reading .tfm files */ /* OK for new form TFM files ? OK */
2802
2803 /* lf, lh, nw, nh, nd, ni, nl, nk, ne are numbers of words */
2804
2805 int readtfm(char *font, FILE *fp_tfm, long widths[]) {
2806         static long qwidths[MAXCHRS];  /* 256 */
2807         int lf, lh, bc, ec, nw, nh, nd, ni, nl, nk, ne, np;
2808         int k;
2809         int wdinx;
2810 /*      int chksum, dsgnsize;           */
2811 /*      int hdinx, itinx, rdinx;        */
2812
2813 /*      if (fp_tfm == NULL) checkexit(5);        */
2814         lf = sreadtwo(fp_tfm);  lh = sreadtwo(fp_tfm);
2815         bc = sreadtwo(fp_tfm);  ec = sreadtwo(fp_tfm);
2816         nw = sreadtwo(fp_tfm);  nh = sreadtwo(fp_tfm);
2817         nd = sreadtwo(fp_tfm);  ni = sreadtwo(fp_tfm);
2818         nl = sreadtwo(fp_tfm);  nk = sreadtwo(fp_tfm);
2819         ne = sreadtwo(fp_tfm);  np = sreadtwo(fp_tfm);
2820 /* first try and make sure this is a TFM file ! */
2821         if (lf < 0 || lh < 0 || nw < 0 || nw > 255 || 
2822                 bc < 0 || ec < 0 || ec > 255 || bc > ec + 1 || 
2823                 lf != 6 + lh + (ec - bc + 1) + nw + nh + nd + ni + nl + nk + ne + np)
2824                 {
2825                 sprintf(logline, " BAD TFM file for %s", font);
2826                 showline(logline, 1);
2827                 showline("\n", 0);
2828 /*              sprintf(logline, "Header: %d %d %d %d %d %d %d %d %d %d %d %d\n",
2829                         lf, lh, bc, ec, nw, nh, nd, ni, nl, nk, ne, np);
2830                 showline(logline, 1); */
2831                 errcount(0);
2832                 return 0;
2833         }
2834 /* now for the header */
2835 /*      chksum = sreadtwo(fp_tfm); */           /* should we bother to verify ? */
2836         (void) sreadtwo(fp_tfm);                /* check sum */
2837 /*      dsgnsize = sreadtwo(fp_tfm);    */
2838         (void) sreadtwo(fp_tfm);        /* design size */
2839 /* discard rest of header */
2840         for (k = 2; k < lh; k++) {      
2841                 (void) getc(fp_tfm); (void) getc(fp_tfm);       
2842         }
2843 /* now read the actual widths */
2844         fseek(fp_tfm, (long) ((6 + lh + (ec - bc + 1)) << 2), SEEK_SET);
2845         for (k = 0; k < nw; k++) {
2846                 qwidths[k] = sreadfour(fp_tfm);
2847 /* character width in design size units * 2^20 */
2848         }
2849         if (qwidths[0] != 0) {  /* qwidths[0] is supposed to be zero */
2850                 sprintf(logline, " BAD TFM file for %s", font);
2851                 showline(logline, 1);
2852                 showline("- ", 0);
2853                 showline("width[0] not zero", 0); /* qwidths[0] */
2854                 errcount(0);
2855                 return 0;
2856         }
2857 /* now go back and read character information */
2858         fseek(fp_tfm, (long) ((6 + lh) << 2), SEEK_SET);
2859         for (k = bc; k <= ec; k++) {
2860                 wdinx = getc(fp_tfm); 
2861                 (void) getc(fp_tfm);    /*              hdinx = getc(fp_tfm);  */
2862                 (void) getc(fp_tfm);    /*              itinx = getc(fp_tfm);  */
2863                 (void) getc(fp_tfm);    /*              rdinx = getc(fp_tfm);  */
2864                 if (wdinx >= nw) {
2865                         sprintf(logline, " BAD TFM file for %s", font);
2866                         showline(logline, 1);
2867                         showline(" - ", 0);
2868                         sprintf(logline, "width index %d (char %d) > width table %d",
2869                                 wdinx, k, nw);
2870                         showline(logline, 0);
2871                         errcount(0);
2872                         return 0;
2873                 }
2874                 widths[k] = qwidths[wdinx];
2875         }
2876         return (int) (ec + 1);
2877 }
2878
2879 /* stuff for reading widths from .pfm files */
2880
2881 int readpfm(char *font, FILE *fp_pfm, long widths[]) {
2882         unsigned long length, offset;
2883 /*      double fwidth; */
2884         long lwidth;
2885         int bc, ec, c, k, n;
2886
2887 /*      if (fp_pfm == NULL) checkexit(5);         */
2888 /* first check that this is a PFM file - start with version number */
2889         if ((c = getc(fp_pfm)) != 0 || (c = getc(fp_pfm)) != 1) {
2890                 sprintf(logline, " Not a proper PFM file %s\n", font);
2891                 showline(logline, 1);
2892                 errcount(0);
2893                 return 0;
2894         }
2895         length = 0L;            /* read length of PFM file  */
2896         for (k = 0; k < 4; k++)                                 /* from byte 2 to byte 6 */
2897                 length = length | (getc(fp_pfm) << (k * 8));
2898         for (k = 6; k < 66; k++) (void) getc(fp_pfm); /* ignore copyright */    
2899         for (k = 66; k < 95; k++) (void) getc(fp_pfm); /* ignore assorted */    
2900         bc = getc(fp_pfm); ec = getc(fp_pfm);  /* first and last character */
2901         for (k = 97; k < 117; k++) (void) getc(fp_pfm); /* skip to end header */
2902         for (k = 117; k < 119; k++) (void) getc(fp_pfm);  /* size PFMEXTENSION */
2903         for (k = 119; k < 123; k++) (void) getc(fp_pfm);  /* ptr EXTEXTMETRICS */
2904         offset = 0L;                                               /* offset of charwidth table */
2905         for (k = 0; k < 4; k++) offset = offset | (getc(fp_pfm) << (k * 8));
2906         if (offset > 8192) {
2907                 sprintf(logline, " Offset too long in %s\n", font);
2908                 showline(logline, 1);
2909                 errcount(0);
2910                 return 0;
2911         }
2912         n = (int) offset;
2913         for (k = 127; k < n; k++) c = getc(fp_pfm);
2914         if (c == EOF) {
2915                 showline(" Premature EOF", 1);
2916                 sprintf(logline, " in PFM file %s\n", font);
2917                 showline(logline, 0);
2918                 errcount(0);
2919                 return 0;
2920         }
2921         for (k = bc; k <= ec; k++) {
2922 /*              fwidths = (double) (getc(fp_pfm) | (getc(fp_pfm) << 8));
2923                 widths[k] = (long) ((fwidth/1000.0) * 1048576.0 + 0.5); */
2924                 lwidth = (long) (getc(fp_pfm) | (getc(fp_pfm) << 8));
2925 /*              widths[k] = (long) (((lwidth << 20) + 500) / 1000);  */
2926                 widths[k] = (long) (((lwidth << 17) + 62) / 125);  
2927 /*              if (lwidth != 0) showline(logline, "w[%d] %ld ", k, lwidth); */
2928 /*              if (widths[k] != 0) showline(logline, " %ld ", k, widths[k]); */
2929         }
2930         if (traceflag) {
2931                 sprintf(logline, "bc = %d ec = %d ", bc, ec);
2932                 showline(logline, 0);
2933         }
2934         return ec;
2935 }
2936
2937 #define DEBUGMMPFM
2938
2939 /* check PFM file for MM instance and extract PostScript FontName */
2940 /* WARNING: this writes back into second argument ! */
2941 /* make sure FontName has enough space for FontName ( > 32 ) 97/June/1 */
2942 /* In typical use, FaceName == NULL and nface == 0 */
2943 /* return 0 if fails in some way */
2944
2945 /* int pfminstance (FILE *input, char *FontName, int nlen) { */
2946 int NamesFromPFM (FILE *input, char *FaceName, int nface,
2947                                   char *FontName, int nfont, char *FileName) {
2948         short version;
2949         long length, offset;
2950         int n, ndrive;
2951         char DriverType[16];    /* space for "PostScript" */
2952         char *s;
2953         
2954 //      if (traceflag) {
2955 //              sprintf(logline, " NamesFromPFM nface %d nfont %d\n", nface, nfont);
2956 //              showline(logline, 0);                   // debugging only
2957 //      }
2958
2959 #ifdef DEBUGMMPFM
2960         if (traceflag)  {
2961                 sprintf(logline, " Read `%s' for MM instance info\n", FileName); /* debugging */
2962                 showline(logline, 0);
2963         }
2964 #endif
2965         fread(&version, sizeof(version), 1, input);
2966         if (version != 256) {
2967 #ifdef DEBUGMMPFM
2968                 sprintf(logline, " Bad version code (%d) in PFM %s ", version, FileName);
2969                 showline(logline, 1);
2970 #endif
2971                 return 0;                               /* not PFM file */
2972         }
2973         fread(&length, sizeof(length), 1, input);
2974         if (fseek(input, 101, SEEK_SET) != 0) {
2975 #ifdef DEBUGMMPFM
2976                 sprintf(logline, " Seek to %ld failed in PFM %s ", 101L, FileName);
2977                 showline(logline, 1);
2978 #endif
2979                 return 0;
2980         }
2981         fread(&offset, sizeof(offset), 1, input);       /* offset to Driver Type */
2982         if (offset >= length || offset == 0) {
2983 #ifdef DEBUGMMPFM
2984                 sprintf(logline, " Bad offset %ld (%d) in PFM %s ", offset, length, FileName);
2985                 showline(logline, 1);
2986 #endif
2987                 return 0;       /* not PFM file */
2988         }
2989         if (fseek(input, offset, SEEK_SET) != 0) {
2990 #ifdef DEBUGMMPFM
2991                 sprintf(logline, " Seek to %ld failed in PFM %s ", offset, FileName);
2992                 showline(logline, 1);
2993 #endif
2994                 return 0;
2995         }
2996         ndrive = sizeof(DriverType);
2997         s = DriverType;                                                         /* temporary space */
2998         n = 0;
2999         while ((*s++ = (char) getc(input)) != '\0') { 
3000                 if (n++ >= ndrive) {
3001 #ifdef DEBUGMMPFM
3002                         sprintf(logline, " %s too long >= %ld in %s ", "DriverType", ndrive, FileName);
3003                         showline(logline, 1);
3004 #endif
3005                         return 0;
3006                 }
3007         }
3008         *s = '\0';                                                                      /* terminate */
3009         if (strcmp(DriverType, "PostScript") != 0) {
3010 #ifdef DEBUGMMPFM
3011                 sprintf(logline, " Driver not %s in %s ", "PostScript", FileName);
3012                 showline(logline, 1);
3013
3014 #endif
3015                 return 0;       /* Not PS font */
3016         }
3017         if (fseek(input, 105, SEEK_SET) != 0) {
3018 #ifdef DEBUGMMPFM
3019                 sprintf(logline, " Seek to %ld failed in PFM %s ", 105L, FileName);
3020                 showline(logline, 1);
3021 #endif
3022                 return 0;
3023         }
3024         fread(&offset, sizeof(offset), 1, input);       /* offset Windows Face Name */
3025         if (offset >= length || offset == 0) {
3026 #ifdef DEBUGMMPFM
3027                 sprintf(logline, " Bad offset %ld (%ld) in PFM %s ", offset, length, FileName);
3028                 showline(logline, 1);
3029 #endif
3030                 return 0;       /* not PFM file */
3031         }
3032         if (fseek(input, offset, SEEK_SET) != 0) {
3033 #ifdef DEBUGMMPFM
3034                 sprintf(logline, " Seek to %ld failed in PFM %s ", offset, FileName);           
3035                 showline(logline, 1);
3036 #endif
3037                 return 0;
3038         }
3039         if (FaceName != NULL) {
3040                 s = FaceName;
3041                 n = 0;
3042                 while ((*s++ = (char) getc(input)) != '\0')
3043                         if (n++ >= nface) {
3044 #ifdef DEBUGMMPFM
3045                         sprintf(logline, " %s too long >= %ld in %s ", "FaceName", nface, FileName);
3046                         showline(logline, 1);
3047 #endif
3048                         return 0;
3049                 }
3050                 *s = '\0';              /* terminate */
3051                 if (strchr(FaceName, ' ') == NULL) {
3052 #ifdef DEBUGMMPFM
3053                         sprintf(logline, " Not MM %s %s? ", "FaceName", FaceName);
3054                         showline(logline, 1);
3055 #endif
3056 /*                      return 0; */    /* not MM instance */
3057                 }
3058         }
3059         if (fseek(input, 139, SEEK_SET) != 0) {
3060 #ifdef DEBUGMMPFM
3061                 sprintf(logline, " Seek to %ld failed in PFM ", 139L);
3062                 showline(logline, 1);
3063 #endif
3064                 return 0;
3065         }
3066         fread(&offset, sizeof(offset), 1, input);       /* offset to PS FontName */
3067         if (offset >= length || offset == 0) {
3068 #ifdef DEBUGMMPFM
3069                 sprintf(logline, " Bad offset %ld (%ld) in PFM ", offset, length);
3070                 showline(logline, 1);
3071 #endif
3072                 return 0;       /* not PFM file */
3073         }
3074         if (fseek(input, offset, SEEK_SET) != 0) {
3075 #ifdef DEBUGMMPFM
3076                 sprintf(logline, " Seek to %ld failed in PFM ", offset);
3077                 showline(logline, 1);
3078 #endif
3079                 return 0;
3080         }
3081
3082 /*      write name back into second argument */
3083         if (FontName != NULL) {
3084                 s = FontName;
3085                 n = 0;
3086                 while ((*s++ = (char) getc(input)) != '\0')
3087                         if (n++ >= nfont) {
3088 #ifdef DEBUGMMPFM
3089                         sprintf(logline, " %s too long >= %ld in %s ", "FontName", nfont, FileName);
3090                         showline(logline, 1);
3091 #endif
3092                         return 0;
3093                 }
3094                 *s = '\0';              /* terminate */
3095 /*              We assume FontName for MM instance must have underscores */
3096                 if (strchr(FontName, '_') == NULL) {
3097 #ifdef DEBUGMMPFM
3098                         sprintf(logline, " Not MM %s %s? ", "FontName", FontName);
3099                         showline(logline, 1);
3100 #endif
3101                         /* return 0; */ /* not MM instance */
3102                 }
3103 #ifdef DEBUGMMPFM
3104                 if (traceflag) {
3105                         sprintf(logline, " FontName from PFM: %s\n", FontName);/* debugging output */
3106                         showline(logline, 0);
3107                 }
3108 #endif
3109         }
3110         return 1;       /* OK, FaceName and FontName returned */
3111 }
3112
3113 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
3114
3115 /* stuff for reading ATMREG.ATM imported from winpslog.c 98/Jan/9 */
3116
3117 unsigned int xreadtwo (FILE *input) {
3118         unsigned int c, d, n;
3119         c = getc(input);
3120         d = getc(input);
3121         n = (d << 8) | c; 
3122         return n;
3123 }
3124
3125 unsigned long xreadfour (FILE *input) {
3126         unsigned int a, b, c, d;
3127         unsigned long n;
3128         a = getc(input);
3129         b = getc(input);
3130         c = getc(input);
3131         d = getc(input);
3132         n = (d << 8) | c;
3133         n = (n << 16) | (b << 8) | a;
3134         return n;
3135 }
3136
3137 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
3138
3139 int bATM41=0;                   // needs to be set based on ATMREG.ATM header
3140
3141 /* read string from ATMREG.ATM up to null, string may be empty */
3142 /* returns -1 if hit EOF or name too long */
3143
3144 int ReadString (FILE *input, char *name, int nlen) {
3145         int c;
3146         int n=0;
3147         char *s=name;
3148
3149         *s = '\0';                              /* in case we pop out early */
3150         for (;;) {                              /* read string up to null */
3151                 c = getc(input);
3152                 if (bATM41)                             // 2000 July 3 ATM 4.1 ???
3153                         (void) getc(input);     // discard second byte of UNICODE
3154                 if (c == EOF) {         /* EOF */
3155                         *s++ = '\0';
3156                         return -1;
3157                 }
3158                 *s++ = (char) c;
3159                 if (c == 0) break;
3160                 n++;
3161                 if (n >= nlen) {        /* too long */
3162                         sprintf(logline, " String in ATMREG.ATM too long %d (> %d)\n", n, nlen);
3163                         showline(logline, 1);
3164                         *name = '\0';   /* flush the name */
3165                     return -1;
3166                 }
3167         }
3168         return 0;
3169 }
3170
3171 #define LF_FACENAME 32
3172 #define LF_FULLFACENAME 64
3173
3174 /* #define PFMName 16 */                /* >= 8+1+3+1 */
3175 /* #define PFBName 16 */                /* >= 8+1+3+1 */
3176
3177 /**************************************************************************/
3178
3179 /* New code for using ATMREG.ATM */
3180
3181 unsigned long startfontlist, endfontlist;
3182 unsigned long startdirlist, enddirlist;
3183 unsigned long startsetlist, endsetlist;
3184 int nDirs, nFonts, nSets;
3185
3186 typedef struct ATMRegRec {
3187         unsigned char nMMM;             // directory path index for MMMName
3188         unsigned char nPFB;             // directory path index for PFBName
3189         unsigned char nPFM;             // directory path index for PFMName
3190         unsigned char MMMflag;  // 0 => TTF, 1 => T1, 2 => MM Master, 4 => MM Instance
3191         char *FontName;                 // PostScript FontName
3192         char *MMMName;                  // File Name of PFM (T1 or MMM instance), MMM (for MM master)
3193         char *PFBName;                  // File Name of PFB (blank for MM instance)
3194         char *PFMName;                  // File Name of PFM (for MM master), MMM (for MM instance)
3195 };
3196
3197 struct ATMRegRec *ATMFonts=NULL;
3198
3199 int ATMfontindex=0;             // number of font entries
3200
3201 // char *DirPaths[MAXDIRS];
3202
3203 char **DirPaths=NULL;
3204
3205 int dirindex=0;
3206
3207 void FreeDirs (void) {
3208         int k;
3209         if (DirPaths == NULL) return;
3210         for (k = 0; k <= nDirs; k++) {
3211                 if (DirPaths[k] != NULL) free(DirPaths[k]);
3212                 DirPaths[k] = NULL;
3213         }
3214         dirindex=1;
3215         free(DirPaths);
3216         DirPaths = NULL;
3217 }
3218
3219 int AllocDirs (int nDirs) {
3220         int k, nlen;
3221         if (DirPaths != NULL) FreeDirs();
3222         nlen = (nDirs + 1) * sizeof(char *);
3223         DirPaths = (char **) malloc (nlen);
3224         if (DirPaths == NULL) {
3225                 sprintf(logline,"ERROR: unable to allocate %d bytes for %d dir entries\n",
3226                            nlen, nDirs);
3227                 showline(logline, 1);
3228                 return -1;
3229         }
3230         DirPaths[0] = _strdup("");
3231         for (k = 1; k <= nDirs; k++) DirPaths[k] = NULL;
3232         dirindex=1;
3233         return 0;
3234 }
3235
3236 void FreeFonts (void) {
3237         int k;
3238         if (ATMFonts == NULL) return;
3239         for (k = 0; k < ATMfontindex; k++) {
3240                 if (ATMFonts[k].FontName != NULL) free(ATMFonts[k].FontName);
3241                 if (ATMFonts[k].MMMName != NULL) free(ATMFonts[k].MMMName);
3242                 if (ATMFonts[k].PFBName != NULL) free(ATMFonts[k].PFBName);
3243                 if (ATMFonts[k].PFBName != NULL) free(ATMFonts[k].PFMName);
3244         }
3245         free(ATMFonts);
3246         ATMFonts = NULL;
3247 }
3248
3249 int AllocFonts (int nFonts) {
3250         int nlen;
3251         if (ATMFonts != NULL) FreeFonts();
3252         nlen = nFonts * sizeof(struct ATMRegRec);
3253         ATMFonts = (struct ATMRegRec *) malloc (nlen);
3254         if (ATMFonts == NULL) {
3255                 sprintf(logline, " Unable to allocate %d bytes for %d fonts\n",
3256                                 nlen, nFonts);
3257                 showline(logline, 1);
3258 //              checkexit(1);
3259                 return -1;
3260         }
3261 //      sprintf(logline, "Allocated %d bytes for %d fonts\n", nlen, nFonts);    // debugging only
3262 //      showline(logline, 0);
3263         ATMfontindex=0;
3264         return 0;
3265 }
3266
3267 void ShowATMREG (void) {
3268         int k;
3269         char *szType;
3270         sprintf(logline, "ATMREG has %d T1 font entries (out of %d total):\n", ATMfontindex, nFonts);
3271         showline(logline, 0);
3272         for (k = 0; k < ATMfontindex; k++) {
3273                 switch(ATMFonts[k].MMMflag) {
3274                         case 0: szType = "TTF "; break;
3275                         case 1: szType = "T1  "; break;
3276                         case 2: szType = "MMM "; break;
3277                         case 4: szType = "MMI "; break;
3278                         default: szType = "ERR "; break;
3279                 }
3280                 sprintf(logline, "%s Fontname: `%s' MMMName: `%s%s' PFBName: `%s%s' PFMName: `%s%s'\n",
3281                                 szType, ATMFonts[k].FontName,
3282                                 DirPaths[ATMFonts[k].nMMM], ATMFonts[k].MMMName,
3283                                 DirPaths[ATMFonts[k].nPFB], ATMFonts[k].PFBName,
3284                                 DirPaths[ATMFonts[k].nPFM], ATMFonts[k].PFMName);
3285                 showline(logline, 0);
3286         }
3287 }
3288
3289 /**********************************************************************************/
3290
3291 int SetupDirs (FILE *input, unsigned long startdirlist, unsigned long enddirlist) {
3292         int c, k, noff, nlen;
3293         int npath=0;
3294         unsigned long noffset;
3295         char pathname[ _MAX_PATH];
3296         char *s;
3297
3298 /*      if (fseek(input, 24, SEEK_SET) >= 0) noffset = xreadfour(input); */
3299
3300         noffset = startdirlist;                 // 36
3301
3302         for (;;) {
3303                 if (noffset >= enddirlist) break;       /* normal exit from this */
3304                 if (fseek(input, noffset, SEEK_SET) < 0) {
3305                         if (traceflag) {
3306                                 sprintf(logline, " Seek to %ld failed\n", noffset);
3307                                 showline(logline, 0);
3308                         }
3309                         break;  /*                  return -1; */
3310                 }
3311                 noff = xreadtwo(input);
3312                 if (noff != 8) {
3313                         if (traceflag) {
3314                                 sprintf(logline, " noff %lu != 8\n", noff);
3315                                 showline(logline, 0);
3316                         }
3317 /*                      break; */       /* new sanity check */
3318                 }
3319                 nlen = xreadtwo(input);
3320                 if (nlen == 0) {
3321                         if (traceflag) {
3322                                 sprintf(logline, " nlen == 0\n");
3323                                 showline(logline, 0);
3324                         }
3325                         break;          /* sanity check */
3326                 }
3327                 if (nlen > _MAX_PATH) {
3328                         if (traceflag) {
3329                                 sprintf(logline, " nlen > %d\n", _MAX_PATH);
3330                                 showline(logline, 0);
3331                         }
3332                         break;          /* new sanity check */
3333                 }
3334                 noffset = xreadfour(input);
3335                 if (noffset == 0) {
3336                         if (traceflag) {
3337                                 sprintf(logline, " noffset == 0\n");
3338                                 showline(logline, 0);
3339                         }
3340                         break;  /* sanity check */
3341                 }
3342                 s = pathname;
3343                 for (k = 0; k < nlen; k++) {
3344                         c = getc(input);
3345                         if (bATM41) (void) getc(input);
3346                         if (c == EOF) {
3347                                 if (traceflag) {
3348                                         sprintf(logline, " Unexpected EOF (%s)\n", "setupdirs");
3349                                         showline(logline, 0);
3350                                 }
3351                                 return -1;
3352                         }
3353                         *s++ = (char) c;
3354                         if (c == 0) break;
3355                 }
3356                 npath++;
3357 /*              if (noiseflag) printf("%d\t%s\n", npath, pathname); */
3358 //              if (dirindex >= MAXDIRS) {
3359                 if (dirindex > nDirs) {
3360                         if (traceflag) {
3361                                 sprintf(logline, " Too many paths (> %d)\n", nDirs);
3362                                 showline(logline, 0);
3363                         }
3364                         return -1;
3365                 }
3366                 DirPaths[dirindex] = xstrdup(pathname);
3367                 dirindex++;
3368         }
3369         return 0;
3370 }
3371
3372 /* Look for given PS FontName in atmreg.atm and return file name of PFB */
3373 /* returns 0 if found, -1 if not found */
3374
3375 #ifdef IGNORED
3376 int SearchATMReg (FILE *input, unsigned long endfontlist,
3377                                   char *szPSFontName, char *szPFBFileName) {
3378         int c, k;
3379         unsigned int stroffset, nlen;
3380         unsigned long next;
3381         int boldflag, italicflag;               /* style bits */
3382         int ttfflag;
3383 /*      following just used for statistics - could remove to save time */
3384         int psflag, mmmflag, mmiflag, genflag;          /* font type bits */
3385         int nMMM, nPFB, nPFM;                           /* index into dir path table */
3386         unsigned int flag[16];                          /* 16 bytes of flags */
3387         char FaceName[LF_FACENAME+1];           /* Windows Face Name - not used */
3388         char StyleName[LF_FACENAME+1];          /* Style Name for TT font - not used */
3389         char FullName[LF_FULLFACENAME+1];       /* Full Name - not used */
3390         char FontName[LF_FULLFACENAME+1];       /* Font Name - used in comparison (T1 only) */
3391         char MMMName[LF_FACENAME+1];            /* PFM file or TTF file or MMM file */
3392         char PFBName[LF_FACENAME+1];            /* PFB file or PSS file - not used */
3393         char PFMName[LF_FACENAME+1];            /* PFM file of MMM font - not used */
3394 //      char *s;
3395
3396         *szPFBFileName = '\0';
3397         
3398         fseek(input, startfontlist, SEEK_SET);
3399
3400 /*       positioned at start of font list at this point */
3401
3402         for (;;) {
3403                 c = getc(input);                                /* check for end of file 99/Mar/1 */
3404                 if (c == EOF) {
3405                         break;
3406                 }
3407                 ungetc(c, input);
3408                 stroffset = xreadtwo(input);    /* offset to first string == 44 */
3409                 nlen = xreadtwo(input);                 /* length of this record in bytes */
3410                 next = xreadfour(input);                /* pointer to next record */
3411                 for (k = 0; k < (28 - 8); k++) (void) getc(input);
3412                 for (k = 0; k < 16; k++) flag[k] = getc(input);
3413                 boldflag = flag[1];
3414                 if (boldflag == 0 || boldflag > 2) {
3415                         if (boldflag > 2) boldflag = 1; /* pretend it is OK */
3416 /*                      break; */        /* impossible */       /* `fixed' 97/Sep/14 */
3417                 }
3418                 else boldflag = boldflag - 1;
3419                 italicflag = flag[2];
3420                 if (italicflag > 1) {
3421 /*                      break; */       /* impossible */        /* `fixed' 97/Sep/14 */
3422                 }
3423                 ttfflag = psflag = mmmflag = mmiflag = genflag = 0;
3424 /*              ttfflag = flag[5]; */
3425                 if (flag[4] == 0) ttfflag = 1;
3426                 else if (flag[4] == 1) psflag = 1;
3427                 else if (flag[4] == 2) mmmflag = 1;
3428                 else if (flag[4] == 4) mmiflag = 1;
3429                 if (flag[6] == 10) {
3430                         genflag = 1;
3431                         mmmflag = 0;
3432                 }
3433                 nMMM = flag[8] | (flag[9] << 8);        /* index into path name table */
3434                 nPFB = flag[10] | (flag[11] << 8);      /* index into path name table */
3435                 nPFM = flag[12] | (flag[13] << 8);      /* index into path name table */
3436 /*              mmflag = flag[12]; */
3437
3438 //              if (ttfflag) ttfcount++;
3439 //              else if (genflag) gencount++;
3440 //              else if (mmiflag) mmicount++;
3441 //              else if (mmmflag) mmmcount++;
3442 //              else pscount++;
3443
3444 /*              These used to all continue when they hit trouble */
3445 /*              Windows Face Name */
3446             if (ReadString(input, FaceName, sizeof(FaceName)) < 0) goto donext;
3447 /*              Style Name (will be empty string for PS SM or MM font) */
3448             if (ReadString(input, StyleName, sizeof(StyleName)) < 0) goto donext;
3449 /*              Full Name  (will be empty string for PS SM or MM font) */
3450             if (ReadString(input, FullName, sizeof(FullName)) < 0) goto donext;
3451 /*              Font Name  (may be empty if font file not yet read by ATM) */
3452             if (ReadString(input, FontName, sizeof(FontName)) < 0) goto donext;
3453 /*              Name of MMM file or PFM file or TTF file */ 
3454             if (ReadString(input, MMMName, sizeof(MMMName)) < 0) goto donext;
3455 /*              Name of PFB file or PSS file */ 
3456             if (ReadString(input, PFBName, sizeof(PFBName)) < 0) goto donext;
3457 /*              Name of PFM file in case of MMM font */ 
3458             if (ReadString(input, PFMName, sizeof(PFMName)) < 0) goto donext;
3459 /*              Flush extension from file name --- MMMName is file name */
3460 //              if ((s = strchr(MMMName, '.')) != NULL) *s = '\0';
3461 /*              Remove underscores from file name */
3462 /*              removeunderscores(MMMName); */
3463 /*              if (testflag == 0) removeunderscores (MMMName); */      /* ??? */
3464 /*              Make all uppercase ? It's a file name so its safe at least */
3465 /*              makeuppercase (MMMName); */     /* ??? */
3466 #ifdef DEBUGATM
3467                 if (traceflag) {
3468 //                      sprintf(logline, "%s %s %s%s %s (%d)\n", MMMName, FaceName,
3469 //                                      boldflag ? "BOLD" : "",
3470 //                                      italicflag ? "ITALIC" : "",
3471 //                                      ttfflag ? "(TT)" : "", pscount);
3472 //                      showline(logline, 0);
3473                         sprintf(logline, "Face: `%s' Style: `%s' Full: `%s' Font: `%s' MMM: `%s' PFB: `%s' PFM: `%s'",
3474                                         FaceName, StyleName, FullName, FontName, MMMName, PFBName, PFMName);
3475                         showline(logline, 0);
3476                 }
3477 #endif
3478 /*              if (strcmp(FontName, szPSFontName) == 0) */     /* ignore TrueType fonts */
3479                 if (ttfflag == 0 && strcmp(FontName, szPSFontName) == 0 &&
3480                           *PFBName != '\0') { // 2000 July 3
3481                         if (DirPaths[nPFB] != NULL)     strcpy(szPFBFileName, DirPaths[nPFB]);
3482                         else *szPFBFileName = '\0';                     // should not happen
3483                         strcat(szPFBFileName, PFBName);
3484                         if (traceflag) {
3485                                 sprintf(logline, " FOUND: %s for %s\n", szPFBFileName, szPSFontName);
3486                                 showline(logline, 0);
3487                         }
3488                         return 0;                                       /* success */
3489                 }
3490 donext:                 /* 1999/Mar/1 */
3491 /*              if (findfontstart(input) < 0) break; */
3492                 if (next >= endfontlist) break;
3493                 if (fseek(input, next, SEEK_SET) < 0) break;
3494         }
3495         *szPFBFileName = '\0';          /* wipe clean again */
3496         return -1;                                      /* failed to find */
3497 }
3498 #endif
3499
3500 /* New version uses ATMFonts structure */ /* First argument is PS FontName */
3501 /* WRITES BACK INTO SECOND ARGUMENT */
3502 /* returns 0 if found, -1 if not found */
3503
3504 int SearchATMReg (char *szPSFontName, char *szPFBFileName) {
3505         int k;
3506         for (k = 0; k < ATMfontindex; k++) {
3507                 if (strcmp(szPSFontName, ATMFonts[k].FontName) == 0) {
3508                         strcpy(szPFBFileName, DirPaths[ATMFonts[k].nPFB]);
3509                         strcat(szPFBFileName, ATMFonts[k].PFBName);             // PFB file name
3510                         return 0;
3511                 }
3512         }
3513         *szPFBFileName = '\0';          /* wipe clean */
3514         return -1;                                      /* failed to find */
3515 }
3516
3517 /* Create new ATMFonts data structure 2000 July */
3518
3519 int ScanATMReg (FILE *input, unsigned long endfontlist) {
3520         int c, k;
3521         unsigned int stroffset, nlen;
3522         unsigned long next;
3523         int boldflag, italicflag;               /* style bits */
3524         int ttfflag;
3525 /*      following just used for statistics - could remove to save time */
3526         int psflag, mmmflag, mmiflag, genflag;          /* font type bits */
3527         int nMMM, nPFB, nPFM;                           /* index into dir path table */
3528         unsigned int flag[16];                          /* 16 bytes of flags */
3529         char FaceName[LF_FACENAME+1];           /* Windows Face Name - not used */
3530         char StyleName[LF_FACENAME+1];          /* Style Name for TT font - not used */
3531         char FullName[LF_FULLFACENAME+1];       /* Full Name - not used */
3532         char FontName[LF_FULLFACENAME+1];       /* Font Name - used in comparison (T1 only) */
3533         char MMMName[LF_FACENAME+1];            /* PFM file or TTF file or MMM file */
3534         char PFBName[LF_FACENAME+1];            /* PFB file or PSS file - not used */
3535         char PFMName[LF_FACENAME+1];            /* PFM file of MMM font - not used */
3536 //      char *s;
3537
3538         if (ATMFonts == NULL) {
3539                 if (AllocFonts(nFonts)) return -1;
3540         }
3541         
3542         ATMfontindex = 0;
3543         
3544 //      sprintf(logline"SEEK TO %d\n", startfontlist);  // debugging only
3545 //      showline(logline, 0);
3546         fseek(input, startfontlist, SEEK_SET);
3547
3548 /*      positioned at start of font list at this point */
3549
3550         for (;;) {
3551                 c = getc(input);                                /* check for end of file 99/Mar/1 */
3552                 if (c == EOF) {
3553                         break;
3554                 }
3555                 ungetc(c, input);
3556                 stroffset = xreadtwo(input);    /* offset to first string == 44 */
3557                 nlen = xreadtwo(input);                 /* length of this record in bytes */
3558                 next = xreadfour(input);                /* pointer to next record */
3559                 for (k = 0; k < (28 - 8); k++) (void) getc(input);
3560                 for (k = 0; k < 16; k++) flag[k] = getc(input);
3561                 boldflag = flag[1];
3562                 if (boldflag == 0 || boldflag > 2) {
3563                         if (boldflag > 2) boldflag = 1; /* pretend it is OK */
3564 /*                      break; */        /* impossible */       /* `fixed' 97/Sep/14 */
3565                 }
3566                 else boldflag = boldflag - 1;
3567                 italicflag = flag[2];
3568                 if (italicflag > 1) {
3569 /*                      break; */       /* impossible */        /* `fixed' 97/Sep/14 */
3570                 }
3571                 ttfflag = psflag = mmmflag = mmiflag = genflag = 0;
3572 /*              ttfflag = flag[5]; */
3573                 if (flag[4] == 0) ttfflag = 1;
3574                 else if (flag[4] == 1) psflag = 1;
3575                 else if (flag[4] == 2) mmmflag = 1;
3576                 else if (flag[4] == 4) mmiflag = 1;
3577                 if (flag[6] == 10) {
3578                         genflag = 1;
3579                         mmmflag = 0;
3580                 }
3581                 nMMM = flag[8] | (flag[9] << 8);        /* index into path name table */
3582                 nPFB = flag[10] | (flag[11] << 8);      /* index into path name table */
3583                 nPFM = flag[12] | (flag[13] << 8);      /* index into path name table */
3584 /*              mmflag = flag[12]; */
3585
3586 //              if (ttfflag) ttfcount++;
3587 //              else if (genflag) gencount++;
3588 //              else if (mmiflag) mmicount++;
3589 //              else if (mmmflag) mmmcount++;
3590 //              else pscount++;
3591
3592 /*              These used to all continue when they hit trouble */
3593 /*              Windows Face Name */
3594                 if (ReadString(input, FaceName, sizeof(FaceName)) < 0) goto donext;
3595 /*              Style Name (will be empty string for PS SM or MM font) */
3596                 if (ReadString(input, StyleName, sizeof(StyleName)) < 0) goto donext;
3597 /*              Full Name  (will be empty string for PS SM or MM font) */
3598                 if (ReadString(input, FullName, sizeof(FullName)) < 0) goto donext;
3599 /*              Font Name  (may be empty if font file not yet read by ATM) */
3600                 if (ReadString(input, FontName, sizeof(FontName)) < 0) goto donext;
3601 /*              Name of MMM file or PFM file or TTF file */ 
3602                 if (ReadString(input, MMMName, sizeof(MMMName)) < 0) goto donext;
3603 /*              Name of PFB file or PSS file */ 
3604                 if (ReadString(input, PFBName, sizeof(PFBName)) < 0) goto donext;
3605 /*              Name of PFM file in case of MMM font */ 
3606                 if (ReadString(input, PFMName, sizeof(PFMName)) < 0) goto donext;
3607 /*              Flush extension from file name --- MMMName is file name */
3608 //              if ((s = strchr(MMMName, '.')) != NULL) *s = '\0';
3609 /*              Remove underscores from file name */
3610 /*              removeunderscores(MMMName); */
3611 /*              if (testflag == 0) removeunderscores (MMMName); */      /* ??? */
3612 /*              Make all uppercase ? It's a file name so its safe at least */
3613 /*              makeuppercase (MMMName); */     /* ??? */
3614 #ifdef DEBUGATM
3615                 if (traceflag) {
3616 //                      sprintf(logline, "%s %s %s%s %s (%d)\n", MMMName, FaceName,
3617 //                                      boldflag ? "BOLD" : "",
3618 //                                      italicflag ? "ITALIC" : "",
3619 //                                      ttfflag ? "(TT)" : "", pscount);
3620 //                      showline(logline, 0);
3621                         sprintf(logline, "Face: `%s' Style: `%s' Full: `%s' Font: `%s' MMM: `%s' PFB: `%s' PFM: `%s'",
3622                                         FaceName, StyleName, FullName, FontName, MMMName, PFBName, PFMName);
3623                         showline(logline, 0);
3624                 }
3625 #endif
3626                 if (ttfflag) goto donext;
3627                 ATMFonts[ATMfontindex].nMMM = (unsigned char) nMMM;
3628                 ATMFonts[ATMfontindex].nPFB = (unsigned char) nPFB;
3629                 ATMFonts[ATMfontindex].nPFM = (unsigned char) nPFM;
3630                 ATMFonts[ATMfontindex].MMMflag = (unsigned char) flag[4];
3631                 ATMFonts[ATMfontindex].FontName = xstrdup(FontName);    // PS FontName
3632                 ATMFonts[ATMfontindex].MMMName = xstrdup(MMMName);              // PFM/MMM File Name
3633                 ATMFonts[ATMfontindex].PFBName = xstrdup(PFBName);              // PFB File Name
3634                 ATMFonts[ATMfontindex].PFMName = xstrdup(PFMName);
3635                 ATMfontindex++;
3636 donext:                 /* 1999/Mar/1 */
3637                 if (next >= endfontlist) break;
3638                 if (fseek(input, next, SEEK_SET) < 0) break;
3639         }
3640         return ATMfontindex;
3641 }
3642
3643 /* sets up pointers to sections of ATMREG.ATM */
3644 /* also determines whether wide strings are used (ATM 4.1) */
3645 /* also reads in directory path table */
3646
3647 unsigned long ReadPointers (FILE *input) {
3648         (void) fseek(input, 6, SEEK_SET);
3649         nDirs = xreadtwo(input);                        /* 6 number of directory paths */
3650         nFonts = xreadtwo(input);                       /* 8 number of font entries */
3651         nSets = xreadtwo(input);                        /* 10 number of font sets (?) */
3652 //      sprintf(logline, "%d Dir Paths %d Font Entries %d Font Sets\n", nDirs, nFonts, nSets);  // debugging only
3653 //      showline(logline, 0);
3654 //      (void) fseek(input, 12, SEEK_SET);      /* start of pointers into file */
3655         enddirlist = xreadfour(input);          /* 12 enddirlist */
3656         (void) xreadfour(input);                        /* 16 mystery ??? */
3657         startfontlist = xreadfour(input);       /* 20 startfontlist */
3658         startdirlist = xreadfour(input);        /* 24 startdirlist */
3659         startsetlist = xreadfour(input);        /* 28 endfontlist */
3660         endfontlist = startsetlist;
3661         endsetlist = xreadfour(input);          /* 32 endsetlist */
3662
3663 //      See whether strings in ATMREG.ATM are in UNICODE format
3664         (void) fseek(input, endsetlist, SEEK_SET);
3665         (void) getc(input);
3666         if (getc(input) == 0) bATM41 = 1;
3667         else bATM41 = 0;
3668         if (traceflag) {
3669                 sprintf(logline, " bATM41 %d\n", bATM41);
3670                 showline(logline, 0);
3671         }
3672         return endfontlist;
3673 }
3674
3675 int SetupATMReg (void) {
3676         char szFullFileName[FNAMELEN]="";
3677
3678         if (useatmreg == 0) return -1;          /* tried already and failed */
3679         if (szATMRegAtm == NULL) {
3680                 setupinifilesub("atmreg.atm", szFullFileName);
3681                 if (traceflag) {
3682                         sprintf(logline, " atmreg.atm: %s ", szFullFileName);
3683                         showline(logline, 0);
3684                 }
3685                 if (*szFullFileName == '\0') {
3686                         useatmreg = 0;                          /* don't try again */
3687                         return -1;
3688                 }
3689                 szATMRegAtm = xstrdup(szFullFileName);
3690         }
3691         return 0;
3692 }
3693
3694 // LOAD information from ATMREG.ATM in convenient form 2000 July 6 
3695
3696 int LoadATMREG (void) {
3697         FILE *input;
3698         int count;
3699
3700         if (! useatmreg) return -1;                     // tried before and failed
3701         if (szATMRegAtm == NULL) {
3702                 if (SetupATMReg()) return -1;   // failed to setup now
3703         }
3704         if (szATMRegAtm == NULL) return -1;     // sanity check
3705         input = fopen(szATMRegAtm, "rb");       // open in binary mode for reading 
3706         if (input == NULL) {
3707                 useatmreg = 0;
3708                 return -1;              // probably because not found
3709         }
3710         if (traceflag) {
3711                 sprintf(logline, "Scanning %s ", szATMRegAtm);
3712                 showline(logline, 0);
3713         }
3714         (void) ReadPointers(input);
3715         if (AllocDirs(nDirs)) {
3716                 useatmreg = 0;
3717                 return -1;
3718         }
3719         SetupDirs(input, startdirlist, enddirlist);
3720         if (AllocFonts(nFonts)) {
3721                 useatmreg = 0;
3722                 return -1;
3723         }
3724         count = ScanATMReg(input, endfontlist);
3725         fclose(input);
3726         if (traceflag) ShowATMREG();            // debugging output
3727         return count;
3728 }
3729
3730
3731 /*      Look up specific font in ATMREG.ATM */
3732 /*      scan atmreg.atm in the windows directory for font info */
3733 /*      called with a single specific PS FontName */
3734 /*      returns -1 if it fails for one reason or another */
3735 /*      WRITES BACK INTO SECOND ARGUMENT */
3736
3737 #ifdef IGNORED
3738 int LookupATMReg (char *szPSFontName, char *szPSFileName) {
3739         FILE *input;
3740         int n=0;
3741
3742         if (! useatmreg) return -1;                     // tried before and failed
3743         if (szATMRegAtm == NULL) {
3744                 if (SetupATMReg()) return -1;   // failed to setup now
3745         }
3746         input = fopen(szATMRegAtm, "rb");       // open in binary mode for reading 
3747         if (input == NULL) return -1;           // probably because not found
3748         if (traceflag) {
3749                 sprintf(logline, "Scanning %s ", szATMRegAtm);
3750                 showline(logline, 0);
3751         }
3752         (void) ReadPointers(input);
3753         if (AllocDirs(nDirs)) return -1;
3754         SetupDirs(input, startdirlist, enddirlist);
3755         (void) fseek (input, startfontlist, SEEK_SET);
3756         n = SearchATMReg(input, endfontlist, szPSFontName, szPSFileName);
3757 //      showline(" LookupATMReg ATTEMPT TO FREE DIRPATHS\n", 0);        // debugging only
3758 //      FreeDirs();
3759         fclose(input);
3760         return n;
3761 }
3762 #endif
3763
3764 /* First arg is PS FontName */ /* WRITES BACK INTO SECOND ARG */
3765
3766 int LookupATMReg (char *szPSFontName, char *szPSFileName) {
3767         int n;
3768         if (! useatmreg) return -1;             // tried before and failed
3769         if (szATMRegAtm == NULL) {              // create ATMFonts structure
3770                 if (LoadATMREG() < 0) return -1;        // failed
3771         }
3772         n = SearchATMReg(szPSFontName, szPSFileName);
3773         if (traceflag) {
3774                 sprintf(logline, " LookupATMReg %s %s %d\n",
3775                                 szPSFontName, szPSFileName, n);
3776                 showline(logline, 0);           // debugging only
3777         }
3778         return n;
3779 }
3780
3781 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
3782
3783 /* could perhaps be speeded up slightly - using table of chars to skip */
3784
3785 /* check that fonts that have no characters used */
3786 /* (because of page limits) are NOT loaded in dviextra.c */
3787
3788 /* check that nothing but nop and font defs happen between eop and bop ? */
3789
3790 /* doesn't complain if pre not encountered ? IT DOES */
3791
3792 /* search for start of DVI in Textures file a bit crude ? */
3793
3794 /* try and avoid actually giving up if at all possible */
3795
3796 /* catch DVI commands before PRE - OK */
3797
3798 /* catch DVI commands after POST */
3799
3800 /* is TeX comment ever used later ? */  /* yes in PS file */
3801
3802 /* may also want to look 100 bytes into the file for start */
3803 /* some Mac files come that way... */
3804
3805 /* bRemapSpace remaps 32 => 195, 13 to 176, 10 => 173, 9 => 170, 0 => 161 */
3806 /* Rational is that text fonts reencoded to TeX 'n ANSI do not use 0 */
3807 /* or 9 or 10, and from now on text fonts will not use 13 for fl, */
3808 /* and TeX does not use 32 in text fonts */
3809 /* But math fonts do use 0, 9, 10, 13 and 32 */
3810 /* but math fonts always have the repetition of 0 - 32 higher up */
3811 /* And for some versions of Acrobat it may be best not to do this */
3812 /* for example transfer material to clipboard is null terminated */
3813 /* 9 is treated as tab, 10 as newline, 13 ignored and 32 ignored */