1 /* Copyright 1990,1991,1992,1993,1994,1995,1996,1997,1998,1999 Y&Y, Inc.
2 Copyright 2007 TeX Users Group
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.
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.
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
19 /**********************************************************************
21 * DVI analyzer to extract font and character usage
24 **********************************************************************/
26 /* Revised 1999 June 13 to run in DLL form */
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"
53 #pragma warning(disable:4100) // unreferenced formal variable
56 #pragma warning(disable:4127) // conditional expression is constant
60 #include <io.h> /* for _access */
61 /* for _findfirst, _findnext, _findclose */
63 /* #define DEBUGALIAS */
65 /* #define DEBUGCOLORSTACK */
67 /* #define DEBUGATM */
71 /* tables to store background color for each page on prescan 98/Jun/30 */
73 COLORSPEC *BackColors=NULL;
75 /* font k is to be used at mag * s / (1000 * d) times its normal size */
77 int fonthit[MAXFONTS]; /* which fonts have been seen - NOT ACCESSED */
79 /* char *currentfont; */ /* pointer to current font */
80 char *currentfont; /* pointer to current font */
82 long pageno; /* for convenience in error messages - may be logical page */
84 /* now for the scan of the DVI file for font character log generation */
86 /* now for the scan of the DVI file for PS output generation */
88 void reset_stack(void) {
92 void check_stack(int pageno) {
95 " ERROR: stack not empty at EOP: %d on page %d ",
96 stinx, pageno); /* pageno ? logical page */
104 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
106 /* we don't have to worry about sign extension here - no need for short int */
108 /* static unsigned int ureadone (FILE *infile) {
112 static unsigned int ureadtwo (FILE *infile) {
113 return (getc(infile) << 8) | getc(infile);
116 static unsigned long ureadthree (FILE *infile) {
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;
123 static unsigned long ureadfour (FILE *infile) {
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;
130 /* we do have to worry about sign extension here - use short int if needed */
132 /* static int sreadone (FILE *infile) {
135 if (c > 127) return (c - 256);
140 /* static short int sreadtwo (FILE *infile) { */ /* ??? */
141 static int sreadtwo (FILE *infile) {
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);
147 } /* needed now for code imported from dviextra.c readtfm etc */
150 /* avoid possible compiler optimization error */
152 static int sreadtwo (FILE *input) { /* experiment 98/Feb/7 */
154 c = getc(input); d = getc(input);
155 if (c > 127) c = c - 256;
159 /* static long sreadthree (FILE *infile) {
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;
166 static long sreadfour (FILE *infile) {
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;
173 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
175 int MaxColor; /* size of save area allocated for color stacks */
176 /* int MaxBack; */ /* size of save area allocated for background color */
178 COLORSPEC **ColorStacks=NULL; /* array of saved color stacks, one per page */
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 */
183 void RestoreColorStack (int page) {
184 COLORSPEC *SavedStack;
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 */
194 if (ColorStacks == NULL) return; /* sanity check */
196 SavedStack = ColorStacks[page];
197 if (SavedStack == NULL) {
198 sprintf(logline, " Bad Color Restore page %d (%d)",
200 showline(logline, 1);
204 colorindex = (int) (SavedStack[0].D + 0.5); /* depth of saved stack */
205 #ifdef DEBUGCOLORSTACK
207 sprintf(logline, " RestoreColorStack from page-1 %d colorindex %d\n",
209 showline(logline, 0);
212 if (colorindex > 0 && colorindex < MAXCOLORSTACK) {
213 for (k = 0; k < colorindex; k++) ColorStack[k] = SavedStack[k+1];
216 sprintf(logline, " ERROR: colorindex %d", colorindex); /* BUG */
217 showline(logline, 1);
219 /* ReleaseColor(); */
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 */
225 void SaveColorStack (int page, int colorindex) {
226 COLORSPEC *SavedStack;
228 /* if (bCarryColor == 0 || bColorUsed == 0) return; */
229 if (bCarryColor == 0) return;
230 /* if (page < 0 || page >= MaxColor) return; */
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]); */
239 #ifdef DEBUGCOLORSTACK
241 sprintf(logline, " SaveColorStack page %d colorindex %d\n",
243 showline(logline, 0);
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(); */
255 /* format of allocated area is count followed by stack dump */
257 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
259 void logdo_push(void) {
262 if (stinx > maxstinx) maxstinx = stinx;
263 /* if (stinx >= maxstack - 1) {
264 showline(" WARNING: The stack will overflow\n", 1);
270 void logdo_pop(void) {
275 " ERROR: The stack will underflow on page %d ",
276 pageno); /* pagenumber ??? logical page */
277 showline(logline, 1);
284 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
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);
294 /* common subroutine for set2 set3 set4 --- which should not occur */
296 void logdo_setsub(unsigned long c) {
298 /* if (ff < 0) invalidset((int) c); */
299 if (ff == BLANKFONT) invalidset((int) c);
301 /* if (bRemapControl && c < MAXREMAP) c = remaptable[c]; */
302 if (bRemapControl || bRemapFont) {
303 if (c < MAXREMAP) c = remaptable[c];
305 else if (c == 32) c = 195;
306 else if (c == 127) c = 196;
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;
322 /* For speed we keep the set1 case separate since it occurs often */
324 void logdo_set1(FILE *infile) {
326 /* c = ureadone(infile); */
329 /* if (ff < 0) invalidset((int) c); */
330 if (ff == BLANKFONT) invalidset((int) c);
332 /* if (bRemapControl && c < MAXREMAP) c = remaptable[c]; */
333 if (bRemapControl || bRemapFont) {
334 if (c < MAXREMAP) c = remaptable[c];
336 else if (c == 32) c = 195;
337 else if (c == 127) c = 196;
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;
352 /* simplified 95/Oct/17 by using logo_setsub for logdo_set2 */
354 void logdo_set2(FILE *infile) {
355 logdo_setsub(ureadtwo(infile));
359 void logdo_set2(FILE *infile) {
361 c = ureadtwo(infile);
363 /* if (ff < 0) invalidset((int) c); */
364 if (ff == BLANKFONT) invalidset((int) c);
366 /* if (bRemapControl && c < MAXREMAP) c = remaptable[c]; */
367 if (bRemapControl || bRemapFont) {
368 if (c < MAXREMAP) c = remaptable[c];
370 else if (c == 32) c = 195;
371 else if (c == 127) c = 196;
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;
387 void logdo_set3(FILE *infile) {
388 logdo_setsub(ureadthree(infile));
391 void logdo_set4(FILE *infile) {
392 logdo_setsub(ureadfour(infile));
395 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
397 /* common subroutine for put2, put3, pu4 --- which should not occur */
399 void logdo_putsub(unsigned long c) {
401 /* if (ff < 0) invalidset((int) c); */
402 if (ff == BLANKFONT) invalidset((int) c);
404 /* if (bRemapControl && c < MAXREMAP) c = remaptable[c]; */
405 if (bRemapControl || bRemapFont) {
406 if (c < MAXREMAP) c = remaptable[c];
408 else if (c == 32) c = 195;
409 else if (c == 127) c = 196;
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;
424 /* For speed we keep the set1 case separate since it occurs sometimes */
426 void logdo_put1(FILE *infile) {
428 /* c = ureadone(infile); */
431 /* if (ff < 0) invalidset((int) c); */
432 if (ff == BLANKFONT) invalidset((int) c);
434 /* if (bRemapControl && c < MAXREMAP) c = remaptable[c]; */
435 if (bRemapControl || bRemapFont) {
436 if (c < MAXREMAP) c = remaptable[c];
438 else if (c == 32) c = 195;
439 else if (c == 127) c = 196;
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;
454 /* simplified 95/Oct/17 by using logo_putsub for logdo_put2 */
456 void logdo_put2(FILE *infile) {
457 logdo_putsub(ureadtwo(infile));
461 void logdo_put2(FILE *infile) {
463 c = ureadtwo(infile);
465 /* if (ff < 0) invalidset((int) c); */
466 if (ff == BLANKFONT) invalidset((int) c);
468 /* if (bRemapControl && c < MAXREMAP) c = remaptable[c]; */
469 if (bRemapControl || bRemapFont) {
470 if (c < MAXREMAP) c = remaptable[c];
472 else if (c == 32) c = 195;
473 else if (c == 127) c = 196;
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;
489 void logdo_put3(FILE *infile) {
490 logdo_putsub(ureadthree(infile));
493 void logdo_put4(FILE *infile) {
494 logdo_putsub(ureadfour(infile));
497 void logdo_set_rule(FILE *infile) {
499 for (k=0; k < 8; k++) (void) getc(infile);
502 void logdo_put_rule(FILE *infile) {
504 for (k=0; k < 8; k++) (void) getc(infile);
507 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
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 */
514 /* returns zero if page is to be printed */ /* non-zero if to be skipped */
516 int skipthispage(long pageno) {
518 /* int hitrange=0; */
519 /* int wantpage=0; */
521 if (rangeindex == 0) return 0; /* easy, no page ranges specified! */
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) ;
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) ;
540 currentpage = pageno; /* remember page number */
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 */
553 return 1; /* not inside any specified range */
556 void logdo_bop(FILE *infile) { /* beginning of page */
558 long current; /* ??? */
560 current = ftell(input) - 1;
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 ??? */
569 for(k=0; k < 10; k++) counter[k] = sreadfour(infile);
571 previous = sreadfour(infile);
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 */
580 if (oddpageflag != 0 && (counter[0] & 1) == 0) skipflag++;
581 if (evenpageflag != 0 && (counter[0] & 1) == 1) skipflag++;
583 /* what about first page ? */
585 if (colorindex > 0) /* avoid error on first page */
586 doColorPop(pagenumber); /* 98/Feb/15 to match ColorPush in eop */
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;
598 void logdo_eop(FILE *infile) { /* end of page */
601 if (bAbort) abortjob(); /* 1992/Nov/24 */
602 if (abortflag) return;
603 check_stack(pagenumber);
605 doColorPush(pagenumber); /* 98/Feb/15 ??? */
606 SaveColorStack(pagenumber, colorindex); /* 98/Feb/19 ??? */
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);
620 if (skipflag == 0) numpages++; /* 94/Oct/12 */
624 void logdo_right1(FILE *infile) { /* rare */
628 void logdo_right2(FILE *infile) {
629 (void) getc(infile); (void) getc(infile);
632 void logdo_right3(FILE *infile) {
633 (void) getc(infile); (void) getc(infile); (void) getc(infile);
636 void logdo_right4(FILE *infile) {
637 (void) getc(infile); (void) getc(infile);
638 (void) getc(infile); (void) getc(infile);
641 void logdo_w0(void) {
644 void logdo_w1(FILE *infile) { /* rare */
648 void logdo_w2(FILE *infile) {
649 (void) getc(infile); (void) getc(infile);
652 void logdo_w3(FILE *infile) {
653 (void) getc(infile); (void) getc(infile); (void) getc(infile);
656 void logdo_w4(FILE *infile) {
657 (void) getc(infile); (void) getc(infile);
658 (void) getc(infile); (void) getc(infile);
661 void logdo_x0(void) {
664 void logdo_x1(FILE *infile) { /* rare */
668 void logdo_x2(FILE *infile) {
669 (void) getc(infile); (void) getc(infile);
672 void logdo_x3(FILE *infile) {
673 (void) getc(infile); (void) getc(infile); (void) getc(infile);
676 void logdo_x4(FILE *infile) {
677 (void) getc(infile); (void) getc(infile);
678 (void) getc(infile); (void) getc(infile);
681 void logdo_down1(FILE *infile) { /* rare */
685 void logdo_down2(FILE *infile) { /* rare */
686 (void) getc(infile); (void) getc(infile);
689 void logdo_down3(FILE *infile) {
690 (void) getc(infile); (void) getc(infile); (void) getc(infile);
693 void logdo_down4(FILE *infile) {
694 (void) getc(infile); (void) getc(infile);
695 (void) getc(infile); (void) getc(infile);
698 void logdo_y0(void) {
701 void logdo_y1(FILE *infile) { /* rare */
705 void logdo_y2(FILE *infile) {
706 (void) getc(infile); (void) getc(infile);
709 void logdo_y3(FILE *infile) {
710 (void) getc(infile); (void) getc(infile); (void) getc(infile);
713 void logdo_y4(FILE *infile) { /* not used */
714 (void) getc(infile); (void) getc(infile);
715 (void) getc(infile); (void) getc(infile);
718 void logdo_z0(void) {
721 void logdo_z1(FILE *infile) { /* rare */
725 void logdo_z2(FILE *infile) {
726 (void) getc(infile); (void) getc(infile);
729 void logdo_z3(FILE *infile) {
730 (void) getc(infile); (void) getc(infile); (void) getc(infile);
733 void logdo_z4(FILE *infile) {
734 (void) getc(infile); (void) getc(infile);
735 (void) getc(infile); (void) getc(infile);
738 void logswitchfont(int fn, FILE *infile) { /* switching to other font */
740 ff = fn; /* set state */
743 if (fnt == BLANKFONT) { /* 93/Dec/11 */
745 c = getc(infile); (void) ungetc(c, infile);
748 " ERROR: Unexpected encounter of DVI trailer on page %d ", pagenumber);
749 showline(logline, 1);
756 sprintf(logline, " ERROR: switch to undefined font (%d) on page %d ",
758 showline(logline, 1);
759 tellwhere(infile, 1);
763 // currentfont = fontchar + MAXCHRS * fnt;
764 if (fontchar[fnt] == NULL) setupfontchar(fnt);
765 currentfont = fontchar[fnt];
766 fonthit[fnt] = 1; /* even if skipflag != 0 ? */
769 void logdo_fnt1(FILE *infile) { /* switch fonts */
771 /* fn = ureadone(infile); */
773 /* if (skipflag == 0) */
774 logswitchfont(fn, infile);
777 void logdo_fnt2(FILE *infile) { /* switch fonts */
779 fn = ureadtwo(infile);
780 /* if (skipflag == 0) */
781 if (fn >= MAXFONTNUMBERS) fn = MAXFONTNUMBERS-1;
782 logswitchfont((int) fn, infile);
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);
791 void logdo_fnt3(FILE *infile) { /* switch fonts */
793 fn = ureadthree(infile); */
794 logdo_fntsub(ureadthree(infile), infile);
797 void logdo_fnt4(FILE *infile) { /* switch fonts */
799 fn = sreadfour(infile);
800 /* if (skipflag == 0) */
802 logdo_fntsub((unsigned long) fn, infile);
805 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
807 void getheadername (FILE *infile) { /* new version 95/Aug/30 */
808 char fname[FNAMELEN]; /* buffer to get token into */
811 /* if (gettoken(infile, headerfile, FNAMELEN) == 0) {*/
812 if (gettoken(infile, fname, sizeof(fname)) == 0) { /* FNAMELEN */
813 showline(" Can't find header\n", 1);
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) {
823 if (*s == '\0' || *s == ',') {
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);
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 ???
845 while (strlen(headerfile) + strlen(fname) + 2 > (size_t) nheaderlength) {
846 nheaderlength += strlen(fname) + 2;
847 headerfile = realloc(headerfile, nheaderlength);
849 if (headerfile == NULL) return; // allocation error - complain ???
851 // add a comma separator, unless this is the first one
852 if (*headerfile != '\0') {
853 s = headerfile + strlen(headerfile);
855 *s = '\0'; // not needed
857 else s = headerfile; // first time
859 // finally: append the header file name ...
863 /* get name of file with DSC header comments */ /* only one allowed */
865 void getcustomname (FILE *infile) {
868 if (dscfile != NULL) {
869 showline(" More than one DSCheader", 1);
873 /* if (gettoken(infile, line, MAXLINE) == 0) { */
874 if (gettoken(infile, line, sizeof(line)) == 0) { /* MAXLINE */
875 showline(" Can't find header\n", 1);
879 dscfile = zstrdup(line); /* remember single file name */
883 /* accumulate verbatim PS header text for prolog */
885 void getheadertext (FILE *infile) { /* new 1993/Dec/29 */
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); */
900 checkexit(1); /* 1995/July/15 */
901 // more serious exit(1) ???
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 */
910 /* accumulate command line args for DVIPSONE - passed through DVI file */
912 void getcommandspec (FILE *infile) { // 99/Sept/6
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);
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
931 /* accumulate verbatim PS header text for prolog */
933 void getcustomtext (FILE *infile) { /* new 1995/July/15 */
934 int c, n, needpercent=0;
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); */
951 checkexit(1); /* 1995/July/15 */
952 // more serious exit(1) ???
954 dsccustom = customnew;
955 u = customnew + dsccustomlen;
956 dsccustomlen = dsccustomlen + (int) nspecial + 1;
958 *u++ = '%'; *u++ = '%';
959 dsccustomlen = dsccustomlen + 2;
961 while (nspecial-- > 0) *u++ = (char) getc(infile);
962 *u++ = '\n'; *u++ = '\0'; /* terminating linefeed and \0 */
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);
970 if (gettoken(infile, line, sizeof(line)) != 0) { /* MAXLINE */
971 sscanf(line, "%d", &BByll);
973 if (gettoken(infile, line, sizeof(line)) != 0) { /* MAXLINE */
974 sscanf(line, "%d", &BBxur);
976 if (gettoken(infile, line, sizeof(line)) != 0) { /* MAXLINE */
977 sscanf(line, "%d", &BByur);
981 /* accumulate Keywords for DOCINFO pdfmark */
983 void getkeywords (FILE *infile) { /* 1996/May/10 */
987 int needcomma=0; /* 0 or 2 if comma and space needed */
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;
993 c = *(keywords + keywordslen - 1);
994 if (c == ',' || c == ' ' || c == '\t') needcomma = 0;
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); */
1006 checkexit(1); /* 1995/July/15 */
1007 // more serious exit(1) ???
1009 keywords = keywordsnew;
1010 u = keywordsnew + keywordslen;
1011 if (needcomma > 0) {
1012 *u++ = ','; /* add , if needed */
1013 *u++ = ' '; /* add if needed */
1015 keywordslen = keywordslen + (int) nspecial + needcomma;
1016 while (nspecial-- > 0) *u++ = (char) getc(infile);
1017 *u++ = '\0'; /* terminating \0 */
1020 // void getcommonstring (FILE *infile, char *newstring)
1021 char *getcommonstring (FILE *infile) {
1023 char *newstring = malloc ((size_t) (nspecial+1));
1024 if (newstring == NULL) {
1025 showline(" Unable to allocate memory\n", 1);
1030 while (nspecial-- > 0) *u++ = (char) getc(infile);
1031 *u++ = '\0'; /* terminating \0 */
1035 // unadvertized ability to change Creator fieldin DocInfo
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);
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);
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);
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);
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);
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);
1079 /* example \special{papersize=5.04in,3.751in} */
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);
1089 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
1091 int bComplainSpecial=1;
1093 /* Attempt at \special{background rgb 0 0 1} support 98 June 30 */
1095 void DoBackGround (FILE *infile, int c) {
1099 COLORSPEC SavedColor;
1101 if (bBackGroundFlag == 0) {
1102 flushspecial(infile);
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);
1112 sprintf(logline, "\n%s %c (%d) ", line, c, c);
1113 showline(logline, 0);
1116 /* if (c > 0) return; */ /* only do in prescan ! */
1118 if (*s == '\0') return;
1119 if (bKeepBlack) return; /* 96/Nov/3 */
1121 SavedColor = CurrColor; /* 99/Apr/06 */
1122 if (strncmp(s, "rgb", 3) == 0) {
1124 m = sscanf(s, "%g %g %g%n\n", &CurrColor.A, &CurrColor.B, &CurrColor.C, &n);
1126 CurrColor.D = -1.0F;
1131 complainspecial(input);
1135 else if (strncmp(s, "cmyk", 4) == 0) {
1137 m = sscanf(s, "%g %g %g %g%n",
1138 &CurrColor.A, &CurrColor.B, &CurrColor.C, &CurrColor.D, &n);
1144 complainspecial(input);
1148 else if (strncmp(s, "gray", 4) == 0) {
1150 m = sscanf(s, "%g%n", &CurrColor.A, &n);
1152 /* CurrentC = CurrentB = CurrentA; CurrentD = -2.0F; */
1153 CurrColor.C = CurrColor.B = CurrColor.A;
1154 CurrColor.D = -2.0F;
1159 complainspecial(input);
1163 else if (_strnicmp(s, "black", 5) == 0) {
1166 /* CurrentC = CurrentB = CurrentA = 0.0F; CurrentD = 1.0F; */
1167 CurrColor.C = CurrColor.B = CurrColor.A = 0.0F;
1170 else if (_strnicmp(s, "white", 5) == 0) {
1173 /* CurrentC = CurrentB = CurrentA = 0.0F;
1175 CurrColor.C = CurrColor.B = CurrColor.A = 0.0F;
1179 complainspecial(input); /* 1995/April/15 */
1184 sprintf(logline, " PAGENUMBER %d (%d %d) ", pagenumber, dvi_t, MaxColor);
1185 showline(logline, 0);
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);
1196 sprintf(logline, "\npage %d %g %g %g %g\n",
1197 pagenumber, CurrColor.A, CurrColor.B, CurrColor.C,
1199 showline(logline, 0);
1201 BackColors[pagenumber] = CurrColor; /* ??? */
1202 bBackUsed = 1; /* mark background color used */
1203 CurrColor = SavedColor; /* 99/Apr/06 */
1211 /* char *tpiccommand[] = {
1212 "pa", "fp", "ip", "da", "dt", "sp", "pn", "ar", "ia",
1213 "sh", "wh", "bk", "tx", ""
1216 char *tpiccommands = "pa fp ip da dt sp pn ar ia sh wh bk tx";
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 */
1228 void logdo_com (FILE *infile) {
1232 if (bIgnoreSpecials) {
1233 flushspecial(infile);
1236 nspecialsav = nspecial; /* 99/Feb/21 */
1237 specstart = ftell(input); /* for complainspecial 99/Feb/21 */
1238 c = getc(infile); /* peek ahead for ! */
1240 if (c == 0 && bFirstNull) { /* is first byte null ? 96/Aug/29 */
1241 flushspecial(infile);
1245 /* if (verbatimflag != 0) { */ /* flushed 97/Mar/9 */
1246 c = getc(infile); nspecial--;
1247 getheadertext(infile);
1249 flushspecial(infile);
1252 /* c = getalphatoken(infile, line, MAXLINE); */
1253 c = getalphatoken(infile, line, sizeof(line)); /* MAXLINE */
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) {
1263 if (strlen(line) == 2 && strstr(tpiccommands, line) != NULL)
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 */
1272 else if (strcmp(line, "background") == 0) {
1273 DoBackGround (infile, c);
1274 /* bColorUsed = 1; */ /* ? */
1276 else if (strcmp(line, "landscape") == 0) { /* 99/Apr/5 foils.cls */
1277 bLandScape = ! bLandScape; /* sets globally ! */
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 ??? */
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);
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);
1317 /* check whether TIFF image inserted re level2 features 96/Dec/20 */
1318 else if (strcmp(line, "insertimage") == 0) bInsertImage++;
1320 flushspecial(infile);
1323 void logdo_xxxi(FILE *infile, unsigned int n) {
1324 /* unsigned int k; */
1325 nspecial = (long) n;
1327 /* for(k = 0; k < n; k++) getc(infile); */
1330 void logdo_xxx1(FILE *infile) { /* for /special */
1333 logdo_xxxi(infile, k);
1336 void logdo_xxx2(FILE *infile) { /* for /special */
1338 k = ureadtwo(infile);
1339 logdo_xxxi(infile, k);
1342 void logdo_xxxl(FILE *infile, unsigned long n) {
1343 /* unsigned long k; */
1346 /* for(k = 0; k < n; k++) getc(infile); */
1349 void logdo_xxx3(FILE *infile) {
1350 logdo_xxxl(infile, ureadthree(infile));
1353 void logdo_xxx4(FILE *infile) {
1354 logdo_xxxl(infile, ureadfour(infile));
1357 /* need to do this even if skipping pages */
1359 void logfnt_def(FILE *infile, unsigned int k) {
1361 unsigned int na, nl, i;
1362 int newfont=1; /* if this is a new one (not defined before) */
1365 char namebuffer[FNAMELEN];
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);
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);
1383 checkexit(1); /* 1993/Dec/11 */
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 */
1394 if (newfont == 0) { /* just skip over if already defined */
1395 for (i = 0; i < na + nl; i++) (void) getc(infile);
1398 /* fp = fontname[fn]; */
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);
1406 tellwhere(infile, 1);
1407 for (i = 0; i < na+nl; i++) (void) getc(infile);
1410 for (i = 0; i < na+nl; i++) *fp++ = (char) getc(infile);
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;
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 */
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);
1444 memset(fontchar[fn], 0, MAXCHRS);
1447 void logdo_fnt_def1(FILE *infile) { /* define font */
1449 /* k = ureadone(infile); */
1451 logfnt_def(infile, k);
1454 void logdo_fnt_def2(FILE *infile) { /* define font */
1456 k = ureadtwo(infile);
1457 if (k >= MAXFONTNUMBERS) k = MAXFONTNUMBERS-1;
1458 logfnt_def(infile, k);
1461 void logdo_fnt_defsub(FILE *infile, unsigned long k) {
1462 if (k >= MAXFONTNUMBERS) k = MAXFONTNUMBERS-1;
1463 logfnt_def(infile, (unsigned int) k);
1466 void logdo_fnt_def3(FILE *infile) { /* define font */
1468 k = ureadthree(infile); */
1469 logdo_fnt_defsub(infile, ureadthree(infile));
1472 void logdo_fnt_def4(FILE *infile) { /* define font */
1474 k = sreadfour(infile);
1476 logdo_fnt_defsub(infile, (unsigned long) k);
1479 /* need to do this even if skipping pages */
1481 void logdo_pre(FILE *infile) {
1482 unsigned int i, k, j;
1486 /* i = ureadone(infile); */
1488 if (i < 1 || i > 3) {
1489 showline("Not a valid DVI file ", 1);
1493 else if (i != ID_BYTE) {
1494 sprintf(logline, "File is DVI version %d - *not* %d\n",
1496 showline(logline, 1);
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 */
1511 comment = malloc(k+1);
1512 if (comment == NULL) {
1513 showline(" Unable to allocate memory\n", 1);
1515 // more serious exit(1) ???
1518 /* if (traceflag) fprintf(stdout, "Comment:"); */
1519 c = getc(infile); /* try and discard initial space */
1521 else (void) ungetc(c, infile);
1522 for (j=0; j < k; j++) {
1524 if (j < MAXCOMMENT) *s++ = (char) c;
1525 /* if (verboseflag) putc(c, stdout); */
1529 showline(comment, 0);
1533 (void) ureadfour(infile); /* flush length code */
1536 /* need to do this even if skipping pages */
1538 void logdo_post(FILE *infile) {
1540 previous = sreadfour(infile); /* was ureadfour ... */
1541 num = ureadfour(infile);
1542 den = ureadfour(infile);
1543 mag = ureadfour(infile);
1546 sprintf(logline, " POST: previous %ld num %ld den %ld mag %ld\n",
1547 previous, num, den, mag);
1548 showline(logline, 0);
1550 /* compare these with what was in preamble ? */
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 */
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);
1561 /* here l and u could be used for bbox info ? */
1562 /* except: don't include headers and footers and other problems */
1566 /* could do this even in forward mode to check on number of pages ? */
1568 void logdo_post_post(FILE *infile) { /* only in reverse ? */
1569 /* unsigned long q; */
1570 /* unsigned int i; */
1572 if (traceflag) showline("Hit POSTPOST!\n", 0);
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); */
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 */
1590 int readovertext(FILE *infile) {
1595 /* if ((c = getc(infile)) == 0) { */
1598 while ((c = getc(infile)) == 0) n++;
1599 if (c == EOF) return 0;
1601 if((c = getc(infile)) == (int) pre) {
1602 (void) ungetc(c, infile);
1603 dvistart = ftell(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 ! */
1613 else if ((c = getc(infile)) == EOF) return 0;
1617 void resetpagerangehit (int flag) {
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 */
1628 /***************************************************************************/
1630 void alloccolorsave (int npages) {
1633 if (ColorStacks != NULL) {
1634 showline(" ERROR: color save stacks allocation\n", 1);
1637 #ifdef DEBUGCOLORSTACK
1639 sprintf(logline, "Allocating color save stack for %d pages\n", npages);
1640 showline(logline, 0);
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);
1648 // more serious exit(1) ???
1650 for (k = 0; k <= npages; k++) ColorStacks[k] = NULL;
1651 MaxColor = npages+1; /* make note of size of allocation */
1654 void freecolorsave (void) {
1655 int k, npages = MaxColor;
1657 if (ColorStacks == NULL) return;
1658 #ifdef DEBUGCOLORSTACK
1659 if (traceflag) showline("Freeing Saved Color Stacks\n", 0);
1661 for (k = 0; k < npages; k++) {
1662 if (ColorStacks[k] != NULL) {
1663 free(ColorStacks[k]);
1664 ColorStacks[k] = NULL;
1667 if (ColorStacks != NULL) {
1673 #ifdef DEBUGCOLORSTACK
1674 void dumpcolorsave (void) { /* debugging only */
1675 int k, m, i, npages = MaxColor-1;
1676 COLORSPEC *ColorSaved;
1678 if (ColorStacks == NULL) {
1679 showline(" No saved color stacks to show\n", 1);
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);
1699 sprintf(logline, " ERROR: ColorStack[%d] is NULL\n", k);
1700 showline(logline, 1);
1706 void allocbackground (int npages) {
1708 if (BackColors != NULL) {
1709 showline(" ERROR: background allocation\n", 1);
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);
1718 // more serious exit(1) ???
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;
1727 void freebackground (void) {
1728 if (BackColors != NULL) free(BackColors);
1732 /***************************************************************************/
1734 int scanlogfileaux(FILE *fp_in) {
1738 // strcpy (headerfile, ""); /* reset to no headers seen */
1739 if (headerfile != NULL) free(headerfile);
1741 if (countzeroflag) resetpagerangehit (1);
1743 numpages = 0; /* number of pages actually processed 94/Oct/12 */
1744 pagenumber = 0; /* pages seen in scan */
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 ??? */
1752 for (k = 0; k < MAXFONTNUMBERS; k++) /* reset status to unused */
1753 finx[k] = (short) BLANKFONT;
1755 /* Get dvi_t up front 98/Jun/30 */
1757 bBackUsed=0; /* non-zero of \special{background ...} used */
1758 bColorUsed = 0; /* assume no color \special until ... 98/Feb/15 */
1760 if (bCarryColor || bBackGroundFlag) {
1761 postposition = gotopost(input); /* in dvianal.c */
1762 (void) getc(input); /* absorb the post byte */
1766 alloccolorsave(dvi_t); /* allocated space for color table */
1767 if (bBackGroundFlag)
1768 allocbackground(dvi_t); /* allocate background color table */
1775 stinx = 0; maxstinx = 0; /* redundant, hopefully */
1777 textures=0; /* start off by assuming normal DVI file */
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);
1786 showline("Not a valid DVI (or Textures) file ", 1);
1788 input = NULL; /* to stop at byte message ? */
1794 showline("Textures DVI file - ", 0);
1800 /* in the above, may also want to look 100 bytes into the file for start */
1801 /* some Mac files come that way... */
1806 sprintf(logline, " Unexpected EOF (%s)\n", "scanlogfile");
1807 showline(logline, 1);
1813 if (skipflag == 0) {
1814 if (ff < 0) invalidset((int) c);
1816 /* if (bRemapControl && c < MAXREMAP) c = remaptable[c]; */
1817 if (bRemapControl || bRemapFont) {
1818 if (c < MAXREMAP) c = remaptable[c];
1820 else if (c == 32) c = 195;
1821 else if (c == 127) c = 196;
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;
1835 else if (c >= 171 && c <= 234) { /* switch to font (c - 171) */
1837 logswitchfont(fn, fp_in);
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;
1902 " ERROR: Unrecognized DVI command: %d", c);
1903 showline(logline, 1);
1904 tellwhere(fp_in, 1);
1906 finish = -1; /* ? */
1912 if (finish != 0) break;
1913 if (bAbort) abortjob(); /* fine grained */
1914 if (abortflag) break;
1916 /* if (maxstinx >= maxstack-1) {
1917 showline( WARNING: The PS stack will probably overflow %d > %d\n",
1918 maxstinx, maxstack -1 );
1921 if (abortflag) return -1;
1925 /* main entry point, prescan DVI file font usage, \specials */
1927 int scanlogfile (FILE *fp_in) {
1929 input = fp_in; /* remember file handle */
1931 if (traceflag) showline("Start PreScan DVI file\n", 0);
1932 /* strcpy (headerfile, ""); */ /* reset to no headers seen */
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);
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();
1954 if (abortflag) return -1;
1958 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
1960 /* Use `texfonts.map' in directory path TEXFONTS for aliasing */
1966 typedef struct map_element_struct { /* list element key . value pair */
1969 struct map_element_struct *next;
1972 typedef map_element_type **map_type;
1974 /* **************************** auxiliary functions *********************** */
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);
1982 static void *xmalloc (unsigned int size) {
1983 void *new_mem = (void *) malloc (size);
1984 if (new_mem == NULL) complain_mem(size);
1988 static void *xrealloc (void *old_ptr, unsigned int size) {
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? */
1994 new_mem = (void *) realloc (old_ptr, size);
1995 /* if (new_mem == NULL) complain_mem(size); */
1997 if (new_mem == NULL) complain_mem(size);
2001 static char *xstrdup (char *s) {
2002 char *new_string = (char *) xmalloc (strlen (s) + 1);
2003 return strcpy (new_string, s);
2006 /* static char *concat3 (char *s1, char *s2, char *s3) {
2008 = (char *) xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1);
2009 strcpy (answer, s1);
2010 strcat (answer, s2);
2011 strcat (answer, s3);
2013 } */ /* used by extend_filename only */
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);
2021 /* Here we work only with suffix-free names - so this is silly */
2023 /* static char *find_suffix (char *name) {
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;
2037 /* static char *extend_filename (char *name, char *default_suffix) {
2038 char *suffix = find_suffix (name);
2040 if (suffix != NULL) return name;
2041 new_s = concat3 (name, ".", default_suffix);
2045 /* static char *remove_suffix (char *s) {
2047 char *suffix = find_suffix (s);
2049 if (suffix == NULL) return NULL;
2051 ret = (char *) xmalloc (suffix - s + 1);
2052 strncpy (ret, s, suffix - s);
2053 ret[suffix - s] = 0;
2057 /* only used by fontmap.c */ /* why not just use fgets on global line ? */
2059 #define BLOCK_SIZE 40
2061 static char *read_line (FILE *f) {
2063 unsigned int limit = BLOCK_SIZE;
2064 unsigned int loc = 0;
2067 line = (char *) xmalloc (limit);
2069 while ((c = getc (f)) != EOF && c != '\n') {
2070 line[loc] = (char) c;
2073 limit += BLOCK_SIZE;
2074 line = (char *) xrealloc (line, limit);
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. */
2087 /* ************************************************************************* */
2089 /* Fontname mapping. We use a straightforward hash table. Should be prime? */
2091 #define MAP_SIZE 307
2093 /* The hash function. We go for simplicity here. */
2095 static unsigned int map_hash (char *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++;
2104 sprintf(logline, "hash %u for %s\n", n, key);
2105 showline(logline, 0);
2111 /* Look up STR in MAP. Return the corresponding `value' or NULL. */
2113 static char *map_lookup_str (map_type map, char *key) {
2114 unsigned int n = map_hash (key);
2115 map_element_type *p;
2117 for (p = map[n]; p != NULL; p = p->next) {
2120 sprintf(logline, "Trying %s against %s\n", key, p->key);
2121 showline(logline, 0);
2124 if (strcmp (key, p->key) == 0) return p->value;
2127 sprintf(logline, "p->next %p\n", p->next);
2128 showline(logline, 0);
2134 sprintf(logline, " failed to find %s\n", key);
2135 showline(logline, 0);
2138 return NULL; /* failed to find it */
2142 static void map_show (map_type map) { /* debugging tool */
2143 map_element_type *p;
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);
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 ... */
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'. */
2162 /* Append the same suffix we took off, if necessary. */
2163 /* if (ret) ret = extend_filename (ret, suffix); */
2165 char *map_lookup (map_type map, char *key) {
2166 char *ret = map_lookup_str(map, key);
2169 /* lets assume we never have to deal with names that have extensions */
2170 /* suffix = find_suffix (key);
2173 char *base_key = remove_suffix (key);
2174 ret = map_lookup_str(map, base_key);
2178 if (ret && suffix) ret = extend_filename (ret, suffix); */
2183 /* If KEY is not already in MAP, insert it and VALUE. */
2184 /* This was a total mess! Fixed 1994/March/18 */
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];
2190 while (*ptr != NULL && !(strcmp(key, (*ptr)->key) == 0))
2191 ptr = &((*ptr)->next);
2194 *ptr = (map_element_type *) xmalloc (sizeof(map_element_type));
2195 (*ptr)->key = xstrdup (key);
2196 (*ptr)->value = xstrdup (value);
2197 (*ptr)->next = NULL;
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 !*/
2212 static void map_file_parse (map_type map, char *map_filename) {
2214 unsigned int map_lineno = 0;
2215 unsigned int entries = 0;
2216 FILE *f = fopen(map_filename, "r");
2219 sprintf(logline, " ERROR: Can't open %s\n", map_filename);
2220 showline(logline, 1);
2221 perrormod(map_filename);
2225 while ((l = read_line(f)) != NULL) {
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, ';');
2234 /* Ignore anything after a % or ; */
2235 if (comment_loc) *comment_loc = 0;
2239 /* If we don't have any filename, that's ok, the line is blank. */
2240 filename = strtok (l, " \t");
2242 char *alias = strtok (NULL, " \t");
2244 /* But if we have a filename and no alias, something's wrong. */
2245 if (alias == NULL || *alias == 0) {
2247 " font name `%s', but no alias (line %u in `%s').\n",
2248 filename, map_lineno, map_filename);
2249 showline(logline, 1);
2251 else { /* We've got everything. Insert the new entry. */
2252 map_insert (map, alias, filename); /* alias is the key */
2258 /* xfclose (f, map_filename); */
2262 sprintf(logline, "%u entries\n", entries);
2263 showline(logline, 0);
2268 /* Look for the file `texfonts.map' in each of the directories in
2269 TEXFONTS. Entries in earlier files override later files. */
2271 /* uses _searchenv ? */
2273 /* map_type map_create (char *envvar) { old version
2274 char filename[_MAX_PATH];
2277 _searchenv ("texfonts.map", envvar, filename);
2278 if (*filename == '\0') return NULL;
2280 map = (map_type) xcalloc (MAP_SIZE, sizeof (map_element_type *));
2281 map_file_parse (map, filename);
2283 if (traceflag) map_show(map);
2288 /* Look for the file `texfonts.map' in each of the directories in
2289 TEXFONTS. Entries in earlier files override later files. */
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
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 */
2305 } /* new sanity check */
2307 if (searchalongpath(mapname, searchpath, pathname, 0) != 0)
2309 else foundfile = 1; /* 1994/Aug/18 */
2312 if ((searchpath = nextpathname(pathname, searchpath)) == NULL) {
2313 /* foundfile = 0; */
2316 s = pathname + strlen(pathname) - 1;
2317 if (*s != '\\' && *s != '/') strcat(pathname, "\\");
2318 strcat(pathname, mapname);
2319 if ((input = fopen(pathname, "r")) != NULL) {
2328 /* Returns NULL if it failed for some reason */
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];
2336 if (traceflag) showline("Creating alias table\n", 0);
2338 /* oursearchenv ("texfonts.map", envvar, pathname); */
2339 oursearchenv ("texfonts.map", texfonts, pathname);
2340 if (*pathname == '\0') {
2343 sprintf(logline, "Could not find %s in\n", "texfonts.map", texfonts);
2344 showline(logline, 0);
2350 map = (map_type) xcalloc (MAP_SIZE, sizeof(map_element_type *));
2351 map_file_parse (map, pathname);
2353 if (traceflag) map_show(map);
2358 /* ************************************************************************* */
2360 /* if we didn't find the font, maybe its alias to be found in texfonts.map */
2362 map_type fontmap = NULL; /* static - keep around once set */
2364 /* returns NULL if failed to find an alias */
2366 char *alias (char *name) {
2367 /* static map_type fontmap = NULL; */ /* static - keep around once set */
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 */
2381 /* Now look for our filename in the mapping. */
2382 mapped_name = map_lookup(fontmap, name);
2383 return mapped_name; /* possibly NULL */
2386 /* ************************************************************** */
2390 /***************************************************************************/
2392 #ifndef SUBDIRSEARCH
2394 /* Moved from DVIPSONE.C since DVIPSLOG.C module is much smaller */
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 */
2401 /* used for pfb search path and eps search path */
2402 /* this version also allows space as separator */
2404 char *nextpathname(char *pathname, char *searchpath) {
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);
2417 strncpy(pathname, searchpath, (unsigned int) n);
2418 *(pathname + n) = '\0'; /* terminate it */
2419 return(s + 1); /* next pathname or NULL */
2422 n = (int) strlen(searchpath);
2423 if (n >= MAXPATHLEN) {
2424 sprintf(logline, " Path too long %s\n", searchpath);
2425 showline(logline, 1);
2428 strcpy(pathname, searchpath);
2429 return(searchpath + n);
2435 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2444 }; */ /* 16 bit world --- in dos.h */
2446 /* struct _finddata_t {
2448 time_t time_create; -1 for FAT file systems
2449 time_t time_access; -1 for FAT file systems
2453 }; */ /* 32 bit world --- in io.h */
2455 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2459 /* Code to implement (possibly recursive) sub-directory search 94/Aug/18 */
2461 #define ACCESSCODE 4
2463 #define SEPARATOR "\\"
2465 /* This is the (possibly recursive) sub-directory searching code */
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 */
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 ? */
2480 int findsubpath (char *filename, char *pathname, int recurse) {
2484 /* struct _finddata_t c_file; */
2485 static struct _finddata_t c_file; /* structure can be reused (?) */
2489 s = pathname + strlen(pathname); /* remember the end of the dirpath */
2491 sprintf(logline, " Entering findsubpath: %s %s %d\n",
2492 filename, pathname, recurse);
2493 showline(logline, 0);
2496 /* First try directly in this directory (may want this conditional) */
2497 strcat (pathname, SEPARATOR); /* \ or / */
2498 strcat (pathname, filename);
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);
2505 sprintf(logline, " SUCCESS: %s\n", pathname);
2506 showline(logline, 0);
2508 return 0; /* success */
2510 if (traceflag) { /* debugging */
2511 /* code = _access(pathname, ACCESSCODE); */
2512 sprintf(logline, " File %s Access %d\n", pathname, code);
2513 showline(logline, 0);
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); */
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 */
2534 return -1; /* failure */
2536 *s = '\0'; /* strip off the \*.* again */
2537 /* Step through sub-directories */
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 */
2546 if (ret != 0) break; /* give up, found nothing more */
2547 continue; /* did find something else, go on */
2549 /* extend pathname with subdir name */
2550 strcat(pathname, SEPARATOR);
2551 strcat(pathname, c_file.name);
2553 sprintf(logline, " Checking subdir: %s\n", pathname);
2554 showline(logline, 0);
2556 /* OK, now try for match in this directory */
2557 if (recurse) { /* recursive version */
2558 if (findsubpath(filename, pathname, recurse) == 0) {
2561 return 0; /* succeeded */
2564 else { /* not recursive */
2565 strcat (pathname, SEPARATOR);
2566 strcat (pathname, filename);
2568 sprintf(logline, " Checking file: %s\n", pathname);
2569 showline(logline, 0);
2571 /* if (_access(pathname, ACCESSCODE) == 0) */
2572 code = _access(pathname, ACCESSCODE); /* check read access */
2575 sprintf(logline, " SUCCESS: %s\n", pathname);
2576 showline(logline, 0);
2580 return 0; /* success */
2582 if (traceflag) { /* debugging */
2583 /* code = _access(pathname, ACCESSCODE); */
2584 sprintf(logline, " File %s Access %d\n", pathname, code);
2585 showline(logline, 0);
2589 /* No match in this directory, so continue */
2592 sprintf(logline, "Ready for dos_findnext: %s %s %d\n",
2593 filename, pathname, recurse);
2594 showline(logline, 0);
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 */
2601 if (ret != 0) break; /* found no more */
2602 } /* end of for{;;} loop */
2607 return -1; /* failed */
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 ...) */
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;
2629 #ifdef DEBUGSEARCHPATH
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 */
2637 sprintf(logline, " File %s SUCCESS\n", pathname);
2638 showline(logline, 0);
2640 return 0; /* success */
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);
2652 /* Now step through paths in pathlist */
2655 if (*s == '\0') break; /* sanity check */
2656 if ((t = strchr(s, ';')) == NULL)
2657 t = s + strlen(s); /* if last path */
2659 strncpy(pathname, s, 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 */
2672 sprintf(logline, " Trying subdir: %s\n", pathname);
2673 showline(logline, 0);
2675 if (findsubpath (filename, pathname, recurse) == 0)
2676 return 0; /* success */
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) {
2684 sprintf(logline, " File %s SUCCESS\n", pathname);
2685 showline(logline, 0);
2687 return 0; /* success */
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);
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) {
2705 sprintf(logline, " File %s SUCCESS\n", pathname);
2706 showline(logline, 0);
2708 return 0; /* success */
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);
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 */
2725 strcpy(pathname, ""); /* failed to find it */
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 ...
2736 FILE *findandopen (char *filename, char *pathlist, char *pathname,
2737 char *mode, int current) {
2740 if (pathname == NULL) {
2741 pathname = (char *) _alloca (FNAMELEN);
2742 if (pathname == NULL) checkexit(1);
2744 if (searchalongpath(filename, pathlist, pathname, current) == 0) {
2745 file = fopen(pathname, mode);
2751 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2753 /* dviextra.c(5813) : fatal error C1001: internal compiler error */
2754 /* (compiler file 'msc2.cpp', line 1011) */
2756 /* dvipslog.c(2008) : fatal error C1001: internal compiler error
2757 (compiler file 'msc2.cpp', line 1011) */
2759 /* stuff for reading .afm files */
2761 int readafm(char *font, FILE *fp_afm, long widths[]) {
2765 /* if (fp_afm == NULL) checkexit(5); */
2766 (void) getrealline(fp_afm, line);
2768 while (strstr(line, "StartCharMetrics") == NULL) {
2769 if(getrealline(fp_afm, line) == 0) {
2771 " Can't find CharMetrics in AFM file for %s\n", font);
2772 showline(logline, 1);
2777 /* could extract UniqueID, BBox and FontInfo stuff at this point */
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) {
2784 " Parse error in line from AFM file for %s: %s",
2786 showline(logline, 1);
2790 if (chr >= 0 && chr < MAXCHRS) {
2791 if (chr > k) k = chr;
2792 widths[chr] = (long) ((fwidth/1000.0) * 1048576.0 + 0.5);
2794 (void) getrealline(fp_afm, line);
2799 /* moved here from dviextra.c */
2801 /* stuff for reading .tfm files */ /* OK for new form TFM files ? OK */
2803 /* lf, lh, nw, nh, nd, ni, nl, nk, ne are numbers of words */
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;
2810 /* int chksum, dsgnsize; */
2811 /* int hdinx, itinx, rdinx; */
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)
2825 sprintf(logline, " BAD TFM file for %s", font);
2826 showline(logline, 1);
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); */
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);
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 */
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);
2853 showline("width[0] not zero", 0); /* qwidths[0] */
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); */
2865 sprintf(logline, " BAD TFM file for %s", font);
2866 showline(logline, 1);
2868 sprintf(logline, "width index %d (char %d) > width table %d",
2870 showline(logline, 0);
2874 widths[k] = qwidths[wdinx];
2876 return (int) (ec + 1);
2879 /* stuff for reading widths from .pfm files */
2881 int readpfm(char *font, FILE *fp_pfm, long widths[]) {
2882 unsigned long length, offset;
2883 /* double fwidth; */
2885 int bc, ec, c, k, n;
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);
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);
2913 for (k = 127; k < n; k++) c = getc(fp_pfm);
2915 showline(" Premature EOF", 1);
2916 sprintf(logline, " in PFM file %s\n", font);
2917 showline(logline, 0);
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]); */
2931 sprintf(logline, "bc = %d ec = %d ", bc, ec);
2932 showline(logline, 0);
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 */
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) {
2949 long length, offset;
2951 char DriverType[16]; /* space for "PostScript" */
2955 // sprintf(logline, " NamesFromPFM nface %d nfont %d\n", nface, nfont);
2956 // showline(logline, 0); // debugging only
2961 sprintf(logline, " Read `%s' for MM instance info\n", FileName); /* debugging */
2962 showline(logline, 0);
2965 fread(&version, sizeof(version), 1, input);
2966 if (version != 256) {
2968 sprintf(logline, " Bad version code (%d) in PFM %s ", version, FileName);
2969 showline(logline, 1);
2971 return 0; /* not PFM file */
2973 fread(&length, sizeof(length), 1, input);
2974 if (fseek(input, 101, SEEK_SET) != 0) {
2976 sprintf(logline, " Seek to %ld failed in PFM %s ", 101L, FileName);
2977 showline(logline, 1);
2981 fread(&offset, sizeof(offset), 1, input); /* offset to Driver Type */
2982 if (offset >= length || offset == 0) {
2984 sprintf(logline, " Bad offset %ld (%d) in PFM %s ", offset, length, FileName);
2985 showline(logline, 1);
2987 return 0; /* not PFM file */
2989 if (fseek(input, offset, SEEK_SET) != 0) {
2991 sprintf(logline, " Seek to %ld failed in PFM %s ", offset, FileName);
2992 showline(logline, 1);
2996 ndrive = sizeof(DriverType);
2997 s = DriverType; /* temporary space */
2999 while ((*s++ = (char) getc(input)) != '\0') {
3000 if (n++ >= ndrive) {
3002 sprintf(logline, " %s too long >= %ld in %s ", "DriverType", ndrive, FileName);
3003 showline(logline, 1);
3008 *s = '\0'; /* terminate */
3009 if (strcmp(DriverType, "PostScript") != 0) {
3011 sprintf(logline, " Driver not %s in %s ", "PostScript", FileName);
3012 showline(logline, 1);
3015 return 0; /* Not PS font */
3017 if (fseek(input, 105, SEEK_SET) != 0) {
3019 sprintf(logline, " Seek to %ld failed in PFM %s ", 105L, FileName);
3020 showline(logline, 1);
3024 fread(&offset, sizeof(offset), 1, input); /* offset Windows Face Name */
3025 if (offset >= length || offset == 0) {
3027 sprintf(logline, " Bad offset %ld (%ld) in PFM %s ", offset, length, FileName);
3028 showline(logline, 1);
3030 return 0; /* not PFM file */
3032 if (fseek(input, offset, SEEK_SET) != 0) {
3034 sprintf(logline, " Seek to %ld failed in PFM %s ", offset, FileName);
3035 showline(logline, 1);
3039 if (FaceName != NULL) {
3042 while ((*s++ = (char) getc(input)) != '\0')
3045 sprintf(logline, " %s too long >= %ld in %s ", "FaceName", nface, FileName);
3046 showline(logline, 1);
3050 *s = '\0'; /* terminate */
3051 if (strchr(FaceName, ' ') == NULL) {
3053 sprintf(logline, " Not MM %s %s? ", "FaceName", FaceName);
3054 showline(logline, 1);
3056 /* return 0; */ /* not MM instance */
3059 if (fseek(input, 139, SEEK_SET) != 0) {
3061 sprintf(logline, " Seek to %ld failed in PFM ", 139L);
3062 showline(logline, 1);
3066 fread(&offset, sizeof(offset), 1, input); /* offset to PS FontName */
3067 if (offset >= length || offset == 0) {
3069 sprintf(logline, " Bad offset %ld (%ld) in PFM ", offset, length);
3070 showline(logline, 1);
3072 return 0; /* not PFM file */
3074 if (fseek(input, offset, SEEK_SET) != 0) {
3076 sprintf(logline, " Seek to %ld failed in PFM ", offset);
3077 showline(logline, 1);
3082 /* write name back into second argument */
3083 if (FontName != NULL) {
3086 while ((*s++ = (char) getc(input)) != '\0')
3089 sprintf(logline, " %s too long >= %ld in %s ", "FontName", nfont, FileName);
3090 showline(logline, 1);
3094 *s = '\0'; /* terminate */
3095 /* We assume FontName for MM instance must have underscores */
3096 if (strchr(FontName, '_') == NULL) {
3098 sprintf(logline, " Not MM %s %s? ", "FontName", FontName);
3099 showline(logline, 1);
3101 /* return 0; */ /* not MM instance */
3105 sprintf(logline, " FontName from PFM: %s\n", FontName);/* debugging output */
3106 showline(logline, 0);
3110 return 1; /* OK, FaceName and FontName returned */
3113 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
3115 /* stuff for reading ATMREG.ATM imported from winpslog.c 98/Jan/9 */
3117 unsigned int xreadtwo (FILE *input) {
3118 unsigned int c, d, n;
3125 unsigned long xreadfour (FILE *input) {
3126 unsigned int a, b, c, d;
3133 n = (n << 16) | (b << 8) | a;
3137 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
3139 int bATM41=0; // needs to be set based on ATMREG.ATM header
3141 /* read string from ATMREG.ATM up to null, string may be empty */
3142 /* returns -1 if hit EOF or name too long */
3144 int ReadString (FILE *input, char *name, int nlen) {
3149 *s = '\0'; /* in case we pop out early */
3150 for (;;) { /* read string up to null */
3152 if (bATM41) // 2000 July 3 ATM 4.1 ???
3153 (void) getc(input); // discard second byte of UNICODE
3154 if (c == EOF) { /* EOF */
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 */
3171 #define LF_FACENAME 32
3172 #define LF_FULLFACENAME 64
3174 /* #define PFMName 16 */ /* >= 8+1+3+1 */
3175 /* #define PFBName 16 */ /* >= 8+1+3+1 */
3177 /**************************************************************************/
3179 /* New code for using ATMREG.ATM */
3181 unsigned long startfontlist, endfontlist;
3182 unsigned long startdirlist, enddirlist;
3183 unsigned long startsetlist, endsetlist;
3184 int nDirs, nFonts, nSets;
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)
3197 struct ATMRegRec *ATMFonts=NULL;
3199 int ATMfontindex=0; // number of font entries
3201 // char *DirPaths[MAXDIRS];
3203 char **DirPaths=NULL;
3207 void FreeDirs (void) {
3209 if (DirPaths == NULL) return;
3210 for (k = 0; k <= nDirs; k++) {
3211 if (DirPaths[k] != NULL) free(DirPaths[k]);
3219 int AllocDirs (int nDirs) {
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",
3227 showline(logline, 1);
3230 DirPaths[0] = _strdup("");
3231 for (k = 1; k <= nDirs; k++) DirPaths[k] = NULL;
3236 void FreeFonts (void) {
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);
3249 int AllocFonts (int nFonts) {
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",
3257 showline(logline, 1);
3261 // sprintf(logline, "Allocated %d bytes for %d fonts\n", nlen, nFonts); // debugging only
3262 // showline(logline, 0);
3267 void ShowATMREG (void) {
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;
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);
3289 /**********************************************************************************/
3291 int SetupDirs (FILE *input, unsigned long startdirlist, unsigned long enddirlist) {
3292 int c, k, noff, nlen;
3294 unsigned long noffset;
3295 char pathname[ _MAX_PATH];
3298 /* if (fseek(input, 24, SEEK_SET) >= 0) noffset = xreadfour(input); */
3300 noffset = startdirlist; // 36
3303 if (noffset >= enddirlist) break; /* normal exit from this */
3304 if (fseek(input, noffset, SEEK_SET) < 0) {
3306 sprintf(logline, " Seek to %ld failed\n", noffset);
3307 showline(logline, 0);
3309 break; /* return -1; */
3311 noff = xreadtwo(input);
3314 sprintf(logline, " noff %lu != 8\n", noff);
3315 showline(logline, 0);
3317 /* break; */ /* new sanity check */
3319 nlen = xreadtwo(input);
3322 sprintf(logline, " nlen == 0\n");
3323 showline(logline, 0);
3325 break; /* sanity check */
3327 if (nlen > _MAX_PATH) {
3329 sprintf(logline, " nlen > %d\n", _MAX_PATH);
3330 showline(logline, 0);
3332 break; /* new sanity check */
3334 noffset = xreadfour(input);
3337 sprintf(logline, " noffset == 0\n");
3338 showline(logline, 0);
3340 break; /* sanity check */
3343 for (k = 0; k < nlen; k++) {
3345 if (bATM41) (void) getc(input);
3348 sprintf(logline, " Unexpected EOF (%s)\n", "setupdirs");
3349 showline(logline, 0);
3357 /* if (noiseflag) printf("%d\t%s\n", npath, pathname); */
3358 // if (dirindex >= MAXDIRS) {
3359 if (dirindex > nDirs) {
3361 sprintf(logline, " Too many paths (> %d)\n", nDirs);
3362 showline(logline, 0);
3366 DirPaths[dirindex] = xstrdup(pathname);
3372 /* Look for given PS FontName in atmreg.atm and return file name of PFB */
3373 /* returns 0 if found, -1 if not found */
3376 int SearchATMReg (FILE *input, unsigned long endfontlist,
3377 char *szPSFontName, char *szPFBFileName) {
3379 unsigned int stroffset, nlen;
3381 int boldflag, italicflag; /* style bits */
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 */
3396 *szPFBFileName = '\0';
3398 fseek(input, startfontlist, SEEK_SET);
3400 /* positioned at start of font list at this point */
3403 c = getc(input); /* check for end of file 99/Mar/1 */
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);
3414 if (boldflag == 0 || boldflag > 2) {
3415 if (boldflag > 2) boldflag = 1; /* pretend it is OK */
3416 /* break; */ /* impossible */ /* `fixed' 97/Sep/14 */
3418 else boldflag = boldflag - 1;
3419 italicflag = flag[2];
3420 if (italicflag > 1) {
3421 /* break; */ /* impossible */ /* `fixed' 97/Sep/14 */
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) {
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]; */
3438 // if (ttfflag) ttfcount++;
3439 // else if (genflag) gencount++;
3440 // else if (mmiflag) mmicount++;
3441 // else if (mmmflag) mmmcount++;
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); */ /* ??? */
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);
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);
3485 sprintf(logline, " FOUND: %s for %s\n", szPFBFileName, szPSFontName);
3486 showline(logline, 0);
3488 return 0; /* success */
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;
3495 *szPFBFileName = '\0'; /* wipe clean again */
3496 return -1; /* failed to find */
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 */
3504 int SearchATMReg (char *szPSFontName, char *szPFBFileName) {
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
3513 *szPFBFileName = '\0'; /* wipe clean */
3514 return -1; /* failed to find */
3517 /* Create new ATMFonts data structure 2000 July */
3519 int ScanATMReg (FILE *input, unsigned long endfontlist) {
3521 unsigned int stroffset, nlen;
3523 int boldflag, italicflag; /* style bits */
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 */
3538 if (ATMFonts == NULL) {
3539 if (AllocFonts(nFonts)) return -1;
3544 // sprintf(logline"SEEK TO %d\n", startfontlist); // debugging only
3545 // showline(logline, 0);
3546 fseek(input, startfontlist, SEEK_SET);
3548 /* positioned at start of font list at this point */
3551 c = getc(input); /* check for end of file 99/Mar/1 */
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);
3562 if (boldflag == 0 || boldflag > 2) {
3563 if (boldflag > 2) boldflag = 1; /* pretend it is OK */
3564 /* break; */ /* impossible */ /* `fixed' 97/Sep/14 */
3566 else boldflag = boldflag - 1;
3567 italicflag = flag[2];
3568 if (italicflag > 1) {
3569 /* break; */ /* impossible */ /* `fixed' 97/Sep/14 */
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) {
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]; */
3586 // if (ttfflag) ttfcount++;
3587 // else if (genflag) gencount++;
3588 // else if (mmiflag) mmicount++;
3589 // else if (mmmflag) mmmcount++;
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); */ /* ??? */
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);
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);
3636 donext: /* 1999/Mar/1 */
3637 if (next >= endfontlist) break;
3638 if (fseek(input, next, SEEK_SET) < 0) break;
3640 return ATMfontindex;
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 */
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 */
3663 // See whether strings in ATMREG.ATM are in UNICODE format
3664 (void) fseek(input, endsetlist, SEEK_SET);
3666 if (getc(input) == 0) bATM41 = 1;
3669 sprintf(logline, " bATM41 %d\n", bATM41);
3670 showline(logline, 0);
3675 int SetupATMReg (void) {
3676 char szFullFileName[FNAMELEN]="";
3678 if (useatmreg == 0) return -1; /* tried already and failed */
3679 if (szATMRegAtm == NULL) {
3680 setupinifilesub("atmreg.atm", szFullFileName);
3682 sprintf(logline, " atmreg.atm: %s ", szFullFileName);
3683 showline(logline, 0);
3685 if (*szFullFileName == '\0') {
3686 useatmreg = 0; /* don't try again */
3689 szATMRegAtm = xstrdup(szFullFileName);
3694 // LOAD information from ATMREG.ATM in convenient form 2000 July 6
3696 int LoadATMREG (void) {
3700 if (! useatmreg) return -1; // tried before and failed
3701 if (szATMRegAtm == NULL) {
3702 if (SetupATMReg()) return -1; // failed to setup now
3704 if (szATMRegAtm == NULL) return -1; // sanity check
3705 input = fopen(szATMRegAtm, "rb"); // open in binary mode for reading
3706 if (input == NULL) {
3708 return -1; // probably because not found
3711 sprintf(logline, "Scanning %s ", szATMRegAtm);
3712 showline(logline, 0);
3714 (void) ReadPointers(input);
3715 if (AllocDirs(nDirs)) {
3719 SetupDirs(input, startdirlist, enddirlist);
3720 if (AllocFonts(nFonts)) {
3724 count = ScanATMReg(input, endfontlist);
3726 if (traceflag) ShowATMREG(); // debugging output
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 */
3738 int LookupATMReg (char *szPSFontName, char *szPSFileName) {
3742 if (! useatmreg) return -1; // tried before and failed
3743 if (szATMRegAtm == NULL) {
3744 if (SetupATMReg()) return -1; // failed to setup now
3746 input = fopen(szATMRegAtm, "rb"); // open in binary mode for reading
3747 if (input == NULL) return -1; // probably because not found
3749 sprintf(logline, "Scanning %s ", szATMRegAtm);
3750 showline(logline, 0);
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
3764 /* First arg is PS FontName */ /* WRITES BACK INTO SECOND ARG */
3766 int LookupATMReg (char *szPSFontName, char *szPSFileName) {
3768 if (! useatmreg) return -1; // tried before and failed
3769 if (szATMRegAtm == NULL) { // create ATMFonts structure
3770 if (LoadATMREG() < 0) return -1; // failed
3772 n = SearchATMReg(szPSFontName, szPSFileName);
3774 sprintf(logline, " LookupATMReg %s %s %d\n",
3775 szPSFontName, szPSFileName, n);
3776 showline(logline, 0); // debugging only
3781 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
3783 /* could perhaps be speeded up slightly - using table of chars to skip */
3785 /* check that fonts that have no characters used */
3786 /* (because of page limits) are NOT loaded in dviextra.c */
3788 /* check that nothing but nop and font defs happen between eop and bop ? */
3790 /* doesn't complain if pre not encountered ? IT DOES */
3792 /* search for start of DVI in Textures file a bit crude ? */
3794 /* try and avoid actually giving up if at all possible */
3796 /* catch DVI commands before PRE - OK */
3798 /* catch DVI commands after POST */
3800 /* is TeX comment ever used later ? */ /* yes in PS file */
3802 /* may also want to look 100 bytes into the file for start */
3803 /* some Mac files come that way... */
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 */