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:4996)
57 #pragma warning(disable:4127) // conditional expression is constant
61 #include <io.h> /* for _access */
62 /* for _findfirst, _findnext, _findclose */
64 /* #define DEBUGALIAS */
66 /* #define DEBUGCOLORSTACK */
68 /* #define DEBUGATM */
72 /* tables to store background color for each page on prescan 98/Jun/30 */
74 COLORSPEC *BackColors=NULL;
76 /* font k is to be used at mag * s / (1000 * d) times its normal size */
78 int fonthit[MAXFONTS]; /* which fonts have been seen - NOT ACCESSED */
80 /* char *currentfont; */ /* pointer to current font */
81 char *currentfont; /* pointer to current font */
83 long pageno; /* for convenience in error messages - may be logical page */
85 /* now for the scan of the DVI file for font character log generation */
87 /* now for the scan of the DVI file for PS output generation */
89 void reset_stack(void)
94 void check_stack(int pageno)
98 sprintf(logline, " ERROR: stack not empty at EOP: %d on page %d ", stinx, pageno); /* pageno ? logical page */
106 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
108 /* we don't have to worry about sign extension here - no need for short int */
110 /* static unsigned int ureadone (FILE *infile) {
114 static unsigned int ureadtwo (FILE *infile)
116 return (getc(infile) << 8) | getc(infile);
119 static unsigned long ureadthree (FILE *infile)
122 /* unsigned int c, d, e; */
123 c = getc(infile); d = getc(infile); e = getc(infile);
124 return ((((unsigned long) c << 8) | d) << 8) | e;
127 static unsigned long ureadfour (FILE *infile)
130 c = getc(infile); d = getc(infile);
131 e = getc(infile); f = getc(infile);
132 return ((((((unsigned long) c << 8) | (unsigned long) d) << 8) | e) << 8) | f;
135 /* we do have to worry about sign extension here - use short int if needed */
137 /* static int sreadone (FILE *infile) {
140 if (c > 127) return (c - 256);
145 /* static short int sreadtwo (FILE *infile) { */ /* ??? */
146 static int sreadtwo (FILE *infile)
149 /* return (getc(infile) << 8) | getc(infile); */ /* 1995/Nov/15 */
150 /* result = (getc(infile) << 8) | getc(infile); */
151 result = ((short int) getc(infile) << 8) | (short int) getc(infile);
153 } /* needed now for code imported from dviextra.c readtfm etc */
156 /* avoid possible compiler optimization error */
158 static int sreadtwo (FILE *input) /* experiment 98/Feb/7 */
161 c = getc(input); d = getc(input);
162 if (c > 127) c = c - 256;
166 /* static long sreadthree (FILE *infile) {
168 c = getc(infile); d = getc(infile); e = getc(infile);
169 if (c > 127) c = c - 256;
170 return ((((long) c << 8) | d) << 8) | e;
173 static long sreadfour (FILE *infile)
176 c = getc(infile); d = getc(infile);
177 e = getc(infile); f = getc(infile);
178 return ((((((long) c << 8) | (long) d) << 8) | e) << 8) | f;
181 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
183 int MaxColor; /* size of save area allocated for color stacks */
184 /* int MaxBack; */ /* size of save area allocated for background color */
186 COLORSPEC **ColorStacks=NULL; /* array of saved color stacks, one per page */
188 /* restore at start of page what was current at end of page-1 */
189 /* called from dvianal.c */ /* page is physical DVI page from start of file */
191 void RestoreColorStack (int page)
193 COLORSPEC *SavedStack;
195 /* don't bother if color \special{...} was never used */
196 if (bCarryColor == 0 || bColorUsed == 0) return;
197 if (page >= MaxColor) return; /* sanity check */
198 page--; /* restore what was saved at eop of *previous* */
199 if (page < 1) { /* nothing saved to restore at start of first page */
203 if (ColorStacks == NULL) return; /* sanity check */
205 SavedStack = ColorStacks[page];
206 if (SavedStack == NULL)
208 sprintf(logline, " Bad Color Restore page %d (%d)",
210 showline(logline, 1);
214 colorindex = (int) (SavedStack[0].D + 0.5); /* depth of saved stack */
215 #ifdef DEBUGCOLORSTACK
218 sprintf(logline, " RestoreColorStack from page-1 %d colorindex %d\n",
220 showline(logline, 0);
223 if (colorindex > 0 && colorindex < MAXCOLORSTACK) {
224 for (k = 0; k < colorindex; k++) ColorStack[k] = SavedStack[k+1];
227 sprintf(logline, " ERROR: colorindex %d", colorindex); /* BUG */
228 showline(logline, 1);
230 /* ReleaseColor(); */
233 /* Save at end of page for start of page+1 */
234 /* called from logdo_eop dvipslog.c */ /* page is DVI page from start of file */
236 void SaveColorStack (int page, int colorindex)
238 COLORSPEC *SavedStack;
240 /* if (bCarryColor == 0 || bColorUsed == 0) return; */
241 if (bCarryColor == 0) return;
242 /* if (page < 0 || page >= MaxColor) return; */
244 if (ColorStacks == NULL) return; /* sanity check */
245 if (ColorStacks[page] != NULL) {
246 sprintf(logline, " Bad Color Save page %d (%d) %08x",
247 page, MaxColor, ColorStacks[page]);
248 showline(logline, 1);
249 /* free(lpColor[page]); */
251 #ifdef DEBUGCOLORSTACK
254 sprintf(logline, " SaveColorStack page %d colorindex %d\n",
256 showline(logline, 0);
259 if (colorindex == 0) return; /* nothing to save ??? */
260 SavedStack = (COLORSPEC *) malloc ((colorindex+1) * sizeof(COLORSPEC));
261 ColorStacks[page] = SavedStack;
262 SavedStack[0].A = SavedStack[0].B = SavedStack[0].C = 0.0F;
263 SavedStack[0].D = (float) colorindex;
264 for (k = 0; k < colorindex; k++) SavedStack[k+1] = ColorStack[k];
265 /* ReleaseColor(); */
268 /* format of allocated area is count followed by stack dump */
270 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
272 void logdo_push(void)
276 if (stinx > maxstinx) maxstinx = stinx;
277 /* if (stinx >= maxstack - 1) {
278 showline(" WARNING: The stack will overflow\n", 1);
292 " ERROR: The stack will underflow on page %d ",
293 pageno); /* pagenumber ??? logical page */
294 showline(logline, 1);
301 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
303 void invalidset(int c)
305 sprintf(logline, " ERROR: Setting char %d without font on page %d ",
306 c, pageno); /* pagenumber ??? logical page */
307 showline(logline, 1);
312 /* common subroutine for set2 set3 set4 --- which should not occur */
314 void logdo_setsub(unsigned long c)
317 /* if (ff < 0) invalidset((int) c); */
318 if (ff == BLANKFONT) invalidset((int) c);
320 /* if (bRemapControl && c < MAXREMAP) c = remaptable[c]; */
321 if (bRemapControl || bRemapFont) {
322 if (c < MAXREMAP) c = remaptable[c];
324 else if (c == 32) c = 195;
325 else if (c == 127) c = 196;
328 /* NOTE: this must match corresponding code in DVIANAL.C */
329 else if (bRemapSpace && c <= 32) { /* 1995/Oct/17 */
330 if (c == 32) c = 195; /* not 160 */
331 else if (c == 13) c = 176; /* 1996/June/4 */
332 else if (c == 10) c = 173; /* 1996/June/4 */
333 else if (c == 9) c = 170; /* 1996/June/4 */
334 else if (c == 0) c = 161;
341 /* For speed we keep the set1 case separate since it occurs often */
343 void logdo_set1(FILE *infile)
346 /* c = ureadone(infile); */
349 /* if (ff < 0) invalidset((int) c); */
350 if (ff == BLANKFONT) invalidset((int) c);
352 /* if (bRemapControl && c < MAXREMAP) c = remaptable[c]; */
353 if (bRemapControl || bRemapFont) {
354 if (c < MAXREMAP) c = remaptable[c];
356 else if (c == 32) c = 195;
357 else if (c == 127) c = 196;
360 else if (bRemapSpace && c <= 32) { /* 1995/Oct/17 */
361 if (c == 32) c = 195; /* not 160 */
362 else if (c == 13) c = 176; /* 1996/June/4 */
363 else if (c == 10) c = 173; /* 1996/June/4 */
364 else if (c == 9) c = 170; /* 1996/June/4 */
365 else if (c == 0) c = 161;
372 /* simplified 95/Oct/17 by using logo_setsub for logdo_set2 */
374 void logdo_set2(FILE *infile)
376 logdo_setsub(ureadtwo(infile));
380 void logdo_set2(FILE *infile)
383 c = ureadtwo(infile);
385 /* if (ff < 0) invalidset((int) c); */
386 if (ff == BLANKFONT) invalidset((int) c);
388 /* if (bRemapControl && c < MAXREMAP) c = remaptable[c]; */
389 if (bRemapControl || bRemapFont) {
390 if (c < MAXREMAP) c = remaptable[c];
392 else if (c == 32) c = 195;
393 else if (c == 127) c = 196;
396 else if (bRemapSpace && c <= 32) { /* 1995/Oct/17 */
397 if (c == 32) c = 195; /* not 160 */
398 else if (c == 13) c = 176; /* 1996/June/4 */
399 else if (c == 10) c = 173; /* 1996/June/4 */
400 else if (c == 9) c = 170; /* 1996/June/4 */
401 else if (c == 0) c = 161;
409 void logdo_set3(FILE *infile)
411 logdo_setsub(ureadthree(infile));
414 void logdo_set4(FILE *infile)
416 logdo_setsub(ureadfour(infile));
419 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
421 /* common subroutine for put2, put3, pu4 --- which should not occur */
423 void logdo_putsub(unsigned long c)
427 /* if (ff < 0) invalidset((int) c); */
428 if (ff == BLANKFONT) invalidset((int) c);
430 /* if (bRemapControl && c < MAXREMAP) c = remaptable[c]; */
431 if (bRemapControl || bRemapFont) {
432 if (c < MAXREMAP) c = remaptable[c];
434 else if (c == 32) c = 195;
435 else if (c == 127) c = 196;
438 else if (bRemapSpace && c <= 32) { /* 1995/Oct/17 */
439 if (c == 32) c = 195; /* not 160 */
440 else if (c == 13) c = 176; /* 1996/June/4 */
441 else if (c == 10) c = 173; /* 1996/June/4 */
442 else if (c == 9) c = 170; /* 1996/June/4 */
443 else if (c == 0) c = 161;
450 /* For speed we keep the set1 case separate since it occurs sometimes */
452 void logdo_put1(FILE *infile)
455 /* c = ureadone(infile); */
458 /* if (ff < 0) invalidset((int) c); */
459 if (ff == BLANKFONT) invalidset((int) c);
461 /* if (bRemapControl && c < MAXREMAP) c = remaptable[c]; */
462 if (bRemapControl || bRemapFont) {
463 if (c < MAXREMAP) c = remaptable[c];
465 else if (c == 32) c = 195;
466 else if (c == 127) c = 196;
469 else if (bRemapSpace && c <= 32) { /* 1995/Oct/17 */
470 if (c == 32) c = 195; /* not 160 */
471 else if (c == 13) c = 176; /* 1996/June/4 */
472 else if (c == 10) c = 173; /* 1996/June/4 */
473 else if (c == 9) c = 170; /* 1996/June/4 */
474 else if (c == 0) c = 161;
481 /* simplified 95/Oct/17 by using logo_putsub for logdo_put2 */
483 void logdo_put2(FILE *infile)
485 logdo_putsub(ureadtwo(infile));
489 void logdo_put2(FILE *infile)
492 c = ureadtwo(infile);
494 /* if (ff < 0) invalidset((int) c); */
495 if (ff == BLANKFONT) invalidset((int) c);
497 /* if (bRemapControl && c < MAXREMAP) c = remaptable[c]; */
498 if (bRemapControl || bRemapFont) {
499 if (c < MAXREMAP) c = remaptable[c];
501 else if (c == 32) c = 195;
502 else if (c == 127) c = 196;
505 else if (bRemapSpace && c <= 32) { /* 1995/Oct/17 */
506 if (c == 32) c = 195; /* not 160 */
507 else if (c == 13) c = 176; /* 1996/June/4 */
508 else if (c == 10) c = 173; /* 1996/June/4 */
509 else if (c == 9) c = 170; /* 1996/June/4 */
510 else if (c == 0) c = 161;
518 void logdo_put3(FILE *infile)
520 logdo_putsub(ureadthree(infile));
523 void logdo_put4(FILE *infile)
525 logdo_putsub(ureadfour(infile));
528 void logdo_set_rule(FILE *infile)
531 for (k=0; k < 8; k++) (void) getc(infile);
534 void logdo_put_rule(FILE *infile)
537 for (k=0; k < 8; k++) (void) getc(infile);
540 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
542 /* int currentrange; */ /* range currently working in */
543 long currentpage; /* page currently working in */
544 int prescanflag; /* prescan is always forward */
545 int pagesequence; /* count of ascending page sequence */
547 /* returns zero if page is to be printed */ /* non-zero if to be skipped */
549 int skipthispage(long pageno)
552 /* int hitrange=0; */
553 /* int wantpage=0; */
555 if (rangeindex == 0) return 0; /* easy, no page ranges specified! */
557 if (countzeroflag != 0) {
558 if (prescanflag != 0 || reverseflag == 0) {
559 /* going forward, we remain in same page sequence if: */
560 /* (positive and ascending) or (negative and descending) */
561 if (currentpage == -LINFINITY) ; /* first time */
562 else if (currentpage >= 0 && pageno >= 0 && pageno > currentpage) ;
563 else if (currentpage <= 0 && pageno <= 0 && pageno < currentpage) ;
566 else if (reverseflag != 0) {
567 /* going backward, we remain in same page sequence if: */
568 /* (positive and descending) or (negative and ascending) */
569 if (currentpage == -LINFINITY) ; /* first time */
570 else if (currentpage >= 0 && pageno >= 0 && pageno < currentpage) ;
571 else if (currentpage <= 0 && pageno <= 0 && pageno > currentpage) ;
574 currentpage = pageno; /* remember page number */
577 for (k = 0; k < rangeindex; k++) {
578 /* is current page in this page range ? */
579 if ((pageno >= beginpages[k]) && (pageno <= endpages[k])) {
580 if (countzeroflag == 0) return 0; /* easy, not using count[0] */
581 if (pagerangeseq[k] < 0) /* no instance specified */
582 return 0; /* means always print */
583 if (pagerangeseq[k] == pagesequence) /* matches instance */
584 return 0; /* OK, print it */
587 return 1; /* not inside any specified range */
590 void logdo_bop(FILE *infile) /* beginning of page */
593 long current; /* ??? */
595 current = ftell(input) - 1;
597 pagenumber++; /* increment pages seen - going forward here */
598 reset_stack(); /* stinx = 0; */
599 ff = -1; /* undefined font */
600 fnt = finx[0]; /* just in case - not clear could be -1 ! or 255 */
601 // currentfont = fontchar; /* just in case */
602 currentfont = fontchar[0]; /* just in case ??? */
604 for(k=0; k < 10; k++) counter[k] = sreadfour(infile);
606 previous = sreadfour(infile);
608 if (countzeroflag != 0) pageno = counter[0];
609 else pageno = (long) pagenumber;
610 skipflag = skipthispage(pageno); /* figure out if skipped */
611 /* if (beginpage != -LINFINITY && pageno < beginpage) skipflag++;
612 if (endpage != LINFINITY && pageno > endpage) skipflag++; */
613 /* following is the logic for two-sided printing */
615 if (oddpageflag != 0 && (counter[0] & 1) == 0) skipflag++;
616 if (evenpageflag != 0 && (counter[0] & 1) == 1) skipflag++;
618 /* what about first page ? */
620 if (colorindex > 0) /* avoid error on first page */
621 doColorPop(pagenumber); /* 98/Feb/15 to match ColorPush in eop */
623 if (bBackGroundFlag) { /* carry background color 99/Apr/05 */
624 if (pagenumber > 0) /* avoid on first page */
625 BackColors[pagenumber] = BackColors[pagenumber-1];
626 /* else if (pagenumber == 0) {
627 BackColors[0].A = BackColors[0].B = BackColors[0].C = -1.0F;
628 BackColors[0].D = -1.0F;
633 void logdo_eop(FILE *infile) { /* end of page */
636 if (bAbort) abortjob(); /* 1992/Nov/24 */
637 if (abortflag) return;
638 check_stack(pagenumber);
640 doColorPush(pagenumber); /* 98/Feb/15 ??? */
641 SaveColorStack(pagenumber, colorindex); /* 98/Feb/19 ??? */
644 (void) ureadfour(infile); /* flush Textures length code */
645 /* may want to check whether length is something reasonable ? */
646 c = getc(infile); (void) ungetc(c, infile); /* peek ahead */
647 /* here we expect to see bop, nop or fnt_def's ONLY */
648 if (c >= 0 && c <= 127) {
649 sprintf(logline, " ERROR: Invalid DVI code (%d) between EOP and BOP ", c);
650 showline(logline, 1);
651 tellwhere(infile, 1);
655 if (skipflag == 0) numpages++; /* 94/Oct/12 */
659 void logdo_right1(FILE *infile) /* rare */
664 void logdo_right2(FILE *infile)
666 (void) getc(infile); (void) getc(infile);
669 void logdo_right3(FILE *infile)
671 (void) getc(infile); (void) getc(infile); (void) getc(infile);
674 void logdo_right4(FILE *infile)
676 (void) getc(infile); (void) getc(infile);
677 (void) getc(infile); (void) getc(infile);
684 void logdo_w1(FILE *infile) /* rare */
689 void logdo_w2(FILE *infile)
691 (void) getc(infile); (void) getc(infile);
694 void logdo_w3(FILE *infile)
696 (void) getc(infile); (void) getc(infile); (void) getc(infile);
699 void logdo_w4(FILE *infile)
701 (void) getc(infile); (void) getc(infile);
702 (void) getc(infile); (void) getc(infile);
709 void logdo_x1(FILE *infile) /* rare */
714 void logdo_x2(FILE *infile)
716 (void) getc(infile); (void) getc(infile);
719 void logdo_x3(FILE *infile)
721 (void) getc(infile); (void) getc(infile); (void) getc(infile);
724 void logdo_x4(FILE *infile)
726 (void) getc(infile); (void) getc(infile);
727 (void) getc(infile); (void) getc(infile);
730 void logdo_down1(FILE *infile) /* rare */
735 void logdo_down2(FILE *infile) /* rare */
737 (void) getc(infile); (void) getc(infile);
740 void logdo_down3(FILE *infile)
742 (void) getc(infile); (void) getc(infile); (void) getc(infile);
745 void logdo_down4(FILE *infile)
747 (void) getc(infile); (void) getc(infile);
748 (void) getc(infile); (void) getc(infile);
755 void logdo_y1(FILE *infile) /* rare */
760 void logdo_y2(FILE *infile)
762 (void) getc(infile); (void) getc(infile);
765 void logdo_y3(FILE *infile)
767 (void) getc(infile); (void) getc(infile); (void) getc(infile);
770 void logdo_y4(FILE *infile) /* not used */
772 (void) getc(infile); (void) getc(infile);
773 (void) getc(infile); (void) getc(infile);
780 void logdo_z1(FILE *infile) /* rare */
785 void logdo_z2(FILE *infile)
787 (void) getc(infile); (void) getc(infile);
790 void logdo_z3(FILE *infile)
792 (void) getc(infile); (void) getc(infile); (void) getc(infile);
795 void logdo_z4(FILE *infile)
797 (void) getc(infile); (void) getc(infile);
798 (void) getc(infile); (void) getc(infile);
801 void logswitchfont(int fn, FILE *infile) /* switching to other font */
804 ff = fn; /* set state */
807 if (fnt == BLANKFONT) { /* 93/Dec/11 */
809 c = getc(infile); (void) ungetc(c, infile);
811 sprintf(logline, " ERROR: Unexpected encounter of DVI trailer on page %d ", pagenumber);
812 showline(logline, 1);
819 sprintf(logline, " ERROR: switch to undefined font (%d) on page %d ",
821 showline(logline, 1);
822 tellwhere(infile, 1);
826 // currentfont = fontchar + MAXCHRS * fnt;
827 if (fontchar[fnt] == NULL) setupfontchar(fnt);
828 currentfont = fontchar[fnt];
829 fonthit[fnt] = 1; /* even if skipflag != 0 ? */
832 void logdo_fnt1(FILE *infile) /* switch fonts */
835 /* fn = ureadone(infile); */
837 /* if (skipflag == 0) */
838 logswitchfont(fn, infile);
841 void logdo_fnt2(FILE *infile) /* switch fonts */
844 fn = ureadtwo(infile);
845 /* if (skipflag == 0) */
846 if (fn >= MAXFONTNUMBERS) fn = MAXFONTNUMBERS-1;
847 logswitchfont((int) fn, infile);
850 void logdo_fntsub(unsigned long fn, FILE *infile) /* switch fonts */
852 /* if (skipflag == 0) */
853 if (fn >= MAXFONTNUMBERS) fn = MAXFONTNUMBERS-1;
854 logswitchfont((int) fn, infile);
857 void logdo_fnt3(FILE *infile) /* switch fonts */
860 fn = ureadthree(infile); */
861 logdo_fntsub(ureadthree(infile), infile);
864 void logdo_fnt4(FILE *infile) /* switch fonts */
867 fn = sreadfour(infile);
868 /* if (skipflag == 0) */
870 logdo_fntsub((unsigned long) fn, infile);
873 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
875 void getheadername (FILE *infile) /* new version 95/Aug/30 */
877 char fname[FNAMELEN]; /* buffer to get token into */
880 /* if (gettoken(infile, headerfile, FNAMELEN) == 0) {*/
881 if (gettoken(infile, fname, sizeof(fname)) == 0) { /* FNAMELEN */
882 showline(" Can't find header\n", 1);
887 // check whether this header file has already been listed
888 // if ((s = strstr(headerfile, fname)) != NULL) {
889 if (headerfile != NULL) {
890 if ((s = strstr(headerfile, fname)) != NULL) {
892 if (*s == '\0' || *s == ',') {
898 // check whether there is enough space for the new name to add
899 // if (strlen(headerfile) + strlen(fname) + 2 >= sizeof(headerfile)) {
900 // sprintf(logline, " No more space for HEADER (> %d)\n", sizeof(headerfile));
901 // showline(logline, 1);
906 if (headerfile == NULL) {
907 // nheaderlength = strlen(headerfile) + 2;
908 nheaderlength = strlen(fname) + 2;
909 headerfile = malloc(nheaderlength);
910 if (headerfile == NULL) return; // allocation error - complain ???
914 while (strlen(headerfile) + strlen(fname) + 2 > (size_t) nheaderlength) {
915 nheaderlength += strlen(fname) + 2;
916 headerfile = realloc(headerfile, nheaderlength);
918 if (headerfile == NULL) return; // allocation error - complain ???
920 // add a comma separator, unless this is the first one
921 if (*headerfile != '\0') {
922 s = headerfile + strlen(headerfile);
924 *s = '\0'; // not needed
926 else s = headerfile; // first time
928 // finally: append the header file name ...
932 /* get name of file with DSC header comments */ /* only one allowed */
934 void getcustomname (FILE *infile)
938 if (dscfile != NULL) {
939 showline(" More than one DSCheader", 1);
943 /* if (gettoken(infile, line, MAXLINE) == 0) { */
944 if (gettoken(infile, line, sizeof(line)) == 0) { /* MAXLINE */
945 showline(" Can't find header\n", 1);
949 dscfile = zstrdup(line); /* remember single file name */
953 /* accumulate verbatim PS header text for prolog */
955 void getheadertext (FILE *infile) /* new 1993/Dec/29 */
961 /* if (headertext == NULL) headernew = malloc (nspecial+2); else */
962 /* first time around, headertext will be NULL, so it acts like malloc */
963 n = headertextlen + (int) nspecial + 2;
964 /* headernew = realloc (headertext, n); */
965 headernew = realloc (headertext, n);
966 if (headernew == NULL) {
967 showline(" Unable to allocate memory\n", 1);
968 /* flushspecial(infile); */
971 checkexit(1); /* 1995/July/15 */
972 // more serious exit(1) ???
974 headertext = headernew;
975 u = headernew + headertextlen;
976 headertextlen = headertextlen + (int) nspecial + 1;
977 while (nspecial-- > 0) *u++ = (char) getc(infile);
978 *u++ = '\n'; *u++ = '\0'; /* terminating linefeed and \0 */
981 /* accumulate command line args for DVIPSONE - passed through DVI file */
983 void getcommandspec (FILE *infile) // 99/Sept/6
989 /* first time around, commandspec will be NULL, so it acts like malloc */
990 n = commandspeclen + (int) nspecial + 2;
991 commandnew = realloc (commandspec, n);
992 if (commandnew == NULL) {
993 showline(" Unable to allocate memory\n", 1);
996 commandspec = commandnew;
997 u = commandnew + commandspeclen;
998 commandspeclen = commandspeclen + (int) nspecial + 1;
999 while (nspecial-- > 0) *u++ = (char) getc(infile);
1000 *u++ = '\n'; *u++ = '\0'; // terminating linefeed and \0
1003 /* accumulate verbatim PS header text for prolog */
1005 void getcustomtext (FILE *infile) /* new 1995/July/15 */
1007 int c, n, needpercent=0;
1011 c = getc(infile); ungetc(c, infile);
1012 if (c != '%') needpercent = 1;
1013 /* if (dsccustom == NULL) customnew = malloc (nspecial+2); else */
1014 /* first time around, dsccustom will be NULL, so it acts like malloc */
1015 n = dsccustomlen + (int) nspecial + 2;
1016 if (needpercent) n = n+2;
1017 /* customnew = realloc (dsccustom, n); */
1018 customnew = realloc (dsccustom, n);
1019 if (customnew == NULL) {
1020 showline(" Unable to allocate memory\n", 1);
1021 /* flushspecial(infile); */
1024 checkexit(1); /* 1995/July/15 */
1025 // more serious exit(1) ???
1027 dsccustom = customnew;
1028 u = customnew + dsccustomlen;
1029 dsccustomlen = dsccustomlen + (int) nspecial + 1;
1031 *u++ = '%'; *u++ = '%';
1032 dsccustomlen = dsccustomlen + 2;
1034 while (nspecial-- > 0) *u++ = (char) getc(infile);
1035 *u++ = '\n'; *u++ = '\0'; /* terminating linefeed and \0 */
1038 void getbbox (FILE *infile) /* Use for CropBox pdfmark not tested */
1040 /* Right now this is in PS coordinates, should be in TeX coordinates */
1041 if (gettoken(infile, line, sizeof(line)) != 0) { /* MAXLINE */
1042 sscanf(line, "%d", &BBxll);
1044 if (gettoken(infile, line, sizeof(line)) != 0) { /* MAXLINE */
1045 sscanf(line, "%d", &BByll);
1047 if (gettoken(infile, line, sizeof(line)) != 0) { /* MAXLINE */
1048 sscanf(line, "%d", &BBxur);
1050 if (gettoken(infile, line, sizeof(line)) != 0) { /* MAXLINE */
1051 sscanf(line, "%d", &BByur);
1055 /* accumulate Keywords for DOCINFO pdfmark */
1057 void getkeywords (FILE *infile) /* 1996/May/10 */
1062 int needcomma=0; /* 0 or 2 if comma and space needed */
1064 /* if (headertext == NULL) headernew = malloc (nspecial+2); else */
1065 /* will add comma separator unless first, or comma or space already */
1066 if (keywordslen == 0) needcomma = 0;
1068 c = *(keywords + keywordslen - 1);
1069 if (c == ',' || c == ' ' || c == '\t') needcomma = 0;
1072 /* n = keywordslen + (int) nspecial + 2; */ /* space for , and \0 */
1073 n = keywordslen + (int) nspecial + needcomma + 1;
1074 /* first time around, keywords will be NULL, so it acts like malloc(n) */
1075 keywordsnew = realloc (keywords, n);
1076 if (keywordsnew == NULL) {
1077 showline(" Unable to allocate memory\n", 1);
1078 /* flushspecial(infile); */
1081 checkexit(1); /* 1995/July/15 */
1082 // more serious exit(1) ???
1084 keywords = keywordsnew;
1085 u = keywordsnew + keywordslen;
1086 if (needcomma > 0) {
1087 *u++ = ','; /* add , if needed */
1088 *u++ = ' '; /* add if needed */
1090 keywordslen = keywordslen + (int) nspecial + needcomma;
1091 while (nspecial-- > 0) *u++ = (char) getc(infile);
1092 *u++ = '\0'; /* terminating \0 */
1095 // void getcommonstring (FILE *infile, char *newstring)
1096 char *getcommonstring (FILE *infile)
1099 char *newstring = malloc ((size_t) (nspecial+1));
1100 if (newstring == NULL) {
1101 showline(" Unable to allocate memory\n", 1);
1106 while (nspecial-- > 0) *u++ = (char) getc(infile);
1107 *u++ = '\0'; /* terminating \0 */
1111 // unadvertized ability to change Creator fieldin DocInfo
1113 void getcreator (FILE *infile)
1115 if (creatorstring != NULL) return; /* ignore all but first */
1116 // creatorstring = malloc ((size_t) (nspecial+1));
1117 // getcommonstring(infile, creatorstring);
1118 creatorstring = getcommonstring(infile);
1121 void gettitle (FILE *infile)
1123 if (titlestring != NULL) return; /* ignore all but first */
1124 // titlestring = malloc ((size_t) (nspecial+1));
1125 // getcommonstring(infile, titlestring);
1126 titlestring = getcommonstring(infile);
1129 void getsubject (FILE *infile)
1131 if (subjectstring != NULL) return; /* ignore all but first */
1132 // subjectstring = malloc ((size_t) (nspecial+1));
1133 // getcommonstring(infile, subjectstring);
1134 subjectstring = getcommonstring(infile);
1137 void getauthor (FILE *infile)
1139 if (authorstring != NULL) return; /* ignore all but first */
1140 // authorstring = malloc ((size_t) (nspecial+1));
1141 // getcommonstring(infile, authorstring);
1142 authorstring = getcommonstring(infile);
1145 void getbase (FILE *infile)
1147 if (basestring != NULL) return; /* ignore all but first */
1148 // basestring = malloc ((size_t) (nspecial+1));
1149 // getcommonstring(infile, basestring);
1150 basestring = getcommonstring(infile);
1153 void getpagemode (FILE *infile)
1155 if (pagemode != NULL) return; /* ignore all but first */
1156 // pagemode = malloc ((size_t) (nspecial+1));
1157 // getcommonstring(infile, pagemode);
1158 pagemode = getcommonstring(infile);
1161 /* example \special{papersize=5.04in,3.751in} */
1163 void getpapersize (FILE *infile)
1165 // if (strcmp(papersize,"") != 0) return; /* ignore all but first */
1166 if (papersize != NULL) return;
1167 // papersize = malloc ((size_t) (nspecial+1));
1168 // getcommonstring(infile, papersize);
1169 papersize = getcommonstring(infile);
1172 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
1174 int bComplainSpecial=1;
1176 /* Attempt at \special{background rgb 0 0 1} support 98 June 30 */
1178 void DoBackGround (FILE *infile, int c)
1183 COLORSPEC SavedColor;
1185 if (bBackGroundFlag == 0)
1187 flushspecial(infile);
1191 s = line + strlen(line);
1192 if (c > 0) *s++ = (char) c; /* stick in terminator */
1193 *s = '\0'; /* just in case */
1194 (void) scanspecial(input, line, MAXLINE);
1198 sprintf(logline, "\n%s %c (%d) ", line, c, c);
1199 showline(logline, 0);
1202 /* if (c > 0) return; */ /* only do in prescan ! */
1204 if (*s == '\0') return;
1205 if (bKeepBlack) return; /* 96/Nov/3 */
1207 SavedColor = CurrColor; /* 99/Apr/06 */
1208 if (strncmp(s, "rgb", 3) == 0)
1211 m = sscanf(s, "%g %g %g%n\n", &CurrColor.A, &CurrColor.B, &CurrColor.C, &n);
1214 CurrColor.D = -1.0F;
1220 complainspecial(input);
1224 else if (strncmp(s, "cmyk", 4) == 0) {
1226 m = sscanf(s, "%g %g %g %g%n",
1227 &CurrColor.A, &CurrColor.B, &CurrColor.C, &CurrColor.D, &n);
1233 complainspecial(input);
1237 else if (strncmp(s, "gray", 4) == 0) {
1239 m = sscanf(s, "%g%n", &CurrColor.A, &n);
1241 /* CurrentC = CurrentB = CurrentA; CurrentD = -2.0F; */
1242 CurrColor.C = CurrColor.B = CurrColor.A;
1243 CurrColor.D = -2.0F;
1248 complainspecial(input);
1252 else if (_strnicmp(s, "black", 5) == 0) {
1255 /* CurrentC = CurrentB = CurrentA = 0.0F; CurrentD = 1.0F; */
1256 CurrColor.C = CurrColor.B = CurrColor.A = 0.0F;
1259 else if (_strnicmp(s, "white", 5) == 0) {
1262 /* CurrentC = CurrentB = CurrentA = 0.0F;
1264 CurrColor.C = CurrColor.B = CurrColor.A = 0.0F;
1268 complainspecial(input); /* 1995/April/15 */
1274 sprintf(logline, " PAGENUMBER %d (%d %d) ", pagenumber, dvi_t, MaxColor);
1275 showline(logline, 0);
1278 /* if (pagenumber < 0 || pagenumber >= dvi_t) */
1279 if (pagenumber < 0 || pagenumber > dvi_t) { /* 99/Feb/21 */
1280 sprintf(logline, " ERROR: bad page number %d\n", pagenumber);
1281 showline(logline, 1);
1287 sprintf(logline, "\npage %d %g %g %g %g\n",
1288 pagenumber, CurrColor.A, CurrColor.B, CurrColor.C,
1290 showline(logline, 0);
1292 BackColors[pagenumber] = CurrColor; /* ??? */
1293 bBackUsed = 1; /* mark background color used */
1294 CurrColor = SavedColor; /* 99/Apr/06 */
1302 /* char *tpiccommand[] = {
1303 "pa", "fp", "ip", "da", "dt", "sp", "pn", "ar", "ia",
1304 "sh", "wh", "bk", "tx", ""
1307 char *tpiccommands = "pa fp ip da dt sp pn ar ia sh wh bk tx";
1311 /* Maybe check for TPIC specials only in selected page range ... */
1312 /* Hmm, may want to search for inserted figure files here and extract */
1313 /* DocumentNeededResources, DocumentFonts to save for writing in header ... */
1314 /* No, use IncludeResource: font ... and IncludeFont: ... ? */
1315 /* also check for \special{insertimage: ...} TIFF images re level2 96/Dec/20 */
1316 /* also check for \special{color ...} */
1317 /* also check for \special{background ...} 98/Jun/30 */
1319 void logdo_com (FILE *infile)
1324 if (bIgnoreSpecials)
1326 flushspecial(infile);
1329 nspecialsav = nspecial; /* 99/Feb/21 */
1330 specstart = ftell(input); /* for complainspecial 99/Feb/21 */
1331 c = getc(infile); /* peek ahead for ! */
1333 if (c == 0 && bFirstNull) { /* is first byte null ? 96/Aug/29 */
1334 flushspecial(infile);
1338 /* if (verbatimflag != 0) { */ /* flushed 97/Mar/9 */
1339 c = getc(infile); nspecial--;
1340 getheadertext(infile);
1342 flushspecial(infile);
1345 /* c = getalphatoken(infile, line, MAXLINE); */
1346 c = getalphatoken(infile, line, sizeof(line)); /* MAXLINE */
1348 /* check whether maybe a TPIC \special */
1349 if (allowtpic != 0 && needtpic == 0 && (c == ' ' || c == 0)) {
1350 /* while (strcmp(tpiccommand[k], "") != 0) {
1351 if (strcmp(line, tpiccommand[k]) == 0) {
1356 if (strlen(line) == 2 && strstr(tpiccommands, line) != NULL)
1360 if (c == ' ' || c == ':') {
1361 if (strcmp(line, "color") == 0) {
1362 doColor(NULL, input, c, 0); /* no PS output */
1363 bColorUsed = 1; /* 98/Feb/14 */
1365 else if (strcmp(line, "background") == 0) {
1366 DoBackGround (infile, c);
1367 /* bColorUsed = 1; */ /* ? */
1369 else if (strcmp(line, "landscape") == 0) { /* 99/Apr/5 foils.cls */
1370 bLandScape = ! bLandScape; /* sets globally ! */
1373 /* check whether a special calling for a header or prolog file */
1374 /* if(c == '=' && strcmp(line, "header") == 0) getheadername(infile); */
1375 /* Separator is `=' */
1376 if(c == '=') { /* extended 93/Dec/29 */
1377 /* if (strcmp(line, "header") == 0) getheadername(infile); */
1378 if (_strcmpi(line, "header") == 0) getheadername(infile);
1379 /* else if (strcmp(line, "headertext") == 0) getheadertext(infile); */
1380 else if (_strcmpi(line, "headertext") == 0) getheadertext(infile);
1381 /* following added in 1995 July */
1382 else if (strcmp(line, "DSCheader") == 0) getcustomname(infile);
1383 else if (strcmp(line, "DSCtext") == 0) getcustomtext(infile);
1384 else if (strcmp(line, "papersize") == 0) getpapersize(infile);
1385 else if (strcmp(line, "DVIPSONE") == 0) getcommandspec(infile);
1386 else if (strcmp(line, "DVIWindo") == 0) flushspecial(infile);
1387 /* else complain ??? */
1389 /* else if (c == ':' && strcmp(line, "dvitops") == 0) { */
1390 /* Separator is `:' */
1391 else if (c == ':') {
1392 if (strcmp(line, "dvitops") == 0) {
1393 /* (void) getalphatoken(infile, line, MAXLINE); */
1394 (void) getalphatoken(infile, line, sizeof(line)); /* MAXLINE */
1395 if (strcmp(line, "prolog") == 0) getheadername(infile);
1397 else if (strcmp(line, "PDF") == 0) { /* 1996/July/4 */
1398 c = getalphatoken(infile, line, sizeof(line)); /* MAXLINE */
1399 if (c == ' ' || c == '=') {
1400 if (_strcmpi(line, "Keywords") == 0) getkeywords(infile);
1401 else if (strcmp(line, "BBox") == 0) getbbox(infile);
1402 else if (_strcmpi(line, "Creator") == 0) getcreator(infile);
1403 else if (_strcmpi(line, "Title") == 0) gettitle(infile);
1404 else if (_strcmpi(line, "Subject") == 0) getsubject(infile);
1405 else if (_strcmpi(line, "Author") == 0) getauthor(infile);
1406 else if (_strcmpi(line, "Base") == 0) getbase(infile);
1407 else if (_strcmpi(line, "PageMode") == 0) getpagemode(infile);
1410 /* check whether TIFF image inserted re level2 features 96/Dec/20 */
1411 else if (strcmp(line, "insertimage") == 0) bInsertImage++;
1413 flushspecial(infile);
1416 void logdo_xxxi(FILE *infile, unsigned int n)
1418 /* unsigned int k; */
1419 nspecial = (long) n;
1421 /* for(k = 0; k < n; k++) getc(infile); */
1424 void logdo_xxx1(FILE *infile) /* for /special */
1428 logdo_xxxi(infile, k);
1431 void logdo_xxx2(FILE *infile) /* for /special */
1434 k = ureadtwo(infile);
1435 logdo_xxxi(infile, k);
1438 void logdo_xxxl(FILE *infile, unsigned long n)
1440 /* unsigned long k; */
1443 /* for(k = 0; k < n; k++) getc(infile); */
1446 void logdo_xxx3(FILE *infile)
1448 logdo_xxxl(infile, ureadthree(infile));
1451 void logdo_xxx4(FILE *infile)
1453 logdo_xxxl(infile, ureadfour(infile));
1456 /* need to do this even if skipping pages */
1458 void logfnt_def(FILE *infile, unsigned int k)
1461 unsigned int na, nl, i;
1462 int newfont=1; /* if this is a new one (not defined before) */
1465 char namebuffer[FNAMELEN];
1467 if (finx[k] != BLANKFONT) { /* seen this font before !!! */
1468 sprintf(logline, " ERROR: Font %d being redefined ", k);
1469 showline(logline, 1);
1470 tellwhere(infile, 1);
1475 else { /* definition of font not seen before */
1476 fn = fnext++; /* grab next slot */
1477 finx[k] = (short) fn;
1478 if (fnext > maxfonts) { /* 94/May/23 */
1479 sprintf(logline, " ERROR: More than %d fonts in use\n", maxfonts);
1480 showline(logline, 1);
1483 checkexit(1); /* 1993/Dec/11 */
1487 fc[fn] = ureadfour(infile); /* read checksum (encoding info) */
1488 /* (void) ureadfour(infile); */
1489 fs[fn] = ureadfour(infile); /* read at size */
1490 /* fd[fn] = ureadfour(infile); */ /* design size */
1491 (void) ureadfour(infile); /* skip over design size */
1494 if (newfont == 0) { /* just skip over if already defined */
1495 for (i = 0; i < na + nl; i++) (void) getc(infile);
1498 /* fp = fontname[fn]; */
1500 if (na + nl >= sizeof(namebuffer)-1) { /* FNAMELEN */
1501 sprintf(logline, " Font name too long: %d (> %d) ",
1502 na + nl, sizeof(namebuffer)-1);
1503 showline(logline, 1);
1506 tellwhere(infile, 1);
1507 for (i = 0; i < na+nl; i++) (void) getc(infile);
1510 for (i = 0; i < na+nl; i++) *fp++ = (char) getc(infile);
1513 if (fontname[fn] != NULL) free(fontname[fn]);
1514 fontname[fn] = zstrdup(namebuffer);
1515 /* strcpy(subfontname[fn], ""); */ /* blank it out */
1516 if (subfontname[fn] != NULL) { /* blank it out */
1517 free(subfontname[fn]);
1518 subfontname[fn] = NULL;
1520 // strcpy(fontvector[fn], ""); /* 1992/May/4 */
1521 // *(fontvector + fn * MAXVECNAME) = '\0'; /* blank it out */
1522 if (fontvector[fn] != NULL) {
1523 free(fontvector[fn]);
1524 fontvector[fn] = NULL; /* blank it out */
1526 fontsubflag[fn] = -1; /* all this goes to extract now */
1527 fontproper[fn] = 0; /* 1992/May/4 */
1528 /* possibly determine whether we need to reencode *control* range ??? */
1529 /* if (substitute != 0) fontsubflag[fn] = fontremap(fontname[fn]);
1530 if (uppercaseflag != 0) uppercase(font, fontname[fn]); else */
1531 /* strcpy(font, fontname[fn]); */ /* what for ??? */
1532 // tempfont = fontchar[fn]; /* reset character counts */
1533 // tempfont = fontchar + MAXCHRS * fn;
1534 /* for (i = 0; i < MAXCHRS; i++) tempfont[i] = 0; */
1535 // for (i = 0; i < MAXCHRS; i++) *tempfont++ = 0; /* 1994/Feb/3 */
1536 if (fontchar[fn] == NULL) {
1537 fontchar[fn] = (char *) malloc(MAXCHRS);
1538 if (fontchar[fn] == NULL) {
1539 showline(" Unable to allocate memory\n", 1);
1544 memset(fontchar[fn], 0, MAXCHRS);
1547 void logdo_fnt_def1(FILE *infile) /* define font */
1550 /* k = ureadone(infile); */
1552 logfnt_def(infile, k);
1555 void logdo_fnt_def2(FILE *infile) /* define font */
1558 k = ureadtwo(infile);
1559 if (k >= MAXFONTNUMBERS) k = MAXFONTNUMBERS-1;
1560 logfnt_def(infile, k);
1563 void logdo_fnt_defsub(FILE *infile, unsigned long k)
1565 if (k >= MAXFONTNUMBERS) k = MAXFONTNUMBERS-1;
1566 logfnt_def(infile, (unsigned int) k);
1569 void logdo_fnt_def3(FILE *infile) /* define font */
1572 k = ureadthree(infile); */
1573 logdo_fnt_defsub(infile, ureadthree(infile));
1576 void logdo_fnt_def4(FILE *infile) /* define font */
1579 k = sreadfour(infile);
1581 logdo_fnt_defsub(infile, (unsigned long) k);
1584 /* need to do this even if skipping pages */
1586 void logdo_pre(FILE *infile)
1588 unsigned int i, k, j;
1592 /* i = ureadone(infile); */
1596 showline("Not a valid DVI file ", 1);
1600 else if (i != ID_BYTE)
1602 sprintf(logline, "File is DVI version %d - *not* %d\n",
1604 showline(logline, 1);
1607 num = ureadfour(infile);
1608 den = ureadfour(infile);
1609 mag = ureadfour(infile);
1610 /* k = ureadone(infile); */
1611 k = getc(infile); /* bytes needed for TeX's comment */
1612 /* s = comment; */ /* was to char comment[MAXCOMMENT] */
1613 // if (strcmp(comment, "") != 0) { /* free if still in use */
1614 if (comment != NULL) { /* free if still in use */
1619 comment = malloc(k+1);
1620 if (comment == NULL)
1622 showline(" Unable to allocate memory\n", 1);
1624 // more serious exit(1) ???
1627 /* if (traceflag) fprintf(stdout, "Comment:"); */
1628 c = getc(infile); /* try and discard initial space */
1630 else (void) ungetc(c, infile);
1631 for (j=0; j < k; j++)
1634 if (j < MAXCOMMENT) *s++ = (char) c;
1635 /* if (verboseflag) putc(c, stdout); */
1639 showline(comment, 0);
1643 (void) ureadfour(infile); /* flush length code */
1646 /* need to do this even if skipping pages */
1648 void logdo_post(FILE *infile)
1651 previous = sreadfour(infile); /* was ureadfour ... */
1652 num = ureadfour(infile);
1653 den = ureadfour(infile);
1654 mag = ureadfour(infile);
1658 sprintf(logline, " POST: previous %ld num %ld den %ld mag %ld\n",
1659 previous, num, den, mag);
1660 showline(logline, 0);
1662 /* compare these with what was in preamble ? */
1664 dvi_l = ureadfour(infile); /* max page height plus depth */
1665 dvi_u = ureadfour(infile); /* max page width */
1666 dvi_s = (int) ureadtwo(infile); /* max stack depth */
1667 dvi_t = (int) ureadtwo(infile); /* number bops limit 65535 */
1669 sprintf(logline, "l %ld u %ld s %ld t %ld\n",
1670 dvi_l, dvi_u, dvi_s, dvi_t);
1671 showline(logline, 0);
1673 /* here l and u could be used for bbox info ? */
1674 /* except: don't include headers and footers and other problems */
1678 /* could do this even in forward mode to check on number of pages ? */
1680 void logdo_post_post(FILE *infile) /* only in reverse ? */
1682 /* unsigned long q; */
1683 /* unsigned int i; */
1685 if (traceflag) showline("Hit POSTPOST!\n", 0);
1687 /* q = ureadfour(infile); */
1688 (void) ureadfour(infile);
1689 /* i = ureadone(infile); */
1690 (void) getc(infile);
1691 /* check ID_BYTE again ? */
1692 /* followed by at least four 223's */
1693 /* if (reverseflag != 0) fseek(infile, previous, SEEK_SET);
1694 else fputs("%% This is really the end !\n", output); */
1697 /* This version scans for Textures length code followed by pre & DVI code */
1698 /* could do something more fancy to get quickly to resource fork */
1699 /* should be fairly safe, unless initial length code is > 256 */
1700 /* Search for 3 or more zeros in a row, followed by dont-care (length) */
1701 /* - followed by pre and ID_BYTE */
1703 int readovertext(FILE *infile)
1709 /* if ((c = getc(infile)) == 0) { */
1712 while ((c = getc(infile)) == 0) n++;
1713 if (c == EOF) return 0;
1715 if((c = getc(infile)) == (int) pre) {
1716 (void) ungetc(c, infile);
1717 dvistart = ftell(infile);
1719 if ((c = getc(infile)) == ID_BYTE) {
1720 if (fseek(infile, dvistart, SEEK_SET) != 0)
1721 return 0; /* seek error */
1722 else return -1; /* think we found it ! */
1727 else if ((c = getc(infile)) == EOF) return 0;
1731 void resetpagerangehit (int flag)
1734 /* for (k = 0; k < rangeindex; k++) pagerangehit[k] = 0; */ /* 1994/Jan/16 */
1735 /* currentrange = -1; */
1736 currentpage = -LINFINITY; /* indicate first time */
1737 prescanflag = flag; /* remember whether in prescan or not */
1738 if (prescanflag != 0 || reverseflag == 0)
1739 pagesequence = 1; /* 1994/Feb/16 */
1740 /* NOTE: don't reset page sequence instance if going in reverse order */
1743 /***************************************************************************/
1745 void alloccolorsave (int npages)
1749 if (ColorStacks != NULL)
1751 showline(" ERROR: color save stacks allocation\n", 1);
1754 #ifdef DEBUGCOLORSTACK
1757 sprintf(logline, "Allocating color save stack for %d pages\n", npages);
1758 showline(logline, 0);
1761 if (npages == 0) npages = 1;
1762 ColorStacks = (COLORSPEC **) malloc((npages+1) * sizeof(COLORSPEC *));
1763 if (ColorStacks == NULL) {
1764 showline(" Unable to allocate memory\n", 1);
1766 // more serious exit(1) ???
1768 for (k = 0; k <= npages; k++) ColorStacks[k] = NULL;
1769 MaxColor = npages+1; /* make note of size of allocation */
1772 void freecolorsave (void)
1774 int k, npages = MaxColor;
1776 if (ColorStacks == NULL) return;
1777 #ifdef DEBUGCOLORSTACK
1778 if (traceflag) showline("Freeing Saved Color Stacks\n", 0);
1780 for (k = 0; k < npages; k++) {
1781 if (ColorStacks[k] != NULL) {
1782 free(ColorStacks[k]);
1783 ColorStacks[k] = NULL;
1786 if (ColorStacks != NULL) {
1792 #ifdef DEBUGCOLORSTACK
1793 void dumpcolorsave (void) /* debugging only */
1795 int k, m, i, npages = MaxColor-1;
1796 COLORSPEC *ColorSaved;
1798 if (ColorStacks == NULL)
1800 showline(" No saved color stacks to show\n", 1);
1803 sprintf(logline, " Saved color stacks for %d pages after prescan:\n", npages);
1804 showline(logline, 1);
1805 /* for (k = 0; k < npages; k++) { */
1806 for (k = 1; k <= npages; k++) {
1807 if (ColorStacks[k] != NULL) {
1808 sprintf(logline, "For page %d:\n", k);
1809 showline(logline, 1);
1810 ColorSaved = ColorStacks[k];
1811 m = (int) (ColorSaved[0].D + 0.5);
1812 for (i = 1; i <= m; i++) {
1813 sprintf(logline, "%d\t%g\t%g\t%g\t%g\n", i,
1814 ColorSaved[i].A, ColorSaved[i].B,
1815 ColorSaved[i].C, ColorSaved[i].D);
1816 showline(logline, 1);
1820 sprintf(logline, " ERROR: ColorStack[%d] is NULL\n", k);
1821 showline(logline, 1);
1827 void allocbackground (int npages)
1830 if (BackColors != NULL) {
1831 showline(" ERROR: background allocation\n", 1);
1834 if (npages == 0) npages = 1;
1835 /* BackColors = (COLORSPEC *) malloc(npages * sizeof(COLORSPEC)); */
1836 BackColors = (COLORSPEC *) malloc((npages+1) * sizeof(COLORSPEC));
1837 if (BackColors == NULL) {
1838 showline(" Unable to allocate memory\n", 1);
1840 // more serious exit(1) ???
1842 /* for (k = 0; k < npages; k++) */
1843 for (k = 0; k <= npages; k++) { /* may not be needed */
1844 BackColors[k].A = BackColors[k].B = BackColors[k].C = -1.0F;
1845 BackColors[k].D = -1.0F;
1849 void freebackground (void) {
1850 if (BackColors != NULL) free(BackColors);
1854 /***************************************************************************/
1856 int scanlogfileaux(FILE *fp_in)
1861 // strcpy (headerfile, ""); /* reset to no headers seen */
1862 if (headerfile != NULL) free(headerfile);
1864 if (countzeroflag) resetpagerangehit (1);
1866 numpages = 0; /* number of pages actually processed 94/Oct/12 */
1867 pagenumber = 0; /* pages seen in scan */
1869 ff = -1; /* redundant */
1870 for (k = 0; k < MAXFONTS; k++) fonthit[k] = 0;
1871 /* for (k = 0; k < maxfonts; k++) fonthit[k] = 0; */ /* ah what the hell */
1872 // currentfont = fontchar; /* just in case */
1873 currentfont = fontchar[0]; /* just in case ??? */
1875 for (k = 0; k < MAXFONTNUMBERS; k++) /* reset status to unused */
1876 finx[k] = (short) BLANKFONT;
1878 /* Get dvi_t up front 98/Jun/30 */
1880 bBackUsed=0; /* non-zero of \special{background ...} used */
1881 bColorUsed = 0; /* assume no color \special until ... 98/Feb/15 */
1883 if (bCarryColor || bBackGroundFlag)
1885 postposition = gotopost(input); /* in dvianal.c */
1886 (void) getc(input); /* absorb the post byte */
1890 alloccolorsave(dvi_t); /* allocated space for color table */
1891 if (bBackGroundFlag)
1892 allocbackground(dvi_t); /* allocate background color table */
1899 stinx = 0; maxstinx = 0; /* redundant, hopefully */
1901 textures=0; /* start off by assuming normal DVI file */
1903 (void) ungetc(c, fp_in);
1904 if (c != (int) pre) { /* not standard DVI file - can figure out ? */
1905 if (readovertext(fp_in) == 0) {
1906 if (strstr(fn_in, ".tex") != NULL) { /* 1994/Feb/24 */
1907 showline("Can't find DVI file ", 1);
1910 showline("Not a valid DVI (or Textures) file ", 1);
1912 input = NULL; /* to stop at byte message ? */
1918 showline("Textures DVI file - ", 0);
1924 /* in the above, may also want to look 100 bytes into the file for start */
1925 /* some Mac files come that way... */
1930 sprintf(logline, " Unexpected EOF (%s)\n", "scanlogfile");
1931 showline(logline, 1);
1937 if (skipflag == 0) {
1938 if (ff < 0) invalidset((int) c);
1940 /* if (bRemapControl && c < MAXREMAP) c = remaptable[c]; */
1941 if (bRemapControl || bRemapFont) {
1942 if (c < MAXREMAP) c = remaptable[c];
1944 else if (c == 32) c = 195;
1945 else if (c == 127) c = 196;
1948 else if (bRemapSpace && c <= 32) { /* 1995/Oct/17 */
1949 if (c == 32) c = 195; /* not 160 */
1950 else if (c == 13) c = 176; /* 1996/June/4 */
1951 else if (c == 10) c = 173; /* 1996/June/4 */
1952 else if (c == 9) c = 170; /* 1996/June/4 */
1953 else if (c == 0) c = 161;
1959 else if (c >= 171 && c <= 234) { /* switch to font (c - 171) */
1961 logswitchfont(fn, fp_in);
1965 case set1: logdo_set1(fp_in); break;
1966 case set2: logdo_set2(fp_in); break; /* silly */
1967 case set3: logdo_set3(fp_in); break; /* silly */
1968 case set4: logdo_set4(fp_in); break; /* silly */
1969 case set_rule: logdo_set_rule(fp_in); break;
1970 case put1: logdo_put1(fp_in); break ;
1971 case put2: logdo_put2(fp_in); break; /* silly */
1972 case put3: logdo_put3(fp_in); break; /* silly */
1973 case put4: logdo_put4(fp_in); break; /* silly */
1974 case put_rule: logdo_put_rule(fp_in); break;
1975 case nop: break; /* do nothing */
1976 case bop: logdo_bop(fp_in); break;
1977 case eop: logdo_eop(fp_in); break;
1978 case push: logdo_push(); break;
1979 case pop: logdo_pop(); break;
1980 case right1: logdo_right1(fp_in); break;
1981 case right2: logdo_right2(fp_in); break;
1982 case right3: logdo_right3(fp_in); break;
1983 case right4: logdo_right4(fp_in); break;
1984 case w0: logdo_w0(); break;
1985 case w1: logdo_w1(fp_in); break;
1986 case w2: logdo_w2(fp_in); break;
1987 case w3: logdo_w3(fp_in); break;
1988 case w4: logdo_w4(fp_in); break; /* not used ? */
1989 case x0: logdo_x0(); break;
1990 case x1: logdo_x1(fp_in); break;
1991 case x2: logdo_x2(fp_in); break;
1992 case x3: logdo_x3(fp_in); break;
1993 case x4: logdo_x4(fp_in); break; /* not used ? */
1994 case down1: logdo_down1(fp_in); break;
1995 case down2: logdo_down2(fp_in); break;
1996 case down3: logdo_down3(fp_in); break;
1997 case down4: logdo_down4(fp_in); break;
1998 case y0: logdo_y0(); break;
1999 case y1: logdo_y1(fp_in); break;
2000 case y2: logdo_y2(fp_in); break;
2001 case y3: logdo_y3(fp_in); break;
2002 case y4: logdo_y4(fp_in); break; /* not used ? */
2003 case z0: logdo_z0(); break;
2004 case z1: logdo_z1(fp_in); break;
2005 case z2: logdo_z2(fp_in); break;
2006 case z3: logdo_z3(fp_in); break;
2007 case z4: logdo_z4(fp_in); break; /* not used ? */
2008 case fnt1: logdo_fnt1(fp_in); break;
2009 case fnt2: logdo_fnt2(fp_in); break; /* silly */
2010 case fnt3: logdo_fnt3(fp_in); break; /* silly */
2011 case fnt4: logdo_fnt4(fp_in); break; /* silly */
2012 case xxx1: logdo_xxx1(fp_in); break;
2013 case xxx2: logdo_xxx2(fp_in); break; /* not used ? */
2014 case xxx3: logdo_xxx3(fp_in); break; /* not used ? */
2015 case xxx4: logdo_xxx4(fp_in); break;
2016 case fnt_def1: logdo_fnt_def1(fp_in); break;
2017 case fnt_def2: logdo_fnt_def2(fp_in); break; /* silly */
2018 case fnt_def3: logdo_fnt_def3(fp_in); break; /* silly */
2019 case fnt_def4: logdo_fnt_def4(fp_in); break; /* silly */
2020 case post: logdo_post(fp_in); break;
2021 case pre: logdo_pre(fp_in); break;
2022 case post_post: logdo_post_post(fp_in); break;
2026 " ERROR: Unrecognized DVI command: %d", c);
2027 showline(logline, 1);
2028 tellwhere(fp_in, 1);
2030 finish = -1; /* ? */
2036 if (finish != 0) break;
2037 if (bAbort) abortjob(); /* fine grained */
2038 if (abortflag) break;
2040 /* if (maxstinx >= maxstack-1) {
2041 showline( WARNING: The PS stack will probably overflow %d > %d\n",
2042 maxstinx, maxstack -1 );
2045 if (abortflag) return -1;
2049 /* main entry point, prescan DVI file font usage, \specials */
2051 int scanlogfile (FILE *fp_in)
2054 input = fp_in; /* remember file handle */
2056 if (traceflag) showline("Start PreScan DVI file\n", 0);
2057 /* strcpy (headerfile, ""); */ /* reset to no headers seen */
2061 // we now forget about Textures files 99/July/14
2062 if (c != pre || d != ID_BYTE)
2064 sprintf(logline, " Not a proper DVI file `%s'\n",
2065 (filenamex != NULL) ? filenamex : "");
2066 showline(logline, 1);
2070 scanlogfileaux(fp_in);
2071 /* if (showlogflag != 0) showlog(stdout); */
2072 if (bBackGroundFlag != 0 && bBackUsed == 0)
2073 freebackground(); /* not needed in this case */
2074 if (bCarryColor != 0 && bColorUsed == 0)
2075 freecolorsave(); /* not needed in this case */
2076 if (traceflag) showline("End PreScan DVI file\n", 0);
2077 #ifdef DEBUGCOLORSTACK
2078 if (traceflag) dumpcolorsave();
2080 if (abortflag) return -1;
2084 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2086 /* Use `texfonts.map' in directory path TEXFONTS for aliasing */
2092 typedef struct map_element_struct { /* list element key . value pair */
2095 struct map_element_struct *next;
2098 typedef map_element_type **map_type;
2100 /* **************************** auxiliary functions *********************** */
2102 static void complain_mem (unsigned int size) /* out of memory */
2104 sprintf(logline, "Unable to honor request for %u bytes.\n", size);
2105 showline(logline, 1);
2109 static void *xmalloc (unsigned int size)
2111 void *new_mem = (void *) malloc (size);
2112 if (new_mem == NULL) complain_mem(size);
2116 static void *xrealloc (void *old_ptr, unsigned int size)
2119 if (old_ptr == NULL)
2120 /* new_mem = xmalloc (size); *//* could just let realloc do this case? */
2121 new_mem = malloc (size); /* could just let realloc do this case? */
2123 new_mem = (void *) realloc (old_ptr, size);
2124 /* if (new_mem == NULL) complain_mem(size); */
2126 if (new_mem == NULL) complain_mem(size);
2130 static char *xstrdup (char *s)
2132 char *new_string = (char *) xmalloc (strlen (s) + 1);
2133 return strcpy (new_string, s);
2136 /* static char *concat3 (char *s1, char *s2, char *s3) {
2138 = (char *) xmalloc (strlen (s1) + strlen (s2) + strlen (s3) + 1);
2139 strcpy (answer, s1);
2140 strcat (answer, s2);
2141 strcat (answer, s3);
2143 } */ /* used by extend_filename only */
2145 static void *xcalloc (unsigned int nelem, unsigned int elsize)
2147 void *new_mem = (void *) calloc (nelem, elsize);
2148 if (new_mem == NULL) complain_mem (nelem * elsize);
2152 /* Here we work only with suffix-free names - so this is silly */
2154 /* static char *find_suffix (char *name) {
2158 dot_pos = strrchr (name, '.');
2159 if (dot_pos == NULL) return NULL;
2160 if ((slash_pos = strrchr (name, '/')) != NULL) ;
2161 else if ((slash_pos = strrchr (name, '\\')) != NULL) ;
2162 else if ((slash_pos = strrchr (name, ':')) != NULL) ;
2163 else slash_pos = name;
2164 if (dot_pos < slash_pos) return NULL;
2168 /* static char *extend_filename (char *name, char *default_suffix) {
2169 char *suffix = find_suffix (name);
2171 if (suffix != NULL) return name;
2172 new_s = concat3 (name, ".", default_suffix);
2176 /* static char *remove_suffix (char *s) {
2178 char *suffix = find_suffix (s);
2180 if (suffix == NULL) return NULL;
2182 ret = (char *) xmalloc (suffix - s + 1);
2183 strncpy (ret, s, suffix - s);
2184 ret[suffix - s] = 0;
2188 /* only used by fontmap.c */ /* why not just use fgets on global line ? */
2190 #define BLOCK_SIZE 40
2192 static char *read_line (FILE *f)
2195 unsigned int limit = BLOCK_SIZE;
2196 unsigned int loc = 0;
2199 line = (char *) xmalloc (limit);
2201 while ((c = getc (f)) != EOF && c != '\n') {
2202 line[loc] = (char) c;
2205 limit += BLOCK_SIZE;
2206 line = (char *) xrealloc (line, limit);
2210 if (c != EOF) line[loc] = 0; /* not EOF */
2211 else if (loc > 0) line[loc] = 0; /* c == EOF, but line not empty */
2212 else { /* c == EOF and nothing on the line --- at end of file. */
2219 /* ************************************************************************* */
2221 /* Fontname mapping. We use a straightforward hash table. Should be prime? */
2223 #define MAP_SIZE 307
2225 /* The hash function. We go for simplicity here. */
2227 static unsigned int map_hash (char *key)
2231 /* There are very few font names which are anagrams of each other
2232 so no point in weighting the characters. */
2233 while (*s != 0) n += *s++;
2237 sprintf(logline, "hash %u for %s\n", n, key);
2238 showline(logline, 0);
2244 /* Look up STR in MAP. Return the corresponding `value' or NULL. */
2246 static char *map_lookup_str (map_type map, char *key)
2248 unsigned int n = map_hash (key);
2249 map_element_type *p;
2251 for (p = map[n]; p != NULL; p = p->next) {
2254 sprintf(logline, "Trying %s against %s\n", key, p->key);
2255 showline(logline, 0);
2258 if (strcmp (key, p->key) == 0) return p->value;
2261 sprintf(logline, "p->next %p\n", p->next);
2262 showline(logline, 0);
2268 sprintf(logline, " failed to find %s\n", key);
2269 showline(logline, 0);
2272 return NULL; /* failed to find it */
2276 static void map_show (map_type map) /* debugging tool */
2278 map_element_type *p;
2281 for (n = 0; n < MAP_SIZE; n++) {
2282 for (p = map[n]; p != NULL; p = p->next) {
2283 sprintf(logline, "n %u key %s next %p\n", n, p->key, p->next);
2284 showline(logline, 0);
2290 /* Look up KEY in MAP; if it's not found, remove any suffix from KEY and
2291 try again. Then paste key back into answer ... */
2293 /* OK, the original KEY didn't work. Let's check for the KEY without
2294 an extension -- perhaps they gave foobar.tfm, but the mapping only
2295 defines `foobar'. */
2297 /* Append the same suffix we took off, if necessary. */
2298 /* if (ret) ret = extend_filename (ret, suffix); */
2300 char *map_lookup (map_type map, char *key)
2302 char *ret = map_lookup_str(map, key);
2305 /* lets assume we never have to deal with names that have extensions */
2306 /* suffix = find_suffix (key);
2309 char *base_key = remove_suffix (key);
2310 ret = map_lookup_str(map, base_key);
2314 if (ret && suffix) ret = extend_filename (ret, suffix); */
2319 /* If KEY is not already in MAP, insert it and VALUE. */
2320 /* This was a total mess! Fixed 1994/March/18 */
2322 static void map_insert (map_type map, char *key, char *value)
2324 unsigned int n = map_hash (key);
2325 map_element_type **ptr = &map[n];
2327 while (*ptr != NULL && !(strcmp(key, (*ptr)->key) == 0))
2328 ptr = &((*ptr)->next);
2331 *ptr = (map_element_type *) xmalloc (sizeof(map_element_type));
2332 (*ptr)->key = xstrdup (key);
2333 (*ptr)->value = xstrdup (value);
2334 (*ptr)->next = NULL;
2338 /* Open and read the mapping file FILENAME, putting its entries into
2339 MAP. Comments begin with % and continue to the end of the line. Each
2340 line of the file defines an entry: the first word is the real
2341 filename (e.g., `ptmr'), the second word is the alias (e.g.,
2342 `Times-Roman'), and any subsequent words are ignored. .tfm is added
2343 if either the filename or the alias have no extension. This is the
2344 same order as in Dvips' psfonts.map; unfortunately, we can't have TeX
2345 read that same file, since most of the real filenames start with an
2346 `r', because of the virtual fonts Dvips uses.
2347 And what a load of bull! And who cares about DVIPS and VF files !*/
2349 static void map_file_parse (map_type map, char *map_filename)
2352 unsigned int map_lineno = 0;
2353 unsigned int entries = 0;
2354 FILE *f = fopen(map_filename, "r");
2357 sprintf(logline, " ERROR: Can't open %s\n", map_filename);
2358 showline(logline, 1);
2359 perrormod(map_filename);
2363 while ((l = read_line(f)) != NULL) {
2367 /* comment_loc = strrchr (l, '%'); */
2368 comment_loc = strchr(l, '%'); /* 96/Aug/20 */
2369 /* if (comment_loc == NULL) comment_loc = strrchr (l, ';'); */
2370 if (comment_loc == NULL) comment_loc = strchr (l, ';');
2372 /* Ignore anything after a % or ; */
2373 if (comment_loc) *comment_loc = 0;
2377 /* If we don't have any filename, that's ok, the line is blank. */
2378 filename = strtok (l, " \t");
2380 char *alias = strtok (NULL, " \t");
2382 /* But if we have a filename and no alias, something's wrong. */
2383 if (alias == NULL || *alias == 0) {
2385 " font name `%s', but no alias (line %u in `%s').\n",
2386 filename, map_lineno, map_filename);
2387 showline(logline, 1);
2389 else { /* We've got everything. Insert the new entry. */
2390 map_insert (map, alias, filename); /* alias is the key */
2396 /* xfclose (f, map_filename); */
2400 sprintf(logline, "%u entries\n", entries);
2401 showline(logline, 0);
2406 /* Look for the file `texfonts.map' in each of the directories in
2407 TEXFONTS. Entries in earlier files override later files. */
2409 /* uses _searchenv ? */
2411 /* map_type map_create (char *envvar) { old version
2412 char filename[_MAX_PATH];
2415 _searchenv ("texfonts.map", envvar, filename);
2416 if (*filename == '\0') return NULL;
2418 map = (map_type) xcalloc (MAP_SIZE, sizeof (map_element_type *));
2419 map_file_parse (map, filename);
2421 if (traceflag) map_show(map);
2426 /* Look for the file `texfonts.map' in each of the directories in
2427 TEXFONTS. Entries in earlier files override later files. */
2429 /* void oursearchenv (char *mapname, char *envvar, char *pathname) { */
2430 void oursearchenv (char *mapname, char *searchpath, char *pathname)
2432 /* char *searchpath; */ /* 97/May/10 */
2433 int foundfile=0; /* set, but not used ? */
2434 #ifndef SUBDIRSEARCH
2439 /* searchpath = _getenv(envvar); */
2440 /* searchpath = grabenv(envvar); */ /* 97/May/10 */
2441 if (searchpath == NULL) { /* 1996/July/30 */
2442 *pathname = '\0'; /* failed env var lookup */
2444 } /* new sanity check */
2446 if (searchalongpath(mapname, searchpath, pathname, 0) != 0)
2448 else foundfile = 1; /* 1994/Aug/18 */
2451 if ((searchpath = nextpathname(pathname, searchpath)) == NULL) {
2452 /* foundfile = 0; */
2455 s = pathname + strlen(pathname) - 1;
2456 if (*s != '\\' && *s != '/') strcat(pathname, "\\");
2457 strcat(pathname, mapname);
2458 if ((input = fopen(pathname, "r")) != NULL) {
2467 /* Returns NULL if it failed for some reason */
2469 /* map_type map_create (char *envvar) { */ /* 94/May/23 */
2470 map_type map_create (char *texfonts) /* 97/May/10 */
2472 char pathname[_MAX_PATH];
2476 if (traceflag) showline("Creating alias table\n", 0);
2478 /* oursearchenv ("texfonts.map", envvar, pathname); */
2479 oursearchenv ("texfonts.map", texfonts, pathname);
2480 if (*pathname == '\0') {
2483 sprintf(logline, "Could not find %s in\n", "texfonts.map", texfonts);
2484 showline(logline, 0);
2490 map = (map_type) xcalloc (MAP_SIZE, sizeof(map_element_type *));
2491 map_file_parse (map, pathname);
2493 if (traceflag) map_show(map);
2498 /* ************************************************************************* */
2500 /* if we didn't find the font, maybe its alias to be found in texfonts.map */
2502 map_type fontmap = NULL; /* static - keep around once set */
2504 /* returns NULL if failed to find an alias */
2506 char *alias (char *name)
2508 /* static map_type fontmap = NULL; */ /* static - keep around once set */
2511 if (usefontmap == 0) return NULL; /* failed to find it before */
2512 /* Now fault in the mapping if necessary. */
2513 if (fontmap == NULL) {
2514 /* fontmap = map_create ("TEXFONTS"); */
2515 fontmap = map_create (texfonts); /* 97/May/10 */
2516 if (fontmap == NULL) { /* check if it worked */
2517 usefontmap = 0; /* don't try this again */
2522 /* Now look for our filename in the mapping. */
2523 mapped_name = map_lookup(fontmap, name);
2524 return mapped_name; /* possibly NULL */
2527 /* ************************************************************** */
2531 /***************************************************************************/
2533 #ifndef SUBDIRSEARCH
2535 /* Moved from DVIPSONE.C since DVIPSLOG.C module is much smaller */
2537 /* Extract next pathname from a searchpath - and write into pathname */
2538 /* return NULL if there are no more pathnames, */
2539 /* otherwise returns pointer to NEXT pathname in searchpath */
2540 /* searchpath = pathname1;pathname2; ... ;pathnamen */
2542 /* used for pfb search path and eps search path */
2543 /* this version also allows space as separator */
2545 char *nextpathname(char *pathname, char *searchpath)
2550 if (*searchpath == '\0') return NULL; /* nothing left */
2551 else if (((s = strchr(searchpath, ';')) != NULL) ||
2552 ((s = strchr(searchpath, ' ')) != NULL)) {
2553 n = (s - searchpath);
2554 if (n >= MAXPATHLEN) {
2555 sprintf(logline, " Path too long %s\n", searchpath);
2556 showline(logline, 1);
2559 strncpy(pathname, searchpath, (unsigned int) n);
2560 *(pathname + n) = '\0'; /* terminate it */
2561 return(s + 1); /* next pathname or NULL */
2564 n = (int) strlen(searchpath);
2565 if (n >= MAXPATHLEN) {
2566 sprintf(logline, " Path too long %s\n", searchpath);
2567 showline(logline, 1);
2570 strcpy(pathname, searchpath);
2571 return(searchpath + n);
2577 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2586 }; */ /* 16 bit world --- in dos.h */
2588 /* struct _finddata_t {
2590 time_t time_create; -1 for FAT file systems
2591 time_t time_access; -1 for FAT file systems
2595 }; */ /* 32 bit world --- in io.h */
2597 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2601 /* Code to implement (possibly recursive) sub-directory search 94/Aug/18 */
2603 #define ACCESSCODE 4
2605 #define SEPARATOR "\\"
2607 /* This is the (possibly recursive) sub-directory searching code */
2609 /* We come in here with the directory name in pathname */
2610 /* Which is also where we plan to return the result when we are done */
2611 /* We search in this directory first, */
2612 /* and we search one level subdirectories (if it ended in \), */
2613 /* or recursively if the flag is set (when it ends in \\). */
2614 /* File name searched for is in filename */
2615 /* Returns zero if successful --- return non-zero if not found */
2617 /* struct _finddata_t c_file; */
2618 /* _finddata_t structure *can* be reused, unlike _find_t 95/Jan/31 */
2619 /* so save on stack space, by having one copy, not one per expand_subdir */
2620 /* possibly allocate this in the caller of findsubpath ? not static ? */
2622 int findsubpath (char *filename, char *pathname, int recurse)
2627 /* struct _finddata_t c_file; */
2628 static struct _finddata_t c_file; /* structure can be reused (?) */
2632 s = pathname + strlen(pathname); /* remember the end of the dirpath */
2634 sprintf(logline, " Entering findsubpath: %s %s %d\n",
2635 filename, pathname, recurse);
2636 showline(logline, 0);
2639 /* First try directly in this directory (may want this conditional) */
2640 strcat (pathname, SEPARATOR); /* \ or / */
2641 strcat (pathname, filename);
2643 /* Try for match in this directory first - precedence over files in subdirs */
2644 /* if (_access(pathname, ACCESSCODE) == 0) */ /* check for read access */
2645 code = _access(pathname, ACCESSCODE);
2648 sprintf(logline, " SUCCESS: %s\n", pathname);
2649 showline(logline, 0);
2651 return 0; /* success */
2653 if (traceflag) { /* debugging */
2654 /* code = _access(pathname, ACCESSCODE); */
2655 sprintf(logline, " File %s Access %d\n", pathname, code);
2656 showline(logline, 0);
2659 *s = '\0'; /* strip off the filename again */
2660 /* no luck, so try and find subdirectories */
2661 strcat (pathname, SEPARATOR); /* \ or / */
2662 strcat (pathname, "*.*");
2663 /* if (_dos_findfirst (pathname, _A_NORMAL | _A_SUBDIR, &c_file) != 0) { */
2664 /* if (_dos_findfirst (pathname,
2665 _A_NORMAL | _A_SUBDIR | _A_RDONLY, &c_file) != 0) */
2666 hFind = _findfirst (pathname, &c_file);
2667 if (hFind > 0) ret = 0; /* found something */
2668 else ret = -1; /* did not find path ? */
2669 /* ret = _dos_findfirst (pathname, _A_NORMAL | _A_SUBDIR | _A_RDONLY, &c_file); */
2671 if (ret) { /* nothing found ? */
2672 if (badpathwarn++ == 0) {
2673 sprintf(logline, "WARNING: bad path `%s' for `%s':\n", pathname, filename);
2674 showline(logline, 1);
2675 perrormod(filename); /* debugging only ? bad path given */
2677 return -1; /* failure */
2679 *s = '\0'; /* strip off the \*.* again */
2680 /* Step through sub-directories */
2682 /* Ignore all but sub-directories here - also ignore . and .. */
2683 if ((c_file.attrib & _A_SUBDIR) == 0 || *c_file.name == '.') {
2684 /* if (_dos_findnext (&c_file) != 0) break; */
2685 ret = _findnext (hFind, &c_file); /* success == TRUE ??? */
2686 /* need to flip polarity of ret ? apparently not ... */
2687 /* ret = _dos_findnext (&c_file); */ /* success == 0 */
2689 if (ret != 0) break; /* give up, found nothing more */
2690 continue; /* did find something else, go on */
2692 /* extend pathname with subdir name */
2693 strcat(pathname, SEPARATOR);
2694 strcat(pathname, c_file.name);
2696 sprintf(logline, " Checking subdir: %s\n", pathname);
2697 showline(logline, 0);
2699 /* OK, now try for match in this directory */
2700 if (recurse) { /* recursive version */
2701 if (findsubpath(filename, pathname, recurse) == 0) {
2704 return 0; /* succeeded */
2707 else { /* not recursive */
2708 strcat (pathname, SEPARATOR);
2709 strcat (pathname, filename);
2711 sprintf(logline, " Checking file: %s\n", pathname);
2712 showline(logline, 0);
2714 /* if (_access(pathname, ACCESSCODE) == 0) */
2715 code = _access(pathname, ACCESSCODE); /* check read access */
2718 sprintf(logline, " SUCCESS: %s\n", pathname);
2719 showline(logline, 0);
2723 return 0; /* success */
2725 if (traceflag) { /* debugging */
2726 /* code = _access(pathname, ACCESSCODE); */
2727 sprintf(logline, " File %s Access %d\n", pathname, code);
2728 showline(logline, 0);
2732 /* No match in this directory, so continue */
2735 sprintf(logline, "Ready for dos_findnext: %s %s %d\n",
2736 filename, pathname, recurse);
2737 showline(logline, 0);
2739 /* if (_dos_findnext (&c_file) != 0) break; */
2740 ret = _findnext (hFind, &c_file); /* success == TRUE ??? */
2741 /* need to flip polarity of ret ? apparently not ... */
2742 /* ret = _dos_findnext (&c_file); */ /* success == 0 */
2744 if (ret != 0) break; /* found no more */
2745 } /* end of for{;;} loop */
2750 return -1; /* failed */
2753 /* Our searchalongpath is (somewhat) analogous to DOS _searchenv */
2754 /* The name of the desired file is given in `filename' */
2755 /* The list of paths is given in `pathlist' */
2756 /* searchalongpath returns the full pathname of first match in `pathname' */
2757 /* (make sure there is enough space there!) */
2758 /* If the file is not found, then pathname contains "" */
2759 /* and it also returns non-zero if it fails. */
2760 /* It first searches in the current directory if currentflag > 0 */
2761 /* It also searches PFM subdirectories if currentflag < 0 97/June/1 */
2762 /* If a path in `pathlist' ends in \, then its sub-directories are searched, */
2763 /* (after the specified directory) */
2764 /* If a path in `pathlist' ends in \\, then this works recursively */
2765 /* (which may be slow and cause stack overflows ...) */
2767 int searchalongpath (char *filename, char *pathlist, char *pathname, int current)
2769 /* struct _find_t c_file; */ /* need to preserve across calls to DOS */
2770 char *s, *t, *u, *send;
2773 #ifdef DEBUGSEARCHPATH
2777 if (current > 0) { /* Try for exact match in current directory first ? */
2778 strcpy(pathname, filename);
2779 if (_access(pathname, ACCESSCODE) == 0) { /* check for read access */
2781 sprintf(logline, " File %s SUCCESS\n", pathname);
2782 showline(logline, 0);
2784 return 0; /* success */
2786 #ifdef DEBUGSEARCHPATH
2787 if (traceflag) { /* debugging */
2788 code = _access(pathname, ACCESSCODE);
2789 sprintf(logline, " File %s Access %d\n",
2790 pathname, _access(pathname, ACCESSCODE));
2791 showline(logline, 0);
2796 /* Now step through paths in pathlist */
2799 if (*s == '\0') break; /* sanity check */
2800 if ((t = strchr(s, ';')) == NULL)
2801 t = s + strlen(s); /* if last path */
2803 strncpy(pathname, s, n);
2805 *u-- = '\0'; /* null terminate */
2806 c = *u; /* check whether ends on \ */
2807 if (c == '\\' || c == '/') { /* yes it does -> subdir search */
2808 *u-- = '\0'; /* remove it */
2809 c = *u; /* check whether ends on \\ */
2810 if (c == '\\' || c == '/') { /* yes it does */
2811 *u-- = '\0'; /* remove it */
2812 recurse = 1; /* recursive subdir search */
2816 sprintf(logline, " Trying subdir: %s\n", pathname);
2817 showline(logline, 0);
2819 if (findsubpath (filename, pathname, recurse) == 0)
2820 return 0; /* success */
2822 else { /* its just a directory */
2823 send = pathname + strlen(pathname); /* remember end for below */
2824 strcat (pathname, SEPARATOR); /* \ or / */
2825 strcat (pathname, filename);
2826 if (_access (pathname, ACCESSCODE) == 0) {
2828 sprintf(logline, " File %s SUCCESS\n", pathname);
2829 showline(logline, 0);
2831 return 0; /* success */
2833 #ifdef DEBUGSEARCHPATH
2834 if (traceflag) { /* debugging */
2835 code = _access(pathname, ACCESSCODE);
2836 sprintf(logline, " File %s Access %d\n",
2837 pathname, _access(pathname, ACCESSCODE));
2838 showline(logline, 0);
2841 if (current < 0) { /* try in PFM sub-directory also 97/June/1 */
2842 *send = '\0'; /* snip off file name again */
2843 strcat (pathname, SEPARATOR); /* \ or / */
2844 strcat (pathname, "PFM"); /* splice in PFM */
2845 strcat (pathname, SEPARATOR); /* \ or / */
2846 strcat (pathname, filename);
2847 if (_access (pathname, ACCESSCODE) == 0) {
2849 sprintf(logline, " File %s SUCCESS\n", pathname);
2850 showline(logline, 0);
2852 return 0; /* success */
2854 #ifdef DEBUGSEARCHPATH
2855 if (traceflag) { /* debugging */
2856 code = _access(pathname, ACCESSCODE);
2857 sprintf(logline, " File %s Access %d\n",
2858 pathname, _access(pathname, ACCESSCODE));
2859 showline(logline, 0);
2865 s = t; /* move on to next item in list */
2866 if (*s == ';') s++; /* step over separator */
2867 else break; /* we ran off the end */
2869 strcpy(pathname, ""); /* failed to find it */
2873 /* search for file in path list and open it if found */
2874 /* return full path name in third arg unless third arg is NULL */
2875 /* if third arg is NULL, a local temporary place is used for the name */
2876 /* if current > 0, look in current directory first */
2877 /* if current < 0, look in PFM sub directories also */
2878 // only place we use _alloca ...
2880 FILE *findandopen (char *filename, char *pathlist, char *pathname, char *mode, int current)
2884 if (pathname == NULL) {
2885 pathname = (char *) _alloca (FNAMELEN);
2886 if (pathname == NULL) checkexit(1);
2888 if (searchalongpath(filename, pathlist, pathname, current) == 0) {
2889 file = fopen(pathname, mode);
2895 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2897 /* dviextra.c(5813) : fatal error C1001: internal compiler error */
2898 /* (compiler file 'msc2.cpp', line 1011) */
2900 /* dvipslog.c(2008) : fatal error C1001: internal compiler error
2901 (compiler file 'msc2.cpp', line 1011) */
2903 /* stuff for reading .afm files */
2905 int readafm(char *font, FILE *fp_afm, long widths[])
2910 /* if (fp_afm == NULL) checkexit(5); */
2911 (void) getrealline(fp_afm, line);
2913 while (strstr(line, "StartCharMetrics") == NULL) {
2914 if(getrealline(fp_afm, line) == 0) {
2916 " Can't find CharMetrics in AFM file for %s\n", font);
2917 showline(logline, 1);
2922 /* could extract UniqueID, BBox and FontInfo stuff at this point */
2924 (void) getrealline(fp_afm, line);
2925 while(strstr(line, "EndCharMetrics") == NULL) {
2926 if(strstr(line, "EndCharMetrics") != NULL) break;
2927 if (sscanf(line," C %d ; WX %lg", &chr, &fwidth) < 2) {
2929 " Parse error in line from AFM file for %s: %s",
2931 showline(logline, 1);
2935 if (chr >= 0 && chr < MAXCHRS) {
2936 if (chr > k) k = chr;
2937 widths[chr] = (long) ((fwidth/1000.0) * 1048576.0 + 0.5);
2939 (void) getrealline(fp_afm, line);
2944 /* moved here from dviextra.c */
2946 /* stuff for reading .tfm files */ /* OK for new form TFM files ? OK */
2948 /* lf, lh, nw, nh, nd, ni, nl, nk, ne are numbers of words */
2950 int readtfm(char *font, FILE *fp_tfm, long widths[])
2952 static long qwidths[MAXCHRS]; /* 256 */
2953 int lf, lh, bc, ec, nw, nh, nd, ni, nl, nk, ne, np;
2956 /* int chksum, dsgnsize; */
2957 /* int hdinx, itinx, rdinx; */
2959 /* if (fp_tfm == NULL) checkexit(5); */
2960 lf = sreadtwo(fp_tfm); lh = sreadtwo(fp_tfm);
2961 bc = sreadtwo(fp_tfm); ec = sreadtwo(fp_tfm);
2962 nw = sreadtwo(fp_tfm); nh = sreadtwo(fp_tfm);
2963 nd = sreadtwo(fp_tfm); ni = sreadtwo(fp_tfm);
2964 nl = sreadtwo(fp_tfm); nk = sreadtwo(fp_tfm);
2965 ne = sreadtwo(fp_tfm); np = sreadtwo(fp_tfm);
2966 /* first try and make sure this is a TFM file ! */
2967 if (lf < 0 || lh < 0 || nw < 0 || nw > 255 ||
2968 bc < 0 || ec < 0 || ec > 255 || bc > ec + 1 ||
2969 lf != 6 + lh + (ec - bc + 1) + nw + nh + nd + ni + nl + nk + ne + np)
2971 sprintf(logline, " BAD TFM file for %s", font);
2972 showline(logline, 1);
2974 /* sprintf(logline, "Header: %d %d %d %d %d %d %d %d %d %d %d %d\n",
2975 lf, lh, bc, ec, nw, nh, nd, ni, nl, nk, ne, np);
2976 showline(logline, 1); */
2980 /* now for the header */
2981 /* chksum = sreadtwo(fp_tfm); */ /* should we bother to verify ? */
2982 (void) sreadtwo(fp_tfm); /* check sum */
2983 /* dsgnsize = sreadtwo(fp_tfm); */
2984 (void) sreadtwo(fp_tfm); /* design size */
2985 /* discard rest of header */
2986 for (k = 2; k < lh; k++) {
2987 (void) getc(fp_tfm); (void) getc(fp_tfm);
2989 /* now read the actual widths */
2990 fseek(fp_tfm, (long) ((6 + lh + (ec - bc + 1)) << 2), SEEK_SET);
2991 for (k = 0; k < nw; k++) {
2992 qwidths[k] = sreadfour(fp_tfm);
2993 /* character width in design size units * 2^20 */
2995 if (qwidths[0] != 0) { /* qwidths[0] is supposed to be zero */
2996 sprintf(logline, " BAD TFM file for %s", font);
2997 showline(logline, 1);
2999 showline("width[0] not zero", 0); /* qwidths[0] */
3003 /* now go back and read character information */
3004 fseek(fp_tfm, (long) ((6 + lh) << 2), SEEK_SET);
3005 for (k = bc; k <= ec; k++) {
3006 wdinx = getc(fp_tfm);
3007 (void) getc(fp_tfm); /* hdinx = getc(fp_tfm); */
3008 (void) getc(fp_tfm); /* itinx = getc(fp_tfm); */
3009 (void) getc(fp_tfm); /* rdinx = getc(fp_tfm); */
3011 sprintf(logline, " BAD TFM file for %s", font);
3012 showline(logline, 1);
3014 sprintf(logline, "width index %d (char %d) > width table %d",
3016 showline(logline, 0);
3020 widths[k] = qwidths[wdinx];
3022 return (int) (ec + 1);
3025 /* stuff for reading widths from .pfm files */
3027 int readpfm(char *font, FILE *fp_pfm, long widths[])
3029 unsigned long length, offset;
3030 /* double fwidth; */
3032 int bc, ec, c, k, n;
3034 /* if (fp_pfm == NULL) checkexit(5); */
3035 /* first check that this is a PFM file - start with version number */
3036 if ((c = getc(fp_pfm)) != 0 || (c = getc(fp_pfm)) != 1)
3038 sprintf(logline, " Not a proper PFM file %s\n", font);
3039 showline(logline, 1);
3043 length = 0L; /* read length of PFM file */
3044 for (k = 0; k < 4; k++) /* from byte 2 to byte 6 */
3045 length = length | (getc(fp_pfm) << (k * 8));
3046 for (k = 6; k < 66; k++) (void) getc(fp_pfm); /* ignore copyright */
3047 for (k = 66; k < 95; k++) (void) getc(fp_pfm); /* ignore assorted */
3048 bc = getc(fp_pfm); ec = getc(fp_pfm); /* first and last character */
3049 for (k = 97; k < 117; k++) (void) getc(fp_pfm); /* skip to end header */
3050 for (k = 117; k < 119; k++) (void) getc(fp_pfm); /* size PFMEXTENSION */
3051 for (k = 119; k < 123; k++) (void) getc(fp_pfm); /* ptr EXTEXTMETRICS */
3052 offset = 0L; /* offset of charwidth table */
3053 for (k = 0; k < 4; k++) offset = offset | (getc(fp_pfm) << (k * 8));
3054 if (offset > 8192) {
3055 sprintf(logline, " Offset too long in %s\n", font);
3056 showline(logline, 1);
3061 for (k = 127; k < n; k++) c = getc(fp_pfm);
3063 showline(" Premature EOF", 1);
3064 sprintf(logline, " in PFM file %s\n", font);
3065 showline(logline, 0);
3069 for (k = bc; k <= ec; k++) {
3070 /* fwidths = (double) (getc(fp_pfm) | (getc(fp_pfm) << 8));
3071 widths[k] = (long) ((fwidth/1000.0) * 1048576.0 + 0.5); */
3072 lwidth = (long) (getc(fp_pfm) | (getc(fp_pfm) << 8));
3073 /* widths[k] = (long) (((lwidth << 20) + 500) / 1000); */
3074 widths[k] = (long) (((lwidth << 17) + 62) / 125);
3075 /* if (lwidth != 0) showline(logline, "w[%d] %ld ", k, lwidth); */
3076 /* if (widths[k] != 0) showline(logline, " %ld ", k, widths[k]); */
3079 sprintf(logline, "bc = %d ec = %d ", bc, ec);
3080 showline(logline, 0);
3087 /* check PFM file for MM instance and extract PostScript FontName */
3088 /* WARNING: this writes back into second argument ! */
3089 /* make sure FontName has enough space for FontName ( > 32 ) 97/June/1 */
3090 /* In typical use, FaceName == NULL and nface == 0 */
3091 /* return 0 if fails in some way */
3093 /* int pfminstance (FILE *input, char *FontName, int nlen) { */
3094 int NamesFromPFM (FILE *input, char *FaceName, int nface,
3095 char *FontName, int nfont, char *FileName)
3098 long length, offset;
3100 char DriverType[16]; /* space for "PostScript" */
3104 // sprintf(logline, " NamesFromPFM nface %d nfont %d\n", nface, nfont);
3105 // showline(logline, 0); // debugging only
3110 sprintf(logline, " Read `%s' for MM instance info\n", FileName); /* debugging */
3111 showline(logline, 0);
3114 fread(&version, sizeof(version), 1, input);
3115 if (version != 256) {
3117 sprintf(logline, " Bad version code (%d) in PFM %s ", version, FileName);
3118 showline(logline, 1);
3120 return 0; /* not PFM file */
3122 fread(&length, sizeof(length), 1, input);
3123 if (fseek(input, 101, SEEK_SET) != 0) {
3125 sprintf(logline, " Seek to %ld failed in PFM %s ", 101L, FileName);
3126 showline(logline, 1);
3130 fread(&offset, sizeof(offset), 1, input); /* offset to Driver Type */
3131 if (offset >= length || offset == 0) {
3133 sprintf(logline, " Bad offset %ld (%d) in PFM %s ", offset, length, FileName);
3134 showline(logline, 1);
3136 return 0; /* not PFM file */
3138 if (fseek(input, offset, SEEK_SET) != 0) {
3140 sprintf(logline, " Seek to %ld failed in PFM %s ", offset, FileName);
3141 showline(logline, 1);
3145 ndrive = sizeof(DriverType);
3146 s = DriverType; /* temporary space */
3148 while ((*s++ = (char) getc(input)) != '\0') {
3149 if (n++ >= ndrive) {
3151 sprintf(logline, " %s too long >= %ld in %s ", "DriverType", ndrive, FileName);
3152 showline(logline, 1);
3157 *s = '\0'; /* terminate */
3158 if (strcmp(DriverType, "PostScript") != 0) {
3160 sprintf(logline, " Driver not %s in %s ", "PostScript", FileName);
3161 showline(logline, 1);
3164 return 0; /* Not PS font */
3166 if (fseek(input, 105, SEEK_SET) != 0) {
3168 sprintf(logline, " Seek to %ld failed in PFM %s ", 105L, FileName);
3169 showline(logline, 1);
3173 fread(&offset, sizeof(offset), 1, input); /* offset Windows Face Name */
3174 if (offset >= length || offset == 0) {
3176 sprintf(logline, " Bad offset %ld (%ld) in PFM %s ", offset, length, FileName);
3177 showline(logline, 1);
3179 return 0; /* not PFM file */
3181 if (fseek(input, offset, SEEK_SET) != 0) {
3183 sprintf(logline, " Seek to %ld failed in PFM %s ", offset, FileName);
3184 showline(logline, 1);
3188 if (FaceName != NULL) {
3191 while ((*s++ = (char) getc(input)) != '\0')
3194 sprintf(logline, " %s too long >= %ld in %s ", "FaceName", nface, FileName);
3195 showline(logline, 1);
3199 *s = '\0'; /* terminate */
3200 if (strchr(FaceName, ' ') == NULL) {
3202 sprintf(logline, " Not MM %s %s? ", "FaceName", FaceName);
3203 showline(logline, 1);
3205 /* return 0; */ /* not MM instance */
3208 if (fseek(input, 139, SEEK_SET) != 0) {
3210 sprintf(logline, " Seek to %ld failed in PFM ", 139L);
3211 showline(logline, 1);
3215 fread(&offset, sizeof(offset), 1, input); /* offset to PS FontName */
3216 if (offset >= length || offset == 0) {
3218 sprintf(logline, " Bad offset %ld (%ld) in PFM ", offset, length);
3219 showline(logline, 1);
3221 return 0; /* not PFM file */
3223 if (fseek(input, offset, SEEK_SET) != 0) {
3225 sprintf(logline, " Seek to %ld failed in PFM ", offset);
3226 showline(logline, 1);
3231 /* write name back into second argument */
3232 if (FontName != NULL) {
3235 while ((*s++ = (char) getc(input)) != '\0')
3238 sprintf(logline, " %s too long >= %ld in %s ", "FontName", nfont, FileName);
3239 showline(logline, 1);
3243 *s = '\0'; /* terminate */
3244 /* We assume FontName for MM instance must have underscores */
3245 if (strchr(FontName, '_') == NULL) {
3247 sprintf(logline, " Not MM %s %s? ", "FontName", FontName);
3248 showline(logline, 1);
3250 /* return 0; */ /* not MM instance */
3254 sprintf(logline, " FontName from PFM: %s\n", FontName);/* debugging output */
3255 showline(logline, 0);
3259 return 1; /* OK, FaceName and FontName returned */
3262 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
3264 /* stuff for reading ATMREG.ATM imported from winpslog.c 98/Jan/9 */
3266 unsigned int xreadtwo (FILE *input)
3268 unsigned int c, d, n;
3275 unsigned long xreadfour (FILE *input)
3277 unsigned int a, b, c, d;
3284 n = (n << 16) | (b << 8) | a;
3288 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
3290 int bATM41=0; // needs to be set based on ATMREG.ATM header
3292 /* read string from ATMREG.ATM up to null, string may be empty */
3293 /* returns -1 if hit EOF or name too long */
3295 int ReadString (FILE *input, char *name, int nlen)
3301 *s = '\0'; /* in case we pop out early */
3302 for (;;) { /* read string up to null */
3304 if (bATM41) // 2000 July 3 ATM 4.1 ???
3305 (void) getc(input); // discard second byte of UNICODE
3306 if (c == EOF) { /* EOF */
3313 if (n >= nlen) { /* too long */
3314 sprintf(logline, " String in ATMREG.ATM too long %d (> %d)\n", n, nlen);
3315 showline(logline, 1);
3316 *name = '\0'; /* flush the name */
3323 #define LF_FACENAME 32
3324 #define LF_FULLFACENAME 64
3326 /* #define PFMName 16 */ /* >= 8+1+3+1 */
3327 /* #define PFBName 16 */ /* >= 8+1+3+1 */
3329 /**************************************************************************/
3331 /* New code for using ATMREG.ATM */
3333 unsigned long startfontlist, endfontlist;
3334 unsigned long startdirlist, enddirlist;
3335 unsigned long startsetlist, endsetlist;
3336 int nDirs, nFonts, nSets;
3338 typedef struct ATMRegRec {
3339 unsigned char nMMM; // directory path index for MMMName
3340 unsigned char nPFB; // directory path index for PFBName
3341 unsigned char nPFM; // directory path index for PFMName
3342 unsigned char MMMflag; // 0 => TTF, 1 => T1, 2 => MM Master, 4 => MM Instance
3343 char *FontName; // PostScript FontName
3344 char *MMMName; // File Name of PFM (T1 or MMM instance), MMM (for MM master)
3345 char *PFBName; // File Name of PFB (blank for MM instance)
3346 char *PFMName; // File Name of PFM (for MM master), MMM (for MM instance)
3349 struct ATMRegRec *ATMFonts=NULL;
3351 int ATMfontindex=0; // number of font entries
3353 // char *DirPaths[MAXDIRS];
3355 char **DirPaths=NULL;
3359 void FreeDirs (void)
3362 if (DirPaths == NULL) return;
3363 for (k = 0; k <= nDirs; k++) {
3364 if (DirPaths[k] != NULL) free(DirPaths[k]);
3372 int AllocDirs (int nDirs)
3375 if (DirPaths != NULL) FreeDirs();
3376 nlen = (nDirs + 1) * sizeof(char *);
3377 DirPaths = (char **) malloc (nlen);
3378 if (DirPaths == NULL) {
3379 sprintf(logline,"ERROR: unable to allocate %d bytes for %d dir entries\n",
3381 showline(logline, 1);
3384 DirPaths[0] = _strdup("");
3385 for (k = 1; k <= nDirs; k++) DirPaths[k] = NULL;
3390 void FreeFonts (void)
3393 if (ATMFonts == NULL) return;
3394 for (k = 0; k < ATMfontindex; k++) {
3395 if (ATMFonts[k].FontName != NULL) free(ATMFonts[k].FontName);
3396 if (ATMFonts[k].MMMName != NULL) free(ATMFonts[k].MMMName);
3397 if (ATMFonts[k].PFBName != NULL) free(ATMFonts[k].PFBName);
3398 if (ATMFonts[k].PFBName != NULL) free(ATMFonts[k].PFMName);
3404 int AllocFonts (int nFonts)
3407 if (ATMFonts != NULL) FreeFonts();
3408 nlen = nFonts * sizeof(struct ATMRegRec);
3409 ATMFonts = (struct ATMRegRec *) malloc (nlen);
3410 if (ATMFonts == NULL) {
3411 sprintf(logline, " Unable to allocate %d bytes for %d fonts\n",
3413 showline(logline, 1);
3417 // sprintf(logline, "Allocated %d bytes for %d fonts\n", nlen, nFonts); // debugging only
3418 // showline(logline, 0);
3423 void ShowATMREG (void)
3427 sprintf(logline, "ATMREG has %d T1 font entries (out of %d total):\n", ATMfontindex, nFonts);
3428 showline(logline, 0);
3429 for (k = 0; k < ATMfontindex; k++) {
3430 switch(ATMFonts[k].MMMflag) {
3431 case 0: szType = "TTF "; break;
3432 case 1: szType = "T1 "; break;
3433 case 2: szType = "MMM "; break;
3434 case 4: szType = "MMI "; break;
3435 default: szType = "ERR "; break;
3437 sprintf(logline, "%s Fontname: `%s' MMMName: `%s%s' PFBName: `%s%s' PFMName: `%s%s'\n",
3438 szType, ATMFonts[k].FontName,
3439 DirPaths[ATMFonts[k].nMMM], ATMFonts[k].MMMName,
3440 DirPaths[ATMFonts[k].nPFB], ATMFonts[k].PFBName,
3441 DirPaths[ATMFonts[k].nPFM], ATMFonts[k].PFMName);
3442 showline(logline, 0);
3446 /**********************************************************************************/
3448 int SetupDirs (FILE *input, unsigned long startdirlist, unsigned long enddirlist)
3450 int c, k, noff, nlen;
3452 unsigned long noffset;
3453 char pathname[ _MAX_PATH];
3456 /* if (fseek(input, 24, SEEK_SET) >= 0) noffset = xreadfour(input); */
3458 noffset = startdirlist; // 36
3461 if (noffset >= enddirlist) break; /* normal exit from this */
3462 if (fseek(input, noffset, SEEK_SET) < 0) {
3464 sprintf(logline, " Seek to %ld failed\n", noffset);
3465 showline(logline, 0);
3467 break; /* return -1; */
3469 noff = xreadtwo(input);
3472 sprintf(logline, " noff %lu != 8\n", noff);
3473 showline(logline, 0);
3475 /* break; */ /* new sanity check */
3477 nlen = xreadtwo(input);
3480 sprintf(logline, " nlen == 0\n");
3481 showline(logline, 0);
3483 break; /* sanity check */
3485 if (nlen > _MAX_PATH) {
3487 sprintf(logline, " nlen > %d\n", _MAX_PATH);
3488 showline(logline, 0);
3490 break; /* new sanity check */
3492 noffset = xreadfour(input);
3495 sprintf(logline, " noffset == 0\n");
3496 showline(logline, 0);
3498 break; /* sanity check */
3501 for (k = 0; k < nlen; k++) {
3503 if (bATM41) (void) getc(input);
3506 sprintf(logline, " Unexpected EOF (%s)\n", "setupdirs");
3507 showline(logline, 0);
3515 /* if (noiseflag) printf("%d\t%s\n", npath, pathname); */
3516 // if (dirindex >= MAXDIRS) {
3517 if (dirindex > nDirs) {
3519 sprintf(logline, " Too many paths (> %d)\n", nDirs);
3520 showline(logline, 0);
3524 DirPaths[dirindex] = xstrdup(pathname);
3530 /* Look for given PS FontName in atmreg.atm and return file name of PFB */
3531 /* returns 0 if found, -1 if not found */
3534 int SearchATMReg (FILE *input, unsigned long endfontlist,
3535 char *szPSFontName, char *szPFBFileName)
3538 unsigned int stroffset, nlen;
3540 int boldflag, italicflag; /* style bits */
3542 /* following just used for statistics - could remove to save time */
3543 int psflag, mmmflag, mmiflag, genflag; /* font type bits */
3544 int nMMM, nPFB, nPFM; /* index into dir path table */
3545 unsigned int flag[16]; /* 16 bytes of flags */
3546 char FaceName[LF_FACENAME+1]; /* Windows Face Name - not used */
3547 char StyleName[LF_FACENAME+1]; /* Style Name for TT font - not used */
3548 char FullName[LF_FULLFACENAME+1]; /* Full Name - not used */
3549 char FontName[LF_FULLFACENAME+1]; /* Font Name - used in comparison (T1 only) */
3550 char MMMName[LF_FACENAME+1]; /* PFM file or TTF file or MMM file */
3551 char PFBName[LF_FACENAME+1]; /* PFB file or PSS file - not used */
3552 char PFMName[LF_FACENAME+1]; /* PFM file of MMM font - not used */
3555 *szPFBFileName = '\0';
3557 fseek(input, startfontlist, SEEK_SET);
3559 /* positioned at start of font list at this point */
3562 c = getc(input); /* check for end of file 99/Mar/1 */
3567 stroffset = xreadtwo(input); /* offset to first string == 44 */
3568 nlen = xreadtwo(input); /* length of this record in bytes */
3569 next = xreadfour(input); /* pointer to next record */
3570 for (k = 0; k < (28 - 8); k++) (void) getc(input);
3571 for (k = 0; k < 16; k++) flag[k] = getc(input);
3573 if (boldflag == 0 || boldflag > 2) {
3574 if (boldflag > 2) boldflag = 1; /* pretend it is OK */
3575 /* break; */ /* impossible */ /* `fixed' 97/Sep/14 */
3577 else boldflag = boldflag - 1;
3578 italicflag = flag[2];
3579 if (italicflag > 1) {
3580 /* break; */ /* impossible */ /* `fixed' 97/Sep/14 */
3582 ttfflag = psflag = mmmflag = mmiflag = genflag = 0;
3583 /* ttfflag = flag[5]; */
3584 if (flag[4] == 0) ttfflag = 1;
3585 else if (flag[4] == 1) psflag = 1;
3586 else if (flag[4] == 2) mmmflag = 1;
3587 else if (flag[4] == 4) mmiflag = 1;
3588 if (flag[6] == 10) {
3592 nMMM = flag[8] | (flag[9] << 8); /* index into path name table */
3593 nPFB = flag[10] | (flag[11] << 8); /* index into path name table */
3594 nPFM = flag[12] | (flag[13] << 8); /* index into path name table */
3595 /* mmflag = flag[12]; */
3597 // if (ttfflag) ttfcount++;
3598 // else if (genflag) gencount++;
3599 // else if (mmiflag) mmicount++;
3600 // else if (mmmflag) mmmcount++;
3603 /* These used to all continue when they hit trouble */
3604 /* Windows Face Name */
3605 if (ReadString(input, FaceName, sizeof(FaceName)) < 0) goto donext;
3606 /* Style Name (will be empty string for PS SM or MM font) */
3607 if (ReadString(input, StyleName, sizeof(StyleName)) < 0) goto donext;
3608 /* Full Name (will be empty string for PS SM or MM font) */
3609 if (ReadString(input, FullName, sizeof(FullName)) < 0) goto donext;
3610 /* Font Name (may be empty if font file not yet read by ATM) */
3611 if (ReadString(input, FontName, sizeof(FontName)) < 0) goto donext;
3612 /* Name of MMM file or PFM file or TTF file */
3613 if (ReadString(input, MMMName, sizeof(MMMName)) < 0) goto donext;
3614 /* Name of PFB file or PSS file */
3615 if (ReadString(input, PFBName, sizeof(PFBName)) < 0) goto donext;
3616 /* Name of PFM file in case of MMM font */
3617 if (ReadString(input, PFMName, sizeof(PFMName)) < 0) goto donext;
3618 /* Flush extension from file name --- MMMName is file name */
3619 // if ((s = strchr(MMMName, '.')) != NULL) *s = '\0';
3620 /* Remove underscores from file name */
3621 /* removeunderscores(MMMName); */
3622 /* if (testflag == 0) removeunderscores (MMMName); */ /* ??? */
3623 /* Make all uppercase ? It's a file name so its safe at least */
3624 /* makeuppercase (MMMName); */ /* ??? */
3627 // sprintf(logline, "%s %s %s%s %s (%d)\n", MMMName, FaceName,
3628 // boldflag ? "BOLD" : "",
3629 // italicflag ? "ITALIC" : "",
3630 // ttfflag ? "(TT)" : "", pscount);
3631 // showline(logline, 0);
3632 sprintf(logline, "Face: `%s' Style: `%s' Full: `%s' Font: `%s' MMM: `%s' PFB: `%s' PFM: `%s'",
3633 FaceName, StyleName, FullName, FontName, MMMName, PFBName, PFMName);
3634 showline(logline, 0);
3637 /* if (strcmp(FontName, szPSFontName) == 0) */ /* ignore TrueType fonts */
3638 if (ttfflag == 0 && strcmp(FontName, szPSFontName) == 0 &&
3639 *PFBName != '\0') { // 2000 July 3
3640 if (DirPaths[nPFB] != NULL) strcpy(szPFBFileName, DirPaths[nPFB]);
3641 else *szPFBFileName = '\0'; // should not happen
3642 strcat(szPFBFileName, PFBName);
3644 sprintf(logline, " FOUND: %s for %s\n", szPFBFileName, szPSFontName);
3645 showline(logline, 0);
3647 return 0; /* success */
3649 donext: /* 1999/Mar/1 */
3650 /* if (findfontstart(input) < 0) break; */
3651 if (next >= endfontlist) break;
3652 if (fseek(input, next, SEEK_SET) < 0) break;
3654 *szPFBFileName = '\0'; /* wipe clean again */
3655 return -1; /* failed to find */
3659 /* New version uses ATMFonts structure */ /* First argument is PS FontName */
3660 /* WRITES BACK INTO SECOND ARGUMENT */
3661 /* returns 0 if found, -1 if not found */
3663 int SearchATMReg (char *szPSFontName, char *szPFBFileName)
3666 for (k = 0; k < ATMfontindex; k++) {
3667 if (strcmp(szPSFontName, ATMFonts[k].FontName) == 0) {
3668 strcpy(szPFBFileName, DirPaths[ATMFonts[k].nPFB]);
3669 strcat(szPFBFileName, ATMFonts[k].PFBName); // PFB file name
3673 *szPFBFileName = '\0'; /* wipe clean */
3674 return -1; /* failed to find */
3677 /* Create new ATMFonts data structure 2000 July */
3679 int ScanATMReg (FILE *input, unsigned long endfontlist)
3682 unsigned int stroffset, nlen;
3684 int boldflag, italicflag; /* style bits */
3686 /* following just used for statistics - could remove to save time */
3687 int psflag, mmmflag, mmiflag, genflag; /* font type bits */
3688 int nMMM, nPFB, nPFM; /* index into dir path table */
3689 unsigned int flag[16]; /* 16 bytes of flags */
3690 char FaceName[LF_FACENAME+1]; /* Windows Face Name - not used */
3691 char StyleName[LF_FACENAME+1]; /* Style Name for TT font - not used */
3692 char FullName[LF_FULLFACENAME+1]; /* Full Name - not used */
3693 char FontName[LF_FULLFACENAME+1]; /* Font Name - used in comparison (T1 only) */
3694 char MMMName[LF_FACENAME+1]; /* PFM file or TTF file or MMM file */
3695 char PFBName[LF_FACENAME+1]; /* PFB file or PSS file - not used */
3696 char PFMName[LF_FACENAME+1]; /* PFM file of MMM font - not used */
3699 if (ATMFonts == NULL) {
3700 if (AllocFonts(nFonts)) return -1;
3705 // sprintf(logline"SEEK TO %d\n", startfontlist); // debugging only
3706 // showline(logline, 0);
3707 fseek(input, startfontlist, SEEK_SET);
3709 /* positioned at start of font list at this point */
3712 c = getc(input); /* check for end of file 99/Mar/1 */
3717 stroffset = xreadtwo(input); /* offset to first string == 44 */
3718 nlen = xreadtwo(input); /* length of this record in bytes */
3719 next = xreadfour(input); /* pointer to next record */
3720 for (k = 0; k < (28 - 8); k++) (void) getc(input);
3721 for (k = 0; k < 16; k++) flag[k] = getc(input);
3723 if (boldflag == 0 || boldflag > 2) {
3724 if (boldflag > 2) boldflag = 1; /* pretend it is OK */
3725 /* break; */ /* impossible */ /* `fixed' 97/Sep/14 */
3727 else boldflag = boldflag - 1;
3728 italicflag = flag[2];
3729 if (italicflag > 1) {
3730 /* break; */ /* impossible */ /* `fixed' 97/Sep/14 */
3732 ttfflag = psflag = mmmflag = mmiflag = genflag = 0;
3733 /* ttfflag = flag[5]; */
3734 if (flag[4] == 0) ttfflag = 1;
3735 else if (flag[4] == 1) psflag = 1;
3736 else if (flag[4] == 2) mmmflag = 1;
3737 else if (flag[4] == 4) mmiflag = 1;
3738 if (flag[6] == 10) {
3742 nMMM = flag[8] | (flag[9] << 8); /* index into path name table */
3743 nPFB = flag[10] | (flag[11] << 8); /* index into path name table */
3744 nPFM = flag[12] | (flag[13] << 8); /* index into path name table */
3745 /* mmflag = flag[12]; */
3747 // if (ttfflag) ttfcount++;
3748 // else if (genflag) gencount++;
3749 // else if (mmiflag) mmicount++;
3750 // else if (mmmflag) mmmcount++;
3753 /* These used to all continue when they hit trouble */
3754 /* Windows Face Name */
3755 if (ReadString(input, FaceName, sizeof(FaceName)) < 0) goto donext;
3756 /* Style Name (will be empty string for PS SM or MM font) */
3757 if (ReadString(input, StyleName, sizeof(StyleName)) < 0) goto donext;
3758 /* Full Name (will be empty string for PS SM or MM font) */
3759 if (ReadString(input, FullName, sizeof(FullName)) < 0) goto donext;
3760 /* Font Name (may be empty if font file not yet read by ATM) */
3761 if (ReadString(input, FontName, sizeof(FontName)) < 0) goto donext;
3762 /* Name of MMM file or PFM file or TTF file */
3763 if (ReadString(input, MMMName, sizeof(MMMName)) < 0) goto donext;
3764 /* Name of PFB file or PSS file */
3765 if (ReadString(input, PFBName, sizeof(PFBName)) < 0) goto donext;
3766 /* Name of PFM file in case of MMM font */
3767 if (ReadString(input, PFMName, sizeof(PFMName)) < 0) goto donext;
3768 /* Flush extension from file name --- MMMName is file name */
3769 // if ((s = strchr(MMMName, '.')) != NULL) *s = '\0';
3770 /* Remove underscores from file name */
3771 /* removeunderscores(MMMName); */
3772 /* if (testflag == 0) removeunderscores (MMMName); */ /* ??? */
3773 /* Make all uppercase ? It's a file name so its safe at least */
3774 /* makeuppercase (MMMName); */ /* ??? */
3777 // sprintf(logline, "%s %s %s%s %s (%d)\n", MMMName, FaceName,
3778 // boldflag ? "BOLD" : "",
3779 // italicflag ? "ITALIC" : "",
3780 // ttfflag ? "(TT)" : "", pscount);
3781 // showline(logline, 0);
3782 sprintf(logline, "Face: `%s' Style: `%s' Full: `%s' Font: `%s' MMM: `%s' PFB: `%s' PFM: `%s'",
3783 FaceName, StyleName, FullName, FontName, MMMName, PFBName, PFMName);
3784 showline(logline, 0);
3787 if (ttfflag) goto donext;
3788 ATMFonts[ATMfontindex].nMMM = (unsigned char) nMMM;
3789 ATMFonts[ATMfontindex].nPFB = (unsigned char) nPFB;
3790 ATMFonts[ATMfontindex].nPFM = (unsigned char) nPFM;
3791 ATMFonts[ATMfontindex].MMMflag = (unsigned char) flag[4];
3792 ATMFonts[ATMfontindex].FontName = xstrdup(FontName); // PS FontName
3793 ATMFonts[ATMfontindex].MMMName = xstrdup(MMMName); // PFM/MMM File Name
3794 ATMFonts[ATMfontindex].PFBName = xstrdup(PFBName); // PFB File Name
3795 ATMFonts[ATMfontindex].PFMName = xstrdup(PFMName);
3797 donext: /* 1999/Mar/1 */
3798 if (next >= endfontlist) break;
3799 if (fseek(input, next, SEEK_SET) < 0) break;
3801 return ATMfontindex;
3804 /* sets up pointers to sections of ATMREG.ATM */
3805 /* also determines whether wide strings are used (ATM 4.1) */
3806 /* also reads in directory path table */
3808 unsigned long ReadPointers (FILE *input)
3810 (void) fseek(input, 6, SEEK_SET);
3811 nDirs = xreadtwo(input); /* 6 number of directory paths */
3812 nFonts = xreadtwo(input); /* 8 number of font entries */
3813 nSets = xreadtwo(input); /* 10 number of font sets (?) */
3814 // sprintf(logline, "%d Dir Paths %d Font Entries %d Font Sets\n", nDirs, nFonts, nSets); // debugging only
3815 // showline(logline, 0);
3816 // (void) fseek(input, 12, SEEK_SET); /* start of pointers into file */
3817 enddirlist = xreadfour(input); /* 12 enddirlist */
3818 (void) xreadfour(input); /* 16 mystery ??? */
3819 startfontlist = xreadfour(input); /* 20 startfontlist */
3820 startdirlist = xreadfour(input); /* 24 startdirlist */
3821 startsetlist = xreadfour(input); /* 28 endfontlist */
3822 endfontlist = startsetlist;
3823 endsetlist = xreadfour(input); /* 32 endsetlist */
3825 // See whether strings in ATMREG.ATM are in UNICODE format
3826 (void) fseek(input, endsetlist, SEEK_SET);
3828 if (getc(input) == 0) bATM41 = 1;
3831 sprintf(logline, " bATM41 %d\n", bATM41);
3832 showline(logline, 0);
3837 int SetupATMReg (void)
3839 char szFullFileName[FNAMELEN]="";
3841 if (useatmreg == 0) return -1; /* tried already and failed */
3842 if (szATMRegAtm == NULL) {
3843 setupinifilesub("atmreg.atm", szFullFileName);
3845 sprintf(logline, " atmreg.atm: %s ", szFullFileName);
3846 showline(logline, 0);
3848 if (*szFullFileName == '\0') {
3849 useatmreg = 0; /* don't try again */
3852 szATMRegAtm = xstrdup(szFullFileName);
3857 // LOAD information from ATMREG.ATM in convenient form 2000 July 6
3859 int LoadATMREG (void)
3864 if (! useatmreg) return -1; // tried before and failed
3865 if (szATMRegAtm == NULL) {
3866 if (SetupATMReg()) return -1; // failed to setup now
3868 if (szATMRegAtm == NULL) return -1; // sanity check
3869 input = fopen(szATMRegAtm, "rb"); // open in binary mode for reading
3870 if (input == NULL) {
3872 return -1; // probably because not found
3875 sprintf(logline, "Scanning %s ", szATMRegAtm);
3876 showline(logline, 0);
3878 (void) ReadPointers(input);
3879 if (AllocDirs(nDirs)) {
3883 SetupDirs(input, startdirlist, enddirlist);
3884 if (AllocFonts(nFonts)) {
3888 count = ScanATMReg(input, endfontlist);
3890 if (traceflag) ShowATMREG(); // debugging output
3895 /* Look up specific font in ATMREG.ATM */
3896 /* scan atmreg.atm in the windows directory for font info */
3897 /* called with a single specific PS FontName */
3898 /* returns -1 if it fails for one reason or another */
3899 /* WRITES BACK INTO SECOND ARGUMENT */
3902 int LookupATMReg (char *szPSFontName, char *szPSFileName)
3907 if (! useatmreg) return -1; // tried before and failed
3908 if (szATMRegAtm == NULL) {
3909 if (SetupATMReg()) return -1; // failed to setup now
3911 input = fopen(szATMRegAtm, "rb"); // open in binary mode for reading
3912 if (input == NULL) return -1; // probably because not found
3914 sprintf(logline, "Scanning %s ", szATMRegAtm);
3915 showline(logline, 0);
3917 (void) ReadPointers(input);
3918 if (AllocDirs(nDirs)) return -1;
3919 SetupDirs(input, startdirlist, enddirlist);
3920 (void) fseek (input, startfontlist, SEEK_SET);
3921 n = SearchATMReg(input, endfontlist, szPSFontName, szPSFileName);
3922 // showline(" LookupATMReg ATTEMPT TO FREE DIRPATHS\n", 0); // debugging only
3929 /* First arg is PS FontName */ /* WRITES BACK INTO SECOND ARG */
3931 int LookupATMReg (char *szPSFontName, char *szPSFileName)
3934 if (! useatmreg) return -1; // tried before and failed
3935 if (szATMRegAtm == NULL) { // create ATMFonts structure
3936 if (LoadATMREG() < 0) return -1; // failed
3938 n = SearchATMReg(szPSFontName, szPSFileName);
3940 sprintf(logline, " LookupATMReg %s %s %d\n",
3941 szPSFontName, szPSFileName, n);
3942 showline(logline, 0); // debugging only
3947 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
3949 /* could perhaps be speeded up slightly - using table of chars to skip */
3951 /* check that fonts that have no characters used */
3952 /* (because of page limits) are NOT loaded in dviextra.c */
3954 /* check that nothing but nop and font defs happen between eop and bop ? */
3956 /* doesn't complain if pre not encountered ? IT DOES */
3958 /* search for start of DVI in Textures file a bit crude ? */
3960 /* try and avoid actually giving up if at all possible */
3962 /* catch DVI commands before PRE - OK */
3964 /* catch DVI commands after POST */
3966 /* is TeX comment ever used later ? */ /* yes in PS file */
3968 /* may also want to look 100 bytes into the file for start */
3969 /* some Mac files come that way... */
3971 /* bRemapSpace remaps 32 => 195, 13 to 176, 10 => 173, 9 => 170, 0 => 161 */
3972 /* Rational is that text fonts reencoded to TeX 'n ANSI do not use 0 */
3973 /* or 9 or 10, and from now on text fonts will not use 13 for fl, */
3974 /* and TeX does not use 32 in text fonts */
3975 /* But math fonts do use 0, 9, 10, 13 and 32 */
3976 /* but math fonts always have the repetition of 0 - 32 higher up */
3977 /* And for some versions of Acrobat it may be best not to do this */
3978 /* for example transfer material to clipboard is null terminated */
3979 /* 9 is treated as tab, 10 as newline, 13 ignored and 32 ignored */