OSDN Git Service

updated codes.
[putex/putex.git] / src / dvisourc / dviextra.c
1 /* Copyright 1990,1991,1992,1993,1994,1995,1996,1997,1998,1999 Y&Y, Inc.
2    Copyright 2007 TeX Users Group
3    Copyright 2014 Clerk Ma
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18    02110-1301 USA.  */
19
20 /**********************************************************************
21 *
22 * Program for decompressing and extracting font files in PFA & PFB format
23 *
24 **********************************************************************/
25
26 #include "dvipsone.h"
27
28 #define ZEROS 512     /* 512 zeros required at end of eexec section */
29 #define ZEROSPERLINE 64   /* 64 zeros per line for safety */
30 #define NOTDEF 256      /* special code for .notdef = MAXCHRS */
31
32 #define COORDINATE "+"    /* prefix for reencoded font 97/June/1 */
33               /* this has apparently not been finsihed */
34
35 unsigned short int cryptin;   /* current seed for input decryption */
36 unsigned short int cryptout;  /* current seed for output encryption */
37
38 char charseen[MAXCHRS + 1]; /* new - which CharStrings unpacked + NOTDEF */
39
40 int clm;          /* current output column */
41
42 int binaryin = 0;     /* non-zero => input binary, not hex */
43
44 int wantcreation=1;     /* copy creation date through to output */
45
46 int aliasesexist=0;     /* if *alias* found in font substitution file */
47 int syntheticsexist=0;    /* if *synthetic* in font substitution file */
48               /* normally not set to avoid need to check table */
49
50 int type3flag = 0;      /* non-zero => font file is PKTOPS output */
51               /* zero => font file is Adobe Type 1 style */
52 int mmflag=0;       /* non-zero => Multiple Master Font 94/Dec/6 */
53
54 int pssflag = 0;      /* non-zero => `font' file is PSS stub 94/Dec/6 */
55 int instanceflag = 0;   /* non-zero => MM instanced via PFM 97/June/1 */
56
57 int fontform = 0;     /* 0 => unrecog, 1 => old form, 2 => new form */
58               /* used only if breakearly is on - NOT USED */
59 int standard = 0;     /* non-zero => StandardEncoding --- NOT USED */
60 int texfont = 0;      /* non-zero => Tex font --- NOT USED */
61
62 int fontchrs = MAXCHRS;   /* actual number of characters in font */
63
64 int hybridflag;       /* 1993/Aug/5 */ /* made global 1994/July/15 */
65
66 int bBaseNameDone = 1;    /* if zero, need not add BaseFontName anymore */
67
68 /* int stripbadend=0; */  /* for now 95/Mar/1 */
69
70 // static char filefontname[MAXFONTNAME]=""; /* from file name */
71 static char filefontname[FNAMELEN]=""; /* from file name */
72 static char realfontname[FNAMELEN]="";    /* from /FontName */
73                       /* but first guess from %!PS line */
74
75 int chrs = -1;        /* current character working on */
76 unsigned long len;      /* counter of bytes in binary input */
77
78 /* Fonts, that --- in Oblique or Narrow form --- are synthetic: */
79
80 char *syntheticfonts[] =
81 {
82   "Helvetica",
83   "Courier",
84   "AvantGarde",
85   "Univers",
86   "Optima",
87   "Futura",
88   "NewsGothic",
89   "EuroStyle",      /* added 97/Oct/23 */
90   "TektonMM",       /* added 99/Apr/12 */
91   ""
92 };
93
94 /* char *basecharacters="aceinousyzACEINOUSYZ"; *//* just basic 58 - Latin 1 */
95
96 /* char *basecharacters="aceinousyzACEINOUSYZdlrtDLRT";*/ /* ISO Latin 1 + 2 */
97
98 /* char *notbasecharacters="bfmpqvxBFMPQVX"; */ /* ??? */
99
100 /* font substitution table - obtained from file */
101 /* fontsubprop small enough to keep in near space - rest banished to far */
102
103 /* static int fontsubprop[MAXSUBSTITUTE]; *//* resident/forced/remapped/alias */
104
105 int fontsubprop[MAXSUBSTITUTE];  /* resident/forced/remapped/alias */
106
107 /* 1993/Nov/15 switches from fixed array to pointers into `namestring' */
108
109 /* static char charnames[MAXCHRS][MAXCHARNAME]; */  /* names read from encoding */
110
111 #define STRINGSPACE (MAXCHRS * MAXCHARNAME / 2)
112
113 /* The above comes to 4096 bytes - textext = 650, SE = 945, ANSI = 1528 */
114
115 char *charnames[MAXCHRS];       /* encoding vector 1993/Nov/15 */
116
117 char namestring[STRINGSPACE];     /* for encoding vector 1993/Nov/15 */
118
119 int stringindex;            /* index into above space */
120
121 /* various encoding vectors needed */
122
123 /* is the following really needed ? YES, if font file Encoding is standard */
124
125 static char *standardencoding[] = {
126  "", "", "", "", "", "", "", "",
127  "", "", "", "", "", "", "", "",
128  "", "", "", "", "", "", "", "",
129  "", "", "", "", "", "", "", "",
130  "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quoteright",
131  "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash",
132  "zero", "one", "two", "three", "four", "five", "six", "seven",
133  "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question",
134  "at", "A", "B", "C", "D", "E", "F", "G",
135  "H", "I", "J", "K", "L", "M", "N", "O",
136  "P", "Q", "R", "S", "T", "U", "V", "W",
137  "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore",
138  "quoteleft", "a", "b", "c", "d", "e", "f", "g",
139  "h", "i", "j", "k", "l", "m", "n", "o",
140  "p", "q", "r", "s", "t", "u", "v", "w",
141  "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "",
142  "", "", "", "", "", "", "", "",
143  "", "", "", "", "", "", "", "",
144  "", "", "", "", "", "", "", "",
145  "", "", "", "", "", "", "", "",
146  "nbspace", "exclamdown", "cent", "sterling", "fraction", "yen", "florin", "section",
147  "currency", "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi", "fl",
148  "", "endash", "dagger", "daggerdbl", "periodcentered", "", "paragraph", "bullet",
149  "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright", "ellipsis", "perthousand", "", "questiondown",
150  "", "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent",
151  "dieresis", "", "ring", "cedilla", "", "hungarumlaut", "ogonek", "caron",
152  "emdash", "", "", "", "", "", "", "",
153  "", "", "", "", "", "", "", "",
154  "", "AE", "", "ordfeminine", "", "", "", "",
155  "Lslash", "Oslash", "OE", "ordmasculine", "", "", "", "",
156  "", "ae", "", "", "", "dotlessi", "", "",
157  "lslash", "oslash", "oe", "germandbls", "", "", "", "",
158 };
159
160 /*  TeX text encoding vector - is this needed ? Yes, if can't find file */
161
162 /* If sharing character names, copy upper part from StandardEncoding */
163
164 #ifdef SHAREENCODING
165 static char *textext[TEXCHRS] =
166 {
167   "Gamma", "Delta", "Theta", "Lambda", "Xi", "Pi", "Sigma", "Upsilon",
168   "Phi", "Psi", "Omega", "ff", "fi", "fl", "ffi", "ffl",
169   "dotlessi", "dotlessj", "grave", "acute", "caron", "breve", "macron", "ring",
170   "cedilla", "germandbls", "ae", "oe", "oslash", "AE", "OE", "Oslash",
171   "suppress"
172 };
173 #else
174 static char *textext[TEXCHRS] =
175 {
176   "Gamma", "Delta", "Theta", "Lambda", "Xi", "Pi", "Sigma", "Upsilon",
177   "Phi", "Psi", "Omega", "ff", "fi", "fl", "ffi", "ffl",
178   "dotlessi", "dotlessj", "grave", "acute", "caron", "breve", "macron", "ring",
179   "cedilla", "germandbls", "ae", "oe", "oslash", "AE", "OE", "Oslash",
180   "suppress", "exclam", "quotedblright", "numbersign", "dollar", "percent", "ampersand", "quoteright",
181   "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash",
182   "zero", "one", "two", "three", "four", "five", "six", "seven",
183   "eight", "nine", "colon", "semicolon", "exclamdown", "equal", "questiondown", "question",
184   "at", "A", "B", "C", "D", "E", "F", "G",
185   "H", "I", "J", "K", "L", "M", "N", "O",
186   "P", "Q", "R", "S", "T", "U", "V", "W",
187   "X", "Y", "Z", "bracketleft", "quotedblleft", "bracketright", "circumflex", "dotaccent",
188   "quoteleft", "a", "b", "c", "d", "e", "f", "g",
189   "h", "i", "j", "k", "l", "m", "n", "o",
190   "p", "q", "r", "s", "t", "u", "v", "w",
191   "x", "y", "z", "endash", "emdash", "hungarumlaut", "tilde", "dieresis"
192 };
193 #endif
194
195 /* "grave", "acute", "circumflex", "tilde", */
196 /* "macron", "breve", "dotaccent", "dieresis", */
197 /* "ring", "cedilla", "hungarumlaut", "ogonek", */
198 /* "caron", "dotlessi", "", "" */
199
200 /* If sharing character names, copy lower part from StandardEncoding */
201
202 /* NOTE: has non-standard added positions `dotlessi' 157 `caron' 141 */
203
204 /* NOTE: if env var ENCODING set then *that* vector is used instead */
205 /*       it is read in and overrides this Windows ANSI encoding */
206
207 /* SHAREENCODING means we copy over some pointers to save memory */
208 /* We might consider reading this one in from disk if needed */
209 /* Now that we may not be using it if ENCODING env var is set */
210
211 #ifdef SHAREENCODING
212 static char *ansiencoding[256] =
213 {
214   "", "", "", "", "", "", "", "",
215   "", "", "", "", "", "", "", "",
216   "", "", "", "", "", "", "", "",
217   "", "", "", "", "", "", "", "",
218   "", "", "", "", "", "", "", "",
219   "", "", "", "", "", "", "", "",
220   "", "", "", "", "", "", "", "",
221   "", "", "", "", "", "", "", "",
222   "", "", "", "", "", "", "", "",
223   "", "", "", "", "", "", "", "",
224   "", "", "", "", "", "", "", "",
225   "", "", "", "", "", "", "", "",
226   "", "", "", "", "", "", "", "",
227   "", "", "", "", "", "", "", "",
228   "", "", "", "", "", "", "", "",
229   "", "", "", "", "", "", "", "",
230   "", "", "quotesinglbase", "florin", "quotedblbase", "ellipsis", "dagger", "daggerdbl",
231   "circumflex", "perthousand", "Scaron", "guilsinglleft", "OE", "caron", "", "",
232   "", "quoteleft", "quoteright", "quotedblleft", "quotedblright", "bullet", "endash", "emdash",
233   "tilde", "trademark", "scaron", "guilsinglright", "oe", "dotlessi", "", "Ydieresis",
234   "nbspace", "exclamdown", "cent", "sterling", "currency", "yen", "brokenbar", "section",
235   "dieresis", "copyright", "ordfeminine", "guillemotleft", "logicalnot", "hyphen", "registered", "macron",
236   "degree", "plusminus", "twosuperior", "threesuperior", "acute", "mu", "paragraph", "periodcentered",
237   "cedilla", "onesuperior", "ordmasculine", "guillemotright", "onequarter", "onehalf", "threequarters", "questiondown",
238   "Agrave", "Aacute", "Acircumflex", "Atilde", "Adieresis", "Aring", "AE", "Ccedilla",
239   "Egrave", "Eacute", "Ecircumflex", "Edieresis", "Igrave", "Iacute", "Icircumflex", "Idieresis",
240   "Eth", "Ntilde", "Ograve", "Oacute", "Ocircumflex", "Otilde", "Odieresis", "multiply",
241   "Oslash", "Ugrave", "Uacute", "Ucircumflex", "Udieresis", "Yacute", "Thorn", "germandbls",
242   "agrave", "aacute", "acircumflex", "atilde", "adieresis", "aring", "ae", "ccedilla",
243   "egrave", "eacute", "ecircumflex", "edieresis", "igrave", "iacute", "icircumflex", "idieresis",
244   "eth", "ntilde", "ograve", "oacute", "ocircumflex", "otilde", "odieresis", "divide",
245   "oslash", "ugrave", "uacute", "ucircumflex", "udieresis", "yacute", "thorn", "ydieresis"
246 };
247 #else
248 static char *ansiencoding[] =
249 {
250   "", "", "", "", "", "", "", "",
251   "", "", "", "", "", "", "", "",
252   "", "", "", "", "", "", "", "",
253   "", "", "", "", "", "", "", "",
254   "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quotesingle",
255   "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash",
256   "zero", "one", "two", "three", "four", "five", "six", "seven",
257   "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question",
258   "at", "A", "B", "C", "D", "E", "F", "G",
259   "H", "I", "J", "K", "L", "M", "N", "O",
260   "P", "Q", "R", "S", "T", "U", "V", "W",
261   "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore",
262   "grave", "a", "b", "c", "d", "e", "f", "g",
263   "h", "i", "j", "k", "l", "m", "n", "o",
264   "p", "q", "r", "s", "t", "u", "v", "w",
265   "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "",
266   "", "", "quotesinglbase", "florin", "quotedblbase", "ellipsis", "dagger", "daggerdbl",
267   "circumflex", "perthousand", "Scaron", "guilsinglleft", "OE", "caron", "", "",
268   "", "quoteleft", "quoteright", "quotedblleft", "quotedblright", "bullet", "endash", "emdash",
269   "tilde", "trademark", "scaron", "guilsinglright", "oe", "dotlessi", "", "Ydieresis",
270   "nbspace", "exclamdown", "cent", "sterling", "currency", "yen", "brokenbar", "section",
271   "dieresis", "copyright", "ordfeminine", "guillemotleft", "logicalnot", "hyphen", "registered", "macron",
272   "degree", "plusminus", "twosuperior", "threesuperior", "acute", "mu", "paragraph", "periodcentered",
273   "cedilla", "onesuperior", "ordmasculine", "guillemotright", "onequarter", "onehalf", "threequarters", "questiondown",
274   "Agrave", "Aacute", "Acircumflex", "Atilde", "Adieresis", "Aring", "AE", "Ccedilla",
275   "Egrave", "Eacute", "Ecircumflex", "Edieresis", "Igrave", "Iacute", "Icircumflex", "Idieresis",
276   "Eth", "Ntilde", "Ograve", "Oacute", "Ocircumflex", "Otilde", "Odieresis", "multiply",
277   "Oslash", "Ugrave", "Uacute", "Ucircumflex", "Udieresis", "Yacute", "Thorn", "germandbls",
278   "agrave", "aacute", "acircumflex", "atilde", "adieresis", "aring", "ae", "ccedilla",
279   "egrave", "eacute", "ecircumflex", "edieresis", "igrave", "iacute", "icircumflex", "idieresis",
280   "eth", "ntilde", "ograve", "oacute", "ocircumflex", "otilde", "odieresis", "divide",
281   "oslash", "ugrave", "uacute", "ucircumflex", "udieresis", "yacute", "thorn", "ydieresis"
282 };
283 #endif
284
285 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
286
287 int mmcount;                /* how many MM base fonts added */
288
289 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
290
291 /* Stuff for initializing resident encoding vectors - to save memory */
292
293 void initializeencoding(int ansitexflag)
294 {
295   int k;
296 #ifdef SHAREENCODING
297   for (k = 33; k < 123; k++)
298     textext[k] = standardencoding[k];
299 /*  now for the fixups */
300 /*  textext[32] = "suppress"; */
301   textext[34] = standardencoding[186];  /* "quotedblright" */
302   textext[60] = standardencoding[161];  /* "exclamdown" */
303   textext[62] = standardencoding[191];  /* "questiondown" */
304   textext[92] = standardencoding[170];  /* "quotedblleft" */
305   textext[94] = standardencoding[195];  /* "circumflex" */
306   textext[95] = standardencoding[199];  /* "dotaccent" */
307   textext[123] = standardencoding[177]; /* "endash" */
308   textext[124] = standardencoding[208]; /* "emdash" */
309   textext[125] = standardencoding[205]; /* "hungarumlaut" */
310   textext[126] = standardencoding[196]; /* "tilde" */
311   textext[127] = standardencoding[200]; /* "dieresis" */
312   for (k = 32; k < 128; k++) ansiencoding[k] = standardencoding[k];
313   ansiencoding[39] = standardencoding[169]; /* "quotesingle" */
314   ansiencoding[96] = standardencoding[193]; /* "grave" */
315 /*  copy over accents for Adobe Level 1 PS interpreter bug as in PSCRIPT */
316 /*  for (k = 0; k < 15; k++) ansiencoding[k] = standardencoding[k+193]; */
317 /*  ansiencoding[15] = standardencoding[245]; *//* dotlessi*/
318 #endif
319 /*  copy over accents for Adobe Level 1 PS interpreter bug as in PSCRIPT */
320 /*  actually, mostly we just need `caron', `dotlessi' and maybe `ring' ... */
321   if (!ansitexflag)
322   {
323     for (k = 0; k < 15; k++) ansiencoding[k] = standardencoding[k+193];
324     ansiencoding[15] = standardencoding[245]; /* dotlessi*/
325   }
326   if (ansitexflag) {  /* or do this in PostScript later ??? 93/Dec/18 */
327             /* this had a bug that was fixed 93/Dec/28 */
328 /*    strcpy(ansiencoding[0], ""); */   /* avoid grave repeat */
329 /*    strcpy(ansiencoding[1], ""); */   /* avoid acute repeat */
330 /*    strcpy(ansiencoding[4], ""); */   /* avoid macron repeat */
331 /*    strcpy(ansiencoding[5], ""); */   /* avoid breve repeat */
332 /*    strcpy(ansiencoding[9], ""); */   /* avoid ring repeat */
333 /*    strcpy(ansiencoding[10], ""); */  /* avoid cedilla repeat */
334 /*    strcpy(ansiencoding[14], ""); */  /* avoid caron repeat */
335     /* 0  - 10 Greek - not in ANSI */
336     /* 11 - 15 f ligatures - not in ANSI */
337     /* 16 - 17 dotlessi dotlessj - not ANSI */
338 /* 16 - 24 dotlessi, dotlessj, grave, acute, caron, breve, macron, ring, cedilla */
339 /* 25 - 31 germandbls, ae, oe, oslash, AE, OE, Oslash */
340 /* actually: dotlessj, caron, breve, - and ring - missing in ANSI */ 
341     for (k = 16; k < 32; k++) ansiencoding[k] = textext[k];
342     ansiencoding[17] = "";        /* flush `dotlessj' */
343     ansiencoding[21] = "";        /* flush `breve' */
344 /* but keep `caron' and `ring' for PS interpreter bug fix (not in ANSI) */
345 /* potential problem with some characters now being repeated higher up ? */
346   }
347 }
348
349 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
350
351 /* stuff for reading in AFM/TFM files and extracting metric information */
352 /* provides alternate of reading AFM file instead */
353 /* if file can't be found or read, don't adjust metric information */
354
355 /* graceful exit with suitable error message */
356 /* graceful exit with meaningful error message */
357 void extgiveup(int code)
358 {
359   char *s=logline;
360
361   if (*task != '\0')
362   {
363     sprintf(s, " while %s", task);
364     s += strlen(s);
365   }
366
367   if (chrs >= 0)
368   {
369     sprintf(s, " for character %d ", chrs);
370     s += strlen(s);
371   }
372
373   if (*filefontname != '\0')
374   {
375     sprintf(s, " in font %s", filefontname);
376     s += strlen(s);
377   }
378
379   strcat(logline, "\n");
380   showline(logline, 1);
381 /*  exit(code); */
382   checkexit(code);          /* 1995/Oct/28 */
383 }
384
385 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
386 /* read four byte length code */
387 unsigned long readlength(FILE* input)
388 {
389   int c, k;
390   unsigned long n = 0L;
391
392   for (k=0; k < 4; k++)
393   {
394     c = getc(input);
395     n = n >> 8; n = n | ((unsigned long) c << 24);
396   }
397   return n;
398 }
399 /* read four byte length code */
400 unsigned long maclength(FILE *input)
401 {
402   int k;
403   unsigned long n = 0L;
404   
405   for (k = 0; k < 4; k++) n = (n << 8) | getc(input);
406   return n;
407 }
408
409 int getnextnon(FILE *input)
410 {
411   int c;
412   c = getc(input);
413   if (c == '\r' && flushcr != 0)
414   {
415     c = getc(input);
416     if (c != '\n')
417     {
418       (void) ungetc(c, input);
419       c = '\n';
420     }
421   }
422   return c;
423 }
424   
425 /* read a line up to newline (or return) */ /* returns EOF if at end of file */
426 /* was char *line */
427 int extgetline(FILE *input, char *buff)
428 {
429   char *s=buff;
430   int c, k=0;
431
432   c = getnextnon(input);
433 /*  if (flushcr != 0) while (c == '\r') c = getc(input); */
434   while (c != '\n') {
435     if (c == EOF) return EOF;
436     if (c == 128) { /* flush over ASCII section headers */
437       binaryin = 1;
438       c = getc(input);
439       if (c == 3) return EOF;
440       if (c != 1) {
441         sprintf(logline,
442           " Expecting %s, not %d", "ASCII section code", c);
443         showline(logline, 1);
444         extgiveup(5);
445         return EOF;
446       }
447       len = readlength(input);  /* read and ignore ! */
448       c = getnextnon(input);
449       if (c == EOF) return EOF; /* never */
450       if (c == '\n') break;
451     }
452     else if (c == 0) { /* Presumably Mac Style ASCII section code */
453       sprintf(logline, " AT BYTE %ld ", ftell(input));  /* debugging */
454       showline(logline, 0);
455       binaryin = 1;
456       (void) ungetc(c, input);
457       len = maclength(input);
458       c = getc(input);
459       if (c == 5) return EOF;
460       if (c != 1) {
461         sprintf(logline, " Expecting %s, not %d",
462             "Mac ASCII section code", c);
463         showline(logline, 1);
464         extgiveup(5);
465         return EOF;
466       }
467       c = getc(input);
468       if (c != 0) {
469         sprintf(logline, " Invalid Mac ASCII section code %d", c);
470         showline(logline, 1);
471         extgiveup(5);
472         return EOF;
473       }
474       len = len -2;
475       c = getnextnon(input);
476       if (c == EOF) return EOF; /* never */
477 /*      if (c == '\r') c = '\n'; */
478       if (c == '\n') break;
479     }
480     *s++ = (char) c; k++;
481     if (k >= MAXLINE) {
482       showline(" Line too long in dviextra getline", 1);
483 /*      extgiveup(6); */      /* flushed */
484       *(s-1) = '\0';        /* terminate the junk at least */
485       if (verboseflag) {    /* 93/Aug/13 */
486         showline("\n", 0);
487         showline(buff, 1);
488         showline("\n", 0);
489       }
490 /*      read to end of line (or EOF) before going on ? */
491       while ((c = getnextnon(input)) != '\n') {
492         if (c == EOF) return EOF;
493       }
494       errcount(0);        /* 93/Aug/13 */
495       *buff = '\0';       /* flush this crap ! */
496       return 0;
497     }
498     c = getnextnon(input);  /* flush any returns */
499   }
500   *s++ = (char) c; k++; /* terminating '\n' */
501   *s++ = '\0';
502   return k;
503 }
504
505 /* hmm, return value of extgetrealline used to be never used ... */
506 /* get non-comment, non-blank */
507 int extgetrealline(FILE *input, char *buff)
508 {
509   int k;
510   k = extgetline(input, buff);
511   while ((*buff == '%' || *buff == '\n') && k >= 0)
512     k = extgetline(input, buff);
513   return k;
514 }
515
516 //////////////////////////////////////////////////////////////////////////////
517
518 int ksubst=0;         // number of entries in substitution table
519
520 char *makespace (char *s, int ndes, int nact)
521 {
522   int k;
523 //  char *s=logline;
524 //  for (k = nact; k < ndes; k++) putc(' ', output);
525   for (k = nact; k < ndes; k++) *s++ = ' ';
526   *s = '\0';
527   return s;
528 }
529
530 char *showproper (char *s, int proper)
531 {
532   if (proper == 0) return s;
533   if ((proper & C_RESIDENT) != 0) sprintf(s, "%s ", RESIDENT);
534   if ((proper & C_FORCESUB) != 0) sprintf(s, "%s ", FORCESUB);
535 /*  if ((proper & C_REMAPIT) != 0) sprintf(s, "%s ", REMAPIT); */
536   if ((proper & C_ALIASED) != 0) sprintf(s, "%s ", ALIASED);
537   if ((proper & C_MISSING) != 0) sprintf(s, "*missing* ");
538   if ((proper & C_UNUSED) != 0) sprintf(s, "*unused* ");
539 /*  if ((proper & C_DEPENDENT) != 0) sprintf(s, "*new-size* "); */
540 /*  if ((proper & C_COMPOUND) != 0) sprintf(s, "%s ", COMPOUND); */
541   if ((proper & C_SYNTHETIC) != 0) sprintf(s, "%s ", SYNTHETIC);
542   if ((proper & C_MTMI) != 0) sprintf(s, "%s ", MTMI);
543   if ((proper & C_EPSF) != 0) sprintf(s, "%s ", EPSF); /* 94/Aug/15 */
544   if ((proper & C_DEPENDENT) != 0) sprintf(s, "*new-size* ");
545   if ((proper & C_REMAPIT) != 0) sprintf(s, "%s ", REMAPIT);
546 /*  if ((proper & C_CONTROL) != 0) sprintf(s, "%s ", CONTROL); */
547   if ((proper & C_NOTBASE) != 0) sprintf(s, "*not-base* ");
548   return s + strlen(s);
549 }
550
551 /* an experiment */
552 void showsubtable(void)
553 {
554   int k;
555   char *s;
556 //  char oldname[MAXTEXNAME];
557   char oldname[FNAMELEN];
558 //  char newname[MAXFONTNAME];
559   char newname[FNAMELEN];
560 //  char vecname[MAXVECNAME];     /* 1994/Feb/4 */
561   char vecname[FNAMELEN];
562
563   showline("Font Substitution Table:\n", 0);
564   for (k = 0; k < ksubst; k++) {
565 //    strcpy(oldname, fontsubfrom + k * MAXTEXNAME);
566     if (fontsubfrom[k] != NULL) strcpy(oldname, fontsubfrom[k]);
567     else *oldname = '\0';
568 //    strcpy(newname, fontsubto + k * MAXFONTNAME);
569     if (fontsubto[k] != NULL) strcpy(newname, fontsubto[k]);
570     else *newname = '\0';
571 //    strcpy(vecname, fontsubvec + k * MAXVECNAME);
572     if (fontsubvec[k] != NULL) strcpy(vecname, fontsubvec[k]);
573     else *vecname = '\0';
574     s = logline;
575     sprintf(s, "%3d %s ", k, oldname);
576     s += strlen(s);
577     s = makespace(s, 10, strlen(oldname));  /* MAXTEXNAME ? */
578     sprintf(s, "=> %s ", newname);
579     s += strlen(s);
580     s = makespace(s, 16, strlen(newname));  /* MAXFONTNAME ? */
581     s = showproper(s, fontsubprop[k]);
582 /*    if (strcmp(fontsubvec[k], "") != 0)
583       fprintf(output, "vec: %s", fontsubvec[k]); */
584     if (strcmp(vecname, "") != 0) {
585       sprintf(s, "vec: %s", vecname);
586       s += strlen(s);
587     }
588 //    putc('\n', output);
589     strcat(s, "\n");
590     showline(logline, 0);
591   }
592 //  putc('\n', output);
593   showline("\n", 0);
594 }
595
596 /* recover TeX internal font number */
597 int original (int k)
598 {
599   int m;
600   for (m = 0; m < MAXFONTNUMBERS; m++)
601   {
602     if (finx[m] == (short) k) return m;
603 //    if (finx[m] == k) return m;
604   }
605   return -1;
606 }
607
608 /* an experiment */
609 void showfonttable (void)
610 {
611   int k, flag, originalfont;
612   double atsize;
613   int proper;
614 //  char oldname[MAXTEXNAME];
615   char oldname[FNAMELEN];
616 //  char newname[MAXFONTNAME];
617   char newname[FNAMELEN];
618   char *s=logline;
619
620 //  fprintf(output, "Font Table:");
621   strcpy(s, "Font Table:");
622   s += strlen(s);
623   if (mag != 1000)
624     sprintf(s, " (Magnification %lg)", (double) mag / 1000);
625   strcat(s, "\n");
626   showline(logline, 0);
627   
628 /*  if (traceflag) printf("mmbase %d fnext %d\n", mmbase, fnext); */
629   for (k = 0; k < fnext; k++)
630   {
631     s = logline;
632     proper = fontproper[k];
633 /*    do only if fontsubflag >= 0 ? */
634 /*    do only if (proper & C_DEPENDENT) != 0 ? */
635 /*    don't bother to list if unused */
636 /*    if (proper & C_UNUSED) != 0) continue; *//* remove 94/Oct/6 */
637     sprintf(s, "%3d ", k);
638     s += strlen(s);
639     originalfont = original(k);   /* original TeX font number */
640     if (originalfont >= 0) sprintf(s, "(%3d) ", originalfont);
641     else s = makespace(s, 6, 0);
642 //    strcpy(oldname, fontname + k * MAXTEXNAME);
643     if (fontname[k] != NULL) strcpy(oldname, fontname[k]);
644     else *oldname = '\0';
645     if (subfontname[k] != NULL) strcpy(newname, subfontname[k]);
646     else *newname = '\0';
647 //    strcpy(newname, subfontname + k * MAXFONTNAME);
648     sprintf(s, "%s ", oldname);
649     s += strlen(s);
650     s = makespace(s, 10, strlen(oldname));
651     if (strcmp(newname, "") != 0 && strcmp(oldname, newname) != 0) {
652       sprintf(s, "=> %s ", newname);
653       s += strlen(s);
654       s = makespace(s, 16, strlen(newname));
655     }
656     atsize = (double) fs[k] * num / den * 72.27 / 254000;
657 /*    possibly also * mag / 1000 ? NO */
658 /*    if (atsize != 0.0) fprintf(output, "at:%6.6lg pt ", atsize); */
659     if (atsize != 0.0) sprintf(s, "at:%6.5lg pt ", atsize);
660 /*    else if (originalfont < 0) fprintf(output, "base for remapped font "); */
661 /*    else if (k >= mmbase) fprintf(output, "MM base font ");  */
662     else if (proper & C_MULTIPLE) sprintf(s, "MM base font ");
663     else if (proper & C_INSTANCE) sprintf(s, "MM instance ");
664     else if (originalfont < 0) sprintf(s, "base for substitution ");
665 /*    or Multiple Master base font 94/Dec/6 */
666     else s = makespace(s, 13, 0);
667     s +=strlen(s);
668     flag = fontsubflag[k];
669     if (flag >= 0) {  /* follow substitution pointer */
670       sprintf(s, "base: %2d ", flag);
671       s +=strlen(s);
672       originalfont = original(flag);
673       if (originalfont >= 0) sprintf(s, "(%3d) ", originalfont);
674       else s = makespace(s, 6, 0);
675       s +=strlen(s);
676     }
677     s = showproper(s, proper);    /* show properties */
678
679 /*    printf("|"); */
680 //    if (strcmp(fontvector[k], "") != 0)
681 //    if (*(fontvector + k * MAXVECNAME) != '\0') {
682     if (fontvector[k] != NULL)
683     {
684 /*      fprintf(output, "vec: %s", fontvector[k]); */
685 /*      fprintf(output, "%s", fontvector[k]); */
686 //      fputs(fontvector[k], output);   /* 1992/July/18 */
687       strcat(s, fontvector[k]);
688       s +=strlen(s);
689     }
690 //    putc('\n', output);
691     strcat(s, "\n");
692     showline(logline, 0);
693   }
694   showline("\n", 0);
695 }
696
697 /* void showencoding (FILE *output) {
698   int i;
699   for (i = 0; i < fontchrs; i++) 
700     fprintf(output, "%d: %s\n", i, charnames[i]);
701 } */ /* debugging only */
702
703 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
704
705 /* moved to dvipslog.c to avoid compiler bug ! 1995/May/25 */
706
707 /* int readtfm(char *, FILE *, long widths[]); */
708 /* int readafm(char *, FILE *, long widths[]); */
709 /* int readpfm(char *, FILE *, long widths[]); */
710
711 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
712
713 /* New common routine 1992/Nov/28 */
714 /* does not use backslash if beginning is blank or already ends on : \ or / */
715
716 void makefilename (char filepath[], char *fontname)
717 {
718   char *s;
719   if (strcmp(filepath, "") != 0) {  /* 1992/Oct/30 */
720     s = filepath + strlen(filepath) - 1;
721     if (*s != ':' && *s != '\\' && *s != '/') strcat(filepath, "\\");
722   }
723   strcat(filepath, fontname);
724 /*  extension(filepath, ext); */
725 }
726
727 /* returns -1 if name was changed - returns 0 if name was not changed */
728
729 /* convert font file name to Adobe style */
730 int underscore (char *filename)
731 {
732   int k, n, m;
733   char *s, *t;
734
735   s = removepath(filename);
736   n = (int) strlen(s);
737   if ((t = strchr(s, '.')) == NULL) t = s + strlen(s);
738   m = t - s;
739   if (m == 8)
740   {
741 /*    printf("NO CHANGE IN %s\n", filename); */ /* debugging */
742     return 0;     /* no change 95/May/28 */
743   }
744   memmove(s + 8, t, (unsigned int) (n - m + 1));
745   for (k = m; k < 8; k++) s[k] = '_';
746   return -1;
747 }
748
749 /* removes underscores at end, assumes there is no file extension ... */
750 /* returns 0 if there were no underscores to remove - returns -1 otherwise */
751
752 /* remove Adobe style underscores */
753 int removeunder (char *filename)
754 {
755   char *s;
756   s = filename + strlen(filename) - 1;
757   if (*s != '_') return 0;    /* 95/May/28 */
758   while (*s == '_') s--;
759   *(s + 1) = '\0';        /* overwrite first underscore in seq */
760   return -1;
761 }
762
763 /* Consolidated code for TFM, AFM, and PFM in one place 95/Mar/31 */
764
765 FILE *lookformetrics (char *font, char *extension, char *path)
766 {
767   char fn_met[FNAMELEN];
768   FILE *fp_met=NULL;
769 #ifndef SUBDIRSEARCH
770   char *searchpath;
771 #endif
772
773   if (traceflag)
774   {
775     sprintf(logline, " Trying %s", path); /* debug 95/Mar/31 */
776     showline(logline, 0);
777   }
778
779 #ifdef SUBDIRSEARCH
780   strcpy(fn_met, font);
781   forceexten(fn_met, extension);
782   fp_met = findandopen(fn_met, path, NULL, "rb", currentfirst);
783   if (fp_met == NULL && tryunderscore != 0)
784   {
785 /*    underscore (fn_met); */
786 /*    fp_met = findandopen(fn_met, path,  NULL, "rb", currentfirst); */
787     if (underscore(fn_met))         /* 95/May/28 */
788       fp_met = findandopen(fn_met, path,  NULL, "rb", currentfirst);
789   }
790 #else
791   searchpath = path;
792   for (;;) {
793     if ((searchpath=nextpathname(fn_met, searchpath)) == NULL) break;
794     makefilename(fn_met, font);     /* 1992/Nov/28 */
795     forceexten(fn_met, extension);
796     if ((fp_met = fopen(fn_met, "rb")) == NULL) {
797       if (tryunderscore == 0) continue;
798       else {
799 /*        underscore(fn_met);
800         if ((fp_met = fopen(fn_met, "rb")) == NULL) continue; 
801         else break; */              /* 1994/Aug/18 */
802         if (underscore(fn_met)) {       /* 1995/May/28 */
803           if ((fp_met = fopen(fn_met, "rb")) != NULL) break;
804         }
805         continue;
806       }
807     }
808     else break;             /* 1994/Aug/18 */
809   }
810 #endif
811   if (traceflag) {            /* 1995/Mar/31 */
812     if(fp_met != NULL) {
813       sprintf(logline, " Using %s", fn_met);
814       showline(logline, 0);
815     }
816   }
817   return fp_met;
818 }
819
820 /* get character widths from .tfm or .afm or .pfm files - for substitution */
821 /* tfm is searched first because it is compact - hence fast */
822 /* pfm is searched last because widths are restricted to being integers */
823 /* returns max numeric code of character in metric info */
824
825 int readwidths (char *font, long widths[])
826 {
827   FILE *fp_met=NULL;
828 /*  char fn_met[FNAMELEN]; */
829   int k;
830 #ifndef SUBDIRSEARCH
831 /*  char *searchpath; */
832 #endif
833
834   task = "looking for font metrics";
835
836   if (tfmpath != NULL)
837   {
838     fp_met = lookformetrics(font, "tfm", tfmpath);
839     if (fp_met != NULL)
840     {
841       k = readtfm(font, fp_met, widths);
842       fclose(fp_met); 
843       return k;
844     }
845   }
846
847   if (texfonts != NULL)
848   {
849     fp_met = lookformetrics(font, "tfm", texfonts);
850     if (fp_met != NULL)
851     {
852       k = readtfm(font, fp_met, widths);
853       fclose(fp_met); 
854       return k;
855     }
856   }
857
858   if (afmpath != NULL)
859   {
860     fp_met = lookformetrics(font, "afm", afmpath);
861     if (fp_met != NULL)
862     {
863       k = readafm(font, fp_met, widths);
864       fclose(fp_met);
865       return k;
866     }
867   }
868
869   if (pfmpath != NULL)
870   {
871     fp_met = lookformetrics(font, "pfm", pfmpath);
872     if (fp_met != NULL)
873     {
874       k = readpfm(font, fp_met, widths);
875       fclose(fp_met);
876       return k;
877     }
878   }
879
880   sprintf(logline, " WARNING: metrics not found for %s", font);
881   showline(logline, 1);
882   errcount(0);
883   return 0;
884 }
885
886 /* for remapping and substituting font names */
887
888 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
889
890 /* stuff for dealing with font file itself */
891 /* get next byte from input */
892 int nextbytein(FILE *input)
893 {
894   int c, d;
895
896   if (binaryin != 0)
897   {
898     if (len == 0)
899     {
900       c = getc(input);
901       if (c != 0 && c != 128)
902       {
903         sprintf(logline, " Expecting %s, not %d", "binary length code", c);
904         showline(logline, 1);
905         extgiveup(3);
906         return -1;
907       }
908       if (c == 128) {   /* PC .pfb file   */
909         c = getc(input);
910         if (c == 1) {  /* somewhat unexpected, but... */
911           len = readlength(input);
912           binaryin = 0;
913           return nextbytein(input); /* try reading in ASCII */
914         }
915         else if (c != 2) {
916           sprintf(logline, " Expecting %s, not %d", "binary section code", c);
917           showline(logline, 1);
918           extgiveup(5);
919           return -1;
920         }
921         len = readlength(input);
922 /*        if (traceflag) printf("Binary Section %lu\n", len);  */
923       }
924       else {        /* Mac style binary file   c == 0 */
925         (void) ungetc(c, input);
926         len = maclength(input);
927         c = getc(input);
928         if (c == 1) { /* somewhat unexpected, but... */
929           binaryin = 0;
930           return nextbytein(input); /* try reading in ASCII */
931         }
932         else if (c != 2) {
933           sprintf(logline, 
934             " Expecting %s, not %d", "Mac binary section code", c);
935           showline(logline, 1);
936           extgiveup(5);
937           return -1;
938         }
939         c = getc(input);
940         if (c != 0) {
941           sprintf(logline, " Invalid Mac style binary record %d", c);
942           showline(logline, 1);
943           extgiveup(15);
944           return -1;
945         }
946         len = len - 2;
947       }
948     }
949 /*    c = getc(input); */
950     if ((c = getc(input)) == EOF)
951     {
952       sprintf(logline, " Unexpected EOF (%s)\n", "nextbytein");
953       showline(logline, 1);
954       extgiveup(7);
955       return -1;
956     }
957     len--;
958     return c;
959   }
960   else {            /* ASCII input */
961     c = getc(input);
962     while (c <= ' ' && c != EOF) c = getc(input);
963     if (c == EOF) {
964       sprintf(logline, " Unexpected EOF (%s)\n", "nextbytein");
965       showline(logline, 1);
966       extgiveup(7);
967       return -1;
968     }
969     if (c >= '0' && c <= '9') c = c - '0';    /* use table ? */
970     else if (c >= 'A' && c <= 'F') c = c - 'A' + 10;
971     else if (c >= 'a' && c <= 'f') c = c - 'a' + 10;
972     else {
973       sprintf(logline, " Invalid hex character: %d", c);
974       showline(logline, 1);
975       extgiveup(7);
976       return -1;
977     }
978     d = getc(input);
979     while (d <= ' ' && d != EOF) d = getc(input);
980     if (d == EOF) {
981       sprintf(logline, " Unexpected EOF (%s)\n", "nextbytein");
982       showline(logline, 1);
983       extgiveup(7);
984       return -1;
985     }
986     if (d >= '0' && d <= '9') d = d - '0';    /* use table ? */
987     else if (d >= 'A' && d <= 'F') d = d - 'A' + 10;
988     else if (d >= 'a' && d <= 'f') d = d - 'a' + 10;
989     else {
990       sprintf(logline, " Invalid hex character: %d", d);
991       showline(logline, 1);
992       extgiveup(7);
993       return -1;
994     }
995     return (c << 4) | d;
996   }
997 }
998
999 /* stuff for encrypting and decrypting */
1000
1001 unsigned char decryptbyte (unsigned char cipher, unsigned short *crypter)
1002 {
1003   unsigned char plain;
1004
1005   plain = (unsigned char) ((cipher ^  (unsigned char) (*crypter >> 8)));
1006   *crypter = (unsigned short) ((cipher + *crypter) * CRYPT_MUL + CRYPT_ADD);
1007
1008   return plain;
1009 }
1010
1011 /* read byte and decrypt */
1012 unsigned char indecrypt(FILE *input)
1013 {
1014   unsigned char cipher;
1015   unsigned char plain;
1016
1017   cipher = (unsigned char) nextbytein(input);
1018   plain = (unsigned char) ((cipher ^ (unsigned char) (cryptin >> 8)));
1019   cryptin = (unsigned short) ((cipher + cryptin) * CRYPT_MUL + CRYPT_ADD);
1020
1021   return plain;
1022 }
1023
1024 // rewritten for efficiency to not use putc but fputs
1025 // now accumulates a line of output in logline
1026 // assumes we are not using logline for something else...
1027
1028 /* stuff for encrypted input and output */
1029
1030 /* encrypt and write */
1031 void outencrypt(unsigned char plain, FILE *output)
1032 {
1033   int c, d;
1034   unsigned char cipher;
1035   char *s=logline+clm;
1036
1037 /*  cipher = (plain ^ (unsigned char) (cryptout >> 8)); */
1038   cipher = (unsigned char) ((plain ^ (unsigned char) (cryptout >> 8)));
1039 /*  cryptout = (cipher + cryptout) * CRYPT_MUL + CRYPT_ADD; */
1040   cryptout = (unsigned short) ((cipher + cryptout) * CRYPT_MUL + CRYPT_ADD);
1041
1042   d = cipher & 15;
1043   c = (cipher >> 4) & 15;
1044   if (c < 10) {
1045 //    putc(c + '0', output);
1046 //    PSputc((char) (c+'0'), output);
1047     *s++ = (char) (c+'0');
1048   }
1049   else {
1050 //    putc(c + 'A' - 10, output);
1051 //    PSputc((char) (c+'A'-10), output);
1052     *s++ = (char) (c+'A'-10);
1053   }
1054   clm++;
1055   if (d < 10) {
1056 //    putc(d + '0', output);
1057 //    PSputc((char) (d+'0'), output);
1058     *s++ = (char) (d+'0');
1059   }
1060   else {
1061 //    putc(d+ 'A' - 10, output);
1062 //    PSputc((char) (d+'A'-10), output);
1063     *s++ = (char) (d+'A'-10);
1064   }
1065   clm++;
1066   if (clm >= columns) {
1067 //    putc('\n', output);
1068 //    PSputc('\n', output);
1069     *s++ = '\n';
1070     *s++ = '\0';
1071     PSputs(logline, output);
1072     clm = 0;
1073   }
1074
1075
1076 void flushencrypt (FILE *output)
1077 {
1078   char *s=logline+clm;
1079   if (clm > 0) {
1080     *s++ = '\n';
1081     *s++ = '\0';
1082     PSputs(logline, output);
1083     clm = 0;
1084   }
1085 }
1086
1087 /* 93/Sep/14 --- avoid using getenline for this in case ^M or ^J */
1088 /* get the magic encrypt start bytes */
1089 int getmagic(FILE *input, char *buff)
1090 {
1091   char *s=buff;
1092   int k=0;
1093   for (k = 0; k < 4; k++) *s++ = (char) indecrypt(input);
1094   *s++ = '\0';
1095   return 4;
1096 }
1097
1098 /* There shouldn't be any returns inside the encrypted part, just newlines */
1099 /* But some stupid fonts disobey this rule => turn return into newline */
1100 /* One problem: can't conveniently look ahead in encrypted part */
1101 /* This gets nasty if there are returns FOLLOWED newlines */
1102 /* so be prepared to see an isolated return or newline at start of line */
1103
1104 /* read encrypted line */
1105 int getenline(FILE *input, char *buff)
1106 {
1107   char *s=buff;
1108 /*  int c; */
1109   int d, k=0;
1110
1111   d = indecrypt(input);
1112 /*  if (d == '\r')  d = indecrypt(input); */  /* bkph - 91/10/1 */
1113 /*  step over initial return/newline - remanants or blank lines */
1114   while (d == '\n' || d == '\r') d = indecrypt(input);
1115   while (d != '\n') {
1116     *s++ = (char) d; k++;
1117     if (k >= MAXLINE) {
1118       *s = '\0';
1119       showline(" Line: ", 1);
1120       showline(buff, 1);
1121       showline("\n", 0);
1122       sprintf(logline, " too long in encrypted getline (> %d)", MAXLINE);
1123       showline(logline, 0);
1124       extgiveup(6);
1125       return -1;
1126     }
1127     d = indecrypt(input);
1128     if (d == '\r')
1129     {
1130 /*      *s = '\0';
1131       printf("RETURN AFTER: %s\n", buff); */
1132 /*      d = indecrypt(input); */ /* bkph 91/10/1 */
1133       d = '\n';
1134     }
1135   }
1136   *s++ = (char) d; k++;
1137   *s++ = '\0';
1138 /*  if (traceflag) printf("IN:  %s", buff); */
1139   return k;
1140 }
1141
1142 // need to remember to flush out logline at end also ...
1143
1144 /* This version assumes string is null terminated */
1145 /* write encrypted line */
1146 void putenline(FILE *output, char *buff)
1147 {
1148   int d; 
1149
1150   while ((d = *buff++) != '\0') {
1151     outencrypt((unsigned char) d, output);
1152   }
1153 }
1154
1155 /* This version specifies length rather than null terminated */
1156 /* write encrypted line */
1157 void putenlinen(FILE *output, char *buff, int n)
1158 {
1159   int d, k; 
1160   
1161   for (k = 0; k < n; k++) {
1162     d = *buff++;
1163     outencrypt((unsigned char) d, output);
1164   }
1165 }
1166
1167 /* used for reading "/charname n RD" for CharStrings */
1168 /* also used for reading "dup n m RD" for Subrs */
1169 /* normally returns zero, when hit end returns -1 */
1170
1171 /* May want to distinguish Subrs and CharStrings case */
1172 /* because Subrs can end on "readonly def" */
1173 /* but that can occur in CharStrings ... */
1174
1175 /* subrflag != 0 for Subrs reading added 93/Aug/13 */
1176 /* get encrypted tokens */
1177
1178 /* reads until it hits RD, -|, end, ND, |-, noaccess def, readonly def */
1179 /* which may mean it reads past end of line ... */
1180
1181 int getcharline(char *buff, FILE *input, int subrflag)
1182 {
1183   int d;
1184   char *t = buff, *s = buff;
1185
1186   d = indecrypt(input);     /* skip over initial white space */
1187 /*  while (d == '\n' || d == '\r' || d == ' ')   */
1188   while (d == '\n' || d == '\r' || d == ' ' || d == '\0') /* 98/Apr/20 */
1189     d = indecrypt(input); 
1190   for(;;) {
1191 /*    d = indecrypt(input);  */
1192 /*    if (d == '\n') {
1193       if (verboseflag) printf("Unexpected end of line\n");
1194       continue;
1195     } */
1196     *s++ = (char) d;
1197     if (d <= ' ') {
1198       if(strncmp(t, "RD", 2) == 0 ||
1199          strncmp(t, "-|", 2) == 0) { /* ready for binary bytes */
1200         *s = '\0';
1201         return 0;   /* start of binary section */
1202       }
1203       else if ((strncmp(t, "end", 3) == 0) ||  /* end of CharStrings */
1204            (strncmp(buff, "ND", 2) == 0) ||   /* or end of Subrs */
1205            (strncmp(buff, "|-", 2) == 0)) { /* or end of Subrs */
1206         *s = '\0';
1207         return -1;      /* end of Subrs or CharStrings */
1208       }
1209 /* 93 Aug  5 */ /* for Subrs only */  
1210       else if (subrflag != 0 &&
1211         (strncmp(buff, "noaccess def", 12) == 0 ||
1212  /* 93 Aug 13 */ /* for Subrs only */ 
1213           strncmp(buff, "readonly def", 12) == 0)) {
1214         *s = '\0';
1215         return -1;      /* end of Subrs or CharStrings */
1216       }
1217       else t = s;   /* remember start of next token */
1218     }
1219 /*    else if (d == '\n') {
1220       if (verboseflag) printf("Unexpected end of line: %s\n", t);
1221       *s = '\0';
1222       return 1;
1223     } */
1224     d = indecrypt(input);
1225   }
1226 }
1227
1228 /* flush rest of CharString */
1229 void flushcharstring(FILE *input, int n)
1230 {
1231   int k, d;
1232   
1233   for (k = 0; k < n; k++) (void) indecrypt(input); /* flush binary part */
1234   d = indecrypt(input);
1235   while (d != '\n') {
1236     d = indecrypt(input);   /* flush ND or |- up to nl (or rt)*/
1237     if (d == '\r') d = '\n';  /* bkph 91/10/1 */
1238   }
1239 }
1240
1241 /* copy CharString or Subr string */
1242 /* the fix may be slightly dicey since it may generate blank line at */
1243
1244 void copycharstring(FILE *output, FILE *input, int n)
1245 {
1246   int d, k; /* c, e */
1247   for (k = 0; k < n; k++) {     /* copy binary CharString itself */
1248     d = indecrypt(input);
1249     outencrypt((unsigned char) d, output);
1250   }
1251   d = indecrypt(input);   /* default is to drop space before ND */
1252 /*  if (d != ' ') */
1253   if (d != ' ' || keepgap != 0) /* 1993 August 5 */
1254     outencrypt((unsigned char) d, output); 
1255     
1256   while (d != '\n') {         /* copy ND or | - up to nl (or rt)*/
1257     d = indecrypt(input);
1258     if (d == '\r') d = '\n';    /* bkph 91/10/1 */
1259     outencrypt((unsigned char) d, output);    
1260   }
1261 }
1262
1263 /* do we want char with this name ? */
1264 /* return negative if not - and character code if yes */ /* changed */
1265
1266 /* Modified for now to keep on looking */ /* allow for multiple encoding ? */ 
1267 /* this will slow things down a bit, but be a lot safer ! */
1268 /* make sure charnames[] is cleaned out before encoding is read from font */
1269
1270 /* int wantthisname(char *charname, int k, char wantchrs[]) {  */
1271 int wantthisname (char *charname, int k, char *wantchrs)
1272 {
1273   int i;
1274 /*  best guess first for speed: */
1275 /*  if (strcmp(charnames[k], charname) == 0) { */ /* 95/Oct/28 */
1276   if (k >= 0 && k < MAXCHRS && strcmp(charnames[k], charname) == 0) {
1277     if (wantchrs[k] != 0) return k; /* nice and easy ! */
1278 /*    else return -1; */        /* no, may occur again ... */
1279   }   /* was return wantchrs[k]; */
1280   for (i = 0; i < fontchrs; i++) {
1281     if (strcmp(charnames[i], charname) == 0) {
1282       if (wantchrs[i] != 0) return i; 
1283 /*      else return -1; */      /* no, may occur again ... */
1284     } /* was return wantchrs[i]; */
1285   }
1286   if (wantnotdef != 0 && strcmp(".notdef", charname) == 0) {
1287     return NOTDEF; 
1288   }
1289 /*  if (traceflag)
1290     printf("Character not in encoding: %s (%d)\n", charname, k); */
1291   return -1;
1292 }
1293
1294 /* Adobe PS interpreters yield `invalidfont' errors when  */
1295 /* base or accent of composite character is not in encoding of font */
1296 /* May need to add more characters to basecharacterlist */
1297 /* use `N' command line argument to deactivate this bug work around */
1298
1299 int copysubrs(FILE *output, FILE *input)
1300 {
1301   int subrnum, nbin;
1302 /*  char buffer[FNAMELEN]; */ /* compromise only for hires Subrs line */
1303   char *s;
1304
1305 /*  First check whether there are no Subrs ! */
1306   if (strstr(line, "ND") != NULL) return 0;
1307   if (strstr(line, "|-") != NULL) return 0;
1308   if (strstr(line, "noaccess def") != NULL) return 0;
1309   if (strstr(line, "readonly def") != NULL) return 0;
1310   while (getcharline(line, input, 1) == 0) {
1311     if (sscanf(line, "dup %d %d RD", &subrnum, &nbin) < 2) {
1312 /*      if (strstr(line, "hires") == NULL) { */
1313       if (hybridflag == 0) {    /* the old result follows ... */
1314         sprintf(logline, " Not a Subrs line: %s", line);
1315         showline(logline, 1);
1316         extgiveup(9);
1317         return -1;
1318       }
1319       else {      /* new 1994/July/15 for hybrid font */
1320 /* Note: this `line' (getcharline) contains multiple lines up to dup ... RD */
1321         if ((s = strstr(line, "dup ")) != NULL) {
1322           if (sscanf(s, "dup %d %d RD", &subrnum, &nbin) == 2) {
1323 /*            strncpy(buffer, s, FNAMELEN); *//* save dup ... RD */
1324             *s = '\0';
1325             putenline(output, line);
1326 /*            strcpy(line, buffer); */
1327             *s = 'd';
1328             strcpy(line, s);
1329           }
1330         }
1331       }
1332     }
1333     putenline(output, line);    /* beginning of subr */
1334     copycharstring(output, input, nbin);
1335   }
1336   s = line + strlen(line) -1; /* to solve problem with \r\n */
1337   if (*s == '\r') *s = '\n';  /* extra blank line maybe */
1338   putenline(output, line);  /* hit the end */
1339 //  flushencrypt(output);   /* flush out last bit */
1340   return 0;
1341 }
1342
1343 /* Tries to find encoding vector first in dvi file directory */
1344 /* - then tries default encoding vector directory */
1345
1346 FILE *openvector(char *vector)
1347 {
1348   FILE *fp_vec;
1349   char fn_vec[FNAMELEN];
1350   char *s, *t;
1351   
1352 /*  if vector contains a path, use it directly - no other trials */
1353   if (strpbrk(vector, "\\:/") != NULL) {
1354     strncpy(fn_vec, vector, FNAMELEN);
1355     extension(fn_vec, "vec"); 
1356 /*    return fopen(fn_vec, "r"); */
1357     fp_vec = fopen(fn_vec, "r");
1358     if (fp_vec != NULL) {
1359       if (traceflag) {
1360         sprintf(logline, "Using encoding vector %s\n", fn_vec);
1361         showline(logline, 0);
1362       }
1363       return fp_vec;
1364     }
1365     return NULL;
1366   }
1367
1368 /*  try first in dvi file directory */
1369   if (dvipath != NULL) strcpy(fn_vec, dvipath);
1370   else strcpy(fn_vec, "");
1371   makefilename(fn_vec, vector);
1372   extension(fn_vec, "vec");
1373   if ((fp_vec = fopen(fn_vec, "r")) != NULL) {
1374     if (traceflag) {
1375       sprintf(logline, "Using encoding vector %s\n", fn_vec);
1376       showline(logline, 0);
1377     }
1378     return fp_vec;
1379   }
1380
1381 /*  try VECPATH directories */  /* modified for multiple directories 97/Aug/10 */
1382   s = vecpath;
1383   for(;;) {
1384     if (*s == '\0') break;        /* safety valve */
1385 /*    strcpy(fn_vec, vecpath); */
1386     strcpy(fn_vec, s);
1387     t = strchr(fn_vec, ';');
1388     if (t != NULL) *t = '\0';     /* isolate one directory path */
1389     makefilename(fn_vec, vector);
1390     extension(fn_vec, "vec");
1391     if ((fp_vec = fopen(fn_vec, "r")) != NULL) {
1392       if (traceflag) {
1393         sprintf(logline, "Using encoding vector %s\n", fn_vec);
1394         showline(logline, 0);
1395       }
1396       return fp_vec;
1397     }
1398     if (t != NULL) s +=(t-fn_vec) + 1;  /* step over dir and ; */
1399     else break;
1400   }
1401
1402 /*  then try in SUBDIRECTORY of default directory */ /* 1992/Nov/28 */
1403   strcpy(fn_vec, vecpath);
1404 /*  strcat(fn_vec, "\\");
1405   strcat(fn_vec, "vec\\"); */
1406   makefilename(fn_vec, "vec\\");  /* subdirectory "vec" */
1407   strcat(fn_vec, vector); 
1408   extension(fn_vec, "vec");
1409   if ((fp_vec = fopen(fn_vec, "r")) != NULL) {
1410     if (traceflag) {
1411       sprintf(logline, "Using encoding vector %s\n", fn_vec);
1412       showline(logline, 0);
1413     }
1414     return fp_vec;
1415   }
1416
1417 /*  try in current directory */       /* 1992/Dec/8 */
1418   *fn_vec = '\0';           /* strcpy(fn_vec, ""); */
1419   makefilename(fn_vec, vector);   /*  */
1420   extension(fn_vec, "vec");   
1421   if ((fp_vec = fopen(fn_vec, "r")) != NULL) {
1422     if (traceflag) {
1423       sprintf(logline, "Using encoding vector %s\n", fn_vec);
1424       showline(logline, 0);
1425     }
1426     return fp_vec;
1427   }
1428
1429   return NULL;
1430 }
1431
1432 /*  Clear out charnames */
1433 void cleanencoding (int start, int end)
1434 {
1435   int k;
1436 /*  strcpy(namestring, ""); */
1437   namestring[0] = '\0';         /* empty string */
1438   stringindex = 1;            /* reset index to next space */
1439   for (k = start; k < end; k++) charnames[k] = namestring;  /* "" */
1440 }
1441
1442 void copyencoding(char *charnames[], char *encoding[], int n)
1443 {
1444   int k;
1445   if (n < 0 || n > 256)
1446   {
1447     sprintf(logline, " ERROR in copyencoding %d\n", n);
1448     showline(logline, 1);
1449     return;
1450   }
1451   for (k = 0; k < n; k++) charnames[k] = encoding[k]; 
1452 /*  if (n < MAXCHRS)
1453     for (k = n; k < MAXCHRS; k++) charnames[k] = "";  */
1454 }
1455
1456 /* we have duplication here if repeated encoding in vector */
1457
1458 void addencoding (int k, char *charname)      /* 93/Nov/15 */
1459 {
1460   int n = strlen(charname) + 1;         /* space needed */
1461   if (stringindex + n >= STRINGSPACE) {
1462     showline(" ERROR: encoding vector too long\n", 1);
1463   }
1464   else {
1465     charnames[k] = namestring + stringindex;    /* ptr */
1466     strcpy (namestring + stringindex, charname);  /* copy */
1467     stringindex += n;               /* step over */
1468   }
1469 }
1470
1471 /* now return 0 if successful, non-zero if failed */
1472
1473 int readencoding (char *vector)
1474 {
1475   char charname[FNAMELEN];    /* just to be safe */
1476
1477   FILE *fp_vec;
1478   int n;              /* not accessed */
1479   int k;
1480
1481 /*  for (k = 0; k < MAXCHRS; k++) strcpy(charnames[k], ""); */
1482   cleanencoding(0, MAXCHRS);        /* 93/Nov/15 */
1483   
1484 //  if (strcmp(vector, "") == 0)        /* rewritten 93/May/19 */
1485   if (vector == NULL) {
1486 //    showline(" ", 0);
1487     showline(" WARNING: No encoding vector specified\n", 1);
1488 /*    Use `textext' as default if no encoding vector specified */
1489     vector = "textext";
1490 /*    for (k = 0; k < TEXCHRS; k++) strcpy(charnames[k], textext[k]); */
1491     copyencoding(charnames, textext, TEXCHRS);    /* 93/Nov/15 */
1492     errcount(0);  
1493     return -1;          /* failed */
1494   }
1495
1496   if ((fp_vec = openvector(vector)) != NULL) {
1497     n = 0;  /* count encoding lines ? */
1498     while (getrealline(fp_vec, line) > 0) { 
1499       if (*line == '%' || *line == ';') continue;
1500 /*      if (sscanf(line, "%d %s", &k, &charname) < 2) {  */
1501       if (sscanf(line, "%d %s", &k, charname) < 2) { 
1502         showline(" Don't understand encoding line: ", 1);
1503         showline(logline, 1);
1504         showline(line, 1);
1505       } 
1506       else if (k >= 0 && k < MAXCHRS) {
1507 /*        assert(strlen(charname) < MAXCHARNAME); */
1508 /*        if (strlen(charname) >= MAXCHARNAME)
1509           fprintf(errout, " char name %s too long", charname); */
1510         addencoding(k, charname);
1511 /*        strcpy(charnames[k], charname); */
1512 /*        strncpy(charnames[k], charname, MAXCHARNAME); */
1513       }
1514       n++;
1515     }
1516     fclose(fp_vec);
1517   }
1518   else {    /* use `textext' as default if encoding vector not found */
1519 /*    for (k = 0; k < TEXCHRS; k++) strcpy(charnames[k], textext[k]); */
1520     copyencoding(charnames, textext, TEXCHRS);    /* 93/Nov/15 */
1521 //    showline(" ", 0);   // ???
1522     sprintf(logline, " WARNING: can't find encoding vector %s ", vector);
1523     showline(logline, 1);
1524 /*    perrormod(fn_vec);  */
1525     perrormod(vector);
1526     errcount(0);  
1527     return -1;        /* failed */
1528   }
1529   return 0;         /* succeeded */
1530 }
1531
1532 void writevector (FILE *fp_out, char *vector, int n)
1533 {
1534   int k, knext=0;   /* n is MAXCHRS */
1535   int kn;
1536 /*  char *s, *svector; */
1537
1538   if (vector == NULL) {
1539     sprintf(logline, " ERROR in writevector %d\n", n);
1540     showline(logline, 1);
1541     return;
1542   }
1543   if (n < 0 || n > 256) {
1544     sprintf(logline, " ERROR in writevector %d\n", n);
1545     showline(logline, 1);
1546     return;
1547   }
1548
1549   if (strcmp(vector, "textext") == 0) {   /* 1992/Nov/19 */
1550     if (textextwritten++ > 0) return;
1551   }
1552 /*  if (strcmp(vector, "ansinew") == 0) {
1553     if (ansiwritten++ > 0) return;
1554   } */                    /* 1993/Sep/30 */
1555   if (strcmp(vector, textencoding) == 0) {  /* 1994/Dec/17 */
1556     if (ansiwritten++ > 0) return;
1557   }
1558
1559   knext = 256;                    /* 93/Feb/15 */
1560   if (bSuppressPartial == 0 && bForceFullArr == 0) {  /* 93/Feb/15 */
1561     for (k = n-1; k >= 0; k--) {    /* find last character code used */
1562       if(strcmp(charnames[k], "") != 0) {
1563         knext = k+1; break; 
1564       }
1565     }
1566   }
1567   if (knext == 0) return;       /* all empty, nothing to do */
1568
1569   if (stripcomment == 0) {
1570     sprintf(logline, "%% %s encoding\n", vector); /* 1992/Nov/17 */
1571     PSputs(logline, fp_out);
1572   }
1573 /*  fprintf(fp_out, "/%s[", vector); */       /* 95/Feb/3 */
1574   sprintf(logline, "/%s[", removepath(vector));   /* strip path */
1575   PSputs(logline, fp_out);
1576   for (k = 0; k < knext; k++) {
1577     if (k != 0 && k % 8 == 0) {
1578 //      putc('\n', fp_out);
1579       PSputc('\n', fp_out);
1580     }
1581     if (strcmp(charnames[k], "") != 0) {
1582       sprintf(logline, "/%s", charnames[k]);
1583       PSputs(logline, fp_out);
1584     }
1585 /*    else fprintf(fp_out, "/.notdef"); */
1586 /*    else fprintf(fp_out, " n");  */ /* 1993/Sep/31 */
1587     else {                  /* 1993/Oct/5 */
1588       kn = k+1;
1589       while (kn < knext && strcmp(charnames[kn], "") == 0) kn++;
1590 /*      if (kn < k + 4) { */
1591       if (kn < k + 5) {   /* only more efficient if more than 4 */
1592         for (k=k; k < kn; k++) {
1593           PSputs(" n", fp_out);
1594         }
1595       }
1596       else {
1597         sprintf(logline, " %d notdef", kn-k);
1598         PSputs(logline, fp_out);
1599       }
1600 /*      if (((kn-1 >> 3) != (k >> 3)) && kn % 8 != 0) */
1601       if ((((kn-1) >> 3) != (k >> 3)) && (kn % 8) != 0) {
1602 //        putc('\n', fp_out);
1603         PSputc('\n', fp_out);
1604       }
1605       k = kn-1;
1606     }
1607   }
1608 //  fprintf(fp_out, "]def\n");
1609   PSputs("]def\n", fp_out);
1610 }
1611
1612 void writedvistart (FILE *fp_out)
1613 {
1614 //  fputs("dvidict begin\n", fp_out);
1615   PSputs("dvidict begin\n", fp_out);
1616 }
1617
1618 void writedviend(FILE *fp_out) /* 1992/Nov/17 */
1619 {
1620 //  fputs("end", fp_out);
1621   PSputs("end", fp_out);
1622   if (stripcomment == 0) {
1623 //    fputs(" % dvidict", fp_out);
1624     PSputs(" % dvidict", fp_out);
1625   }
1626 //  putc('\n', fp_out);
1627   PSputc('\n', fp_out);
1628 }
1629
1630 /* Following used to be in preamble: */
1631
1632 /* /dviencoding 256 array def */
1633 /* /dvicodemake{string cvs dup 0 97 put cvn dviencoding 3 1 roll put}bd */
1634 /* 0 1 9{dup 10 add 2 dvicodemake} for */
1635 /* 10 1 99{dup 100 add 3 dvicodemake} for */
1636 /* 100 1 255{dup 1000 add 4 dvicodemake} for */
1637
1638 void writedviencode(FILE *fp_out)   /* 1993/Sep/30 */
1639 {
1640   int k;
1641   char charname[5];   /* space for a255 + zero */
1642
1643   writedvistart(fp_out);
1644   cleanencoding(0, MAXCHRS);        /* reset string table */
1645   for (k = 0; k < MAXCHRS; k++) {       /* fixed 1994/Feb/3 */
1646     sprintf(charname, "a%d", k);
1647     addencoding (k, charname);
1648 /*    charnames[k] = namestring + stringindex; */
1649 /*    stringindex = stringindex + strlen (namestring + stringindex) + 1; */
1650   }
1651   writevector(fp_out, "dviencode", MAXCHRS); 
1652   writedviend(fp_out);        /* 1993/Sep/30 */
1653 }
1654
1655 void writetextext(FILE *fp_out)
1656 {
1657 /*  int k; */
1658
1659 /*  not allowed to use `TeX text' encoding if forcing full 256 vector */
1660 /*  (no longer a problem, since we extend TeX text vector if needed */
1661 /*  if (bForceFullArr == 0) { */        /* 93/Feb/15 */
1662   writedvistart(fp_out);
1663
1664 /*  for (k = 0; k < TEXCHRS; k++) strcpy(charnames[k], textext[k]); */
1665   copyencoding(charnames, textext, TEXCHRS);    /* 93/Nov/15 */
1666
1667   if (bForceFullArr == 0) writevector(fp_out, "textext", TEXCHRS);
1668   else {                  /* 1993/Sep/30 */
1669 /*    for (k = TEXCHRS; k < MAXCHRS; k++) strcpy(charnames[k], ""); */
1670     cleanencoding(TEXCHRS, MAXCHRS);  /* redundant ? */
1671     writevector(fp_out, "textext", MAXCHRS);
1672   }
1673   writedviend(fp_out);        /* 1992/Nov/17 */
1674 /*  } */
1675 }
1676
1677 /* Write Windows ANSI encoding or what user defined in ENCODING env var */
1678
1679 /* void writeansicode(FILE *fp_out) { */      /* 1993/Sep/30 */
1680 /* void writeansicode(FILE *fp_out, char *textencoding) { */  /* 1994/Dec/17 */
1681 void writeansicode(FILE *fp_out, char *textenconame)  /* 1995/Feb/3 */
1682 {
1683 /*  int k; */
1684
1685 /*  if (ansiwritten > 0) return; */ /* already exists 1992/Nov/19 */
1686
1687   writedvistart(fp_out);
1688 /*  for (k = 0; k < MAXCHRS; k++) strcpy(charnames[k], ansiencoding[k]); */
1689   copyencoding(charnames, ansiencoding, MAXCHRS); /* 93/Nov/15 */
1690 /*  writevector(fp_out, "ansinew", MAXCHRS);  */
1691 /*  writevector(fp_out, textencoding, MAXCHRS); */  /* 94/Dec/17 */
1692   writevector(fp_out, textenconame, MAXCHRS);   /* 95/Feb/3 fix 96/May/28 */
1693   writedviend(fp_out);        /* 1993/Sep/30 */
1694 }
1695
1696 /*  overwrite Windows ANSI encoding hard-wired in here */
1697
1698 /* void writetextencode(FILE *fp_out, char *textencoding) {*//* 94/Dec/17 */
1699 int readtextencode(char *textencoding)  /* 94/Dec/17 */
1700 {
1701   int k;
1702 /*  char *dupcharname; */
1703
1704   if (readencoding(textencoding) == 0) {
1705     for (k = 0; k < MAXCHRS; k++) {
1706 /*      dupcharname = _strdup(charnames[k]);
1707       if (dupcharname == NULL) {
1708         fputs("Unable to allocate memory\n", errout);
1709         checkexit(1);
1710       } */
1711       ansiencoding[k] = zstrdup(charnames[k]);
1712       if (ansiencoding[k] == NULL) {
1713         showline("Unable to allocate memory\n", 1);
1714         checkexit(1);
1715         return -1;
1716       }
1717     }
1718   }
1719 /*  writeansicode(fp_out); */
1720   return 0;
1721 }
1722
1723 #define ACCENTCHRS 15
1724
1725 #define BASECHRS (26+26)
1726
1727 /* Adjust wantchrs table so base and accent of composites are there */
1728 /* (i) we MUST have the base and accent character CharStrings */
1729 /* (ii) for present Adobe interpreters they must ALSO be in encoding */
1730 /* so its easiest to implement this by adjusting wantchrs */
1731
1732 /* keep track of which accents already dealt with in accenthit */
1733 /* (based on StandardEncoding position of accent - 193) */
1734 /* keep track of which base chars already dealt with in basehit */
1735 /* (based on position of base in string `basecharacters') */
1736
1737 /* returns non-zero if any accented character were found */
1738
1739 int expandaccents (char *wantchrs)
1740 {
1741   char *testname;
1742   char basename[9];     /* dotlessi is max length */
1743   int i, j, k, c, n;
1744   int compflag, foundflag;
1745   int composedflag=0;     /* any composites ? */
1746   char *standname;      /* 93/Sep/16 */
1747
1748 /*  int accentcomplain[ACCENTCHRS]; */    /* for accents from 193 to 207 */
1749   int accenthit[ACCENTCHRS];        /* for accents from 193 to 207 */
1750 /*  int basehit[sizeof(basecharacters)]; */  /* for 28 base characters */
1751   int basehit[BASECHRS];        /* for 26 + 26 base characters */
1752
1753 /*  for (k = 0; k < ACCENTCHRS; k++) accentcomplain[k] = 0; */  /* 93/Sep/16 */
1754   for (k = 0; k < ACCENTCHRS; k++) accenthit[k] = 0;    /* 94/Feb/17 */
1755 /*  for (k = 0; k < sizeof(basecharacters); k++) basehit[k] = 0; */
1756   for (k = 0; k < BASECHRS; k++) basehit[k] = 0;      /* 94/Feb/17 */
1757
1758 /*  composedflag = 0; */
1759   for (k = 0; k < MAXCHRS; k++) {
1760     if (wantchrs[k] == 0) continue;   /* ignore unwanted characters */
1761     testname = charnames[k];      /* potential composite char */
1762     n = strlen(testname);
1763 /*    This eliminates the bulk of charnames, since they are one char long */
1764 /*    if (n < 5 || n > 11) continue; */   /* aring --- acircumflex */
1765     if (n < 4 || n > 14 || n == 13) continue; /* ldot --- uhungarumlaut */
1766     c = testname[0];          /* potential base character */
1767 /*    see if in filter list --- is it worth limiting base chars ? */
1768 /*    if (strchr(basecharacters, c) == NULL) continue; */ /* must be base */
1769 /*    if ((s = strchr(basecharacters, c)) == NULL) continue; */
1770 /*    n = s - basecharacters; */  /* compute offset in array 1994/Feb/17 */
1771 /*    if (strchr(notbasecharacters, c) != NULL) continue; */ /* NO */
1772 /*    if (c < 'A' || c > 'z' || (c < 'a' && c > 'Z') continue; */ /* NOP ? */
1773     if (c < 'A') continue;
1774     else if (c <= 'Z') n = c - 'A';
1775     else if (c < 'a') continue;
1776     else if (c <= 'z') n = c - 'a' + 26;
1777     else continue;
1778 /*    have eliminated names that are too long or too short - or bad start */
1779 /*    if (traceflag) printf("Testing %s ", testname); */
1780     compflag = 0;           /* reset composite char flag */
1781 /*    NOTE: we only need to worry about accents in StandardEncoding ! */
1782     for (i = 193; i <= 207; i++) {    /* check through accents */
1783 /*      note that two of the `accent' positions are actually "" */
1784 /*      charname = standardencoding[i]; */
1785 /*      if (strcmp(testname + 1, charname) == 0) { */
1786       if (strcmp(testname + 1, standardencoding[i]) == 0) {
1787         compflag = 1; break;    /* found accent in table */
1788       }
1789     }
1790 /*    What about hungarumlaut => hungar and dotaccent => dot */
1791     if (compflag == 0) {  
1792       if (strcmp(testname + 1, "dot") == 0) { /* 93/Sep/16 */
1793         i = 199;    /* dotaccent */
1794         compflag = 1;
1795       }
1796       else if (strcmp(testname + 1, "hungar") == 0) { /* 93/Sep/16 */
1797         i = 205;    /* hungarumlaut */
1798         compflag = 1;
1799       }
1800       else if (strcmp(testname + 1, "dblacute") == 0) {/* 94/May/25 */
1801         i = 205;    /* hungarumlaut */
1802         compflag = 1;
1803       }
1804       else if (strcmp(testname + 1, "hacek") == 0) {/* 94/May/25 */
1805         i = 207;    /* caron */
1806         compflag = 1;
1807       }
1808     }
1809     if (compflag != 0) {    /* So, *is* it a composite character ? */
1810 /*      composedflag = 0; */    /* was a bug ! */
1811       composedflag = 1;     /* fix 1994/Feb/17 */
1812
1813 /*  speed up: 94/Feb/17 keep track of which already inserted - in basehit */
1814       if (basehit[n] == 0) {    /* see whether already dealt with */
1815         basehit[n]++;     /* note that we have been here */
1816 /*        request base character first */
1817 /*        basename[0] = (char) c; */
1818 /*        basename[1] = '\0'; */
1819         if (c == 'i') {
1820           strcpy(basename, "dotlessi");
1821           c = 245;  /* standard encoding position for dotlessi */
1822         }
1823         else {
1824           basename[0] = (char) c;
1825           basename[1] = '\0';
1826         }
1827         if (strcmp(charnames[c], basename) == 0) {  /* fast case */
1828           wantchrs[c] = 1;
1829         }
1830         else {          /* otherwise have to search for it */
1831           foundflag = 0;
1832           for (j = 0; j < MAXCHRS; j++) {
1833             if (strcmp(charnames[j], basename) == 0) {
1834               wantchrs[j] = 1;
1835               foundflag = 1;
1836               break;
1837             }
1838           }
1839           if (foundflag == 0) {
1840             sprintf(logline, " `%s' not in encoding", basename);
1841             showline(logline, 1);
1842             errcount(0);
1843           }
1844         }
1845       } /* end of if basehit[n] == 0 */
1846
1847 /* then request accent character */
1848 /* speed up: 94/Feb/17 keep track of which already inserted - in accenthit */
1849       if (accenthit[i - 193] == 0) {  /* check if already dealt with */
1850         accenthit[i - 193]++;   /* mark that we dealt with this */
1851         standname = standardencoding[i];      /* 93/Sep/13 */
1852 /*        if (strcmp(charnames[i], testname+1) == 0) */  /* fast case */
1853         if (strcmp(charnames[i], standname) == 0) {  /* fast case */
1854           wantchrs[i] = 1;
1855         }
1856         else {          /* otherwise have to search for it */
1857           foundflag = 0;
1858           for (j = 0; j < MAXCHRS; j++) {
1859 /*            if (strcmp(charnames[j], testname+1) == 0) { */
1860             if (strcmp(charnames[j], standname) == 0) {
1861               wantchrs[j] = 1;
1862               foundflag = 1;
1863               break;
1864             }
1865           }
1866           if (foundflag == 0) {
1867 /* we don't need this anymore, since we come in here only once accenthit */
1868 /*            if (accentcomplain[i - 193] == 0) {*/ /* 93/Sep/16 */
1869               sprintf(logline, " `%s' not in encoding", standname);
1870               showline(logline, 1);
1871 /*              accentcomplain[i- 193]++; */
1872               errcount(0);
1873 /*            } */
1874           }
1875         }
1876       }
1877     }
1878   }
1879   return composedflag;
1880 }
1881
1882 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
1883
1884 /* Check whether font calls for characters *not* found in encoding! */
1885 /* 1995/July/15 */
1886
1887 int missingchars (char *wantchrs, char *encoding)
1888 {
1889   int k, unknowns = 0;
1890
1891   for (k = 0; k < fontchrs; k++) {
1892 /*    if (wantchrs[k] != 0 && strcmp(charnames[k], "") == 0) unknowns++;*/
1893     if (wantchrs[k] != 0 && charnames[k][0] == '\0') unknowns++;
1894 /*    if (wantchrs[k] != 0) printf("%d\t%s\n", k, charnames[k]); */
1895   }
1896 /*  Encoding passed in may be just "" if read from PFA file 96/May/26 */
1897   if (unknowns > 0) {
1898 /*    fprintf(errout, " ERROR: %d character%s used not in `%s'",
1899       unknowns, (unknowns == 1) ? "" : "s", encoding); */
1900     sprintf(logline, " ERROR: %d character%s used not in ",
1901       unknowns, (unknowns == 1) ? "" : "s");
1902     showline(logline, 1);
1903 //    if (*encoding != '\0') 
1904     if (encoding != NULL) {
1905       sprintf(logline, "`%s'", encoding);
1906       showline(logline, 0);
1907     }
1908     else showline("encoding", 0);
1909     errcount(0);
1910   }
1911   return unknowns;
1912 }
1913
1914 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
1915
1916 /* could keep a record of which accent we already complained about */
1917
1918 /* end of code for dealing with composite characters encoding */
1919
1920 /* write out encoding - cheaply if possible */
1921 /* worry about remapped fonts ? */
1922
1923 /* POSSIBLE PROBLEM: synthetic font, where /FontName appears after /Encoding */
1924 /* not sure it is really worth worrying about... */
1925
1926 /* Maybe simplify this if StandardEncoding and no remapping ??? */
1927
1928 /* void writeencoding(FILE *output, char wantchrs[], int syntheticflag) { */
1929
1930 /* This also adjusts wantchrs to reflect base and accent characters */
1931
1932 /* why aren't we just doing a return instead of setting `done' */
1933
1934 /* void writeencoding(FILE *output, char *wantchrs, int syntheticflag) {*/
1935 void writeencoding(FILE *output, char *wantchrs, int syntheticflag, char *encoding)
1936 {
1937   int k, standardok=0, textextok=0, ansiok=0, nullchar=0;
1938 /*  int done=0; */
1939 /*  int i; */
1940 /*  char *charname;  */
1941   int composedflag=0;     /* if composite characters used */
1942
1943 /*  syntheticflag = fontproper[i] & C_SYNTHETIC; */
1944 /*  for (k = fontchrs-1; k >= 0; k--) if (wantchrs[k] != 0) break; */
1945 /*  fprintf(output, "/Encoding %d array\n", k+1); */
1946 /*  fprintf(output, "0 1 %d {1 index exch /.notdef put} for\n", k); */
1947 /*      if (wantchrs[chr] != 0) fprintf(output, "%s", line); */
1948 /*      fprintf(output, "%s", line); */
1949
1950 /*  unless 'N' flag used, force in base and accent characters */
1951
1952   if (accentedflag != 0) composedflag = expandaccents(wantchrs);
1953   else composedflag = 0;
1954
1955   if (strcmp(encoding, "standard") == 0) {
1956 /*    encoding = "StandardEncoding"; */   /* 94/Oct/25 */
1957 /*    fprintf(output, "/Encoding StandardEncoding def\n");  */
1958 //    fputs("/Encoding StandardEncoding def\n", output); 
1959     PSputs("/Encoding StandardEncoding def\n", output); 
1960     return;           /* 94/Oct/25 */
1961   }
1962
1963 /*  Just refer to encoding by name if permitted to do so */
1964   if (strcmp(encoding, "") != 0)
1965   {
1966     if (bAllowShortEncode) {  /* 94/Oct/25 */
1967 /*      fprintf(output, "/Encoding %s def\n", encoding); */
1968 /*      get rid of path name when referring to encoding 95/Feb/3 */
1969       sprintf(logline, "/Encoding %s def\n", removepath(encoding));
1970       PSputs(logline, output);
1971       return;   /*  done = 1; */
1972     }
1973     else goto writefull; /* need to write out encoding in full!  */
1974   }
1975
1976 /*  do not allow use of dviencoding if accented characters seen */
1977
1978 /*  Construct new encoding vector */
1979 /*  Check whether numeric vector will do *//*  most efficient - if allowed */
1980 /*  but we don't like this anymore because of clone problems ... */
1981 /*  if (done == 0 && composedflag == 0 &&  */
1982   if (composedflag == 0 && 
1983       syntheticflag == 0 &&   /* do we need to worry about this ? */
1984         busedviencode != 0) { /*  && accentedflag == 0 */
1985 /*    fprintf(output, "/Encoding dviencoding def\n"); */
1986 //    fputs("/Encoding dviencoding def\n", output);
1987     PSputs("/Encoding dviencoding def\n", output);
1988     return;   /*    done = 1; */
1989   }     /* end of dviencoding test */
1990
1991 /*  added bSuppressPartial == 0 reference 1992/Sep/12 */
1992 /*  added bForceFullArr == 0 reference 1993/Feb/13 */
1993 /*  took out bForceFullArr == 0 reference 1993/Sep/30 by extending textext */ 
1994
1995 /*  check whether textext will do */
1996 /*  if (done == 0 && composedflag == 0 && bAllowTexText != 0 && */
1997   if (composedflag == 0 && bAllowTexText != 0 &&
1998 /*      bSuppressPartial == 0 && bForceFullArr == 0) { */
1999       bSuppressPartial == 0) {
2000     textextok = 1;
2001 /*    for (k = 0; k < fontchrs; k++) { */
2002     for (k = fontchrs-1; k >= 0; k--) {   /* 93/Oct/2 */
2003       if (wantchrs[k] != 0) {
2004         if (k >= TEXCHRS ||       /* 93/Oct/2 */
2005           charnames[k][0] == '\0' ||  /* 95/July/15 */
2006           strcmp(charnames[k], textext[k]) != 0) {
2007           textextok = 0; break;
2008         }
2009       }
2010     }   
2011     if (textextok != 0) {   /* fairly easy */
2012 /*      fprintf(output, "/Encoding textext def\n"); */
2013 //      fputs("/Encoding textext def\n", output);
2014       PSputs("/Encoding textext def\n", output);
2015       return;   /*  done = 1; */
2016     }
2017   }     /* end of textext trial */
2018
2019 /*  check whether Windows ANSI will do 1993/Sep/30 */
2020
2021 /*  if (done == 0 && bWindowsFlag != 0) { */
2022 /*  if (bWindowsFlag != 0) { */
2023   if (bWindowsFlag != 0 && bAllowANSI != 0 &&   /* 94/Oct/25 */
2024       bSuppressPartial == 0) {        /* 95/May/23 */
2025     ansiok = 1;
2026
2027 /*    for (k = 0; k < fontchrs; k++) { */
2028     for (k = fontchrs-1; k >= 0; k--) {     /* 93/Oct/2 */
2029       if (wantchrs[k] != 0) {
2030         if (charnames[k][0] == '\0' ||  /* 95/July/15 */
2031           strcmp(charnames[k], ansiencoding[k]) != 0) {
2032           ansiok = 0; break;
2033         }
2034       }
2035     }   
2036     if (ansiok != 0) {    /* fairly easy */
2037 /*      fprintf(output, "/Encoding ansinew def\n"); */
2038       sprintf(logline, "/Encoding %s def\n",
2039 /*        textencoding); */         /* 94/Dec/17*/
2040         textenconame);            /* 94/Dec/17*/
2041       PSputs(logline, output);
2042       return;   /*    done = 1; */
2043     }
2044   }
2045
2046 /*  check whether StandardEncoding will do */
2047 /*  if (done == 0 && bAllowStandard != 0) { */
2048   if (bAllowStandard != 0 &&
2049       bSuppressPartial == 0) {      /* 95/May/23 ??? */
2050     standardok = 1;
2051 /*    for (k = 0; k < fontchrs; k++) { */
2052     for (k = fontchrs-1; k >= 0; k--) {   /* 93/Oct/2 */
2053       if (wantchrs[k] != 0) {
2054         if (charnames[k][0] == '\0' ||  /* 95/July/15 */
2055           strcmp(charnames[k], standardencoding[k]) != 0) {
2056           standardok = 0; break;
2057         }
2058       }
2059     }
2060     if (standardok != 0) {        /* nice and easy ! */
2061 /*      fprintf(output, "/Encoding StandardEncoding def\n"); */
2062 //      fputs("/Encoding StandardEncoding def\n", output);
2063       PSputs("/Encoding StandardEncoding def\n", output);
2064       return;   /*    done = 1; */
2065     }
2066   }
2067
2068 writefull:
2069
2070 /*  Couldn't use standard, textext, or Windows ANSI for some reason */
2071 /*  if (done == 0) { */
2072     k = fontchrs-1;         /* use full if partial suppress */
2073 /*    if (bSuppressPartial == 0 || bForceFullArr != 0) { */
2074     if (bSuppressPartial == 0 && bForceFullArr == 0) { /* 1993/Feb/15 */
2075       for (k = fontchrs-1; k >= 0; k--) if (wantchrs[k] != 0) break;
2076     }
2077 /*    printf(" suppress %d force %d k+1 %d\n",
2078       bSuppressPartial, bForceFullArr, k+1); */ /* debugging */
2079     sprintf(logline, "/Encoding %d array", k+1);
2080     PSputs(logline, output);
2081 //    putc('\n', output);
2082     PSputc('\n', output);
2083     sprintf(logline, "0 1 %d {1 index exch /.notdef put} for\n", k);
2084     PSputs(logline, output);
2085     
2086 /*    nullchar=0; */
2087     for (k = 0; k < fontchrs; k++) {
2088       if (wantchrs[k] != 0 ||       /* addition 1992/Sep/12 */
2089 /*        (bSuppressPartial != 0 && strcmp(charnames[k], "") != 0)) { */
2090         (bSuppressPartial != 0 && charnames[k][0] != 0)) {
2091 /*        if (strcmp(charnames[k], "") != 0) */
2092         if (charnames[k][0] != '\0') {  /* 95/July/15 */
2093           sprintf(logline, "dup %d /%s put\n", k, charnames[k]);
2094           PSputs(logline, output);
2095         }
2096         else {
2097           nullchar++;
2098 /*          fprintf(errout, " Null char name %d", k); */
2099         }
2100       }
2101     }
2102 //    fprintf(output, "readonly def\n");
2103     PSputs("readonly def\n", output);
2104     if (nullchar > 0) {         /* somewhat redundant ... */
2105       if (traceflag) { 
2106         sprintf(logline, " %d null char names", nullchar);
2107         showline(logline, 1);
2108       }
2109     }
2110     return; 
2111 /*  } */
2112 }
2113
2114 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2115
2116 /*  cm-text-fonts cm
2117   (r|bx|tt|sltt|vtt|tex|ss|ssi|ssdc|ssbx|ssqi|dunh|bxsl|b|ti|bxti|csc|tcsc)
2118   ([0-9]+) */
2119
2120 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2121
2122 void beginresource (FILE *output, char *filefontname)
2123 {
2124   if (stripcomment == 0) {          /* 1994/Feb/3 */
2125 //    fputs("%%BeginResource: ", output);
2126     PSputs("%%BeginResource: ", output);
2127 //    fputs("font ", output);
2128     PSputs("font ", output);
2129 //    fputs(filefontname, output);
2130     PSputs(filefontname, output);
2131 //    putc('\n', output);
2132     PSputc('\n', output);
2133   }
2134 }
2135
2136 int endresource (FILE *output)
2137 {
2138   if (stripcomment == 0) {
2139 //    fputs("%%EndResource\n", output);
2140     PSputs("%%EndResource\n", output);
2141   }
2142 /*  good place to check for output error also ... */
2143 //  if (ferror(output) != 0)
2144   if (output != NULL && ferror(output)) {
2145     showline("\n", 0);
2146 //    sprintf(logline, " ERROR in output file %s\n", outputfile);
2147     showline("ERROR in output file", 1);
2148     perrormod((outputfile != NULL) ? outputfile : "");
2149     extgiveup(7);
2150     return -1;
2151   }
2152   return 0;
2153 }
2154
2155 /* Just copy if we don't recognize the format ... no remapping  */
2156 /* --- pretty desperate move ! */ /* don't try to be efficient */
2157 /* int i is font number in case needed for error message */
2158
2159 void copyunknown (FILE *output, FILE *input, int i, char *fontnamek)
2160 {
2161   int c;
2162   if (verboseflag) {
2163     showline(fontnamek, 0);   /* 1995/Mar/1 */
2164   }
2165   else {
2166     showline("*", 0);
2167   }
2168   showline(" WARNING: Font type not recognized!\n", 1);
2169   while ((c = getc(input)) != EOF) {
2170 //    putc(c, output);
2171     PSputc(c, output);
2172   }
2173 /*  return 1; */      /* just copied the damn thing ! */
2174 }
2175
2176 /* copy ascii section of a compressed file - old version */
2177 /* returns EOF if EOF hit */
2178
2179 int copyascii (FILE *output, FILE *input, long n, int firstline)
2180 {
2181   int c;
2182
2183   c = getc(input); n--;
2184   if (c == '\r' && flushcr != 0) {
2185     c = getc(input); n--;
2186     if (c != '\n') {
2187       (void) ungetc(c, input); n++;
2188       c = '\n';
2189     }
2190   }
2191   else if (firstline == 0) {
2192 //    putc('\n', output);
2193     PSputc('\n', output);
2194   }
2195
2196   while (c != EOF) {
2197     if (c == 128 || c == 0) {     /* hit start of next section */
2198       (void) ungetc(c, input);  n++;
2199       break;
2200     }
2201     if (c == '\n') clm = 0;
2202 //    putc(c, output);
2203     PSputc(c, output);
2204     c = getc(input); n--;
2205     if (c == '\r' && flushcr != 0) {
2206       c = getc(input); n--;
2207       if (c != '\n') {
2208         (void) ungetc(c, input); n++;
2209         c = '\n';
2210       }
2211     }
2212   }
2213   if (c == EOF) {
2214     sprintf(logline, " Unexpected EOF (%s)\n", "copyascii");
2215     showline(logline, 1);
2216     return EOF;
2217   }
2218   if (n != 0) {
2219     sprintf(logline, " Length discrepancy %ld", n);
2220     showline(logline, 1);
2221   }
2222   return 0;
2223 }  
2224
2225 /* copy ascii section of a compressed file - strip {restore}if */
2226 /* returns EOF if EOF hit */ /* special kludge for wrapped synthetic fonts */
2227
2228 int copystrip (FILE *output, FILE *input, long n, int firstline)
2229 {
2230   int c;
2231   char *s, *t;
2232
2233   c = getc(input); n--;
2234   if (c == '\r' && flushcr != 0) {
2235     c = getc(input); n--;
2236     if (c != '\n') {
2237       (void) ungetc(c, input); n++;
2238       c = '\n';
2239     }
2240   }
2241   else if (firstline == 0) {
2242 //    putc('\n', output);
2243     PSputc('\n', output);
2244   }
2245
2246   s = line;               /* use line as buffer */
2247   while (c != EOF) {
2248     if (c == 128 || c == 0) {     /* hit start of next section */
2249       (void) ungetc(c, input);  n++;
2250       break;
2251     }
2252     if (c == '\n' || c == '\r') {
2253       *s++ = (char) c;
2254       *s = '\0';        /* terminate line */
2255       if ((s = strstr(line, "{restore}")) != NULL) {
2256         if ((t = strstr(line, "cleartomark")) != NULL) {
2257           *s++ = (char) c;
2258           *s++ = '\0';      /* cut off after cleartomark */
2259 //          fputs(line, output);  /* 1992/Aug/20 */
2260           PSputs(line, output); /* 1992/Aug/20 */
2261         }
2262         if (stripcomment == 0) {    /* 1995/May/14 */
2263 //          fputs("% font wrapper removed\n", output);
2264           PSputs("% font wrapper removed\n", output);
2265         }
2266       }
2267       else {
2268 //        fputs(line, output);  /* finally output it */
2269         PSputs(line, output); /* finally output it */
2270       }
2271       s = line;       /* reset line buffer */
2272       clm = 0;
2273     }
2274 /*    putc(c, output); */
2275     else *s++ = (char) c;   /* check for line length exceeded ? */
2276     c = getc(input); n--;   /* get next character */
2277     if (c == '\r' && flushcr != 0) {
2278       c = getc(input); n--;
2279       if (c != '\n') {
2280         (void) ungetc(c, input); n++;
2281         c = '\n';
2282       }
2283     }
2284   }
2285   if (c == EOF) {
2286     sprintf(logline, " Unexpected EOF (%s)\n", "copystrip");
2287     showline(logline, 1);
2288     return EOF;
2289   }
2290   if (n != 0) {
2291     sprintf(logline, " Length discrepancy %ld", n);
2292     showline(logline, 1);
2293   }
2294   return 0;
2295 }  
2296
2297 /* copy binary section of a compressed file */
2298
2299 int copybinary (FILE *output, FILE *input, long n)
2300 {
2301   int c, d;
2302   long k;
2303   
2304   for (k = 0; k < n; k++) {
2305     c = getc(input); 
2306     if (c == EOF) {
2307       sprintf(logline, " Unexpected EOF (%s)\n", "copybinary");
2308       showline(logline, 1);
2309       return -1;
2310     }
2311     d = c & 15; c = (c >> 4) & 15;
2312     if (c > 9) c = c + 'A' - 10; else c = c + '0';
2313     if (d > 9) d = d + 'A' - 10; else d = d + '0';
2314 //    putc(c, output);
2315     PSputc(c, output);
2316 //    putc(d, output);
2317     PSputc(d, output);
2318     if ((clm += 2) >= columns) {
2319 //      putc('\n', output);
2320       PSputc('\n', output);
2321       clm = 0;
2322     }
2323   }
2324   return 0;
2325
2326
2327 void copypfa (FILE *output, FILE *input, int stripflag)
2328 {
2329   int c;
2330   char *s, *t;
2331   
2332   if (stripflag == 0) {         /* normal easy case */
2333     while ((c = getc(input)) != EOF) {
2334       if (c == '\r' && flushcr != 0) {
2335         c = getc(input);
2336         if (c != '\n') {
2337           (void) ungetc(c, input);
2338           c = '\n';
2339         }
2340       }
2341 //      putc(c, output);
2342       PSputc(c, output);
2343     }
2344   }
2345   else {        /* need to watch for closing wrapper */
2346     while (extgetline (input, line) != EOF) {
2347       if ((s = strstr(line, "{restore}")) != NULL) {
2348         if ((t = strstr(line, "cleartomark")) != NULL) {
2349           *s++ = '\n';
2350           *s++ = '\0';      /* cut off after cleartomark */
2351 //          fputs(line, output);  /* 1992/Aug/20 */
2352           PSputs(line, output); /* 1992/Aug/20 */
2353         }
2354         continue;         /* just flush it */
2355       }
2356 //      fputs(line, output);
2357       PSputs(line, output);
2358     }
2359   }
2360 }
2361
2362 /* special purpose hack for fonts in PFA format that suck rocks */
2363 /* flush this eventually ... */
2364
2365 void copymtmi (FILE *output, FILE *input, int stripflag)
2366 {
2367 /*  int c; */
2368   char *s, *t;
2369 /*  char buffer[MAXCHRS]; */
2370
2371   if (stripflag == 0) showline(" no wrapper ", 1);    /* debugging */
2372
2373   while (extgetline (input, line) != EOF) {
2374     if ((s = strstr(line, "{restore}")) != NULL) {
2375       if ((t = strstr(line, "cleartomark")) != NULL) {
2376         *s++ = '\n';
2377         *s++ = '\0';      /* cut off after cleartomark */
2378 //        fputs(line, output);  /* 1992/Aug/20 */
2379         PSputs(line, output); /* 1992/Aug/20 */
2380       }
2381       continue; 
2382     }
2383 //    fputs(line, output);
2384     PSputs(line, output);
2385   }
2386 }
2387
2388 /* This is typically called after already wading into the ASCII section */
2389 /* but only if syntheticflag or mtmiflag non-zero */
2390 /* int i is font number in case needed for error message */
2391
2392 void copyfont (FILE *output, FILE *input, int i, int mtmiflag, int stripflag)
2393 {
2394   int c, d, firstline = 1;
2395   int ascii=1, binary=0;    /* section counts */ /* presently not used */
2396   long n;
2397
2398   firstline = 0;        /* since we already past start of file ! */
2399   c = getc(input);      /* skip over initial white space */
2400   while (c == '\n' || c == '\r' || c == ' ') c = getc(input); 
2401   (void) ungetc(c, input);
2402 /*  putc('\n', output); */  /* ??? */
2403   clm = 0;
2404   if (c == 0) {     /* assume MacIntosh format */
2405 /*    showline(" MAC ", 0); */  /* debugging */
2406     n = maclength(input);
2407     c = getc(input); d = getc(input);   /* d should be zero */
2408     while (c != 5) {
2409       if (c == 1) {
2410         ascii++;
2411         if (copyascii(output, input, n - 2, firstline) != 0) break;
2412         firstline = 0;
2413       }
2414       else if (c == 2) {
2415         binary++;
2416         if (copybinary(output, input, n - 2) != 0) break;
2417       }
2418       else {
2419         sprintf(logline, " Unrecognized section code %d", c);
2420         showline(logline, 1);
2421         break;
2422       }
2423       n = maclength(input);
2424       c = getc(input); d = getc(input);
2425       if (c == EOF) {
2426         sprintf(logline, " Unexpected EOF (%s)\n", "copyfont");
2427         showline(logline, 1);
2428         break;
2429       }
2430     }
2431   }
2432   else if (c == 128) {  /* assume PFB format */
2433 /*    showline(" PFB ", 0); */    /* debugging */
2434     c = getc(input); d = getc(input);
2435     while (d != 3) {
2436       n = readlength(input);
2437       if (d == 1) {     /* ASCII section code */
2438         ascii++;
2439 /*        printf(" strip %d ascii %d ", stripflag, ascii); *//* debug */
2440         if (stripflag != 0 && ascii > 1) {
2441           if (copystrip(output, input, n, firstline) != 0) break;
2442         }
2443         else {
2444           if (copyascii(output, input, n, firstline) != 0) break; 
2445         }
2446         firstline = 0;
2447       }
2448       else if (d == 2) {    /* binary section code */
2449         binary++;
2450         if (copybinary(output, input, n) != 0) break;
2451       }
2452       else {
2453         sprintf(logline, " Unrecognized section code %d", d);
2454         showline(logline, 1);
2455         break;
2456       }
2457       c = getc(input); d = getc(input);
2458       if (c == EOF) {
2459         sprintf(logline, " Unexpected EOF (%s)\n", "copyfont");
2460         showline(logline, 1);
2461         break;
2462       }
2463     }
2464   }
2465   else if ((c >= '0' && c <= '9') || 
2466     (c >= 'A' && c <= 'F') ||
2467       (c >= 'a' && c <= 'f')) { /* assume PFA format */
2468 /*    showline(" PFA ", 0); */        /* debugging */
2469     if (mtmiflag == 0) copypfa (output, input, stripflag); /* normal PFA */
2470     else copymtmi (output, input, stripflag);   /* MTMI */
2471   }
2472   else {
2473     sprintf(logline, " Don't understand font file format %d", c);
2474     showline(logline, 1);
2475     errcount(0);
2476   }
2477 /*  following duplicates code at end of extracttype1 */
2478   endresource(output);            /* share code */
2479 }
2480
2481 /* Use the following more in future to avoid dependency on line breaks ? */
2482
2483 /* grab next white space delimited token in line */ /* read line if needed */
2484 /* assumes pump has been primed, i.e. line read and strtok called once */
2485
2486 char *grabnexttoken(FILE *input, char *line)
2487 {
2488   char *str=NULL, *s;
2489
2490   for (;;) {
2491     while ((s = strtok(str, " \t\n\r")) == NULL) {
2492       for(;;) {         /* need to grab a new line then */
2493         if (extgetrealline(input, line) < 0) return NULL; /* EOF */
2494 /*        ignore comments and blank lines - continue round the loop */
2495         if (*line != '%' && *line != '\n' && *line != '\r') break;
2496       }
2497       str = line;
2498     }
2499     if (*s != '%') break;   /* escape if not comment */
2500 /*    following added to strip comments off ends of lines 1992/Sep/17 */
2501     for(;;) {         /* need to grab a new line then */
2502       if (extgetrealline(input, line) < 0) return NULL; /* EOF */
2503 /*      ignore comments and blank lines - continue round the loop */
2504       if (*line != '%' && *line != '\n' && *line != '\r') break;
2505     }
2506     str = line;
2507   }
2508   return s;
2509 }
2510
2511 /* new tokenized version follows */
2512 int gobbleencoding (FILE *input)
2513 {
2514   int chr, c, n;
2515   int base=10;
2516   char *s, *t;
2517
2518 /*  cleanencoding(0, MAXCHRS);  */
2519
2520 /*  may want to remove some debugging error message output later ... */
2521   s = strtok(line, " \t\n\r");  /* start the pipeline */
2522   for (;;) {          /*  exit if hit `readonly' or `def' ??? */
2523     if (strcmp(s, "dup") != 0) {
2524       if (strcmp(s, "readonly") == 0 ||
2525         strcmp(s, "def") == 0) break; /* normal exit */
2526       sprintf(logline, " Expecting %s, not: `%s' ", "`dup'", s);
2527       showline(logline, 1);
2528       break;
2529     }
2530     if ((s = grabnexttoken(input, line)) == NULL) break;
2531 /*    Cater to stupid Adobe Universal Greek font format */ /* 92/Sep/17 */
2532     if (strchr(s, '#') != NULL) { /* stupid encoding vector format */
2533       (void) sscanf(s, "%d#%n", &base, &n); /* try and get base */
2534       s +=n; chr=0;
2535       for (;;) {      /* more general version 92/Sep/27 */
2536         c = *s++;
2537         if (c >= '0' && c <= '9') c = c - '0';
2538         else if (c >= 'A' && c <= 'Z') c = c - 'A' + 10;
2539         else if (c >= 'a' && c <= 'z') c = c - 'a' + 10;
2540         else {
2541           s--; break;
2542         }
2543         chr = chr * base + c;
2544       }
2545     }           /* end of radixed number case */
2546     else if (sscanf(s, "%d", &chr) < 1) {
2547       sprintf(logline, " Expecting %s, not: `%s' ", "number", s);
2548       showline(logline, 1);
2549       break;
2550     }
2551 /*    deal with idiotic Fontographer format - no space before /charname */
2552     if ((t = strchr(s, '/')) != NULL) s = t;  /* 1992/Aug/21 */
2553     else if ((s = grabnexttoken(input, line)) == NULL) break;
2554     if (*s != '/')  {
2555       sprintf(logline, "Bad char code `%s' ", s);
2556       showline(logline, 1);
2557       break;      // ???
2558     }
2559     else s++;
2560 /*    if (chr >= 0 && chr < fontchrs && strlen(s) < MAXCHARNAME) { */
2561     if (chr >= 0 && chr < fontchrs) {       /* 93/Nov/15 */
2562 /*      printf("%d: %s ", chr, s); */ /* debugging */
2563 /*      strcpy(charnames[chr], s); */
2564       if (strcmp(s, ".notdef") != 0)    /* ignore .notdef 97/Jan/7 */
2565         addencoding(chr, s);      /* 93/Nov/15 */
2566     }
2567     else {
2568       sprintf(logline, "Invalid char number %d ", chr);
2569       showline(logline, 1);
2570       break;      // ???
2571     }
2572     if ((s = grabnexttoken(input, line)) == NULL) break;
2573     if (strcmp(s, "put") != 0) {
2574       sprintf(logline, " Expecting %s not: `%s' ", "`put'", s);
2575       showline(logline, 1);
2576 /*      break; */ /* ??? */
2577     }
2578     if ((s = grabnexttoken(input, line)) == NULL) break;
2579   }
2580 /*  normally come here because line does not contain `dup'  */
2581 /*  but does contain `readonly' or `def' */
2582 /*  attempt to deal with Fontographer 4.0.4 misfeature 94/Nov/9 */
2583 /*  if `readonly' appears on one line and `def' appears on the next */
2584   if (strcmp(s, "readonly") == 0) { 
2585     if ((s = grabnexttoken(input, line)) != NULL) {
2586       if (strcmp(s, "def") != 0) {
2587         sprintf(logline, " Expecting %s, not: `%s' ", "`def'", s);
2588         showline(logline, 1);
2589 //        return -1;    // ???
2590       }
2591     }
2592   }
2593 /*  need to clean out current line at all ? */
2594   return 0;
2595 }
2596
2597 /* check whether a TeX font - result not really used */
2598 /* used only if resident font names are to be upper cased (-U) */
2599 /* (so maybe the `lowercase' is not needed ?) */ /* or use _strnicmp(...) */
2600 /* May be useful when PostScript FontName same as filename, but uppercase */
2601
2602 int istexfont (char *fname)
2603 {
2604   if (_strnicmp (fname, "cm", 2) == 0 ||  /* Computer Modern (visible) */
2605     _strnicmp (fname, "lcm", 3) == 0 || /* SliTeX (visible) */
2606     _strnicmp (fname, "icm", 3) == 0 || /* Computer Modern invisible */
2607     _strnicmp (fname, "ilcm", 4) == 0 ||  /* SliTeX invisible */
2608     _strnicmp (fname, "msam", 4) == 0 ||  /* AMS math symbol */
2609     _strnicmp (fname, "msbm", 4) == 0 ||  /* AMS math symbol */
2610     _strnicmp (fname, "eu", 2) == 0 ||    /* Euler fonts */
2611     _strnicmp (fname, "wncy", 4) == 0 ||  /* Washington Cyrillic */ 
2612     _strnicmp (fname, "logo", 4) == 0 ||  /* logo fonts - METAFONT */
2613     _strnicmp (fname, "lasy", 4) == 0 ||  /* LaTeX symbol font */
2614     _strnicmp (fname, "line", 4) == 0 ||  /* LaTeX line fonts */
2615     _strnicmp (fname, "lcircle", 7) == 0 || /* LaTeX circle fonts */
2616     _strnicmp (fname, "mtmi", 4) == 0 ||  /* MTMI, MTMIB, MTMIH */
2617     _strnicmp (fname, "mtmu", 4) == 0 ||  /*     , MTMUB, MTMUH */
2618     _strnicmp (fname, "mtms", 4) == 0 ||  /* MTMS, MTMSB */
2619     _strnicmp (fname, "mtsy", 4) == 0 ||  /* MTSY, MTSYB, MTSYH, MTSYN */
2620     _strnicmp (fname, "mtex", 4) == 0 ||  /* MTEX, MTEXB, MTEXH */
2621     _strnicmp (fname, "mtgu", 4) == 0 ||  /* MTGU, MTMGUB */
2622     _strnicmp (fname, "rmtm", 4) == 0   /* RMTMI, RMTMIB, RMTMIH */
2623                         /*      , RMTMUB, RMTMUH */
2624 /*    _strnicmp (fname, "lm", 2) == 0 || */ /* LucidaMath */
2625 /*    _strnicmp (fname, "lbm", 3) == 0 || */  /* LucidaNewMath */
2626     ) return 1;
2627   else return 0;
2628 }
2629
2630 /* separated out 97/Feb/6 */ /* returns 0 if failed */
2631 /* this should also check for /BaseFontName and suppress replacement ? */
2632 /* WARNING: this writes back into second argument ! */
2633
2634 int FindFontPFBaux (FILE *input, char *FontName, int nlen)
2635 {
2636   char token[] = "/FontName ";
2637   int c, k=0;
2638   char *s=FontName;
2639
2640   while ((c = getc(input)) != EOF) {
2641     if (c == '%')       /* Try and avoid comment lines ... */
2642       while (c >= ' ') c = getc(input); /* Skip to end of line */
2643     if (c != token[k]) {
2644       k = 0;          /* no match, reset ... */
2645       continue;
2646     }
2647     k++;
2648     if (k >= 10) {        /* completed the match ? */
2649       while ((c = getc(input)) != '/' && c != EOF) { /* up to slash */
2650         if (c > ' ') {  /* only white space allowed here 97/June/1 */
2651           k = 0;
2652           continue; /* ignore /FontName *not* followed by /xxxxx */
2653         }
2654       }
2655       k = 0; 
2656       s = FontName;
2657 /*      while ((c = getc(input)) > ' ' && k < MAXFONTNAME) */
2658       while ((c = getc(input)) > ' ' && k++ < nlen)
2659 /*        buffer[k++] = (char) c; */
2660         *s++ = (char) c;
2661 /*      fclose (input); */
2662 /*      if (c != EOF && k < MAXFONTNAME) { */
2663       if (c != EOF && k < nlen) {
2664 /*        buffer[k] = '\0'; */
2665         *s = '\0';
2666 /*        strcpy (FontName, buffer); */
2667 #ifdef DEBUG
2668         if (traceflag) {
2669           sprintf(logline, "Found /FontName %s in %s\n", FontName, FileName);
2670           showline(logline, 0);
2671         }
2672 #endif
2673         return 1;   /* success */
2674       }
2675       else return 0;    /* failed, EOF in FontName or name too long */
2676     }
2677   }
2678   return 0;     /* failed - EOF read the whole file */
2679 }
2680
2681 // FILE *OpenFont(char *font, int flag);
2682
2683 /* Attempt to find FontName from PFB file when forcereside != 0 */
2684 /* An experiment 1993/Sep/30 */
2685 /* WARNING: this writes back into second argument ! */
2686
2687 int FindFontPFB (char *FileName, char *FontName, int nlen) /* 1993/Sep/30 */
2688 {
2689   int flag;
2690   FILE *input;
2691
2692   if ((input = OpenFont(FileName, 0)) == NULL) {
2693 #ifdef DEBUG
2694     if (traceflag) {
2695       sprintf(logline, "Unable to find font file for %s\n", FileName);  /* debug ? */
2696       showline(logline, 0);
2697     }
2698 #endif
2699     return 0;
2700   }
2701
2702   flag = FindFontPFBaux(input, FontName, nlen);
2703
2704   fclose (input);
2705   if (flag == 0) {
2706     sprintf(logline, "Unable to find FontName in %s\n", FileName);
2707     showline(logline, 1);
2708   }
2709   return flag;
2710 }
2711
2712 /* finding PS FontName from PFM file */
2713
2714 // FILE *openpfm (char *font);
2715
2716 /* WARNING: this writes back into second argument ! */
2717
2718 int FindFontPFM (char *FileName, char *FontName, int nlen) /* 1997/June/1 */
2719 {
2720   FILE *input;
2721   int flag;
2722
2723   if (traceflag) {
2724     sprintf(logline, "FindFontPFM nlen %d\n", nlen);
2725     showline(logline, 0);
2726   }
2727   if ((input = openpfm(FileName)) == NULL) {
2728 #ifdef DEBUG
2729     if (traceflag) {
2730       sprintf(logline, "Unable to find font file for %s\n", FileName);  /* debug ? */
2731       showline(logline, 0);
2732     }
2733 #endif
2734     return 0;
2735   }
2736   flag = NamesFromPFM(input, NULL, 0, FontName, nlen, FileName);
2737   fclose (input);
2738 /*  printf("FontName %s for FileName %s\n", FontName, FileName); */
2739   return flag;
2740 }
2741
2742 /* Try and find font name in PFB / PFA file or in PFM file */
2743 /* WARNING: this writes back into second argument ! */
2744
2745 int FindFontName (char *FileName, char *FontName, int nlen) /* 1993/Sep/30 */
2746 {
2747   if (traceflag) {
2748     sprintf(logline, " FindFontName `%s' %d\n", FileName, nlen);
2749     showline(logline, 0); // debugging only
2750   }
2751   if (FindFontPFB (FileName, FontName, nlen) == 0) {
2752     if (FindFontPFM(FileName, FontName, nlen) == 0) return 0;
2753   }
2754   return 1;
2755 }
2756
2757 /*  Split out 1992/Oct/8 - avoid assumption FontName occurs before Encoding */
2758 /*  Now use even earlier - avoid assumption FontName comes after FontInfo */
2759 /*  returns non-zero if font appears to be synthetic font */
2760
2761 /*  drops real PostScript FontName in realfontname if found */
2762
2763 int parseline(char *line, FILE *output, int syntheticflag, int mtmiflag)
2764 {
2765   double m11, m12, m21, m22, m31, m32;
2766   int ftp, k, n;
2767   char *s;
2768
2769 /*  Try and pick out FontType */ 
2770   if ((s = strstr(line, "/FontType")) != NULL) {
2771     if(sscanf(s, "/FontType %d", &ftp) == 1) {
2772       if (ftp != 1) {
2773         sprintf(logline, " Not a Type 1 font: %s", line);
2774         showline(logline, 1);
2775         errcount(0);  
2776       }
2777     }
2778 //    fputs(line, output);
2779     PSputs(line, output);
2780   }
2781 /*  Try and pick out FontName */
2782   else if ((s = strstr(line, "/FontName")) != NULL) {
2783 /*    if (sscanf(s, "/FontName /%s", realfontname) > 0) { */
2784     s += 9;           /* step over `/FontName' */
2785     while (*s != '/' && *s != '\0') s++;  /* 1993/Aug/15 */
2786 /*    Verify that the FontName we got from %! line is correct 97/Jan/30 */
2787     if (bAddBaseName && *realfontname != '\0') {
2788       if (*s == '/') {  /* fix 1997/June/1 */
2789         n = strlen(realfontname);
2790         if (strncmp(s+1, realfontname, n) != 0) {
2791           sprintf(logline, " ERROR: %s != ", realfontname);
2792           showline(logline, 1);
2793           if (sscanf(s, "/%s", realfontname) > 0) {
2794             sprintf(logline, "%s ", realfontname);
2795           }
2796           else {
2797             sprintf(logline, "%s ", s);
2798           }
2799           showline(logline, 0);
2800         }
2801       }
2802     }
2803     if (sscanf(s, "/%s", realfontname) > 0) {
2804 /*      if (verboseflag) fputs(realfontname, stdout); */
2805 /* Don't trust `Oblique' (and `Narrow') fonts */ 
2806 /* Helvetica and Courier may be the only common cases of such fonts ??? */
2807 /* Helvetica, Helvetica-Light, Helvetica-Black, Helvetica-Narrow */
2808 /* Maybe also `Slanted' and  `Narrow' and `Condensed' and `Expanded' ??? */
2809 /* Inverted order of tests for efficiency -- 1993/Nov/4 */
2810       if (syntheticsafe != 0) {
2811         if (strstr(s, "Oblique") != NULL ||
2812           strstr(s, "BoldObl") != NULL || /* 1994/Feb/3 */
2813           strstr(s, "Narrow") != NULL) {  /* 1993/June/14 */
2814           for (k = 0; k < 16; k++) {
2815             if (strcmp("", syntheticfonts[k]) == 0) break;
2816             if (strstr(s, syntheticfonts[k]) != NULL) {
2817               syntheticflag = 1;
2818               if (verboseflag) {
2819                 showline(" assumed synthetic", 0); /* debugging */ 
2820               }
2821               break;
2822             }
2823           }
2824         } 
2825       }
2826 /*      lowercase(realfontname, realfontname); */ /* removed 95/Aug/22 */
2827     } 
2828 /* check whether TeX font */ /* result not used much ... */
2829     texfont = 0;              /* 1992/Dec/22 */
2830     if (istexfont(realfontname) != 0) {
2831 /* also check if actually one of 75 TeX fonts (what about LATEX, SliTeX) ? */
2832       texfont = 1; standard = 0; 
2833     }
2834 /* Should we replace /FontName or not ? *//* Presently hard wired to do this */
2835 /* May need to be more careful here - assuming one line */
2836 /*    if (bSubRealName == 0) { */     /* 1995/Aug/22 */
2837     if (bSubRealName == 0 || mmflag != 0) { /* 1997/June/1 */
2838 /*      we don't normally come here these days ... */
2839 /*      copy realfontname to subfontname[k] ?  */
2840 /*      strcpy(subfontname + k * MAXFONTNAME, realfontname); */
2841 //      if (strcmp(fontprefix, "") == 0) {
2842       if (fontprefix != NULL) {
2843         *s = '\0';          /* s points at /<fname> */
2844 //        fputs(line, output);
2845         PSputs(line, output);
2846         *s = '/';
2847 //        putc('/', output);
2848         PSputc('/', output);
2849 /*  possibly modify if bRandomPrefix is set ??? */
2850 //        fputs(fontprefix, output);
2851         PSputs(fontprefix, output);
2852 //        fputs(s+1, output);
2853         PSputs(s+1, output);
2854       }
2855       else {
2856 //        fputs(line, output);  /* no prefix, just copy over */
2857         PSputs(line, output); /* no prefix, just copy over */
2858       }
2859     }
2860 /* Don't mess with FontName of old MTMI */
2861     else if (mtmiflag != 0) {
2862 //      fputs(line, output);  /* 1992/Aug/22 */
2863       PSputs(line, output); /* 1992/Aug/22 */
2864     }
2865 /* Don't mess with FontName of MM base font ? old method */ /* 1994/Dec/6 */
2866 /*    else if (bMMNewFlag == 0 && mmflag != 0) fputs(line, output); */
2867 /* Don't touch: 2 copy exch /FontName exch put */   /* 95/May/14 */
2868     else if (strstr(line, "/FontName exch") != NULL) {
2869 //      fputs(line, output);
2870       PSputs(line, output);
2871     }
2872     else {                      /* 1992/Oct/31 */
2873 //      fputs("/FontName /", output);
2874       PSputs("/FontName /", output);
2875 /* don't need to check here whether its resident or not ! */
2876 //      if (strcmp(fontprefix, "") != 0) 
2877       if (fontprefix != NULL) {
2878 /*        possibly modify if bRandomPrefix is set ??? */
2879 //        fputs(fontprefix, output);
2880         PSputs(fontprefix, output);
2881       }
2882 /* following inserted 1992/Dec/22 - for new `U' flag */
2883 /*      if (uppercaseflag != 0 && istexfont(filefontname) != 0) */
2884       if (uppercaseflag != 0 && texfont != 0)
2885         uppercase(filefontname, filefontname);
2886 /*      if(_stricmp(filefontname, realfontname) == 0)
2887         strcpy(filefontname, realfontname); */ /* ??? */
2888 //      fputs(filefontname, output);
2889       PSputs(filefontname, output);
2890 //      fputs(" def\n", output);
2891       PSputs(" def\n", output);
2892     }
2893   }
2894 /*  Try and pick out FontMatrix */
2895 /*  Following usually doesn't get triggered because FontName seen first */
2896 /*  Can't be more selective here, since don't know FontName ... */
2897   else if ((s = strstr(line, "/FontMatrix")) != NULL) {
2898     if (sscanf(s, "/FontMatrix[%lg %lg %lg %lg %lg %lg]",
2899       &m11, &m12, &m21, &m22, &m31, &m32) == 6) {
2900       if (syntheticsafe != 0 && syntheticflag == 0) {
2901         if (m11 != m22 || m21 != 0.0 || m12 != 0.0) {
2902           showline(" WARNING: use *synthetic* in sub file", 1);
2903 /*          errcount(0);          */  /* 1994/Jan/7 */
2904           syntheticflag = 1;
2905         }
2906       }
2907     }
2908 //    fputs(line, output);
2909     PSputs(line, output);
2910   }
2911   else {
2912 //    fputs(line, output);
2913     PSputs(line, output);
2914   }
2915   return syntheticflag;
2916 }
2917
2918 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
2919
2920 unsigned long checkdefault = 0x59265920;  /* default signature */
2921
2922 /* Takes first six letters of encoding vector name and compresses */
2923 /* into four bytes using base 40 coding */ /* 40^6 < s^32 */
2924 /* Treats lower case and upper case the same, ignores non alphanumerics */
2925 /* Except handles -, &, and _ */
2926
2927 unsigned long codefourty(char *codingvector)
2928 {
2929   unsigned long result=0;
2930   int c, k;
2931   char *s=codingvector;
2932
2933   if (strcmp(codingvector, "") == 0) {
2934     codingvector = "native";    /* if not specified ... */
2935     return checkdefault;      /* use default signature */
2936   }
2937   for (k = 0; k < 6; k++) {
2938     for (;;) {
2939       c = *s++;
2940       if (c >= 'A' && c <= 'Z') c = c - 'A';
2941       else if (c >= 'a' && c <= 'z') c = c - 'a';
2942       else if (c >= '0' && c <= '9') c = (c - '0') + ('Z' - 'A') + 1;
2943       else if (c == '-') c = 36;
2944       else if (c == '&') c = 37;
2945       else if (c == '_') c = 38;
2946       else c = 39;          /* none of the above */
2947 /*      else continue; */       /* not alphanumeric character */
2948 /*      result = result * 36 + c; */
2949       result = result * 40 + c;
2950       break;
2951     }
2952   }
2953   return result;
2954 }
2955
2956 int decodefourty(unsigned long checksum, char *codingvector)
2957 {
2958   int c;
2959   int k;
2960 /*  char codingvector[6+1]; */
2961
2962 /*  if (checksum == checkdefault) { */
2963   if (checksum == 0) {
2964     strcpy(codingvector, "unknown");
2965     return 1;
2966   }
2967   else if ((checksum >> 8) == (checkdefault >> 8)) {  /* last byte random */
2968     strcpy (codingvector,  "native");   /* if not specified ... */
2969     return 1;               /* no info available */
2970   }
2971   else {
2972     for (k = 0; k < 6; k++) {
2973 /*      c = (int) (checksum % 36); */
2974       c = (int) (checksum % 40);
2975 /*      checksum = checksum / 36; */
2976       checksum = checksum / 40;
2977       if (c <= 'z' - 'a' ) c = c + 'a';
2978       else if (c < 36) c = (c + '0') - ('z' - 'a') - 1;
2979       else if (c == 36) c = '-';
2980       else if (c == 37) c = '&';
2981       else if (c == 38) c = '_';
2982       else c = '.';       /* unknown */
2983       codingvector[5-k] = (char) c;
2984     }
2985     codingvector[6] = '\0';
2986   }
2987   return 0;               /* encoding info returned */
2988 }
2989
2990 int checkencoding(int k)
2991 {
2992   char checksumvector[8];         /* 6 chars + null */
2993   if (fc[k] == nCheckSum) return 0;         /* correct encoding */
2994   if (decodefourty(fc[k], checksumvector) != 0) return 0;
2995 /*  if (_strnicmp(checksumvector, textencoding, 6) != 0) */ /* 95/Feb/3 */
2996   if (_strnicmp(checksumvector, textenconame, 6) == 0) return 0;
2997 //  showline(" ", 0);
2998   showline(" WARNING: encoding mismatch ", 1);
2999   sprintf(logline,  "TFM: `%s..' versus PFB: `%s'", 
3000 /*    checksumvector, textencoding); */
3001     checksumvector, textenconame);          /* 95/Feb/3 */
3002   showline(logline, 1);
3003   return 1;                     /* failed */
3004 }
3005
3006 int checkremapencode(int k, char *fontnamek)    /* 1995/July/15 */
3007 {
3008   char checksumvector[8];             /* 6 chars + null */
3009
3010   if (decodefourty(fc[k], checksumvector) != 0) return 0;
3011 //  if (_strnicmp(checksumvector, fontvector + k * MAXVECNAME, 6) == 0)
3012   if (fontvector[k] != NULL &&
3013       _strnicmp(checksumvector, fontvector[k], 6) == 0) 
3014     return 0; 
3015   showline(" WARNING: encoding mismatch ", 1);
3016   sprintf(logline, " in %s ", fontnamek);     /* 95/July/30 */
3017   showline(logline, 1);
3018   sprintf(logline,  "TFM: `%s..' versus vector: `%s'\n", 
3019       checksumvector, fontvector[k] != NULL ? fontvector[k] : "");
3020 //      checksumvector, fontvector + k * MAXVECNAME);
3021   showline(logline, 1);
3022   return 1;
3023 }
3024
3025 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
3026
3027 /* share some code between extracttype1 and extracttype3 ??? */
3028 /* e.g. for BeginResource and EndResource ? OK, that has been done */
3029 /* actually, appears to be some divergence now ... */
3030
3031 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
3032
3033 /* decompress a Type 1 font file and send it to specified output */
3034
3035 /* int extracttype1(FILE *output, FILE *input, int i) { */
3036 /* int extracttype1(FILE *output, FILE *input, int fn) { */
3037 int extracttype1 (FILE *output, FILE *input, int fn, char *fontnamek)
3038 {
3039   int nvec, ns, ne, c, d, k, nbin, n, nchrs, flag;
3040 /*  int chr, nfdict; */
3041   int count, property, syntheticflag, mtmiflag;
3042 /*  int hybridflag; */    /* 1993/Aug/5 */ /* made global 1994/July/15 */
3043 /*  int ftp; */
3044   int stripflag=0;
3045 /*  int oldcount; */
3046 /*  int m; */   /* debug only */
3047   int l;      /* 1994/Jan/30 for `unseen' repeat appearance */
3048   int guess;    /* 1995/Oct/25 */
3049   char *s, *t, *vector;
3050   char charname[FNAMELEN];      /* just to be safe */
3051 //  char subfontnamek[MAXFONTNAME];
3052   char subfontnamek[FNAMELEN];
3053   char *wantchrs;
3054
3055   hybridflag=0;
3056   binaryin = 0;
3057 /*  macstyle = 0; */
3058 //  wantchrs = fontchar + MAXCHRS * fn;
3059   wantchrs = fontchar[fn]; 
3060   if (wantchrs == NULL) showline(" BAD wantchrs", 1);
3061   property = fontproper[fn];
3062 //  vector = fontvector + fn * MAXVECNAME;
3063   vector = fontvector[fn];
3064
3065   syntheticflag = (property & C_SYNTHETIC);
3066   mtmiflag = (property & C_MTMI);
3067   mmflag = (property & C_MULTIPLE);           /* 95/May/13 */
3068 //  strcpy(subfontnamek, subfontname + fn * MAXFONTNAME); /* 97/June/1 */
3069   if (subfontname[fn] != NULL) strcpy(subfontnamek, subfontname[fn]);
3070   else *subfontnamek = '\0';
3071
3072   if (bSuppressPartial != 0) syntheticflag = 1;   /* 1992/Sep/12 */
3073
3074 /*  if (syntheticflag != 0) printf(" synthetic font"); */   /* debugging */
3075   if (mtmiflag != 0) showline(" NOT Type 1", 1);
3076
3077   count = 0;        /* preliminary - may update later with accents */
3078   for (k = 0; k < MAXCHRS; k++) if (wantchrs[k] != 0) count++;
3079 /*  printf("%d used in ", count, fontnamek); */ /* debug 95/Mar/31 */
3080 /*  if (bMMNewFlag == 0 && mmflag != 0) count = MAXCHRS;*//* 94/Dec/6 */
3081   if (count == 0) {
3082 /*    strcpy(charname, fontname + fn * MAXTEXNAME); */
3083 /*    fprintf(errout, " No characters used in font %s (%d)",
3084       charname, fn);  */ /* 1995/Jan/5 */
3085     if (traceflag) showline(" No characters used in font", 1);
3086 /*    else if (verboseflag) putc('*', stdout); */   /* 1995/Feb/1 */
3087     fontproper[fn] |= C_UNUSED;     /* 1995/Feb/1 */
3088 /*    strcpy(charname, fontname + fn * MAXTEXNAME);  */
3089 /*    printf("Font %s (%d) marked C_UNUSED\n", charname, fn); */
3090     return -1;    /* shouldn't ever happen ? unless page sub range ... */
3091   }
3092   else if (verboseflag) {
3093     showline(fontnamek, 0);
3094   }
3095   else {
3096     showline("*", 0);
3097   }
3098
3099 /*  if (syntheticflag != 0) count = MAXCHRS; */ /* 1992/Aug/22 */
3100   
3101 /*  Now actually start looking at the file! */
3102
3103   if (bAddBaseName) {     /* try and get /FontName 97/Feb/6 */
3104     bBaseNameDone = 1;
3105     *realfontname = '\0';
3106     if (FindFontPFBaux (input, realfontname, sizeof(realfontname))) /* FNAMELEN */
3107       bBaseNameDone = 0;  /* found it, so use it */
3108     rewind(input);
3109   }
3110
3111   c = getc(input);
3112   (void) ungetc(c, input);
3113   if (c == 0) {       /* check if this is a Mac style font file */
3114 /*    macstyle = 1; */ /* try and position at start of ASCII length field */
3115 /*    need to figure out where we are in Mac file */
3116 /*    could be (a) at start of MacBinary header */
3117 /*         (b) at start of resource fork (128 byte later) */
3118 /*         (c) at start of actual resource (256 byter after that) */
3119     binaryin = 1;
3120     (void) getc(input);         /* first byte (0) again */
3121     if ((c = getc(input)) != 0) {   /* start of MacBinary ? */
3122       for (k = 2; k < 384; k++) (void) getc(input); /* yes */
3123       c = getc(input); (void) ungetc(c, input);
3124       if (c != 0) {         /* try and verify format */
3125         showline(" ERROR: Not a valid PC (or Mac) style font file ", 1);
3126         errcount(0);
3127         return 0;   /* errcount ? */
3128       }
3129     }
3130     else {    /* now try and check whether at start of resource fork, */
3131           /* which starts with (0, 0, 1, 0) = 256 length */
3132       c = getc(input);  d = getc(input);
3133       if (c == 1 && d == 0) {
3134 /*        then skip over resource fork section */
3135         for (k = 4; k < 256; k++) (void) getc(input);
3136         c = getc(input); (void) ungetc(c, input);
3137         if (c != 0) {         /* try and verify format */
3138           showline(" ERROR: Not a valid PC (or Mac) style font file ",1 );
3139           errcount(0);
3140           return 0;   /* errcount ? */
3141         }
3142       }
3143       else { /* try and imagine we are right there actually */
3144 /*        rewind(input); */ /* back to start of length code */
3145         (void) getc(input); (void) getc(input);  /* skip length */
3146       }       
3147     }
3148   } /* end of first byte is zero in file case */
3149
3150   chrs = -1;
3151   task = "copying heading line";
3152   k = extgetline(input, line);    /* get first line of font */
3153   if (*line != '%' || *(line + 1) != '!') {
3154     showline(" Nonstandard font file start: ", 1);
3155     showline(line, 1);
3156     errcount(0);
3157   }
3158   if (strstr(line, "Type3") != NULL || strstr(line, "Font-3") != NULL) {
3159     type3flag = 1;    /* well, maybe lets try Type 3 then ! */
3160     rewind(input);
3161     return 0;     /* indicate lack of success ! */
3162   }
3163
3164   if (stripcomment == 0) {
3165     if (mmflag) beginresource(output, subfontnamek);  /* 97/June/1 */
3166     else beginresource(output, filefontname);   /* share code */
3167 /*    fprintf(output, "%s", line); */ /* copy %! heading line  ??? */
3168 //    fputs(line, output);
3169     PSputs(line, output);
3170     if (wantcreation != 0) {
3171       k = extgetline(input, line);  /* check second line of font */
3172 /*      if (*line != '%' || strncmp(line, "%%CreationDate", 14) == 0) */
3173       if (strncmp(line, "%%CreationDate", 14) == 0) /* 1995/April/12 */
3174 /*        fprintf(output, "%s", line); */
3175 //        fputs(line, output);
3176         PSputs(line, output);
3177 /*  this line gets output below anyway, unless its a comment */
3178     }
3179   }
3180   
3181   task = "looking for FontInfo";
3182
3183 /*  strcpy(realfontname, ""); */  /* 95/Aug/22 */ /* removed 97/Jan/30 */
3184
3185   while (strstr(line, "/FontInfo") == NULL && k >= 0) { 
3186 /*  Try and strip out that `font wrapper' stuff checking for existing font ! */
3187 /*  ===> NOTE: this is in outer level <=== */
3188 /*  Used in Courier, Helvetica for example */
3189 /*  Also junk in Fontographer style fonts - up to three lines long */
3190 /*    if (stripchecking != 0 && syntheticflag == 0) { */
3191     if (stripchecking != 0) { 
3192       if (strstr(line, "FontDirectory") != NULL) {
3193         stripflag++;
3194         k = extgetline(input, line);
3195         if (strstr(line, "/FontType") != NULL) {
3196           k = extgetline(input, line);
3197         }
3198         if (strstr(line, "{save true}") != NULL) { /* 1992/Aug/21 */
3199           k = extgetline(input, line);
3200         }
3201 /* search up to line containing `{false}ifelse' ? */
3202 /* search up to `<x> dict begin' ? */
3203         while (strstr(line, "dict") == NULL) {    /* 1992/Oct/22 */
3204           k = extgetline(input, line); 
3205           if (k == EOF) break;
3206         }
3207         if (stripcomment == 0) {
3208 //          fputs("% font wrapper removed\n", output);
3209           PSputs("% font wrapper removed\n", output);
3210         }
3211 /*        putc('\n', output); */    /* at least leave some space */
3212       } /* end of strstr(line, "FontDirectory") != NULL */
3213     } /* end of stripchecking != 0 */
3214
3215 /*  ignore comment lines OTHER than copyright or trademark line */
3216     if (*line == '%') {
3217       if (strstr(line, "opyright") != NULL ||
3218         strstr(line, "rademark") != NULL ||
3219         strstr(line, "(c)") != NULL)
3220 //        fputs(line, output);
3221         PSputs(line, output);
3222     }
3223 /*  Ignore blank lines */
3224     else if (*line != '\n') {
3225 /*      fputs(line, output); */   /* 1992/July/18 */ /* 95/April/12 */
3226 /*  Check for FontName even this early - added 95/April/12 */
3227       syntheticflag = parseline(line, output, syntheticflag, mtmiflag);
3228 /*  parseline outputs the line itself (or modified version) */
3229     }
3230     k = extgetline(input, line);
3231 /*    getrealline(input, line); */
3232   }
3233
3234 /*  Should now have /FontInfo line */ /* increase dictionary allocation */
3235   if (bAddBaseName && !bBaseNameDone) {
3236     flag = 0;
3237     if ((s = strstr(line, "/FontInfo")) != NULL) {
3238       s +=10;
3239       if (sscanf(s, "%d%n dict", &k, &n) == 1) {
3240         char buffer[FNAMELEN];  /* long enough ? */
3241         strcpy(buffer, s+n);
3242         sprintf(s, "%d", k+1);
3243         strcat(s, buffer);
3244 /*        printf(line); */    /* debugging */
3245         flag++;
3246       }
3247     }
3248     if (flag == 0) {
3249       showline(" ERROR: unable to extend FontInfo dictionary\n", 1);
3250       bBaseNameDone++;
3251     }
3252   }
3253
3254   task = "stripping out FontInfo"; 
3255 /*  Now strip info ONLY if busedviencode is set --- 1992/July/18 */
3256 /*  It would be dangerous to retain /Notice in /FontInfo directory only, */
3257 /*    since /Notice may be multiline  --- changes 1992/July/18 */
3258 /*  This has a somewhat flakey termination test ... */
3259 /*  usually the end is `end readonly def' */
3260     
3261   while (strstr(line, "end ") == NULL && k >= 0) { 
3262     if (stripinfo == 0 || busedviencode == 0) {
3263 //      fputs(line, output);
3264       PSputs(line, output);
3265     }
3266     else if ((s = strstr(line, "/Notice")) != NULL) {
3267       sprintf(logline, "%% %s", s); /* s+1 ? */
3268       PSputs(logline, output);
3269     }
3270 /*    Try and put it after the /FullName in /FontInfo dictionary ? */
3271     if (strstr(line, "/BaseFontName ") != NULL) bBaseNameDone++;
3272 /*    In this case however the FontInfo dict is now one entry too large */
3273 /*    if (strstr(line, "/FullName") != NULL) {
3274       if (bAddBaseName && !bBaseNameDone) {
3275         fprintf(output, "/BaseFontName (%s) def\n", realfontname);
3276         bBaseNameDone++;
3277       }
3278     } */
3279     k = extgetrealline(input, line);
3280   }
3281 /*  If haven't placed BaseFontName yet, do it here */ /* 97/Jan/30 */
3282   if (bAddBaseName && !bBaseNameDone) {
3283     sprintf(logline, "/BaseFontName (%s) def\n", realfontname);
3284     PSputs(logline, output);
3285     bBaseNameDone++;
3286   } 
3287
3288   if (stripinfo == 0 || busedviencode == 0) { /* terminating line FontInfo */
3289 //    fputs(line, output);
3290     PSputs(line, output);
3291   }
3292
3293 /*  does this assume FontName comes before Encoding ? YES, ugh */
3294   task = "looking for Encoding & FontName";
3295   k = extgetrealline(input, line);        /* look for encoding */
3296   while (strstr(line, "/Encoding") == NULL && k >= 0) {
3297     syntheticflag = parseline(line, output, syntheticflag, mtmiflag);
3298     k = extgetrealline(input, line);
3299   }
3300
3301 /*  special case hack when "def" is on line *after* StandardEncoding 98/Oct/8 */
3302   if (strstr(line, "StandardEncoding") != NULL) { 
3303     if (strstr(line, "def") == NULL) {
3304       s = line + strlen(line);
3305       *(s-1) = ' ';     /* turn line termination into space */
3306       k = extgetrealline(input, s);
3307 /*      printf("LINE: %s", line); */
3308     }
3309   }
3310
3311 /* Now we have hit the encoding vector --- /Encoding in line */
3312   
3313   if (mtmiflag != 0) {  /* don't mess with vector if font sucks rocks */
3314 //    fputs(line, output);    /* 1992/Aug/22 */
3315     PSputs(line, output);     /* 1992/Aug/22 */
3316   }
3317
3318 /*  else if (bMMNewFlag == 0 && mmflag != 0) fputs(line, output); */
3319   else if ((property & C_REMAPIT) == 0) {   /* if font is not remapped */
3320     if (strstr(line, "StandardEncoding") != NULL) { /* easy case! */
3321       standard = 1; texfont = 0; fontchrs = MAXCHRS;
3322       if (bWindowsFlag != 0) {
3323         if (verboseflag) {
3324 //          putc('~', stdout);  
3325 //          if (logfileflag) putc('~', logfile);
3326           showline("~", 0);
3327         }
3328 /*        for (k = 0; k < fontchrs; k++)
3329           strcpy(charnames[k], ansiencoding[k]); */
3330 /* ansi encoding may have been changed if env var ENCODING is set ??? */
3331         copyencoding(charnames, ansiencoding, fontchrs); /* 93/Nov/15*/
3332 /*        writeencoding(output, wantchrs, syntheticflag, "ansinew"); */
3333 /*        writeencoding(output, wantchrs, syntheticflag, textencoding); */
3334         missingchars(wantchrs, textenconame); /* TEST 95/July/15 */
3335         writeencoding(output, wantchrs, syntheticflag, textenconame);
3336         if (bCheckEncoding) (void) checkencoding(fn); /* 95/Jan/10 */
3337         nansified++;    /* count how many we did this way */
3338       } /* if (bWindowsFlag != 0) */
3339       else {
3340 /*        for (k = 0; k < fontchrs; k++)
3341           strcpy(charnames[k], standardencoding[k]); */
3342         copyencoding(charnames, standardencoding, fontchrs); /* 93/Nov/15*/
3343         missingchars(wantchrs, "standard");   /* TEST 95/July/15 */
3344         writeencoding(output, wantchrs, syntheticflag, "standard");
3345       }
3346 /*      writeencoding(output, wantchrs, syntheticflag); */  /* ??? */
3347     }   /* end of StandardEncoding case (unremapped) */
3348     else {    /* font was not using StandardEncoding (unremapped) */
3349       standard = 0;
3350       if(sscanf(line, "/Encoding %d array", &nvec) < 1) {
3351         sprintf(logline, " Don't understand encoding vector: %s", 
3352           line);
3353         showline(logline, 1);
3354         extgiveup(9);
3355         return -1;
3356       }
3357 /*      fontchrs = nvec; */     /* can we trust this ? NO better not */
3358
3359 /*      task = "reading Encoding";  */
3360       k = extgetrealline(input, line);
3361 /*      have to ignore "0 1 255 {1 index exch /.notdef put} for" line */
3362       if (sscanf(line, "%d 1 %d {", &ns, &ne) < 2) {
3363 /*        maybe no need to complain ? */
3364         showline(" No /.notdef line", 1); 
3365       }
3366       else k = extgetrealline(input, line); /* 92/02/04 */
3367 /*      grabbed next line (or hung onto this, if NOT  /.notdef line) */
3368 /*      clear out charnames - background of blanks */
3369 /*      for (k = 0; k < MAXCHRS; k++) strcpy(charnames[k], ""); */
3370 /*      for (k = 0; k < MAXCHRS; k++) *charnames[k] = '\0';*//* 92/02/04 */
3371       cleanencoding(0, MAXCHRS);          /* 93/Nov/15 */
3372
3373       task = "reading Encoding"; 
3374 /*      k = extgetrealline(input, line); */ /* 92/02/04 now done above */
3375 /*      while (strstr(line, " def") == NULL)  */
3376 /*      scan encoding - ends on "readonly def" usually */
3377 /*      new tokenized version follows */
3378       gobbleencoding(input);
3379 /*      writeencoding(output, wantchrs, syntheticflag); */  /* ??? */
3380       missingchars(wantchrs, "");     /* NEW TEST 95/July/15 */
3381       writeencoding(output, wantchrs, syntheticflag, "");
3382     } /* Finished with NOT StandardEncoding case */
3383   } /* finish with non-remapped font case */ 
3384
3385   else {  /* now for what to do if non-resident font remapped C_REMAPIT */
3386     if (verboseflag) {
3387 //      putc('^', stdout);  
3388 //      if (logfileflag) putc('^', logfile);
3389       showline("^", 0);
3390     }
3391 /*    first flush old encoding vector */
3392     if (strstr(line, "StandardEncoding") == NULL)  {
3393 /*    scan encoding - ends on "readonly def" usually */
3394 /*    has to ignore "0 1 255 {1 index exch /.notdef put} for" line */
3395 /*    skip over encoding in font - ignore it totally */
3396 /*    Encoding ends with token `def' or `readonly' */ 
3397 /*    and token `def' and `readonly should not occur in Encoding */
3398       while ((strstr(line, "def") == NULL ||
3399         strstr(line, "put") != NULL) && k >= 0) { /* NEW 1991/11/23 */
3400         k = extgetrealline(input,line);
3401       }
3402     }
3403     readencoding(vector); /* read desired encoding */
3404 /*    writeencoding(output, wantchrs, syntheticflag); */
3405     missingchars(wantchrs, vector);     /* NEW TEST 95/July/15 */
3406     writeencoding(output, wantchrs, syntheticflag, "");
3407   } /* end of dealing with encoding vector */
3408
3409 /*  if (traceflag) showencoding(stdout);  */
3410
3411   task = "copying font dict up to eexec";
3412   k = extgetrealline(input, line);
3413   while (strstr(line, "eexec") == NULL && k >= 0) { /* copy up to eexec */
3414     syntheticflag = parseline(line, output, syntheticflag, mtmiflag);
3415     k = extgetrealline(input, line);
3416   }
3417 //  fputs(line, output);    /* 1992/July/18 */
3418   PSputs(line, output);   /* 1992/July/18 */
3419
3420   if (bSubRealName == 0) {        /* 95/Aug/22 */
3421 /*    we don't normally come here these days ... */
3422 //    strcpy(subfontname + fn * MAXFONTNAME, realfontname);
3423     if (subfontname[fn] != NULL) free(subfontname[fn]);
3424     subfontname[fn] = zstrdup(realfontname);
3425 /*    if we are going to use the PS FontName here we'll need it later */
3426   }
3427
3428   if (k == EOF) {     /* NEW */
3429     showline(" Premature EOF", 1);
3430     showline(" in font file", 1);
3431     errcount(0);
3432     return -1;    /* NEW --- shouldn't happen ! */
3433   }
3434
3435 /*  Problem: what if syntheticflag set, but stripflag also set !!! */
3436   if (syntheticflag != 0 ||
3437        mtmiflag != 0) { /* pretty much just expand PFB to PFA */
3438 /*    copyfont(output, input, i, mtmiflag, stripflag); */
3439     copyfont(output, input, fn, mtmiflag, stripflag);
3440     return 1;
3441   }
3442
3443   cryptin = REEXEC;
3444   cryptout = REEXEC;
3445   clm = 0;        // important for outencrypt
3446
3447   task = "entering encrypted section";
3448
3449   c = getc(input);
3450   while (c <= ' ' && c > 0) c = getc(input);  /* skip over white space */
3451   if (c == 128) {     /* see whether .pfb input format */
3452     binaryin = 1;
3453     c = getc(input);
3454     if (c != 2) {
3455       sprintf(logline, 
3456         " Expecting %s, not %d", "binary section code", c);
3457       showline(logline, 1);
3458       extgiveup(5);
3459       return -1;
3460     }
3461     len = readlength(input);
3462   }
3463   else if (c == 0) {      /* see whether Mac binary input format */
3464     binaryin = 1;
3465     (void) ungetc(c, input);
3466     len = maclength(input);
3467     c = getc(input);
3468     if (c != 2) {
3469       sprintf(logline, " Expecting %s, not %d", "Mac binary section code", c);
3470       showline(logline, 1);
3471 /*      shownext(input); */
3472       extgiveup(5);
3473       return -1;
3474     }
3475     c = getc(input);
3476     if (c != 0) {
3477       sprintf(logline, " Invalid Mac Binary section code %d", c);
3478       showline(logline, 1);
3479       extgiveup(5);
3480       return -1;
3481     }
3482     len = len -2;
3483   }
3484   else if (c > 128) {   /* see whether raw binary - totally flakey ! */
3485     binaryin = 1;
3486     len = (1U << 31); /* conversion to unsigned long ... */
3487     (void) ungetc(c, input);
3488   }
3489   else (void) ungetc(c, input);
3490
3491 /* copying across the four random encoding bytes at start also */
3492
3493   n = getmagic(input, line);        /* 1993/Sep/14 */
3494   putenlinen(output, line, n);      /* 1993/Sep/14 */
3495   
3496   task = "looking for CharString dict";
3497   n = getenline(input, line);
3498   while ((s = strstr(line, "/CharStrings")) == NULL) {
3499 /*  Omit UniqueID if font remapped AND dviencoding in use  */
3500     if ((property & C_REMAPIT) != 0) {
3501       if (busedviencode != 0 && strstr(line, "/UniqueID") != NULL) {
3502 /*        if (verboseflag) printf(" Stripping UniqueID"); */
3503         n = getenline(input, line); continue; 
3504       }
3505     }
3506     putenlinen(output, line, n);
3507     if (strstr(line, "/Subrs") != NULL) {
3508       copysubrs(output, input);
3509 /* may want to inject a spurious newline here ... */
3510 /*      printf("Old line %s", line); */ /* |- */
3511 /*      n = getenline(input, line); */
3512 /*      printf("New line %s", line); */ /* end noaccess put */
3513       if (abortflag) return -1;
3514     }
3515 /*    else  */
3516     n = getenline(input, line);
3517 /* check on possibility of Synthetic Font */
3518 /* possibly suppress discarding of unwanted characters ? */
3519 /* Synthetic fonts won't work when remapped ? */
3520 /* ===> NOTE: this is in encrypted level <=== */
3521 /* possibly have to deal differently with the ending ? */
3522 /* need to transfer the rest of the font just as is because of byte count */
3523     if (strstr(line, "FontDirectory") != NULL) { /* 1992/Aug/24 */
3524 /* don't complain if already noted that it was synthetic ... */
3525       if (syntheticsafe != 0 && syntheticflag == 0) {
3526         showline(" ERROR: use *synthetic* in sub file", 1);
3527         errcount(0);
3528         syntheticflag = -1;   /* is it safe to do this now ? */
3529       }
3530 /*      else if (verboseflag) printf(" synthetic"); */
3531     }
3532     if (strstr(line, "hires") != NULL) {     /* 1993/Jan/17 */
3533       if (hybridflag == 0) showline(" hybrid", 0);  /* first time */
3534       hybridflag++;
3535     }
3536 /*    if (traceflag) printf("LINE: %s", line); */
3537   }
3538   if (strncmp(line, "2 index", 7) == 0)  fontform = 2;  /* new form */
3539   else if (strncmp(line, "dup", 3) == 0) fontform = 1;  /* old form */
3540   else fontform=0;                  /* not recognized */
3541   if (sscanf(s, "/CharStrings %d%n", &nchrs, &n) < 1) {
3542     putenline(output, line);    /* 1993 Aug 5 - allow line split */
3543     n = getenline(input, line);
3544     s = line;
3545     if (strstr(line, "dict dup") == NULL ||
3546       sscanf(s, "%d%n", &nchrs, &n) < 1) {
3547       sprintf(logline, " Don't understand CharStrings line: %s", line);
3548       showline(logline, 1);
3549       extgiveup(2);
3550       return -1;
3551     }
3552   }
3553   else {        /* normal case: /CharString <n> dict dup on line */
3554     *(s+13) = '\0';       /* terminate after `/CharStrings' */
3555     putenline(output, line);  /* start of modified /CharString line */
3556   }
3557 /*  *s = '\0';        */  /* terminate before /CharStrings */
3558 /*  putenline(output, line); */ /* start of modified /CharString line */
3559
3560 charagain:              /* 1993 Aug 5 - hybrid font loop */
3561
3562   if (accentedflag != 0) {    /* need to redo the count */
3563     count = 0;          /* if accented characters allowed */
3564     for (k = 0; k < MAXCHRS; k++) if (wantchrs[k] != 0) count++;  
3565   }
3566   if (wantnotdef != 0) count++;
3567 /*  if (count > MAXCHRS) count = MAXCHRS; */  /* notdef ??? */
3568   if (syntheticflag != 0) count = nchrs;  /* 1992/Aug/22 */
3569   nchrs = count;        /* count of desired characters */
3570 /*  nchrs=0; */
3571 /*  for (k=0; k < fontchrs; k++) if (wantchrs[k] != 0) nchrs++; */
3572 /*  if (wantnotdef != 0) nchrs++; */
3573 /*  sprintf(line, "/CharStrings %d", nchrs); */
3574   sprintf(line, "%d", nchrs);   /* 1993 Aug 5 */
3575   putenline(output, line);  /* middle of modified /CharString line */
3576   *(s+n) = ' ';       /* fix up, in case it became `\0' */
3577   putenline(output, s + n); /* end of modified /CharString line */
3578
3579   task = "scanning CharStrings";
3580   chrs = 0;         /* not used ? 95/Oct/28 */
3581 /*  for (k = 0; k < MAXCHRS; k++); charseen[k] = 0; *//* do earlier ??? */
3582   for (k = 0; k < MAXCHRS+1; k++) charseen[k] = 0; /* fix 1992/Aug/21 */
3583   for(;;) {
3584     if (getcharline(line, input, 0) != 0) break;
3585 /* the token "end" indicates the end of the CharString section */
3586     if (sscanf(line, "/%s %d %n", charname, &nbin, &n) < 2) { 
3587       sprintf(logline, " Not a CharString line: %s", line);
3588       showline(logline, 1);
3589 /*      fprintf(errout, " charname %s, nbin %d, n %d", 
3590         charname, nbin, n);
3591       n = sscanf(line, "/%s %d %n", &charname, &nbin, &n);
3592       fprintf(errout, " found only %d items in %d chars, first %d ! ", 
3593         n, strlen(line), (int) *line); */
3594       if (getcharline(line, input, 0) != 0) break;
3595       errcount(0);      /* a little risky going on here ? */
3596 /*      extgiveup(9); */  /* or, just flush THIS file ? */
3597     }
3598 /*    assert(strlen(charname) < MAXCHARNAME); */
3599 /*    if (strlen(charname) >= MAXCHARNAME)
3600       fprintf(errout, " char name %s too long", charname); */
3601 /*  flushed 93/Nov/15 */
3602 /*  possibly check here whether syntheticflag is set ??? */
3603 /*  in that case just transfer all characters */ /* 1992/Aug/22 */
3604 /*  shouldn't this depend on whether we used StandardEncoding ? */
3605 /*    k = wantthisname(charname, chrs, wantchrs); */
3606     guess = -1;
3607 /*    single character charnames equal their char code 95/Oct/28 */
3608     if (*(charname+1) == '\0') guess = *charname;
3609     k = wantthisname(charname, guess, wantchrs);
3610     if (k >= 0 || syntheticflag != 0) {         /* 1992/Aug/22 */
3611 /*      if (k < 0 || k >= MAXCHRS) 
3612         fprintf(errout, "Way out of range k %d ", k);   else  */
3613 /*      charseen[k] = 1; */   /* new - so can tell which missing */
3614       if (syntheticflag != 0) k = NOTDEF;   /* prevent error */
3615       else charseen[k]++;   /* new - so can tell which missing */
3616 /*      debugging only */
3617 /*  for dviencoding, change name to numeric code, unless its .notdef */
3618       if (busedviencode != 0 && k != NOTDEF) { /* change charname */
3619         if (strstr(line + n, "RD") != NULL) /* overwrite */
3620           sprintf(line, "/a%d %d RD ", k, nbin);
3621         else sprintf(line, "/a%d %d -| ", k, nbin);
3622       }
3623 /* above assumes using either RD or -| ??? */
3624       putenline(output, line);    /* beginning of character */
3625       copycharstring(output, input, nbin);
3626 /*      printf("%d ", k); */    /* debugging */
3627 /* this may not be accurate if repeated encoding and both char codes used .. */
3628       count--;        /* how many we extracted so far */
3629 /*      debugging only */
3630 /*      if (count == 0 && breakearly != 0 && fontform != 0) break; */
3631     }
3632     else flushcharstring(input, nbin);
3633     chrs++;         /* not used ? 95/Oct/28 */
3634     if (bAbort) abortjob();       /* 1992/Nov/24 */
3635     if (abortflag) return -1;
3636   }
3637   
3638 /*  believe that count should be zero here ! */
3639   if (count > 0) {              /* 1994/Jan/30 */
3640 /*  first check whether `missing' characters appear twice in encoding */    
3641 /*  this is important now that we use TEXANSI and extend encoding at bottom */
3642 /*  can only be equal to character lower in code, so don't start at zero */
3643     for (k = 1; k < MAXCHRS; k++) {   /* check the suspects */
3644       if ((wantchrs[k] != 0) && (charseen[k] == 0)) {
3645 /*  don't play with characters that have no names ! 96/May/26 */
3646         if (strcmp(charnames[k], "") == 0) continue;
3647         for (l = 0; l < k; l++) { /* does it appear earlier */
3648 /*  don't play with characters that have no names ! 96/May/26 */
3649           if (strcmp(charnames[l], "") == 0) continue;
3650           if (strcmp(charnames[k], charnames[l]) == 0) {
3651             charseen[k]++;
3652             count--;
3653             break;
3654           }
3655         }
3656       }
3657     }
3658   }
3659   if (count > 0) {
3660 /*    fprintf(errout, " %d characters (out of %d) not found: ", 
3661       count, nchrs); */
3662     sprintf(logline, " %d character%s (out of %d) not found: ", 
3663       count, (count == 1) ? "" : "s", nchrs);
3664     showline(logline, 1);
3665 /*    fprintf(errout, "fontchrs: %d ", fontchrs); */
3666     for (k = 0; k < MAXCHRS; k++) {   /* list the bad ones */
3667       if ((wantchrs[k] != 0) && (charseen[k] == 0)) {
3668 /*  characters may have no names if not in encoding 96/May/26 */
3669 /*        fprintf(errout, " %s (%d)", charnames[k], k);  */
3670         if (strcmp(charnames[k], "") != 0)
3671           sprintf(logline, " %s (%d)", charnames[k], k); 
3672         else sprintf(logline, " (%d)", k);  /* 96/May/26 ? */
3673         showline(logline, 1);
3674       }
3675 /*      debugging only */
3676 /*      if ((wantchrs[k] != 0) && (charseen[k] != 0)) {
3677         fprintf(errout, " %s [%d]", charnames[k], k);
3678       } */
3679     }
3680     errcount(0); /* ??? */
3681   }
3682
3683   chrs = -1;
3684   task = "copying end of CharString dict def";
3685   putenline(output, line);      /* copy beginning of end line */
3686   n = getenline(input, line);     /* copy rest of line */
3687   putenline(output, line);
3688
3689 /*  1993 August 5 - deal with `hybrid' font - second set of CharStrings */
3690 /*  if (strncmp(line, "hires", 5) == 0) { */
3691   if (strstr(line, "hires") != NULL) {    /* 1994/July/15 */
3692     n = getenline(input, line);   /* get potential <n> dict dup line */
3693     s = line;
3694     if (strstr(line, "dict dup") != NULL &&
3695       sscanf(s, "%d%n", &nchrs, &n) == 1) goto charagain;
3696     if ((s = strstr(line, "dict dup")) != NULL) { /* 1994/July/15 */
3697       while (s > line && *(s-1) == ' ') s--;
3698       while (s > line && *(s-1) > ' ') s--; /* Try and step back */
3699       if (sscanf(s, "%d%n", &nchrs, &n) == 1) {
3700 /*        printf("CHARSTRING: %s", s); */ /* debugging */
3701         *s = '\0';        /* terminate after `/CharStrings' */
3702         putenline(output, line); /* start modified /CharString line */
3703         goto charagain;
3704       }
3705     }
3706   }
3707   else n = getenline(input, line);      /* copy /FontName line */
3708   
3709 /* if by mistake we wade into second /CharStrings of hybrid font, following */
3710 /* goes wrong because it copies binary stuff and treats 0 char as end string */
3711
3712   task = "copying end of font dict def";
3713 /*  n = getenline(input, line); */      /* copy /FontName line */
3714   while (strstr(line, "closefile") == NULL) {
3715     putenline(output, line);
3716     n = getenline(input, line);
3717   }
3718
3719   putenline(output, line);
3720   flushencrypt(output);           // ???
3721
3722 /*  A problem here if the font has junk at the end of binary section ... */
3723 /*  Will this `fix' screw up treatment of Mac fonts ? */
3724
3725 /*  96/Feb/22 deal with junk at end of encrypted section */
3726 /*  Looking for M-@C-A (ASCII section heading) for PFB */
3727 /*  Looking for EOL for PFA */
3728 /*  Looking for C-@C-B for Mac */
3729   if (bStripBadEnd) {
3730     long current = ftell(input);
3731     c = getc(input);
3732     while (c != 128 && c != '0' && c != 0 && c >= ' ') {
3733       sprintf(logline, " JUNK %d (%c) at byte %ld", c, c, current);
3734       showline(logline, 1);
3735       current = ftell(input);
3736       c = getc(input);
3737     }
3738 /*    putc(c, output); */ /* ??? */
3739     ungetc(c, input); /* ??? */
3740   }
3741
3742 /*  task = "adding zeros & cleartomark"; */
3743   task = "copying ASCII section at end";
3744
3745 /*  putzeros(output, nestedflag); */      /* add zeros at end */
3746   c = getc(input); 
3747   if (c != '\n') (void) ungetc(c, input);   /* ??? */
3748 //  putc('\n', output);             /* for PFB not for PFA ? */
3749   PSputc('\n', output);             /* for PFB not for PFA ? */
3750   while (extgetline(input, line) != EOF) {  /* new way to finish off */
3751 /*    fputs(line, output);  */
3752 /*    Try and strip out that old Adobe crap checking for existing font ! */
3753 /*    Also junk in Fontographer style fonts */  /* 1992/Aug/21 */
3754 /*    Used in Courier, Helvetica for example */
3755 /*    if (stripchecking != 0 && syntheticflag == 0) {  */
3756     if (stripchecking != 0) {
3757       if ((s = strstr(line, "{restore}")) != NULL) {
3758         stripflag--;
3759         if ((t = strstr(line, "cleartomark")) != NULL) {
3760           *s++ = '\n';
3761           *s++ = '\0';      /* cut off after cleartomark */
3762 //          fputs(line, output);  /* 1992/Aug/20 */
3763           PSputs(line, output); /* 1992/Aug/20 */
3764         }
3765         if (stripcomment == 0) {    /* 1995/May/14 */
3766 //          fputs("% font wrapper removed\n", output);
3767           PSputs("% font wrapper removed\n", output);
3768         }
3769         continue; 
3770       }
3771     }
3772 //    fputs(line, output);
3773     PSputs(line, output);
3774   }
3775
3776   endresource(output);      /* share some code */
3777   if (stripflag != 0) 
3778     showline(" WARNING: broken wrapper ", 1); /* 1992/Oct/7 */
3779   return 1;             /* indicate success */
3780 }
3781   
3782 /* This is very specific for output from PKTOPS */
3783 /* Does not provide for encoding vector */
3784 /* Does not provide for remapping */
3785 /* First cues on `cleartomark' after encrypted stuff */
3786 /*    (OR: cues on second line that starts with "}def" if unencrypted */
3787 /* Then cues on `definefont' at end of font */
3788
3789 /* returns 0 if failed right away */
3790
3791 /* int extracttype3(FILE *output, FILE *input, int i) { */
3792 int extracttype3 (FILE *output, FILE *input, int i, char *fontnamek)
3793 {
3794   int nchar, copyflag, endflag, count;
3795   char *s;
3796   char *wantchrs;
3797
3798   if (verboseflag) {
3799 /*    printf("%s", fontnamek); */   /* 1995/Mar/1 */
3800     showline(fontnamek, 0);
3801   }
3802   else {
3803 /*    putc('*', stdout); */     /* 1995/Mar/1 */
3804     showline("*", 0);
3805   }
3806
3807 //  wantchrs = fontchar + MAXCHRS * i;
3808   wantchrs = fontchar[i]; 
3809   if (wantchrs == NULL) showline(" BAD wantchrs", 1);
3810 /*  property = fontproper[i]; */
3811 /*  vector = fontvector[i]; */
3812   
3813   (void) getline(input, line);
3814   if (*line != '%' || *(line + 1) != '!') {
3815     showline(" Nonstandard font file start: ", 1);
3816     showline(line, 1);
3817     errcount(0);
3818   }
3819   if (strstr(line, "Type1") != NULL || strstr(line, "Font-1") != NULL) {
3820     type3flag = 0;    /* well, maybe let try Type 1 then ! */
3821     rewind(input);
3822     return 0;     /* indicate lack of success */
3823   }
3824   if (verboseflag) showline(" BITMAP", 0); 
3825   if (stripcomment == 0) {
3826     beginresource(output, filefontname);    /* share code */
3827 //    fputs(line, output);
3828     PSputs(line, output);
3829     if (wantcreation != 0) {
3830       (void) getline(input, line);
3831       if (*line != '%' || strncmp(line, "%%CreationDate", 14) == 0)
3832 //        fputs(line, output);
3833         PSputs(line, output);
3834     }
3835   }
3836 /*  fprintf(output, "%s", line); */
3837
3838   count = 0;    /* number of lines starting with "}def" seen so far */
3839   for(;;) {
3840     if (getrealline(input, line) == 0) {
3841       sprintf(logline, " Unexpected EOF (%s)\n", "extracttype3");
3842       showline(logline, 1);
3843       errcount(0);  
3844       break;      /* was: return -1;  */
3845     }
3846     if (strstr(line, "serverdict") == NULL) { /* omit serverdict line ! */
3847 //      fputs(line, output);
3848       PSputs(line, output);
3849     }
3850     if (strstr(line, "cleartomark") != NULL) break; /* end preamble ? */
3851     if (strncmp(line, "}def", 4) == 0) {      /* end preamble ? */
3852       if (count++ >= 1) break;
3853     }
3854   }
3855
3856 /*  now copy across character bitmaps */
3857   for (;;) {        
3858     endflag = 0;      /* set when `definefont' seen ... */
3859     for (;;) {
3860       if (getrealline(input, line) == 0) { /* EOF */
3861         endflag = 1; break; 
3862       }
3863       if (*line == '/') {     /* replace fontname ??? */
3864         if ((s = strstr(line, "/FontName")) != NULL) {
3865 /*          if (sscanf(s, "/FontName /%s", realfontname) > 0)  */
3866           s += 9;           /* step over `/FontName' */
3867           while (*s != '/' && *s != '\0') s++;  /* 1993/Aug/15 */
3868           if (sscanf(s, "/%s", realfontname) > 0) {
3869             lowercase(realfontname, realfontname);  /* why ? */
3870           }
3871 /* check whether TeX font */ /* code inserted 1996/May/20 */
3872           texfont = 0;              /* 1992/Dec/22 */
3873           if (istexfont(realfontname) != 0) {
3874 /* also check if actually one of 75 TeX fonts (what about LATEX, SliTeX) ? */
3875             texfont = 1; standard = 0; 
3876           }
3877           if (bSubRealName != 0) {
3878 /*            we normally do this these days ... */
3879 /*  replaced following single line by code for prefix 96/May/20 ... */
3880 /*            sprintf(line, "/FontName /%s def\n", filefontname); */
3881             strcpy(line, "/FontName /");
3882 /*  look at fontprefix here also */
3883 //            if (strcmp(fontprefix, "") != 0)
3884             if (fontprefix != NULL)
3885               strcat(line, fontprefix);
3886             if (uppercaseflag != 0 && texfont != 0)
3887               uppercase(filefontname, filefontname);
3888 /*            if(_stricmp(filefontname, realfontname) == 0)
3889               strcpy(filefontname, realfontname); */ /* ??? */
3890             strcat(line, filefontname);
3891             strcat(line, " def\n");     /* down to here */
3892           }
3893         }
3894         else break;
3895       }
3896 /*      else break; */
3897
3898 //      fputs(line, output);
3899       PSputs(line, output);
3900       if (strstr(line, "definefont") != NULL) { /* end of font */
3901         endflag = 1; break; 
3902       }
3903     }
3904
3905     if (endflag != 0) {
3906 /*      printf(" found definefont"); */  /* debugging */
3907       break;
3908     }
3909
3910 /*    presently assuming simple numeric code - no encoding vector */
3911     if (sscanf(line, "/a%d ", &nchar) == 1)
3912     {
3913       copyflag = wantchrs[nchar]; 
3914 /*      printf(" (%d %d)", nchar, copyflag); */ /* debugging */
3915       if (copyflag != 0) {
3916 //          fputs(line, output);
3917           PSputs(line, output);
3918     }
3919 /*      else putc('@', stdout); */        /* debugging */
3920       for (;;) {
3921         if (getrealline(input, line) == 0) {
3922           sprintf(logline, " Unexpected EOF (%s)\n", "extracttype3");
3923           showline(logline, 1);
3924           break;      /* was:   return -1; */
3925         }
3926         if (copyflag != 0) {
3927 //          fputs(line, output);
3928           PSputs(line, output);
3929         }
3930         if (*line == '>') break;    /* end of this CharDef */
3931       }
3932     }
3933     else {
3934 //      fputs(line, output);
3935       PSputs(line, output);
3936     }
3937     if (bAbort) abortjob();   /* 1992/Nov/24 */
3938   }
3939
3940   endresource(output);
3941   return 1;               /* indicate success */
3942 }
3943   
3944 void complainbadfont (int flag) {
3945   sprintf(logline, " Bad Font File %d", flag);
3946   showline(logline, 1);
3947   errcount(0);
3948   checkexit(1);       /* this is pretty serious ! */
3949 }
3950
3951 void newcopyascii (FILE *output, FILE *input, unsigned long len)
3952 {
3953   size_t n, m;  
3954 //  unsigned int k;
3955 //  unsigned char buffer[MAXLINE];
3956   char buffer[MAXLINE+1];
3957   char *s;
3958
3959 //  m = sizeof(buffer);
3960   m = sizeof(buffer-1);   // leave space for null
3961   if (len < m) m = (size_t) len;
3962   while ((n = fread(buffer, 1, m, input)) != 0) {
3963 //    for (k = 0; k < n; k++) if (buffer[k] == '\r') buffer[k] = '\n';
3964     s = buffer;
3965 //    replace return with newlinw:
3966     while ((s = strchr(s, '\r')) != NULL) *s='\n';
3967 //    fwrite(buffer, 1, n, output);
3968     buffer[n] = '\0';     // terminate for PSputs
3969     PSputs(buffer, output);   // 99/Aug/13
3970     len -= n;
3971     if (len <= 0) break;
3972     if (len < m) m = (size_t) len;    // last bit
3973 /*    printf(" len %lu n %u m %u", len, n, m); */
3974   }
3975 }
3976
3977 #define COLUMNS 78
3978
3979 void newcopybinary (FILE *output, FILE *input, unsigned long len)
3980 {
3981   size_t n, m;
3982   unsigned char inbuffer[COLUMNS / 2];
3983   char outbuffer[COLUMNS + 2];      // space for \n and null
3984   int c, d, kk;
3985   unsigned int k;
3986
3987   m = sizeof(inbuffer);
3988   if (len < m) m = (size_t) len;
3989   while ((n = fread(inbuffer, 1, m, input)) != 0) {
3990     kk = 0;
3991     for (k = 0; k < n; k++) {
3992       c = inbuffer[k];
3993       d = c & 15;
3994       c = c >> 4;
3995       if (c > 9) c = c + 'A' - 10;
3996       else c = c + '0';
3997       if (d > 9) d = d + 'A' - 10;
3998       else d = d + '0';
3999       outbuffer[kk++] = (char) c;
4000       outbuffer[kk++] = (char) d;
4001     }
4002 //    fwrite(outbuffer, 2, n, output);
4003     outbuffer[kk++] = '\n';
4004     outbuffer[kk++] = '\0';     // terminate for PSPuts
4005     PSputs(outbuffer, output);    // 99/Aug/13
4006 //    putc('\n', output);
4007 //    PSputc('\n', output);
4008     len -= n;
4009     if (len <= 0) break;
4010     if (len < m) m = (size_t) len;  // last bit
4011   }
4012 }
4013
4014 /* Needed in dvispeci.c to deal with %%IncludeResource: font & %%IncludeFont */
4015 /* Do the dumbest possible thing - treat only plain PFA & PFB formats */
4016 /* called from dvispeci.c */
4017
4018 int decompressfont (FILE *output, FILE *input, char *FontName)
4019 {
4020   int c, d;
4021   int eof = 0;
4022 /*  size_t n; */
4023   long len;
4024
4025   beginresource(output, FontName);
4026   c = getc(input);
4027   ungetc(c, input);
4028   if (c != 128) {         /* we have to assume it is PFA format */
4029     newcopyascii(output, input, 0xFFFFFFFF);
4030   }
4031   else {
4032     for(;;) {
4033       c = getc(input); d = getc(input);
4034       if (c != 128) {
4035         complainbadfont(c);
4036         return -1;
4037       }
4038       switch(d) {
4039         case 1:         /* ASCII */
4040           len = readlength(input);
4041 /*          printf(" ASCII %lu", len); */
4042           newcopyascii(output, input, len);
4043           break;
4044         case 2:         /* Binary */
4045           len = readlength(input);
4046 /*          printf(" BINARY %lu", len); */
4047           newcopybinary(output, input, len);
4048           break;
4049         case 3:         /* EOF */
4050           eof = 1;
4051 /*          printf(" EOF"); */
4052           break;
4053         default:
4054           complainbadfont(d);
4055           return -1;
4056       }
4057       if (eof) break;
4058     }
4059   }
4060   endresource(output);
4061   return 0;
4062 }
4063
4064 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
4065 /* check whether we need any font substitution */
4066 int needsubstitute(void)
4067 {
4068   int k, proper;
4069
4070   for (k = 0; k < fnext; k++)
4071   {
4072     if (fontsubflag[k] >= 0)
4073     {
4074       proper = fontproper[k];
4075       if ((proper & C_RESIDENT) != 0) continue;
4076       if ((proper & C_REMAPIT) != 0) continue;
4077       if ((proper & C_DEPENDENT) != 0) continue;    /* NEW */
4078 /*      if ((proper & C_UNUSED) != 0) continue; */    /* ??? */
4079 /*      if (strcmp(fontname[k], subfontname[k]) == 0) continue; */ /* ? */
4080 /* font k occurs at other size already if fontname[k] == subfontname[k] */
4081 /*      if ((proper & C_ALIASED) != 0) continue;  */
4082       return -1;
4083     }
4084   }
4085   return 0;
4086 }
4087
4088 /* check to see if some resident fonts are remapped */
4089 int needremap(void)
4090 {
4091   int k;
4092   int winflag = 0;
4093   int proper;
4094
4095 /*  return positive if bWindowsFlag != 0 and some residents 93/Oct/4 */
4096 /*  returns negative if at least one font needs some other remapping */
4097
4098   for (k=0; k < fnext; k++) {
4099     proper = fontproper[k];
4100 /*    if ((fontproper[k] & C_REMAPIT) != 0 &&
4101       (fontproper[k] & C_RESIDENT) != 0) */
4102     if ((proper& C_RESIDENT) != 0) {    /* 93/Oct/4 */
4103       if ((proper & C_REMAPIT) != 0) return -1;
4104 /*      if (*textencoding != 0) winflag++;  else */ /* 94/Dec/17 */
4105       if (bWindowsFlag != 0) winflag++;     /* was just this */
4106 /* special case sy = Symbol and zd = ZapfDingbats ? */  /* 94/Feb/3 */
4107 /*      if (bWindowsFlag != 0) {
4108         strcpy(font, fontname + k * MAXTEXNAME);
4109         if (strcmp(font, "sy") != 0 &&
4110           strcmp(font, "zd") != 0)
4111             winflag++;
4112       } */            /* resident and not sy or zd */
4113     }
4114   }
4115 /*  return 0; */
4116   return winflag;
4117 }     /* only if remapped font is also printer resident */
4118
4119 /* returns total number of substitutes so far */
4120
4121 /* read font substitution */
4122 int readsubstitutes (FILE *input)
4123 {
4124   char oldname[FNAMELEN], newname[FNAMELEN], vector[FNAMELEN];
4125   int n, nlen, nnames, property;
4126 /*  int k=0; */
4127   int k=ksubst;                 /* 1994/Feb/4 */
4128   int count=ksubst;
4129   char *s, *u, *sd;
4130
4131   if (traceflag) {
4132     sprintf(logline, "Reading `%s'\n", fontsubfile); /* debugging */
4133     showline(logline, 0);
4134   }
4135   while (getrealline(input, line) != 0) {
4136     if (*line == '%' || *line == ';') continue; /* 92/Oct/30 */
4137     property = 0;       /* reset resident/forced/remap flag */
4138
4139 /*    nnames = sscanf(line, "%s %s%n", oldname, newname, &n); */
4140     s = line;                 /* 1993/Nov/6 */
4141     while (*s == ' ' || *s == '\t') s++;    /* ignore white space */
4142     nnames = sscanf(s, "%s %s%n", oldname, newname, &n);
4143     if (avoidreside != 0 && nnames == 2) {    /* 1993/July/15 */
4144 /*      not sure this is safe?  what if using this for alias ? */
4145       strcpy(newname, oldname); /* replace PS FontName ??? */
4146     }
4147     if (nnames == 1) { 
4148 /*      just one name given */
4149       if (complainflag) { /* eventually flush this error message ? */
4150         sprintf(logline, "No substitute specified: %s", line);
4151         showline(logline, 1);
4152       }
4153       strcpy(newname, "");  /* ??? */
4154 /*      strcpy(newname, oldname); */      /* ??? */
4155 /*      property |= (C_FORCESUB | C_RESIDENT); */
4156       property |= C_FORCESUB;         /* 1993/May/19 */
4157     }
4158     else if (strcmp(newname, oldname) == 0) {
4159 /*      `old' name same as `new' name */
4160       if (complainflag) { /* eventually flush this error message ? */
4161         sprintf(logline, "Substitute same as original: %s", line);
4162         showline(logline, 1);
4163       }
4164 /*      property |= (C_FORCESUB | C_RESIDENT); */
4165       property |= C_FORCESUB;         /* 1993/May/19 */
4166     }
4167     if (strchr(newname, '*') != NULL) {
4168 /*      only one name given */
4169       if (complainflag) { /* eventually flush this error message ? */
4170         sprintf(logline, "No substitute specified: %s", line);
4171         showline(logline, 1);
4172       }
4173       strcpy(newname, oldname);   /* ??? */
4174       n = (int) strlen(oldname);    /* step only over first name */
4175 /*      property |= (C_FORCESUB | C_RESIDENT); */
4176       property |=C_FORCESUB;          /* 1993/MAY/19 */
4177 /*      errcount(0);  */ /* continue; */
4178     }
4179 //    if ((nlen = strlen(oldname)) >= MAXTEXNAME) 
4180     if ((nlen = strlen(oldname)) > sizeof(oldname)-1) { /* FNAMELEN */
4181       sprintf(logline, " Font name too long: %s (%d > %d)",
4182           oldname, nlen, sizeof(oldname)-1);
4183       showline(logline, 1);
4184 //      *(oldname + MAXTEXNAME - 1) = '\0';
4185       *(oldname + sizeof(oldname)-1) = '\0';
4186 /*      errcount(0); */   /* 1995/July/27 */
4187       continue;
4188     }
4189 //    if ((nlen = strlen(newname)) >= MAXFONTNAME) {
4190     if ((nlen = strlen(newname)) > sizeof(newname)-1) { /* FNAMELEN */
4191       sprintf(logline, " Font name too long: %s (%d > %d)",
4192           newname, nlen, sizeof(newname)-1);
4193       showline(logline, 1);
4194 //      *(newname + MAXFONTNAME - 1) = '\0';
4195       *(newname + sizeof(newname)-1) = '\0';
4196 /*      errcount(0); */   /* 1995/July/27 */
4197       continue;
4198     }
4199
4200 /* try and analyze flags of form  *xyz*  on substitution line */
4201
4202 /*    s = line + n; */
4203     s +=n;              /* 1993/Nov/6 */
4204     if (*s <= ' ') *s++='\0';     /* isolate start of line */
4205     strcpy(vector, "");
4206
4207     sd = strtok(s, " \t\n\r");      /* get next token */
4208     while (sd != NULL) {
4209       if (*sd == '%') break;      /* 1992/Aug/24 */
4210       if (*sd == ';') break;      /* 1995/Mar/5 */
4211       if (strchr(sd, '*') == NULL) {
4212         sprintf(logline, 
4213           "Do not recognize `%s' in font substitution for: %s\n", 
4214             sd, line);
4215         showline(logline, 1);
4216         errcount(0);
4217       }
4218       else if (strcmp(sd, RESIDENT) == 0) property |= C_RESIDENT;
4219       else if (strcmp(sd, FORCESUB) == 0) property |= C_FORCESUB;
4220       else if (strcmp(sd, ALIASED) == 0)  {
4221         property |= C_ALIASED;
4222         aliasesexist++;
4223       }
4224 /* COMPOUND & HYBRID just for backward compatability ... */
4225       else if (strcmp(sd, SYNTHETIC) == 0 ||
4226             strcmp(sd, COMPOUND) == 0 ||
4227               strcmp(sd, HYBRID) == 0) { 
4228         property |= C_SYNTHETIC;
4229         syntheticsexist++;
4230       }
4231       else if (strcmp(sd, MTMI) == 0) property |= C_MTMI;
4232       else if (strcmp(sd, EPSF) == 0) property |= C_EPSF;  /* 94/Aug/15 */
4233 /*      else if (strcmp(sd, CONTROL) == 0) property |= C_CONTROL; */ /* 95/Oct/15 */
4234       else if (strcmp(sd, REMAPIT) == 0) {
4235         property |= C_REMAPIT;      /* remap */
4236         strcpy(vector, "textext");    /* default */
4237         sd = strtok(NULL, " \t\n\r"); /* try and find vector */
4238         if (sd != NULL) {
4239 /*        if no encoding vector given, then use default and go on */
4240           if (strchr(sd, '*') != NULL) continue;
4241           strncpy(vector, sd, 12+1);  /* file-name + extension */
4242 /* strip off extension, if any - assumes it is "vec" ... */
4243           if ((u = strchr(vector, '.')) != NULL) *u = '\0';
4244 /* limit to eight characters - otherwise not file name */
4245           if (strlen(vector) > 8) vector[8] = '\0';
4246 /*          if (verboseflag) printf("vector is %s\n", vector); */
4247         }
4248       }
4249       else if (strncmp(sd, "*user-", 6) == 0) {
4250 /*      Paul Anagnostopolous memorial hack to allow user-defined markers */
4251       }
4252       else {
4253         sprintf(logline, 
4254         "Do not recognize `%s' in font substitution for: %s\n", 
4255           sd, line);
4256         showline(logline, 1);
4257         errcount(0);  
4258       }
4259       sd = strtok(NULL, " \t\n\r"); /* advance to next token */
4260     }
4261
4262 /*  avoid problem when only one font name, or first name equals second name */
4263     if ((property & C_SYNTHETIC) != 0) {
4264       property &= ~C_FORCESUB;    /* 1993/Nov/7 */
4265     }
4266
4267     if (forcereside != 0) {
4268       property |= C_RESIDENT;   /* 1992/July/5 */
4269       property |= C_FORCESUB;   /* 1992/July/5 */
4270     }
4271
4272     if (avoidreside != 0) {
4273       property &= ~C_RESIDENT;  /* 1993/March/26 */
4274 /*  not sure the following makes sense     1993/July/15 */
4275 /*      property &= ~C_FORCESUB;  */ /* 1993/March/26 */
4276     }
4277
4278 /* above checks that all items where recognized ??? */
4279
4280 /*    *(oldname + MAXTEXNAME - 1) = '\0'; */ /* redundant ? */
4281 /*    strncpy(fontsubfrom[k], oldname, MAXTEXNAME); */
4282 /*    *(newname + MAXTEXNAME - 1) = '\0'; */ /* redundant ? */
4283 /*    strncpy(fontsubto[k], newname, MAXFONTNAME); */
4284 /*    strncpy(fontsubvec[k], vector, MAXVECNAME); */
4285 //    oldname[MAXTEXNAME-1]='\0';     /* prevent disaster */
4286     *(oldname + sizeof(oldname)-1) = '\0';  /* prevent disaster */
4287 //    newname[MAXFONTNAME-1]='\0';    /* prevent disaster */
4288     *(newname + sizeof(newname)-1) = '\0';  /* prevent disaster */
4289 //    vector[MAXVECNAME-1]='\0';      /* prevent disaster */
4290     *(vector + sizeof(vector)-1) = '\0';  /* prevent disaster */
4291 //    strcpy(fontsubfrom + k * MAXTEXNAME, oldname);
4292     if (fontsubfrom[k] != NULL) free(fontsubfrom[k]);
4293     fontsubfrom[k] = zstrdup(oldname);
4294 //    strcpy(fontsubto + k * MAXFONTNAME, newname);
4295     if (fontsubto[k] != NULL) free(fontsubto[k]);
4296     fontsubto[k] = zstrdup(newname);
4297 //    strcpy(fontsubvec + k * MAXVECNAME, vector);  /* 1994/Feb/2 */
4298     if (fontsubvec[k] != NULL) free(fontsubvec[k]);
4299     fontsubvec[k] = zstrdup(vector);
4300     fontsubprop[k] = property;
4301 /*    printf("FROM %s TO %s VECTOR %s ", oldname, newname, vector);
4302     printf("PROPERTY %d\n", property); */
4303
4304 /*    if we are being forced to download & no other flags on, ignore */
4305 /*    if (avoidreside != 0 && (property & ~C_FORCESUB) == 0) */
4306 /*    if no substitution & at most *force* on, then ignore it */
4307     if (strcmp(newname, oldname) == 0 && (property & ~C_FORCESUB) == 0)
4308       continue; /* 1993/July/16 */
4309
4310     k++;
4311     count++;    /* 1995/July/30 */
4312     if (k >= maxsubstitute-1) {
4313 /*      fprintf(errout, " Too many font subs (> %d)", maxsubstitute);*/
4314 /*      errcount(0); */
4315       k--;
4316     } 
4317   }   
4318
4319   if (count >= maxsubstitute-1) { /* moved here 95/July/30 - avoid repeat */
4320     sprintf(logline, " WARNING: Too many font subs (%d > %d)\n",
4321         count, maxsubstitute);
4322     showline(logline, 1);
4323     errcount(0);
4324   }
4325   ksubst = k;   /* remember number of entries in substitution table */
4326 /*  fclose(input); */               /* 1994/Feb/4 */
4327 /*  if (traceflag) showsubtable(stdout); */ /* an experiment */ 
4328   return ksubst;
4329 }
4330
4331 /* See whether font file can be found */
4332
4333 /* This tries each pathname on the searchpath - for each pathname: */
4334 /* - tries in order .pfb, .pfa, no extension (Mac format), */
4335 /* - then tries underscores: __.pfb, and __.pfa */
4336 /* - then tries .pss (Multiple Master Stub File) 94/Dec/6 */
4337 /* - and last tries .ps - assumed to be font produced by PKTOPS */
4338 /*  leaves result bits in instanceflag (MM), pssflag (MM), type3flag */
4339
4340 #ifdef SUBDIRSEARCH
4341
4342 /* try and open a font */
4343 FILE *OpenFont_Sub (char *font)
4344 {
4345   FILE *fp_in=NULL;
4346   static char fn_in[FNAMELEN];          /* preserve ? why ? */
4347
4348   task = "trying to open font file";
4349   if (font == NULL) return NULL;
4350   type3flag = 0;        /* start by assuming Type 1 font */
4351   pssflag = 0;        /* start by assuming not PSS stub */
4352   instanceflag = 0;     /* start by assuming not MM instance via PFM */
4353
4354   if (fontpath == NULL) return NULL;
4355   strcpy(fn_in, font);
4356   forceexten(fn_in, "pfb"); /* Try PFB form */
4357   if ((fp_in = findandopen(fn_in, fontpath, NULL, "rb", currentfirst)) != NULL)
4358     return fp_in;
4359   forceexten(fn_in, "pfa"); /* Try PFA form */
4360   if((fp_in = findandopen(fn_in, fontpath, NULL, "rb", currentfirst)) != NULL)
4361     return fp_in;
4362   removeexten(fn_in);     /* Try Mac form */
4363   if ((fp_in = findandopen(fn_in, fontpath, NULL, "rb", currentfirst)) != NULL)
4364     return fp_in;
4365   if (tryunderscore != 0) { /* try with underscores */
4366 /*    underscore(fn_in); */
4367     if (underscore(fn_in)) {
4368     forceexten(fn_in, "pfb"); /* Try PFB form */
4369     if((fp_in = findandopen(fn_in, fontpath,  NULL, "rb", currentfirst)) != NULL)
4370        return fp_in;
4371     forceexten(fn_in, "pfa"); /* Try PFA form */
4372     if((fp_in = findandopen(fn_in, fontpath, NULL, "rb", currentfirst)) != NULL)
4373        return fp_in;
4374     }
4375   }
4376
4377 /*  Now deal with ATM 4.0 way of doing multiple masters 97/June/1 */
4378   removeexten(fn_in);         /* remove extension again */
4379   removeunder(fn_in);         /* remove underscores again */
4380   forceexten(fn_in, "pfm");     /* MM PFM file 97/June/1 */
4381 /*  check in listed directories *and* PFM subdirectories */
4382   if ((fp_in = findandopen(fn_in, fontpath, NULL, "rb", -1)) != NULL) {
4383 /*    check whether ordinary PFM or MM instance PFM file */
4384     if (traceflag) {
4385       sprintf(logline, "Found %s\n", fn_in);  /* debugging */
4386       showline(logline, 0);
4387     }
4388     instanceflag = 1;
4389     return fp_in;
4390   }
4391   if (tryunderscore != 0) { /* try with underscores */
4392     if (underscore(fn_in)) {
4393       if ((fp_in = findandopen(fn_in, fontpath, NULL, "rb", currentfirst)) != NULL) {
4394 /*        check whether ordinary PFM or MM instance PFM file */
4395         if (traceflag) {
4396           sprintf(logline, "Found %s\n", fn_in);  /* debugging */
4397           showline(logline, 0);
4398         }
4399         instanceflag = 1;
4400         return fp_in;
4401       }
4402     }
4403   }
4404
4405 /*  Now deal with older way of doing multiple master fonts */
4406   removeexten(fn_in);         /* remove extension again */
4407   removeunder(fn_in);         /* remove underscores again */
4408   forceexten(fn_in, "pss");     /* MM PSS stub file 94/Dec/6 */
4409   if ((fp_in = findandopen(fn_in, fontpath, NULL, "rb", currentfirst)) != NULL) {
4410     pssflag = 1;          /* make a note */
4411     return fp_in;
4412   }
4413
4414 /*  Now deal with old Type 3 PK font files made by PKTOPS */
4415   forceexten(fn_in, "ps");      /* try PKTOPS output format */
4416   if ((fp_in = findandopen(fn_in, fontpath, NULL, "rb", currentfirst)) != NULL) {
4417     type3flag = 1;          /* not reliable - test later */
4418     return fp_in;
4419   }
4420   return NULL;              /* all variations failed ! */
4421 }
4422
4423 #else
4424 /* try and open a font */
4425 FILE *OpenFont_Sub (char *font)
4426 {
4427   FILE *fp_in;
4428   char *searchpath, *s;
4429   static char fn_in[FNAMELEN];          /* preserve ? why ? */
4430   
4431   task = "trying to open font file";
4432   if (font == NULL) return NULL;
4433   type3flag = 0;        /* start by assuming Type 1 font */
4434   if (fontpath == NULL) return NULL;
4435   searchpath = fontpath;
4436   for(;;) {
4437     if ((searchpath=nextpathname(fn_in, searchpath)) == NULL) break;
4438     s = fn_in + strlen(fn_in) - 1;
4439     if (*s != ':' && *s != '\\' && *s != '/') strcat(fn_in, "\\");
4440     strcat(fn_in, font);        /* use makefilename ??? */
4441     forceexten(fn_in, "pfb");     /* try .pfb first */
4442     if ((fp_in = fopen(fn_in, "rb")) != NULL) return fp_in;
4443     forceexten(fn_in, "pfa");     /* try .pfa next */
4444     if ((fp_in = fopen(fn_in, "rb")) != NULL) return fp_in;
4445     removeexten(fn_in);         /* try Mac form next */
4446     if ((fp_in = fopen(fn_in, "rb")) != NULL) return fp_in;
4447     if (tryunderscore != 0) {     /* try underscore form ? */
4448 /*      underscore(fn_in); */
4449       if (underscore(fn_in)) {    /* 95/May/28 */
4450       forceexten(fn_in, "pfb");     /* try .pfb first */
4451       if ((fp_in = fopen(fn_in, "rb")) != NULL) return fp_in;
4452       forceexten(fn_in, "pfa");     /* try .pfa next */
4453       if ((fp_in = fopen(fn_in, "rb")) != NULL) return fp_in;
4454       }
4455     }
4456     removeexten(fn_in);         /* remove extension again */
4457     removeunder(fn_in);         /* remove underscores again */
4458     forceexten(fn_in, "ps");      /* try PKTOPS output format */
4459     if ((fp_in = fopen(fn_in, "rb")) != NULL) { /* "r" ? */
4460       type3flag = 1;  return fp_in;   /* not reliable - test later */
4461     }
4462   }
4463   return NULL;              /* all variations failed ! */
4464 }
4465
4466 #endif
4467
4468 typedef struct ATMRegRec {
4469   unsigned char nMMM;   // directory path index for MMMName
4470   unsigned char nPFB;   // directory path index for PFBName
4471   unsigned char nPFM;   // directory path index for PFMName
4472   unsigned char MMMflag;  // 0 => TTF, 1 => T1, 2 => MM Master, 4 => MM Instance
4473   char *FontName;     // PostScript FontName
4474   char *MMMName;      // File Name of PFM (T1 or MMM instance), MMM (for MM master)
4475   char *PFBName;      // File Name of PFB (blank for MM instance)
4476   char *PFMName;      // File Name of PFM (for MM master), MMM (for MM instance)
4477 };
4478
4479 extern struct ATMRegRec *ATMFonts;
4480
4481 // New 2000 July 6
4482
4483 FILE *OpenFont_Reg (char *font)
4484 {
4485   static char fn_in[FNAMELEN];          /* preserve ? why ? */
4486   char *s;
4487   int k;
4488   FILE *input;
4489
4490   task = "trying to open font file";
4491   if (font == NULL) return NULL;
4492   type3flag = 0;        /*  Type 1 font */
4493   pssflag = 0;
4494   instanceflag= 0;
4495
4496   if (useatmreg == 0) return NULL;
4497 //  First look for match between DVI TFM and PFB file name
4498   for (k = 0; k < ATMfontindex; k++) {
4499     strcpy(fn_in, ATMFonts[k].PFBName);
4500     if ((s = strrchr(fn_in, '.')) != NULL) *s = '\0';
4501     if (_strcmpi(font, fn_in) == 0) {
4502       if (ATMFonts[k].MMMflag & 4) instanceflag = 1;
4503       if (! instanceflag) {
4504         strcpy(fn_in, DirPaths[ATMFonts[k].nPFB]);
4505         strcat(fn_in, ATMFonts[k].PFBName);   // PFB file name
4506       }
4507       else {
4508         strcpy(fn_in, DirPaths[ATMFonts[k].nMMM]);
4509         strcat(fn_in, ATMFonts[k].MMMName);   // PFM file name
4510       }
4511       input = fopen(fn_in, "rb");
4512 //      sprintf(logline, " font %s match %d %s => %s (%X)\n",
4513 //          font, k, ATMFonts[k].PFBName, fn_in,input);
4514 //      showline(logline, 0);   // debugging only
4515       return input;
4516     }
4517   }
4518   if (! usepsfontname) return NULL;
4519 //  Then allow for (exact) match between DVI TFM and PS FontName 
4520   for (k = 0; k < ATMfontindex; k++) {
4521     if (strcmp(font, ATMFonts[k].FontName) == 0) {
4522       if (ATMFonts[k].MMMflag & 4) instanceflag = 1;
4523       if (! instanceflag) {
4524         strcpy(fn_in, DirPaths[ATMFonts[k].nPFB]);
4525         strcat(fn_in, ATMFonts[k].PFBName);   // PFB file name
4526       }
4527       else {
4528         strcpy(fn_in, DirPaths[ATMFonts[k].nMMM]);
4529         strcat(fn_in, ATMFonts[k].MMMName);   // PFM file name
4530       }
4531       input = fopen(fn_in, "rb");
4532 //      sprintf(logline, " font %s match %d %s => %s (%X)\n",
4533 //          font, k, ATMFonts[k].FontName, fn_in, input);
4534 //      showline(logline, 0);   // debugging only
4535       return input;
4536     }
4537   }
4538   return NULL;
4539 }
4540
4541 /*  Rewritten 1994/March/18 to allow use of `texfonts.map' */
4542 /*  Note that the name in the font-tables is *not* changed */
4543 /*  We only grab a file under a different name and open it */
4544 /*  On screen output, replaced PS FontName etc uses the name in the DVI file */
4545
4546 /* try and open a font */
4547 FILE *OpenFont (char *font, int aliasflag)
4548 {
4549   FILE *input=NULL;
4550   char *aliasname;
4551
4552   if (font == NULL) return NULL;    /* sanity check */
4553 /*  first try name as given */
4554   if (useatmreg) input = OpenFont_Reg(font);
4555   if (input != NULL) return input;
4556   input = OpenFont_Sub(font);
4557   if (input != NULL) return input;
4558 /*  if (aliasflag && bTexFontsMap) { */   /* allowed to use texfonts.map? */
4559 /*  time for aliases? allowed to use texfonts.map? or have we already used? */
4560   if (aliasflag && bTexFontsMap && ! bForceFontsMap) {
4561     aliasname = alias(font);      /* in dvipslog.c */
4562     if (aliasname != NULL) {
4563       if (traceflag) {
4564         sprintf(logline, " font %s alias %s\n", font, aliasname);
4565         showline(logline, 0);
4566       }
4567       if (useatmreg) input = OpenFont_Reg(font);
4568       if (input != NULL) return input;
4569       input = OpenFont_Sub(aliasname);  /* with some luck we find it */
4570       if (input != NULL) return input;
4571     }
4572   }
4573   return input;
4574 }
4575
4576 char fn_pfm[FNAMELEN];      /* preserve ? why ? */
4577
4578 /* try and open a PFM file */
4579 FILE *openpfm (char *font)
4580 {
4581   FILE *fp_in=NULL;
4582 /*  static char fn_in[FNAMELEN]; */     /* preserve ? why ? */
4583 #ifndef SUBDIRSEARCH
4584   char *s, *t;
4585   char *searchpath;
4586 #endif
4587   
4588   if (fontpath == NULL) return NULL;
4589
4590 #ifdef SUBDIRSEARCH
4591   strcpy(fn_pfm, font);
4592   forceexten(fn_pfm, "pfm");      /* force .pfm */
4593   fp_in = findandopen(fn_pfm, fontpath, NULL, "rb", currentfirst);
4594   if (fp_in != NULL) return fp_in;
4595   if (tryunderscore)
4596   {
4597 /*    underscore (fn_pfm); */
4598     if (underscore (fn_pfm)) {  /* 95/May/28 */
4599       fp_in = findandopen(fn_pfm, fontpath, NULL, "rb", currentfirst);
4600       if (fp_in != NULL) return fp_in;
4601     }
4602   }
4603   strcpy(fn_pfm, "pfm\\");
4604   strcat(fn_pfm, font);
4605   forceexten(fn_pfm, "pfm");      /* force .pfm */
4606   fp_in = findandopen(fn_pfm, fontpath, NULL, "rb", currentfirst);
4607   if (fp_in != NULL) return fp_in;
4608   if (tryunderscore)
4609   {
4610 /*    underscore (fn_pfm); */
4611     if (underscore (fn_pfm)) {  /* 95/May/28 */
4612       fp_in = findandopen(fn_pfm, fontpath, NULL, "rb", currentfirst);
4613       if (fp_in != NULL) return fp_in;
4614     }
4615   }
4616 #else
4617   searchpath = fontpath;
4618   for(;;) {
4619     if ((searchpath=nextpathname(fn_pfm, searchpath)) == NULL) break;
4620     s = fn_pfm + strlen(fn_pfm) - 1;
4621     if (*s != ':' && *s != '\\' && *s != '/') strcat(fn_pfm, "\\"); 
4622     t = s + strlen(s);
4623     strcat(fn_pfm, font);       /* use makefilename ??? */
4624     forceexten(fn_pfm, "pfm");      /* force .pfm */
4625     if ((fp_in = fopen(fn_pfm, "rb")) != NULL) return fp_in;
4626     if (tryunderscore != 0) {     /* try underscore form ? */
4627 /*      underscore(fn_pfm); */
4628       if (underscore(fn_pfm)) {   /* 95/May/28 */
4629         forceexten(fn_pfm, "pfm");  
4630         if ((fp_in = fopen(fn_pfm, "rb")) != NULL) return fp_in;
4631       }
4632     }
4633     strcpy(t, "pfm\\");         /* try in subdirectory */
4634     strcat(fn_pfm, font);       /* use makefilename ??? */
4635     forceexten(fn_pfm, "pfm");      /* force .pfm */
4636     if ((fp_in = fopen(fn_pfm, "rb")) != NULL) return fp_in;
4637     if (tryunderscore != 0) {     /* try underscore form ? */
4638 /*      underscore(fn_pfm); */
4639       if (underscore(fn_pfm)) {   /* 95/May/28 */
4640         forceexten(fn_pfm, "pfm");  
4641         if ((fp_in = fopen(fn_pfm, "rb")) != NULL) return fp_in;
4642       }
4643     }
4644   }
4645 #endif
4646   if (traceflag)
4647   {
4648     sprintf(logline, "Failed to open %s\n", fn_pfm);    /* debugging only */
4649     showline(logline, 0);
4650   }
4651   return NULL;            /* all variations failed ! */
4652 }
4653
4654 /* first look for same font different sizes */
4655 void flagduplicates (void)
4656 {
4657   int k, i, j;
4658   char *fromfont;
4659   char *tofont;
4660
4661   for (k = 0; k < fnext; k++) { /* look for duplicate names first ! */
4662     if (fontsubflag[k] >= 0) continue;  /* ? */ /* mapped already */
4663     for (i = k + 1; i < fnext; i++) {
4664 //      if (strcmp(fontname[k], fontname[i]) == 0) 
4665       if (fontname[k] != NULL && fontname[i] != NULL &&
4666           strcmp(fontname[k], fontname[i]) == 0) { 
4667 //      if (strcmp(fontname + k * MAXTEXNAME,
4668 //              fontname + i * MAXTEXNAME) == 0) 
4669 /*        strcpy(subfontname[i], fontname[k]); */  /* ??? test ??? */
4670 //        strcpy(subfontname + i * MAXFONTNAME,
4671 //            fontname + k * MAXTEXNAME);       
4672         if (subfontname[i] != NULL) free(subfontname[i]);
4673         subfontname[i] = zstrdup(fontname[k]);
4674         fontproper[i] |= C_DEPENDENT; /* NEW */
4675 /*        if (fontproper[k] & C_RESIDENT)
4676           fontproper |= C_RESIDENT; */  /* 95/July/5 ??? */
4677 /* flag it as dependent - that is, another size of the same thing */
4678 /* following USED to be the way to test: */
4679 /* font k occurs at other size already if fontname[k] == subfontname[k] */
4680 /*        strcpy(subfontname[i], subfontname[k]); */ /* ??? test ??? */
4681 /*        fontproper[i] = fontproper[k];  */   /* ??? test ??? */
4682         fontsubflag[i] = k;     /* point to substitute */
4683         fromfont = fontchar[i];  
4684 //        fromfont = fontchar + MAXCHRS * i;
4685         tofont = fontchar[k]; 
4686 //        tofont = fontchar + MAXCHRS * k;
4687         if (fromfont == NULL) {
4688           sprintf(logline, " BAD fromfont %d ", i);
4689           showline(logline, 1);
4690         }
4691         if (tofont == NULL) {
4692           sprintf(logline, " BAD tofont %d ", k);
4693           showline(logline, 1);
4694         }
4695         for (j = 0; j < MAXCHRS; j++)
4696           if (fromfont[j] != 0) tofont[j] = 1;  /* combine req */
4697       }
4698     }
4699   }
4700 }
4701
4702 /* look up in substitution table what this font maps to */
4703
4704 /* int fontremapsub (char *font) {  */  /* expects lower case fontname  */
4705 /* expects lower case fontname  */
4706 int fontremapsub (char *font)
4707 {
4708   int k;
4709
4710   if (font == NULL) return -1;
4711   for (k = 0; k < ksubst; k++) {
4712 /*    if (strcmp(font, fontsubfrom[k]) == 0)  */
4713 //    if (strcmp(font, fontsubfrom + k * MAXTEXNAME) == 0) 
4714     if (fontsubfrom[k] != NULL &&
4715         strcmp(font, fontsubfrom[k]) == 0) 
4716       return k;
4717   }
4718   return -1;        /* didn't find a substitute */
4719 }
4720
4721 /* WARNING: following writes back into argument */
4722 /* NOT ANYMORE IT DOESN'T - now caller needs to pick up fontsubto[k] */
4723
4724 /* expects lower case fontname  */
4725 int fontremap (char *font)
4726 {
4727   int k;
4728 //  char oldname[MAXFONTNAME];
4729   char oldname[FNAMELEN];
4730 //  char newname[MAXFONTNAME];
4731   char newname[FNAMELEN];
4732
4733   if (font == NULL) return -1;
4734   if ((k = fontremapsub(font)) >= 0)
4735   {
4736 //    strcpy(newname, fontsubto + k * MAXFONTNAME);
4737     strcpy(newname, fontsubto[k]);
4738     if (verboseflag && quietflag == 0 &&
4739 /*      ((fontsubprop[k] & C_REMAPIT) == 0))  */ /* ??? */
4740       ((fontsubprop[k] & C_RESIDENT) == 0)) {
4741 /*      fprintf(stdout, "Substituting %s for %s\n", fontsubto[k], font);*/
4742       strcpy(oldname, font);
4743       sprintf(logline, "Substituting %s for %s\n", newname, oldname);
4744       showline(logline, 1);
4745     }
4746 /*    strcpy(font, fontsubto[k]); */    /* write back into argument */
4747 /*    strcpy(font, fontsubto + k * MAXFONTNAME); */ /* back into argument */
4748 //    strcpy(font, newname);            /* NO! */
4749   }
4750   return k;   /* pointer to substitute */
4751 }
4752
4753 /* need also copy across fontsubprop[k] to fontproper[.] ? */
4754 /* not announce if its just a remap ? */
4755 /* not announce if its just printer resident ? */
4756
4757 /*  see whether this font is being forced to be substituted */
4758 /* expects lower case fontname  */
4759 int forcedsubstitute (char *font)
4760 {
4761   int k;
4762
4763   if (font == NULL) return -1;
4764   for (k = 0; k < ksubst; k++)
4765   {
4766     if ((fontsubprop[k] & C_FORCESUB) != 0 && 
4767 /*    if (((fontsubprop[k] & C_FORCESUB) != 0 || */ /* NO */
4768 /*      (fontsubprop[k] & C_RESIDENT) != 0) &&  *//* 1992/July/4 */
4769 /*      strcmp(font, fontsubfrom[k]) == 0) { */
4770 //      strcmp(font, fontsubfrom + k * MAXTEXNAME) == 0) {
4771         fontsubfrom[k] != NULL &&
4772         strcmp(font, fontsubfrom[k]) == 0) {
4773 /*      if (verboseflag && quietflag == 0)
4774         fprintf(stdout, "Forcing substitute %s for %s\n",
4775           fontsubto[k], font) */
4776 /*      strcpy(font, fontsubto[k]); */  /* later */
4777       return k;   /* pointer to substitute */
4778     }
4779   }
4780   return -1;        /* didn't find a forcing substitution */
4781
4782
4783 /*  is this font synthetic based on substitution table -- 1993/Nov/6 */
4784 /* expects lower case fontname  */
4785 int checksynthetic (char *font)
4786 {
4787   int k;
4788
4789   if (font == NULL) return -1;
4790   for (k = 0; k < ksubst; k++) {
4791     if ((fontsubprop[k] & C_SYNTHETIC) != 0 && 
4792 //      strcmp(font, fontsubfrom + k * MAXTEXNAME) == 0) {
4793         fontsubfrom[k] != NULL &&
4794         strcmp(font, fontsubfrom[k]) == 0) {
4795       return k;   /* pointer to synthetic */
4796     }
4797   }
4798   return -1;
4799
4800
4801 /*  see whether font name is being aliased based on font substitution table */
4802 /* replace aliases with real names */
4803 void replacealias (void)
4804 {
4805   int k, n;
4806 /*  need to have these `near' for verboseflag output ... */
4807 //  char newname[MAXFONTNAME];
4808   char newname[FNAMELEN];
4809 //  char oldname[MAXFONTNAME];
4810   char oldname[FNAMELEN];
4811   
4812   task = "looking for aliases";
4813
4814   for (k = 0; k < fnext; k++) {
4815 //    strcpy(oldname, fontname + k * MAXTEXNAME);
4816     if (fontname[k] != NULL) strcpy(oldname, fontname[k]);
4817     *oldname = '\0';
4818 /*    if ((n = fontremapsub(fontname[k])) >= 0 && */
4819 /*    n is index into font substitution table --- or -1 if not found */
4820     if ((n = fontremapsub(oldname)) >= 0 &&
4821       (fontsubprop[n] & C_ALIASED) != 0) {
4822 //      strcpy(newname, fontsubto + n * MAXFONTNAME);
4823       strcpy(newname, fontsubto[n]);
4824       if (verboseflag && quietflag == 0) {
4825 /*        strcpy(oldname, fontname + k * MAXTEXNAME); */
4826 /*        printf("Using %s for %s\n", fontsubto[n], fontname[k]);  */
4827         sprintf(logline, "Using %s for %s\n", newname, oldname);  
4828         showline(logline, 0);
4829       }
4830 /*      strcpy(fontname[k], fontsubto[n]); */   /* copy real name */
4831 //      strcpy(fontname + k * MAXTEXNAME, newname); /* copy real name */
4832 /*        fontsubto + n * MAXFONTNAME); */  /* copy real name */
4833       if (fontname[k] != NULL) free(fontname[k]);
4834       fontname[k] = zstrdup(newname);
4835     }
4836   }
4837 }
4838
4839 /*  see whether font name is being aliased based on texfonts.map 95/Dec/29 */
4840 /* replace aliases with real names */
4841 void replacetexfontsmap (void)
4842 {
4843   int k;
4844 /*  int n; */
4845   char *s;
4846 //  char newname[MAXFONTNAME];
4847   char newname[FNAMELEN];
4848 //  char oldname[MAXFONTNAME];
4849   char oldname[FNAMELEN];
4850   
4851   task = "looking for aliases";
4852
4853   for (k = 0; k < fnext; k++) {
4854 //    strcpy(oldname, fontname + k * MAXTEXNAME);
4855     if (fontname[k] != NULL) strcpy(oldname, fontname[k]);
4856     else *oldname = '\0';
4857 /*    if ((n = fontremapsub(fontname[k])) >= 0 && */
4858 /*    if ((n = fontremapsub(oldname)) >= 0 && 
4859       (fontsubprop[n] & C_ALIASED) != 0) */
4860     if ((s = alias(oldname)) != NULL) {
4861 /*      strcpy(newname, fontsubto + n * MAXFONTNAME); */
4862       strcpy(newname, s);
4863       if (verboseflag && quietflag == 0) {
4864 /*        strcpy(oldname, fontname + k * MAXTEXNAME); */
4865 /*        printf("Using %s for %s\n", fontsubto[n], fontname[k]);  */
4866         sprintf(logline, "Using %s for %s\n", newname, oldname);  
4867         showline(logline, 0);
4868       }
4869 /*      strcpy(fontname[k], fontsubto[n]); */   /* copy real name */
4870 //      strcpy(fontname + k * MAXTEXNAME, newname);  /* copy real name */
4871 /*        fontsubto + n * MAXFONTNAME); */  /* copy real name */
4872       if (fontname[k] != NULL) free(fontname[k]);
4873       fontname[k] = zstrdup(newname);  /* copy real name */
4874
4875     }
4876   }
4877 }
4878
4879 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
4880
4881 /* returns 0 normally, -1 on EOF, +1 if start of new section (128) */
4882
4883 int readaline (char *line, FILE *input)
4884 {
4885   int c;
4886   char *s=line;
4887
4888   *line = '\0';
4889   c = getc(input); ungetc(c, input);
4890   if (c == EOF) return -1;    /* is first character  -1 ? */
4891   if (c == 128) return +1;    /* is first character 128 ? */
4892   while ((c = getc(input)) != EOF && c != '\r' && c != '\n') *s++ = (char) c;
4893   if (c == '\r') {
4894     c = getc(input);
4895     if (c != '\n') {
4896       ungetc(c, input);
4897       c = '\n';
4898     }
4899   }
4900   *s++ = (char) c;
4901   *s = '\0';
4902 /*  printf("%s", line); */ /* DEBUGGING */
4903   return 0;
4904 }
4905
4906 /*    find MM base file name from PS FontName of base font */
4907 /*    find base font file name */ /* WORK IN PROGRESS !!!! */
4908 /*    only called if bMMShortCut == 0 ??? */
4909 /*    returns -1 if not OK */
4910 /*    picks up PS FontName from subfontname[k] */
4911 /*    puts base font file name in fontname[k] */
4912
4913 /* Could we do this using the new ATMFonts table ??? 2000 July 7 */
4914
4915 int FindMMBaseFile (int k)
4916 {
4917 /*  char FontName[MAXTEXNAME]; */   /* 95/May/25 */
4918 //  char FontName[MAXFONTNAME];   /* 95/July/27 */
4919   char FontName[FNAMELEN];    /* 99/Nov/6 */
4920   char pfbname[FNAMELEN];     /* 95/May/25 */
4921   FILE *mmfile=NULL;
4922   char *s, *sl, *pe;
4923   int c;
4924
4925   *pfbname = '\0';
4926   if (bMMShortCut != 0) {
4927 /*    strcpy (pfbname, fontname + k * MAXTEXNAME); */
4928     return 0;         /* just use first 5 chars + "___" ??? */
4929   }
4930 //  strcpy (FontName, subfontname + k * MAXFONTNAME); 
4931   if (subfontname[k] != NULL) strcpy(FontName, subfontname[k]);
4932   else *FontName = '\0';
4933 #ifdef DEBUG
4934   if (traceflag) {
4935     sprintf(logline, "Trying to find MM base font PS name for %s\n", FontName);
4936     showline(logline, 0);
4937   }
4938 #endif
4939 /*  strcpy (pfbname, fontname + k * MAXTEXNAME); */ /* first guess */
4940   if ((s = strchr(FontName, '_')) != NULL && s > FontName) {  /* 97/June/1 */
4941     if (traceflag) {
4942       sprintf(logline, "Stripping Instance Name %s ", FontName);
4943       showline(logline, 0);
4944     }
4945     *s = '\0';
4946     if (traceflag) {
4947       sprintf(logline, "=> %s\n", FontName);
4948       showline(logline, 0);
4949     }
4950   }
4951 //  PFB file name written back into second argument
4952   mmfile = fopenfont(FontName, pfbname, 1); // in dvispeci.c
4953
4954   if (mmfile != NULL) {
4955     if (traceflag) {
4956       sprintf(logline, "FILE %s ", pfbname);  /* 95/May/27 */
4957       showline(logline, 0);
4958     }
4959     sl = removepath(pfbname);       /* remove file path */
4960     if ((pe = strchr(sl, '.')) == NULL)
4961       pe = sl + strlen(sl);       /* ignore extension */
4962     pe--;
4963     while (*pe == '_') pe--;        /* step back over _ */
4964     pe++;
4965     c = *pe;
4966     *pe = '\0';               /* temporarily terminate */
4967     if (traceflag) {
4968       sprintf(logline, "=> %s\n", sl);  /* 95/May/27 */
4969       showline(logline, 0);
4970     }
4971 //    if (strlen(sl) < MAXTEXNAME)      /* 1995/July/27 */
4972     if (strlen(sl) < FNAMELEN) {
4973 //      strcpy (fontname + k * MAXTEXNAME, sl);
4974       if (fontname[k] != NULL) free(fontname[k]);
4975       fontname[k] = zstrdup(sl);
4976     }
4977     else {
4978       sprintf(logline, "Name too long: %s\n", sl);
4979       showline(logline, 1);
4980     }
4981     if (pe != NULL) *pe = (char) c;     /* restore what was there */
4982 /*    if (bMMShortCut) return 0; */       /* already done */
4983 /*    strcpy (fontname + k * MAXTEXNAME, FileName); */
4984     fclose(mmfile);       /* ?? */
4985 /*    printf("FOUND %s ", FileName); */     /* debugging */
4986     return 0;         /* OK */
4987   }
4988   else {
4989 /*    fprintf(errout, " ERROR: MM base `%s' not found\n", FontName);  */
4990     if (traceflag) {
4991       sprintf(logline, " WARNING: MM base `%s' not found ", FontName);
4992       showline(logline, 1);
4993     }
4994 /*    errcount(0); */       /* 95/May/28 */
4995 /*    just a WARNING: since it drops back to extending with "___" */
4996 /*    assumed to be of form kprg_xyz --- should we check for _ ??? */
4997 /*    if (strchr(pfbname, '_') != NULL) { */
4998 //    strcpy (pfbname, fontname + k * MAXTEXNAME); /* 97/June/1 */
4999     if (fontname[k] != NULL) strcpy (pfbname, fontname[k]); /* 97/June/1 */
5000     else *pfbname = '\0';
5001     if (*(pfbname+4) == '_') {             /* 97/June/1 */
5002       strcpy (pfbname + 5, "___");  /* last three characters */
5003       if (traceflag) {
5004         sprintf(logline, "using %s ", pfbname);
5005         showline(logline, 1);
5006       }
5007 /*      test for existence first ? */
5008 //      strcpy (fontname + k * MAXTEXNAME, pfbname);
5009       if (fontname[k] != NULL) free(fontname[k]);
5010       fontname[k] = zstrdup(pfbname);
5011     }
5012     return -1;            /* NOT ok */
5013   }
5014 }
5015
5016 /* get some compiler error here ??? */
5017 /* dviextra.c(4379) : fatal error C1001: internal compiler error */
5018 /*    (compiler file 'msc3.cpp', line 429) */
5019
5020 /* Called with MM instance font number */
5021 /* Finds corresponding MM base font - or adds it if not found */
5022 /* Adds characters needed by new instance */
5023
5024 /* add the corresponding MM base 94/Dec/6 */
5025 int AddMMBase (int m)
5026 {
5027   int k, i;
5028   char *basewantchrs; /* wanted chars array of MM base font */
5029   char *instwantchrs; /* wanted chars array of MM instance */
5030 /*  char basefontname[MAXTEXNAME]; */       /* 95/May/25 */
5031 /*  char basefilename[MAXFONTNAME]; */      /* 95/May/25 */
5032 //  char psfontname[MAXFONTNAME];       /* 97/June/1 */
5033   char psfontname[FNAMELEN];
5034 //  char psbasename[MAXFONTNAME];       /* 97/June/1 */
5035   char psbasename[FNAMELEN];
5036   char *s;
5037
5038 //  strcpy(psfontname, subfontname + m * MAXFONTNAME);
5039   if (subfontname[m] != NULL) strcpy(psfontname, subfontname[m]);
5040   else *psfontname = '\0';
5041 /*  Truncate MM instance PS FontName if that is what we have 97/June/1 */
5042   if ((s = strchr(psfontname, '_')) != NULL && s > psfontname)
5043   {
5044     *s = '\0';
5045   }
5046 /*  if (bMMShortCut == 0) { 
5047     strcpy (stubfilename, fontname + m * MAXTEXNAME);
5048     (void) FindMMBaseFile (stubfilename, basefilename);
5049     strcpy (subfontname + m * MAXFONTNAME, basefilename);
5050   } */  /* new 95/May/25 ? */
5051 //  instwantchrs = fontchar + MAXCHRS * m;
5052   instwantchrs = fontchar[m];
5053   if (fontchar[m] == NULL) showline(" BAD instwantchrs", 1);
5054 /*  printf("Adding MM base for font %d\n", m); *//* debugging 95/May/25 */
5055 /*  check whether we have already added this MM base font */
5056 /*  for (k = mmbase; k < fnext; k++)  */      /* no longer separate */
5057   for (k = 0; k < fnext; k++) {         /* 95/May/14 */
5058     if ((fontproper[k] & C_MULTIPLE) == 0) continue;
5059 //    strcpy(psbasename, subfontname + k * MAXFONTNAME);
5060     if (subfontname[k] != NULL) strcpy(psbasename, subfontname[k]);
5061     else *psbasename = '\0';
5062 /*  old way check whether matches on first five characters of font file name */
5063 #ifdef DEBUG
5064     if (traceflag) {
5065       sprintf(logline, "COMPARE %s and %s\n", psbasename, psfontname);
5066       showline(logline, 0);
5067     }
5068 #endif
5069     if (bMMShortCut) {      /* assume base name ends in "___" */
5070 //      if (strncmp(fontname + k * MAXTEXNAME, 
5071 //            fontname + m * MAXTEXNAME, 5) != 0) continue; 
5072       if (fontname[k] != NULL && fontname[m] != NULL &&
5073           strncmp(fontname[k], fontname[m], 5) != 0) continue; 
5074     }
5075 /*    else new way check whether matches PS FontName in PSS stub */
5076 /*    else if (strcmp(subfontname + k * MAXFONTNAME, */
5077     else if (strcmp(psbasename, psfontname) != 0) continue;
5078 /*             subfontname + m * MAXFONTNAME) != 0) continue; */
5079 /*    get here if we found a match */
5080 #ifdef DEBUG
5081     if (traceflag) {
5082       sprintf(logline, "Already installed MM base font %s %d\n", psbasename, k);
5083       showline(logline, 0);
5084     }
5085 #endif
5086     if (fontchar[k] == NULL) setupfontchar(k);
5087 //    basewantchrs = fontchar + MAXCHRS * k;  /* 95/May/12 */
5088     basewantchrs = fontchar[k]; /* 95/May/12 */
5089     for (i = 0; i < MAXCHRS; i++)     /* or in the bits */
5090       if (instwantchrs[i] != 0) basewantchrs[i] = 1;
5091     return k;
5092   }   
5093
5094 #ifdef DEBUG
5095   if (traceflag)
5096   {
5097     sprintf(logline, "Need to construct new MM base entry %s\n", psfontname);
5098     showline(logline, 0);
5099   }
5100 #endif
5101
5102 /*  Get here only if MM base font not found, have to add a new MM base font */
5103 /*  We construct MM base font file name from stub PSS file name */
5104 /*  Typically MM base font has same name, but ends in ___ ??? */
5105 //  strcpy(fontname + fnext * MAXTEXNAME, fontname + m * MAXTEXNAME);
5106 //  strcpy(fontname + fnext * MAXTEXNAME + 5, "___");
5107   if (fontname[fnext] != NULL) free(fontname[fnext]);
5108   if (fontname[m] != NULL) {
5109     char buffer[FNAMELEN];
5110     strcpy(buffer, fontname[m]);
5111     strcpy(buffer+5, "___");    /* MM Master ends in ___ */
5112     fontname[fnext] = zstrdup(buffer);
5113   }
5114   else fontname[fnext] = NULL;
5115 /*  if (bMMShortCut == 0) { */ /* copy PS FileName from instance, exists yet ??? */
5116 /*  strcpy(subfontname + fnext * MAXFONTNAME, subfontname + m * MAXFONTNAME); */
5117 #ifdef DEBUG
5118   if (traceflag)
5119   {
5120     sprintf(logline, "New base font with PS FontName %s\n", psfontname);
5121     showline(logline, 0);
5122   }
5123 #endif
5124 //  strcpy(subfontname + fnext * MAXFONTNAME, psfontname);
5125   if (subfontname[fnext] != NULL) free(subfontname[fnext]);
5126   subfontname[fnext] = zstrdup(psfontname);
5127 /*  hope this does not create problems with tests on subfontname ... */
5128 /*  should we call FindMMBaseFile here to fill in fontname[fnext] ? */
5129 /*  or do this later when inserting base font ? */
5130 /*    (void) FindMMBaseFile(fnext); */
5131 /*  } */
5132
5133 /*  if (traceflag) {
5134     strcpy(line, subfontname + fnext * MAXFONTNAME);
5135     printf("Claims FontName is %s\n", line); 
5136   } *//* debugging 95/May/25 */
5137   fontproper[fnext] = C_MULTIPLE;
5138   fontsubflag[fnext] = -1;
5139   if (fontchar[fnext] == NULL) setupfontchar(fnext);
5140 //  basewantchrs = fontchar + MAXCHRS * fnext;  /* 95/May/12 */
5141   basewantchrs = fontchar[fnext]; /* 95/May/12 */
5142   for (i = 0; i < MAXCHRS; i++)       /* just copy, first instance */
5143     basewantchrs[i] = instwantchrs[i];
5144   if (bMMShortCut == 0) {
5145     if (FindMMBaseFile(fnext) != 0) { /* or do later ? */
5146 /*      fprintf(errout, " WARNING: MM base `%s' not found\n", FontName); */
5147     }
5148   }
5149   fnext++;
5150   mmcount++;                  /* how many MM base fonts */
5151   if (fnext >= maxfonts - 1)
5152   {
5153 /*    fprintf(errout, "Too many MM base fonts (%d)\n", fnext - mmbase); */
5154     sprintf(logline, " ERROR: Too many MM base fonts (%d)\n", mmcount);
5155     showline(logline, 1);
5156     errcount(0);
5157     fnext--;
5158   }
5159   return fnext;
5160 }
5161
5162 /* Now add in the base fonts for MM instances - separated out 95/May/12 */
5163 /* Add this to font table *after* base fonts for substitution */
5164 /* Do we get into any problems because of not checking for substitution ? */
5165 /* Not used anymore ? */
5166
5167 /* Old style PSS stubs look like this: */
5168
5169 /* 128, 1, x, x, x, x (length)
5170 %!PS-AdobeFont-1.0 TektonMM_100_LT_564_NO 001.000
5171 /TektonMM_100_LT_564_NO /TektonMM findfont [.63058 0 .36942 0] makeblendedfont
5172 dup /FontName /TektonMM_100_LT_564_NO put
5173 definefont pop
5174 128, 3 */
5175
5176 /* which becomes the following */
5177
5178 /* %!PS-AdobeFont-1.0 TektonMM_100_LT_564_NO 001.000
5179 /zjrg_001 /zjrg____ findfont [.63058 0 .36942 0] makeblendedfont
5180 dup /FontName /zjrg_001 put
5181 definefont pop */
5182
5183 /*  Get PS FontName from PSS stub file and stick in subfontname[k] */
5184 /*  NOTE: in case of PSS stub, this will be the *base font* PS FontName */
5185 /*  Get PS FontName from PFM metric file and stick in subfontname[k] */
5186 /*  NOTE: in case of PFM file, this will be the *instance* PS FontName */
5187
5188 /* Could we do this using the new ATMFonts table ??? 2000 July 7 */
5189
5190 //int AddMMFontName (FILE *input, int k, int pssflag, char *FileName) 
5191 int AddMMFontName (FILE *input, int k, int pssflag, char *FileName, int nlen)
5192 {
5193   int c, m, flag;
5194   char *s;
5195
5196 //  *(subfontname + k * MAXFONTNAME) = '\0';
5197   if (subfontname[k] != NULL) { /* reset in case not found */
5198     free(subfontname[k]);
5199     subfontname[k] = NULL;
5200   }
5201 /*  PSS file case first --- now outdated since ATM NT no longer */
5202   if (pssflag) {    /* read PSS file to extract MM base FontName */
5203     if ((c = getc(input)) != 128) return -1;  /* sanity test */
5204     if ((c = getc(input)) != 1) return -1;    /* sanity test */
5205     for (m = 0; m < 4; m++) (void) getc(input); /* skip over length */
5206     while (readaline(line, input) == 0) {
5207 /*      printf("LINE: %s", line); */  /* debugging 95/May/25 */
5208       if (*line == '%') continue;       /* ignore comments */
5209       if ((s = strstr(line, "findfont")) != NULL)
5210       {
5211         s--;
5212         while (*s <= ' ' && s >= line) *s-- = '\0';
5213         if ((s = strrchr(line, '/')) == NULL) return -1;
5214         s++;
5215 //        strcpy(subfontname + k * MAXFONTNAME, s);
5216         if (subfontname[k] != NULL) free(subfontname[k]);
5217         subfontname[k] = zstrdup(s);
5218                 /* MM base PS FontName *//* if using PSS */
5219 /*        printf("FontName from PSS stub is %s\n", s); */
5220 /*        debugging 95/May/25 */
5221         return 0;
5222       }
5223     }
5224     return -1;
5225   }
5226 /*  PFM file case next - now standard since ATM NT no longer PSS */
5227   else {  /* instanceflag != 0 presumably *//* Read PFM for PS FontName */
5228 //    printf("HEY! sizeof(FileName) = %d!\n", sizeof(FileName));  // 4 why ???
5229 /*    read PFM file to get instance PS FontName */
5230 //    flag = NamesFromPFM(input, NULL, 0, line, MAXFONTNAME, FileName);
5231 //    flag = NamesFromPFM(input, NULL, 0, line, sizeof(FileName), FileName);
5232     flag = NamesFromPFM(input, NULL, 0, line, nlen, FileName);
5233 /*    do we really want to test for that underscore ??? */
5234     if (flag != 0 && strchr(line, '_') != NULL) { 
5235 //      strcpy(subfontname + k * MAXFONTNAME, line);
5236       if (subfontname[k] != NULL) free(subfontname[k]);
5237       subfontname[k] = zstrdup(line);
5238 #ifdef DEBUG
5239       if (traceflag) {
5240         sprintf(logline, "MM PS FontName %s\n", line);
5241         showline(logline, 0);
5242       }
5243 #endif
5244 /*  MM base PS FontName */ /* NO: now it is the instance PS FontName */
5245       return 0;
5246     }
5247     else {  /* NamesFromPFM failed or no _ in name returned */
5248 /*      this message now comes up for missing fonts ... */
5249       sprintf(logline,
5250           " Not a PFM file for a MM instance (%s) ", line);
5251       showline(logline, 1);
5252     }
5253     return -1;
5254   }
5255 }
5256
5257 int notvalidPSS (int pssflag) { /* PSS or PFM file */
5258   sprintf(logline, " ERROR: not a valid %s file ",
5259        pssflag ? "MM PS Stub" : "PFM");
5260   showline(logline, 1);
5261   return -1;
5262 }
5263
5264 /* This tries to open font files to see which actually exist */
5265 /* also checks forced substitution flags */ /* should check resident ? */
5266
5267 /* we are assuming this happens *before* we start adding MM base fonts */
5268
5269 void checksubstitute (void)
5270 {
5271   FILE *fp_in;
5272   int k, j, i, n, baseexist, wipeflag;
5273 //  char fontnamek[MAXTEXNAME];
5274   char fontnamek[FNAMELEN];
5275 /*  char subfontnamek[MAXTEXNAME]; */
5276 //  char subfontnamek[MAXFONTNAME];         /* fix 1995/July/15 */
5277   char subfontnamek[FNAMELEN];          /* fix 1995/July/15 */
5278 /*  int proper; */
5279 //  char masterfontname[MAXFONTNAME];       /* saved 1995/July/15 */
5280   char masterfontname[FNAMELEN];        /* saved 1995/July/15 */
5281   char *fromfont;
5282   char *tofont;
5283
5284   task = "looking for substitutions";
5285   for (k = 0; k < fnext; k++) {
5286     wipeflag = 0;               /* 1995/July/15 */
5287 /*    proper = fontproper[k]; */
5288 /*    printf("k %d proper ", k); */       /* debugging */
5289 /*    don't bother if font unused (?) */
5290     if ((fontproper[k] & C_UNUSED) != 0) continue;  /* ??? */
5291 /*    don't bother if this font is another size of an existing one */
5292     if ((fontproper[k] & C_DEPENDENT) != 0) continue; /* NEW */
5293 /*    if (strcmp(fontname[k], subfontname[k]) == 0) continue; */ /* size ? */
5294 /*    if forced substitution, pretend couldn't open file */
5295 //    strcpy (fontnamek, fontname + k * MAXTEXNAME);
5296     if (fontname[k] != NULL) strcpy(fontnamek, fontname[k]);
5297     else *fontnamek = '\0';
5298
5299 /*    if ((n = forcedsubstitute(fontname[k])) >= 0 || */
5300     if ((n = forcedsubstitute(fontnamek)) >= 0 ||
5301 /*      (fp_in = OpenFont(fontname[k])) == NULL) { */
5302       (fp_in = OpenFont(fontnamek, 1)) == NULL) {
5303 /*      printf("FORCED %s %s\n", subfontname[k], fontname[k]); */
5304 /*      strcpy(subfontname[k], fontname[k]); */ /* copy real name */
5305 /* the following is a hack to deal with conflicing use of subfontname */
5306 /* both for substitution and for MM PS FontName ... */
5307 /* attempt to allow remapping (without name change) */
5308 //      if (*(subfontname + k * MAXFONTNAME) != '\0')   /* 95/July/15 */
5309       if (subfontname[k] != NULL) { 
5310 /*        if (fontproper[k] & C_MULTIPLE) { } */
5311         wipeflag = 1;             
5312 //        strcpy (masterfontname, subfontname + k * MAXFONTNAME);
5313         strcpy(masterfontname, subfontname[k]);
5314         if (traceflag) {              /* debugging */
5315           sprintf(logline, "Wiping out %s with %s (%d)\n",
5316                masterfontname, fontnamek, fontproper[k]);
5317           showline(logline, 0);
5318         }
5319       }
5320 //      strcpy(subfontname + k * MAXFONTNAME,
5321 //        fontname + k * MAXTEXNAME);     
5322       if (subfontname[k] != NULL) free(subfontname[k]);
5323
5324       if (fontname[k] != NULL)
5325         subfontname[k] = zstrdup(fontname[k]);  /* copy real name */
5326       else subfontname[k] = NULL;
5327
5328 /* in forced substitution we actually already know n ... */
5329 /* WARNING: fontremap writes new name back into given argument ... */
5330 /*      so need to pass actual  argument */
5331 /*      if ((n = fontremap(subfontname[k])) >= 0) { */
5332 //      if ((n = fontremap(subfontname + k * MAXFONTNAME)) >= 0) 
5333       if ((n = fontremap(subfontname[k])) >= 0) {
5334         if (subfontname[k] != NULL) free(subfontname[k]);
5335         subfontname[k] = zstrdup(fontsubto[n]);   // 99/Nov/17
5336 /*        fontproper[k] = fontsubprop[n];     */
5337         fontproper[k] |= fontsubprop[n];  /* check */
5338         if ((fontproper[k] & C_REMAPIT) == 0)
5339           fontsubflag[k] = n;       /* mark it */
5340 /*  for now anything non-neg - later get proper pointer */
5341         else { /* remapped ? C_REMAPIT */
5342 /*          strcpy(fontvector[k], fontsubvec[n]); */ /* 94/Feb/2 */
5343 //          strcpy(fontvector[k], fontsubvec + n * MAXVECNAME);
5344 //          strcpy(fontvector + k * MAXVECNAME, fontsubvec + n * MAXVECNAME);
5345           if (fontvector[k] != NULL) free(fontvector[k]);
5346 //          fontvector[k] = zstrdup(fontsubvec + n * MAXVECNAME);
5347           fontvector[k] = zstrdup(fontsubvec[n]);
5348 /*          printf("COPYING %s TO %d from %d\n", fontvector[k], k, n); */
5349 /* Lets check the encoding vector at this point ! 1995/July/15 */
5350           if (bCheckEncoding)         /* 1995/Aug/15 */
5351             checkremapencode(k, fontnamek); /* 1995/July/15 */
5352         }
5353         if ((fontproper[k] & C_FORCESUB) != 0 &&  /* substitute ? */
5354           (fontproper[k] & C_RESIDENT) == 0) {  /* not resident ? */
5355 //          strcpy(subfontnamek, subfontname + k * MAXFONTNAME);
5356           if (subfontname[k] != NULL)
5357             strcpy(subfontnamek, subfontname[k]);
5358           else *subfontnamek = '\0';
5359 /*          if ((fp_in = OpenFont(subfontname[k])) == NULL) { */
5360           if ((fp_in = OpenFont(subfontnamek, 1)) == NULL) {
5361             sprintf(logline, 
5362              "Font %s (substituted for %s) could not be found\n",
5363 /*              subfontname[k], fontname[k]); */
5364               subfontnamek, fontnamek);
5365             showline(logline, 1);
5366           }
5367           else {
5368             if (traceflag) {
5369               sprintf(logline, "Substituting * %s for %s\n", 
5370                  subfontnamek, fontnamek);/* debug 95/Mar/31 */
5371               showline(logline, 0);
5372             }
5373             fclose(fp_in);
5374           }
5375         }
5376       }
5377       else {                /* no substitute found */
5378         fontproper[k] |= C_MISSING;   /* new */
5379         sprintf(logline, 
5380           " WARNING: Can't find font %s (and no substitute)\n", 
5381 /*            fontname[k]);  */
5382             fontnamek);
5383         showline(logline, 1);
5384         errcount(0);
5385       }
5386       if (wipeflag) {           /* a hack 1995/July/15 */
5387 //        strcpy(subfontname + k * MAXFONTNAME, masterfontname);
5388         if (subfontname[k] != NULL) free(subfontname[k]);
5389         subfontname[k] = zstrdup(masterfontname);
5390         if (traceflag) {          /* debugging */
5391           sprintf(logline, "Restoring %s (%d)\n", masterfontname, fontproper[k]);
5392           showline(logline, 0);
5393         }
5394 /*        fontproper[k] = C_MULTIPLE; */ /* | C_REMAPIT */
5395 /*        fontproper[k] = C_MULTIPLE | C_REMAPIT; */  /* ??? */
5396         wipeflag = 0;
5397       }
5398     }   /* end of forced substitute or font file not found */
5399     else {  /* font file *does* exist */
5400       if (instanceflag != 0) {
5401 /*        this is an instance of an MM font */
5402         fontproper[k] |= C_INSTANCE;
5403 /*        subfontname is MM *instance* FontName, not MM base */
5404         fontproper[k] |= C_NOTBASE; 
5405 /*        if (AddMMFontName(fp_in, k, pssflag) != 0) *//* get PS FontName */
5406         if (AddMMFontName(fp_in, k, pssflag,
5407                   fontnamek, sizeof(fontnamek)) != 0) { /* FNAMELEN */
5408           notvalidPSS(pssflag); /* specify which PSS file ? */
5409           sprintf(logline, "`%s' ", fontnamek);
5410           showline(logline, 0);
5411         }
5412         AddMMBase(k);   /* add corresponding MM base */
5413       }
5414 /*      fclose(fp_in); */     /* quitely close it again for now ! */
5415       if (pssflag != 0) {     /* note that MM instance 94/Dec/6 */
5416         fontproper[k] |= C_INSTANCE;
5417 /*        subfontname is MM *base* FontName, not MM instance */
5418 /*        if (bMMShortCut == 0) { */ /* 95/May/25 */
5419 /*        if (AddMMFontName(fp_in, k, pssflag) != 0) */
5420         if (AddMMFontName(fp_in, k, pssflag,     /* get PS FontName */
5421                   fontnamek, sizeof(fontnamek)) != 0) { /* FNAMLEN */
5422           notvalidPSS(pssflag); /* specify which PSS file ? */
5423           sprintf(logline, "`%s' ", fontnamek);
5424           showline(logline, 0);
5425         }
5426 /*        don't add it now ? */
5427 /*        may need to stick in base for subst - so things will get mixed up */
5428 /*        if (bMMNewFlag) */
5429         AddMMBase(k);   /* add corresponding MM base */
5430       }
5431       fclose(fp_in);        /* quitely close it again for now ! */
5432       if (syntheticsexist) {        /* 1993/Nov/6 */
5433 /*        if (checksynthetic(fontname[k]) >= 0) { */  /* 1993/Nov/6 */
5434         if (checksynthetic(fontnamek) >= 0) { /* 1993/Nov/6 */
5435 /*          printf(" SYNTHETIC "); */ /* DEBUGGING */
5436           fontproper[k] |= C_SYNTHETIC;
5437         }
5438       }
5439     }
5440   } /* end of for (k = 0; k < fnext; k++) loop */
5441
5442   task = "checking whether base font exists";
5443   for (k = 0; k < fnext; k++) {
5444     if (fontsubflag[k] >= 0) {
5445       baseexist = 0;
5446       if ((fontproper[k] & C_RESIDENT) != 0) baseexist = 1;  /* ? */
5447       else if ((fontproper[k] & C_REMAPIT) != 0) baseexist = 1; 
5448 /*      else if ((fontproper[k] & C_ALIASED) != 0) baseexist = 1;  */
5449       else {
5450         for (i = 0; i < fnext; i++) {
5451           if (i == k) continue; /* ignore if same */
5452 /*          if (strcmp(fontname[i], subfontname[k]) == 0) { */
5453           if (fontname[i] != NULL && subfontname[k] != NULL &&
5454               strcmp(fontname[i], subfontname[k]) == 0) { 
5455 //          if (strcmp(fontname + i * MAXTEXNAME,
5456 //                subfontname + k * MAXFONTNAME) == 0)
5457             fontsubflag[k] = i; baseexist = -1; /* base found */
5458 //            fromfont = fontchar + MAXCHRS * k;
5459             fromfont = fontchar[k];  
5460 //            tofont = fontchar + MAXCHRS * i;
5461             tofont = fontchar[i]; 
5462             if (fromfont == NULL) {
5463               sprintf(logline, " BAD fromfont %d ", k);
5464               showline(logline, 1);
5465             }
5466             if (tofont == NULL) {
5467               sprintf(logline, " BAD tofont %d ", i);
5468               showline(logline, 1);
5469             }
5470             for (j = 0; j < MAXCHRS; j++) /* or in char req */
5471               if (fromfont[j] != 0) tofont[j] = 1;
5472             break;
5473           }
5474         }
5475       }
5476       if (baseexist == 0) { /* base font does not exist - create it */
5477         task = "adding in base font"; 
5478         if (fnext >= maxfonts - 1) {  /* 1994/May/21 */
5479           sprintf(logline, 
5480              "Too many base fonts and substitutions (%d)\n", fnext);
5481           showline(logline, 1);
5482           errcount(0);
5483           fnext--;
5484         }
5485         fontsubflag[k] = fnext;
5486 /*        strcpy(fontname[fnext], subfontname[k]); */ /* ??? */
5487 //        strcpy(fontname + fnext * MAXTEXNAME,
5488 //          subfontname + k * MAXFONTNAME); 
5489         if (fontname[fnext] != NULL) free(fontname[fnext]);
5490         if (subfontname[k] != NULL)
5491           fontname[fnext] = zstrdup(subfontname[k]);
5492         else fontname[fnext] = NULL;
5493 //        strcpy(subfontname + fnext * MAXTEXNAME, "");
5494         if (subfontname[fnext] != NULL) {
5495           free(subfontname[fnext]);
5496           subfontname[fnext] = NULL;
5497         }   /* 95/Mar/31 --- make clean for S output */
5498
5499 /* following may have been exposed by fixing bug in previous comment line .. */
5500         fontproper[fnext] = fontproper[k];  /* 0 ??? unmask problem ? */
5501 /*        if ((fontproper[fnext] & C_REMAPIT) != 0) { 
5502           strcpy(fontvector[fnext], fontsubvec[k]);
5503         } */
5504         fontsubflag[fnext] = -1;
5505 /*        following for debugging only: */
5506 /*        if (fontproper[k] != 0) 
5507           printf("%d <= %d proper %d\n", fnext, k, fontproper[k]); */
5508         if (fontchar[fnext] == NULL) setupfontchar(fnext); // 2000/Apr/4
5509
5510 //        fromfont = fontchar + MAXCHRS * k;
5511         fromfont = fontchar[k]; 
5512 //        tofont = fontchar + MAXCHRS * fnext;
5513         tofont = fontchar[fnext]; 
5514         if (fromfont == NULL) {
5515           sprintf(logline, " BAD fromfont %d ", k);
5516           showline(logline, 1);
5517         }
5518         if (tofont == NULL) {
5519           sprintf(logline, " BAD tofont %d ", fnext);
5520           showline(logline, 1);
5521         }
5522 /*    copy across to base font those chars used in font substituted for */
5523         for (j = 0; j < MAXCHRS; j++) tofont[j] = fromfont[j];
5524 /*        for (j = 0; j < MAXCHRS; j++) { 
5525           if (tofont[j]) printf("USING %d ", j);
5526         } */ /* debug 95/Mar/31 */
5527
5528         fnext++;
5529 /*        mmbase = fnext; *//* update start of MM base fonts 95/Mar/31 */
5530       }
5531     }
5532   }
5533 }
5534
5535 /* Font substitution file is first searched for in dvi directory */
5536 /* then in default substitution file directory */
5537 /* now pass in subfile as argument so we can read more than one 1994/Feb/4 */
5538
5539 /* FILE *OpenFontsub(void) {  */
5540 FILE *OpenFontsub (char *subfile)
5541 {
5542   FILE *input;
5543
5544   if (strcmp(subfile, "") == 0) return NULL;  /* 1994/Feb/4 */
5545
5546 /*  printf("FONTSUBREST %s\n", subfile);  */
5547
5548 /*  if FONTSUBREST contains a path, use it directly - no other trials */
5549   if (strpbrk(subfile, "\\/:") != NULL) {
5550     strcpy(fontsubfile, subfile); 
5551     extension(fontsubfile, "sub"); 
5552 /*    printf("FONTSUBFILE %s\n", fontsubfile);  */
5553     return(fopen(fontsubfile, "r"));
5554   }
5555
5556 /*  if not fully qualified name, try in DVI file directory */
5557   if (dvipath != NULL) strcpy(fontsubfile, dvipath);
5558   else strcpy(fontsubfile, "");
5559 /*  if (strcmp(fontsubfile, "") != 0)
5560     strcat(fontsubfile, "\\");
5561   strcat(fontsubfile, subfile); */
5562   makefilename(fontsubfile, subfile);   /* 1992/Nov/28 */
5563   extension(fontsubfile, "sub");
5564 /*  printf("FONTSUBFILE %s\n", fontsubfile);   */
5565   if ((input = fopen(fontsubfile, "r")) != NULL) return input;
5566
5567 /*  try in specified font substitution `path' */
5568   strcpy(fontsubfile, fontsubpath);
5569 /*  strcat(fontsubfile, "\\");
5570   strcat(fontsubfile, subfile); */
5571   makefilename(fontsubfile, subfile);   /* 1992/Nov/28 */
5572   extension(fontsubfile, "sub");  
5573 /*  printf("FONTSUBFILE %s\n", fontsubfile);  */
5574   if ((input = fopen(fontsubfile, "r")) != NULL) return input;
5575
5576 /*  try in SUBDIRECTORY of font substitution `path' *//* 1992/Nov/28 */
5577   strcpy(fontsubfile, fontsubpath);
5578 /*  strcat(fontsubfile, "\\");
5579   strcat(fontsubfile, "sub\\"); */
5580   makefilename(fontsubfile, "sub\\");   /* "sub" sundirectory */
5581   strcat(fontsubfile, subfile);
5582   extension(fontsubfile, "sub");    
5583 /*  printf("FONTSUBFILE %s\n", fontsubfile);  */
5584   if ((input = fopen(fontsubfile, "r")) != NULL) return input;
5585
5586 /*  try in current directory */       /* 1992/Dec/8 */
5587   *fontsubfile = '\0';          /* strcpy(fontsubfile, ""); */
5588   makefilename(fontsubfile, subfile);   /*  */
5589   extension(fontsubfile, "sub");    
5590 /*  printf("FONTSUBFILE %s\n", fontsubfile);  */
5591   if ((input = fopen(fontsubfile, "r")) != NULL) return input;
5592
5593   return NULL;
5594 }
5595
5596 /* int charneeded(char wantchrs[]) {  
5597   int k;
5598   for (k = 0; k < fontchrs; k++)  if (wantchrs[k] != 0) return -1;
5599   return 0;
5600 } */
5601
5602 /* see whether font actually used */
5603 int charneeded (char *wantchrs)
5604 {
5605   int k;
5606   if (wantchrs == NULL) return 0;
5607 /*  test in decreasing order of expected use */
5608 //  for (k = 0; k < fontchrs; k++)  if (wantchrs[k] != 0) return -1;
5609   for (k = 64; k < 128; k++) if (wantchrs[k]) return -1;
5610   for (k = 32; k < 64; k++) if (wantchrs[k]) return -1;
5611   for (k = 0; k < 32; k++) if (wantchrs[k]) return -1;
5612   for (k = 160; k < fontchrs; k++) if (wantchrs[k]) return 1; /* G2 */
5613   for (k = 128; k < 160; k++) if (wantchrs[k]) return 1;  /* C2 */
5614   return 0;
5615 }
5616
5617 /* read font substitution table */  /* returns non-zero if success */
5618
5619 /* return value not used ? */
5620 int GetSubstitutes (void)
5621 {
5622   FILE *input;
5623   char nextfontsub[FNAMELEN];     /* need for multi sub files */
5624   int k, flag=0;              /* 1994/Feb/5 */
5625   char *s, *sc, *sl;              /* 1994/Feb/5 */
5626
5627   ksubst = 0;             /* reset table 1994/Feb/4 */
5628 /*  note this may modify the command line, but that is not reused ... */
5629   for (k = 0; k < subfontfileindex; k++) {  /* 1994/Feb/8 */
5630 /*    s = fontsubrest; */
5631     s = subfontfile[k];           /* 1994/Feb/8 */
5632     while (s != NULL) {
5633       if ((sc = strchr(s, ',')) != NULL) *sc = '\0';
5634 /*      if ((input = OpenFontsub()) != NULL) { */
5635 /*      input = OpenFontsub(fontsubrest); */
5636       strcpy(nextfontsub, s);
5637 /*      if ((input = OpenFontsub(s)) != NULL) { */
5638       if ((input = OpenFontsub(nextfontsub)) != NULL)
5639       {
5640 /*        if (traceflag)
5641           printf("Reading %s\n", nextfontsub); */ /* debugging */
5642         readsubstitutes(input);   /* read font substitution file */
5643         fclose(input);                /* 1994/Feb/4 */
5644         flag++;
5645 /*        if (traceflag) showsubtable(stdout); */ /* an experiment */ 
5646 /*        return -1; */         /* OK, specified file worked */
5647       }
5648       else
5649       {
5650         sl = removepath(fontsubfile);
5651 /*        fprintf(errout, "WARNING: Can't find font subst file: "); */
5652         sprintf(logline, " WARNING: Can't find %s subst file %s\n",
5653              "font", sl);
5654         showline(logline, 1);
5655         perrormod (sl);
5656 /*        putc('\n', errout); */
5657         errcount(0);
5658       }
5659       if (sc != NULL) s = sc+1; /* can't use strtok ... */
5660       else s = NULL;
5661     }
5662   }
5663
5664 /*  else {  */
5665   if (flag == 0) {      /* if no substitution files specified */
5666 /*    substitute = 0;  */ /* NO: still have built in table ... */
5667 /*    fprintf(errout, "WARNING: Can't find font substitution file\n"); */
5668 /*    perrormod(fontsubfile);  */
5669 /*    perrormod(removepath(fontsubfile)); */      /* 1992/Nov/28 */
5670 /*    errcount(0);  */
5671 /*  then try standard substitution file */
5672 /*    if (strcmp(fontsubrest, "standard") == 0) return 0; *//* failed */
5673 /*    if (strcmp(fontsubrest, "standard") != 0) { */ /* 1994/Feb/10 */
5674 /*      strcpy(fontsubrest, "standard"); */
5675 /*      if((input = OpenFontsub()) != NULL) { */
5676       if((input = OpenFontsub("standard")) != NULL)
5677       {
5678         readsubstitutes(input);
5679         fclose(input);                /* 1994/Feb/4 */
5680 /*        if (traceflag) showsubtable(stdout); */ /* an experiment */ 
5681 /*        return -1; */         /* OK, standard file worked */
5682         flag++;
5683       }
5684       else
5685       {
5686         sl = removepath(fontsubfile);
5687 /*        substitute = 0;  */ /* NO: still have built in table ? */
5688         sprintf(logline, " WARNING: Can't find %s subst file %s\n",
5689             "standard", sl);
5690         showline(logline, 1);
5691 /*        perrormod(fontsubfile);  */
5692         perrormod(sl);    /* 1992/Nov/28 */
5693 //        errcount(0);
5694       }
5695 /*    }  */ /* if strcmp fontsubrest standard removed 1994/Feb/10 */
5696 /*    return 0;  */ /* No success ! */
5697   }
5698 /*  if (traceflag) showsubtable(stdout); */ /* an experiment */ 
5699   if (showsubflag)
5700   {
5701     showsubtable(); /* an experiment */
5702 //    if (logfileflag) showsubtable(logfile);
5703   }
5704
5705   return flag;  /* non zero if some substitution table has been read */
5706 }
5707
5708 /* separated out 94/Oct/5 */
5709 int markunusedfonts0 (void)
5710 {
5711   int k, unused=0;
5712
5713 /*  fontproper[k] &= ~C_UNUSED; */
5714   for (k = 0; k < fnext; k++)
5715   {
5716 /*    if (charneeded(fontchar[k]) == 0)  */
5717 //    if (fontproper[k] | C_MULTIPLE) continue; /* for now 94/Dec/6 ??? */
5718     if (fontproper[k] & C_MULTIPLE) continue; /* fixed 2000 July 4 */
5719 //    if (charneeded(fontchar + MAXCHRS * k) == 0) 
5720     if (charneeded(fontchar[k]) == 0) {
5721       fontproper[k] |= C_UNUSED;
5722       unused++;
5723     }
5724   }
5725   return unused;
5726 }
5727
5728 /* following called from dvipsone.c before calling extract itself */
5729 /* task = "checking for duplicate & substitutions"; */
5730
5731 /* get font tables straightened out first */
5732 void preextract (void)
5733 {
5734   int k;
5735 /*  FILE *input; */
5736 //  char fontnamek[MAXTEXNAME];
5737   char fontnamek[FNAMELEN];
5738 //  char subfontnamek[MAXTEXNAME];
5739   char subfontnamek[FNAMELEN];
5740
5741 /*  if (fnext == 0) return; */      /* no fonts - nothing to do ??? */
5742 /*  mmbase = fnext; */          /* start of MM base fonts if any */
5743   mmcount = 0;            /* number of MM base fonts added */
5744
5745   chrs = -1;
5746 /*  Do we want to read substitution table if already forced all reside ? */
5747 /*  YES: need to get PS FontNames if possible etc */
5748 /*  following moved to dvipsone.c 95/Oct/15 */
5749 /*  if (substituteflag) (void) GetSubstitutes(); */ 
5750 /*  if (GetSubstitutes() < 0) fprintf(errout, " Can't get substitutes"); */
5751   if (fnext == 0) return;       /* moved down here 95/May/8 */
5752
5753 /*  replace aliased names right away based on substitution table */
5754   if (aliasesexist) replacealias(); /* replace aliased names right away */
5755
5756 /*  replace aliased names right away based on texfonts.map 1995/Dec/29 */
5757   if (bForceFontsMap) replacetexfontsmap(); /* 1995/Dec/29 */
5758
5759   flagduplicates(); /* look for same font at different magnifications */
5760 /*  mark unused fonts here */
5761 /*  markunusedfonts0();  */ /* this was before 94/Oct/5 - problem ? */
5762
5763   if (substituteflag)   // try to open fonts and 
5764     checksubstitute();  // work out which fonts will be substituted for 
5765
5766 /*  mmbase = fnext; */      /* update start of MM base fonts 95/Mar/31 ??? */
5767 /*  if (bMMNewFlag == 0) AddInBaseFonts();  */ /* old way  95/May/12 */
5768 /*  mark unused fonts here ? */ /* after fonts in different sizes combined */
5769   markunusedfonts0();   /* new place on 94/Oct/5 */
5770
5771 /*  Deal with situtation where all fonts considered resident */
5772 /*  moved down here 1992/July/4 */  /* do this LAST */
5773   if (forcereside != 0)
5774   {
5775     for (k = 0; k < fnext; k++)
5776     {
5777 /*      debugging output 95/Sep/16 */
5778 /*      if (fontsubflag[k] < 0) { */      /* 1992/July/4 */
5779 /*  Don't mark fonts substituted for as resident */
5780 /*  Don't mark MM font instances resident.  But, don't know base FontName ? */
5781 /*      if (fontsubflag[k] < 0) { */
5782       if (fontsubflag[k] < 0 &&
5783         (fontproper[k] & C_INSTANCE) == 0)  {   /* 1995/Sep/16 */
5784         fontproper[k] |= C_RESIDENT; 
5785 /*        fontproper[k] |= C_FORCESUB; */
5786       }
5787 /* Try and get the real PS FontName */ /* Maybe do earlier ??? */
5788 /* Avoid repetition ??? - don't do if C_DEPENDENT flag is on ??? */
5789 /* Don't mess with it if a substitute has already been found in table ??? */
5790 /* Don't do if C_FORCESUB is on ??? */
5791 /*      if (strcmp(subfontname[k], fontname[k]) == 0)   */
5792 /*      if ((fontproper[k] & C_DEPENDENT) == 0 &&
5793         (fontproper[k] & C_FORCESUB) == 0) */
5794 /*      if ((fontproper[k] & C_DEPENDENT) == 0) { */
5795 /* In case of font instance, don't want to overwrite MM base name */
5796 /* Also, don't really need this for MM base, since already done ... */
5797       if ((fontproper[k] & C_DEPENDENT) == 0 &&
5798         (fontproper[k] & C_INSTANCE) == 0) {    /* 1995/Sep/16 */
5799 //        strcpy (fontnamek, fontname + k * MAXTEXNAME);
5800         if (fontname[k] != NULL) strcpy(fontnamek, fontname[k]);
5801         else *fontnamek = '\0';
5802 //        strcpy (subfontnamek, subfontname + k * MAXTEXNAME);
5803         if (subfontname[k] != NULL) strcpy(subfontnamek, subfontname[k]);
5804         else *subfontnamek = '\0';
5805 #ifdef DEBUG
5806         if (traceflag)
5807         {
5808           sprintf(logline, "%d %s %s %d\n", k,  fontnamek, subfontnamek,
5809             fontproper[k]);   /* debugging */
5810           showline(logline, 0);
5811         }
5812 #endif
5813 /*        WARNING: FindFontName writes back into second argument ! */
5814 /*        FindFontName(fontname[k], subfontname[k]);*//* 1993/Sep/30 */
5815 //        FindFontName(fontnamek, subfontnamek, MAXFONTNAME); /* 1994/Feb/2 */
5816         FindFontName(fontnamek, subfontnamek, sizeof(subfontnamek)); /* FNAMELEN */
5817 /*        printf("%d %s %s %d\n", k, fontnamek, subfontnamek,
5818             fontproper[k]); */  /* debugging */
5819 /* need to copy back result 1994/Feb/3 */
5820 //        strcpy(subfontname + k * MAXTEXNAME, subfontnamek);
5821         if (subfontname[k] != NULL) free(subfontname[k]);
5822         subfontname[k] = zstrdup(subfontnamek);
5823       }
5824     }
5825   }
5826 }
5827
5828 /* following contains kludgy test to avoid repeating vector */
5829
5830 void constructvectors(FILE *fp_out)
5831 {
5832   int k, i, flag;
5833
5834 /*  maybe nothing to do here if just need ansinew due to `-X' flag */
5835 /*  we should already have the ansinew vector dumped out */
5836
5837   writedvistart(fp_out);        /* 93/Sep/30 */
5838   for (k=0; k < fnext; k++)
5839   {
5840     if ((fontproper[k] & C_REMAPIT) != 0 &&
5841         (fontproper[k] & C_RESIDENT) != 0)
5842     {
5843       flag = 0;
5844       for (i = 0; i < k; i ++)
5845       {
5846         if ((fontproper[i] & C_REMAPIT) != 0 &&
5847             (fontproper[i] & C_RESIDENT) != 0 &&
5848 /*          strcmp(fontvector + i * MAXVECNAME, fontvector + k * MAXVECNAME) == 0) */
5849             fontvector[i] != NULL &&
5850             fontvector[k] != NULL &&
5851             strcmp(fontvector[i], fontvector[k]) == 0)
5852             {
5853               flag = 1; break;
5854             }
5855       }
5856       if (flag == 0) {
5857 //        readencoding(fontvector + k * MAXVECNAME);
5858         readencoding(fontvector[k]);
5859 //        writevector(fp_out, fontvector[k], MAXCHRS);
5860 //        writevector(fp_out, fontvector + k * MAXVECNAME, MAXCHRS);
5861         writevector(fp_out, fontvector[k], MAXCHRS);
5862       }
5863     }
5864   }
5865 /*  fprintf(fp_out, "%s\n", textext); */  /* for text fonts */
5866 /*  fprintf(fp_out, "%s\n", textype); */  /* for typewriter fonts */
5867
5868   writedviend(fp_out);        /* 1992/Nov/17 */
5869 }
5870
5871 /* Check whether font itself, or its base font are resident */
5872
5873 int fontreside (int f)              /* 1995/July/5 */
5874 {
5875   int k;
5876   if ((fontproper[f] & C_RESIDENT) != 0) return 1;
5877   if ((fontproper[f] & C_DEPENDENT) != 0) {
5878     k = fontsubflag[f];
5879     if (k >= 0) {
5880       if ((fontproper[k] & C_RESIDENT) != 0) return 1;
5881     }
5882   }
5883   return 0;
5884 }
5885
5886 /* suppress above remapped font is not resident ? */
5887
5888 /* f is always the short font number */
5889 /* fn is the internal font number if bShortFont == 0 || bUseInternal != 0 */
5890 /* fn is the short font number if bShortFont != 0 && bUseInternal == 0 */
5891
5892 void dofont (FILE *fp_out, int f, int fn)
5893 {
5894 //  char fname[MAXFONTNAME];
5895   char fname[FNAMELEN];
5896   int n;
5897   int property;
5898
5899   if (f < 0 || f >= maxfonts) {       /* 93/May/23 */
5900     sprintf(logline, "Bad font index %d\n", f); /* debugging */
5901     showline(logline, 1);
5902 /*    should we skip it in this case to avoid access errors ? */
5903   }
5904
5905   property = fontproper[f];         /* 97/June/1 */
5906 /*  if (traceflag)
5907     printf("font %d fontname %s subfontname %s fontsubflag %d\n",
5908       f, fontname[f], subfontname[f], fontsubflag[f]); */
5909 //  strcpy(fname, fontname + f * MAXTEXNAME);
5910   if (fontname[f] != NULL) strcpy(fname, fontname[f]);
5911   else *fname = '\0';
5912
5913 /*  if (strcmp(subfontname[f], "") == 0) { */
5914 //  if (*(subfontname + f * MAXFONTNAME) == '\0') /* 1994/Feb/2 */
5915   if (subfontname[f] == NULL) {
5916 /*    strcpy(fname, fontname[f]); */
5917 /*    strcpy(fname, fontname + f * MAXTEXNAME); */
5918   }
5919   else {          /* i.e. subfontname[f] is not empty */
5920 /*    strcpy(fname, fontname[f]); */        /* if nothing else */
5921 /*    strcpy(fname, fontname + f * MAXTEXNAME); */  /* if nothing else */
5922     if ((property & C_DEPENDENT) != 0) {    /* NEW */
5923 /*      if (strcmp(fontname[f], subfontname[f]) == 0) {  */
5924 /*      if this font already used earlier at other size */
5925       n = fontsubflag[f];
5926 #ifdef DEBUG
5927       sprintf(logline, "%d %s (%d)", f, fname, n); /* debugging */
5928       showline(logline, 0);
5929 //      sprintf(logline, "%s", (subfontname + f * MAXFONTNAME));
5930       sprintf(logline, "%s", subfontname[f]);
5931       showline(logline, 0);
5932       showline("\n", 0);
5933 #endif
5934       if ((fontproper[n] & C_RESIDENT) != 0) { /* what ? */
5935         if ((fontproper[n] & C_REMAPIT) == 0) { /* ? */
5936 /*          strcpy(fname, fontname[n]); */    /* 1992/July/4 */
5937 //          strcpy(fname, fontname + n * MAXTEXNAME); /* 94/Feb/2 */
5938           if (fontname[n] != NULL) 
5939             strcpy(fname, fontname[n]); /* 94/Feb/2 */
5940           else *fname = '\0';
5941 /*          if (strcmp(subfontname[n], "") != 0) */ /* 1992/July/4 */
5942 //          if (*(subfontname + n * MAXFONTNAME) != '\0') /* 94/Feb/2 */
5943           if (subfontname[n] != NULL) {
5944 /*            strcpy(fname, subfontname[n]);  */
5945             strcpy(fname, subfontname[n]);
5946           }
5947         }
5948 /*        printf("Remapped %d to %s\n", f, fname); */
5949       }
5950     }       /* end of (proper & C_DEPENDENT) != 0 case */
5951     else if ((property & C_RESIDENT) != 0) {
5952 /*    if this font used here for first time */
5953       if ((property & C_REMAPIT) == 0) {
5954 /*        strcpy(fname, subfontname[f]);  */
5955 //        strcpy(fname, subfontname + f * MAXFONTNAME); 
5956         if (subfontname[f] != NULL) strcpy(fname, subfontname[f]); 
5957         else *fname = '\0';
5958       }
5959 /*        printf("Remapped %d to %s\n", f, fname);  */
5960     } /* end of (proper & C_RESIDENT) != 0 case */
5961   }
5962
5963 /*  Use remapped name instead of FontName if resident and ANSI */
5964   if ((property & C_RESIDENT) != 0 &&
5965     (property & C_REMAPIT) == 0 && bWindowsFlag != 0) {
5966 /* special case sy = Symbol and zd = ZapfDingbats ? */  /* 94/Feb/3 */
5967 /*      strcpy(fname, fontname[f]); */  /* experiment 93/Oct/4 */
5968 //      strcpy(fname, fontname + f * MAXTEXNAME); /* 94/Feb/2 */
5969     if (fontname[f] != NULL) strcpy(fname, fontname[f]);  /* 94/Feb/2 */
5970     else *fname = '\0';
5971   }
5972   if ((property & C_DEPENDENT) != 0) {  /* experiment 93/Oct/7 */
5973     n = fontsubflag[f];         /* what are we dependent on */
5974 /*  Use remapped name instead of FontName if dependent of resident and ANSI */
5975     if ((fontproper[n] & C_RESIDENT) != 0 &&
5976       (fontproper[n] & C_REMAPIT) == 0 && bWindowsFlag) {
5977 /* special case sy = Symbol and zd = ZapfDingbats ? */  /* 94/Feb/3 */
5978 /*        strcpy(fname, fontname[n]); */    /* experiment 93/Oct/7 */
5979 //        strcpy(fname, fontname + n * MAXTEXNAME); /* 94/Feb/2 */
5980       if (fontname[n] != NULL) strcpy(fname, fontname[n]);  /* 94/Feb/2 */
5981       else *fname = '\0';
5982     }
5983 /*    subfontname is MM *instance* FontName, not MM base */
5984     if ((fontproper[n] & C_NOTBASE) != 0) {
5985 //      strcpy(fname, subfontname + n * MAXTEXNAME);  /* 97/Dec/4 */
5986       if (subfontname[n] != NULL) strcpy(fname, subfontname[n]);
5987       else *fname = '\0';
5988     }
5989   }
5990
5991   if (fs[f] != 0) {     /* zero if font not used directly */
5992 /*  if ((property & C_ALIASED) != 0)
5993     strcpy(fname, subfontname[f]); */
5994     if ((property & C_UNUSED) == 0) { /* if actually used */
5995       if (strcmp(fname, "") == 0) {
5996 /* fprintf(errout, " ERROR: Empty name: fn %d f %d fontname %s subfontname %s\n", 
5997           fn, f, fontname[f], subfontname[f]); */
5998         sprintf(logline, " ERROR: Empty name: fn %d f %d\n",  fn, f);
5999         showline(logline, 1);
6000       }
6001 /*      fprintf(fp_out, "/fn%d /%s %ld mf ", fn, fname, fs[f]); */
6002 /*      fprintf(fp_out, "/fn%d /", fn); */ /* 1994/June/7 */
6003       sprintf(logline, "/fn%d /", bUseInternal ? fn : f);
6004       PSputs(logline, fp_out);
6005 /*  Is this use of prefix always OK? What if we are not dealing with PS name */
6006 /*      if (strcmp(fontprefix, "") != 0) fputs(fontprefix, fp_out); */
6007 //      if (strcmp(fontprefix, "") != 0)      /* 95/July/5 */
6008       if (fontprefix != NULL) {
6009         if (fontreside(f) == 0) {
6010 /*          possibly modify if bRandomPrefix is set ??? */
6011 //          fputs(fontprefix, fp_out);
6012           PSputs(fontprefix, fp_out);
6013         }
6014       }
6015       if (uppercaseflag != 0 && istexfont(fname) != 0) 
6016         uppercase(fname, fname);        /* 92/Dec/22 */
6017 /* This is where we insert  fname  after the /fn... */
6018 /* #ifdef ALLOWSCALE
6019       if (outscaleflag)
6020         fprintf(fp_out, "%s %.9lg mf ", fname, fs[f] / outscale);
6021       else
6022   #endif */
6023       if (bSubRealName == 0) {    /* a hack to hack something */
6024 /*      we don't normally come here these days ... */
6025 /*      use real PS FontName --- unless new size of another font */
6026         if ((property & C_DEPENDENT) == 0) {
6027 //          strcpy(fname, subfontname + f * MAXFONTNAME);
6028           if (subfontname[f] != NULL) strcpy(fname, subfontname[f]);
6029           else *fname = '\0';
6030         }
6031         else {
6032           n = fontsubflag[f];   /* what are we dependent on ? */
6033 //          strcpy(fname, subfontname + n * MAXFONTNAME);
6034           if (subfontname[n] != NULL) strcpy(fname, subfontname[n]);
6035           else *fname = '\0';
6036         }
6037       }
6038       if (property & C_INSTANCE) {
6039 /*        strcpy(fname, subfontname + f * MAXFONTNAME); */
6040         *fname = '\0';
6041
6042 //        strcat(fname, subfontname + f * MAXFONTNAME);
6043         if (subfontname[f] != NULL) strcat(fname, subfontname[f]);
6044 #ifdef DEBUG
6045         if (traceflag) {
6046           sprintf(logline, "subfontname (%d): %s ", f, fname);
6047           showline(logline, 0);
6048         }
6049 #endif
6050         if (traceflag) {      /* debugging */
6051 //          if (logfileflag) showproper(logfile, fontproper[f]);
6052           showproper(logline, fontproper[f]);
6053           showline(logline, 0);
6054         }
6055 /* not sure this is the best way for MM instances - mayby use subfontname */
6056       }
6057 /* This is where we insert  fname  after the /fn... */
6058 #ifdef ALLOWSCALE
6059       if (outscaleflag) {
6060         sprintf(logline, "%s %.9lg mf ", fname, (double) fs[f] /
6061             outscale);
6062       }
6063       else {
6064         sprintf(logline, "%s %ld mf ", fname, fs[f]);
6065       }
6066       PSputs(logline, fp_out);      
6067 #else
6068       {
6069         sprintf(logline, "%s %ld mf ", fname, fs[f]);
6070         PSputs(logline, fp_out);
6071       }
6072 #endif
6073 /*      fputs(fname, fp_out); */
6074 /*      fprintf(fp_out, " %ld mf ", fs[f]); */
6075
6076       sprintf(logline, "/f%d{fn%d sf}def\n",
6077         bShortFont ? f : fn, bUseInternal ? fn : f); 
6078       PSputs(logline, fp_out);
6079 /*      fprintf(fp_out, "/f%d{fn%d sf}def\n", fn, fn);*/ /* 1994/June/7 */
6080 #ifdef DEBUG
6081 /*      printf("fontname %s subfontname %s fontproper %0x\n",
6082         fontname[f], subfontname[f], property); */
6083 #endif
6084     }
6085 /*    else printf("Font %d noted as C_UNUSED\n", f); */ /* 95/Feb/1 */
6086   }
6087 }
6088
6089 /* Replace PostScript FontName in PSS stub with new one */
6090
6091 int replacename (char *line, char *fname)
6092 {
6093   char *s, *t;
6094   char buffer[FNAMELEN];
6095
6096   if ((s = strchr(line, '/')) == NULL) return -1;
6097   s++;
6098   if ((t = strchr(s, ' ')) == NULL) t = strchr(s, '/');
6099   if (t == NULL) return -1;
6100   if (strlen(t) >= sizeof buffer)   /* FNAMELEN */
6101     return -1;
6102   strcpy(buffer, t);
6103   strcpy(s, fname);
6104   strcat(s, buffer);
6105   return 0;
6106 }
6107
6108 /* copy and process Multiple Master Instance PSS stub file */
6109 /* fname is file name of MM instance stub */
6110 /* bname is file name of MM base font */
6111 /* encode is optional encoding vector - no longer used */
6112 /* returns -1 if file format bad or parsing error */
6113
6114 /* int copyPSS_sub(FILE *output, FILE *input, char *fname, char *encode) { */
6115 /* int copyPSS_sub(FILE *output, FILE *input, char *fname, char *bname, char *encode) { */
6116 int copyPSS_sub(FILE *output, FILE *input, char *fname, char *bname, char *encode, int proper)
6117 {
6118 /*  int c; */
6119   char *s;
6120 //  char basename[MAXTEXNAME];  /*  char basename[16]; */
6121   char basename[FNAMELEN];  /*  char basename[16]; */
6122
6123   if (getc(input) != 128) return -1;    /* check ASCII section */
6124   if (getc(input) != 1) return -1;    /* should be 128, 1 */
6125 /*  skip over 4 byte length code */
6126   getc(input); getc(input); getc(input); getc(input);
6127   if (readaline(line, input) != 0) return -1;
6128   while (*line == '%') {          /* copy comment lines over */
6129 //    fputs(line, output);
6130     PSputs(line, output);
6131     if (readaline(line, input) != 0) return -1;
6132   }
6133 /*  while ((s = strchr(line, '/')) == NULL) {  */
6134   while ((s = strstr(line, "findfont")) == NULL) {
6135 //    fputs(line, output);
6136     PSputs(line, output);
6137     if (readaline(line, input) != 0) return -1;
6138   }
6139   if ((s = strchr(line, '/')) == NULL) return -1;
6140 /*  replace PostScript Multiple Master *Instance* FontName */
6141   if (replacename (s, fname) != 0) return -1;
6142 /*  if (bMMNewFlag) { */
6143   if ((s = strchr(line+1, '/')) == NULL) return -1;
6144 /*  Construct MM base font file name from stub PSS file name */
6145   if (bMMShortCut) {            /* disallow this ? */
6146     strcpy(basename, fname);
6147     strcpy(basename+5, "___");
6148 /*    MM base font has same name, but ends in ___ simple minded ? */
6149   }
6150   else strcpy(basename, bname);
6151 /*  Replace PostScript Multiple Master *Base* FontName */
6152 /*  Should more generally check whether Base Font is resident ? */
6153 /*  if (forcereside == 0) */        /* 95/Sep/16 */
6154   if ((proper & C_RESIDENT) == 0)     /* 95/Sep/16 later */
6155     if (replacename (s, basename) != 0) return -1;
6156 /*  } */
6157   while ((s = strstr(line, "/FontName")) == NULL) {
6158 //    fputs(line, output);
6159     PSputs(line, output);
6160     if (readaline(line, input) != 0) return -1;
6161   }
6162 /*  if (replacename (s+9, fname) != 0) return -1; */
6163   if ((s = strchr(s+1, '/')) == NULL) return -1;
6164 /*  replace PostScript Multiple Master *Instance* FontName */
6165   if (replacename (s, fname) != 0) return -1;
6166   while ((s = strstr(line, "definefont")) == NULL) {
6167 //    fputs(line, output);
6168     PSputs(line, output);
6169     if (readaline(line, input) != 0) return -1;
6170   }
6171 /*  if (bMMNewFlag == 0) {*/  /* Insert new encoding vector in PSS 95/May/13 */
6172 /*  Should more generally check whether Base Font is resident ? */
6173 /*  if (forcereside != 0) { */  /* new encoding vector in PSS 95/Sep/16 */
6174   if (proper & C_RESIDENT) {  /* new encoding vector in PSS 95/Sep/16 */
6175     if (encode != NULL && *encode != '\0') {
6176       sprintf(logline, "dup /Encoding %s put\n", encode);
6177       PSputs(logline, output);
6178     }
6179     else if (bWindowsFlag != 0) {
6180       sprintf(logline, "dup /Encoding get StandardEncoding eq{");
6181       PSputs(logline, output);
6182       sprintf(logline, "dup /Encoding %s put\n", textenconame);   
6183       PSputs(logline, output);
6184       PSputs("}if\n", output);
6185     }
6186   }
6187 //  fputs(line, output);
6188   PSputs(line, output);
6189   return 0;
6190 }
6191
6192 /* Danger above is that MM font that is not a text font can get reencoded! */
6193 /* Fixed 96/Sep/29 */
6194
6195 /* use copyPSS_sub(output, input, fname, encode); to copy and expand PSS */
6196
6197 /* compressfont(output, input, FontName) to copy Multiple Master itself ? */ 
6198 /* how to we get the FontName ??? */ /* needed for BeginResource ... */
6199 /* what about those comments about FontNeeded, FontProvided etc ? */
6200
6201 /* work in progress: deal with PSS stub for Multiple Master */
6202
6203 int copyPSS(FILE *fp_out, FILE *fp_in, int k)
6204 {
6205   int flag, m;
6206   int proper=0;
6207   char *s;
6208 //  char vecname[MAXVECNAME];     /* 1994/Feb/4 */
6209   char vecname[FNAMELEN];
6210 /*  char basename[MAXFONTNAME]; */    /* 1995/May/25 */
6211 //  char basename[MAXTEXNAME];      /* 1997/June/1 */
6212   char basename[FNAMELEN];
6213 //  char psfontname[MAXFONTNAME];   /* 1997/June/1 */
6214   char psfontname[FNAMELEN];
6215
6216 /*  strcpy(oldname, fontsubfrom + k * MAXTEXNAME); */
6217 /*  strcpy(newname, fontsubto + k * MAXFONTNAME); */
6218 //  strcpy(vecname, fontsubvec + k * MAXVECNAME);
6219   if (fontsubvec[k] != NULL) strcpy(vecname, fontsubvec[k]);
6220   else *vecname = '\0';
6221 /*  file name of corresponding MM base font - old way and default */
6222 //  strcpy(psfontname, subfontname + k * MAXFONTNAME);  /* 97/June/1 */
6223   if (subfontname[k] != NULL) strcpy(psfontname, subfontname[k]); /* 97/June/1 */
6224   else *psfontname = '\0';
6225   if ((s = strchr(psfontname, '_')) != NULL && s > psfontname) {
6226     return 0;   /* actual instance PS FontName - redundant */
6227   }
6228 //  strcpy(basename, fontname + k * MAXTEXNAME);    /* 95/May/25 */
6229   if (fontname[k] != NULL) strcpy(basename, fontname[k]);   /* 95/May/25 */
6230   else *basename = '\0';
6231   strcpy(basename + 5, "___");            /* 95/May/25 */
6232   if (bMMShortCut == 0) {     /* find corresponding MM base entry */
6233     flag = 0;
6234     for (m = 0; m < fnext; m++) {
6235       if ((fontproper[m] & C_MULTIPLE) == 0) continue;
6236 //      if (strcmp (subfontname + k * MAXFONTNAME,
6237 //        subfontname + m * MAXFONTNAME) == 0) 
6238       if (subfontname[k] != NULL && subfontname[m] != NULL &&
6239           strcmp (subfontname[k], subfontname[m]) == 0) {
6240 /* we assume that the actual MM font file name has been placed here already */
6241 /* which will not be the case if the darn thing is declared resident ? */
6242         proper = fontproper[m];   /* pick up properties of base */
6243 //        strcpy (basename, fontname + m * MAXTEXNAME);
6244         if (fontname[m] != NULL) strcpy (basename, fontname[m]);
6245         else *basename = '\0';
6246         flag = 1;
6247         break;
6248       }
6249     }
6250     if (flag == 0) {          /* should not happen - debugging */
6251       sprintf(logline, " Assuming MM base `%s'", basename);
6252       showline(logline, 1);
6253     }
6254   }
6255
6256   beginresource(fp_out, filefontname); /* %%BeginResource: font zjrg_001 */
6257 /*  flag = copyPSS_sub(fp_out, fp_in, filefontname, vecname); */
6258   flag = copyPSS_sub(fp_out, fp_in, filefontname, basename, vecname, proper);
6259   if (flag != 0) {
6260     notvalidPSS(1);   /* pssflag == 1 */
6261     sprintf(logline, "`%s' ", filefontname);
6262     showline(logline, 0);
6263   }
6264   endresource(fp_out);         /* %%EndResource */
6265   return flag;
6266 }
6267
6268 int IsItUsed (char *wantchrs)
6269 {
6270   int k;
6271   if (wantchrs == NULL) return 0;
6272 /*  test in decreasing order of expected use */
6273 //  for (k = 0; k < fontchrs; k++)  if (wantchrs[k] != 0) return -1;
6274   for (k = 64;  k < 128; k++) if (wantchrs[k]) return 1;  /* G1b */
6275   for (k = 32;  k < 64;  k++) if (wantchrs[k]) return 1;  /* G1a */
6276   for (k = 0;   k < 32;  k++) if (wantchrs[k]) return 1;  /* C1 */
6277   for (k = 160; k < fontchrs; k++) if (wantchrs[k]) return 1; /* G2 */
6278   for (k = 128; k < 160; k++) if (wantchrs[k]) return 1;  /* C2 */
6279   return 0;
6280 }
6281
6282 /* See if can mark unused fonts (in jobs with less than full page range) */
6283
6284 int MarkUnusedFonts (void)        /* an experiment 95/Mar/5 */
6285 {
6286   int fn, flag=0;
6287 /*  int k, count, property; */
6288 //  char fontnamek[MAXTEXNAME];
6289   char fontnamek[FNAMELEN];
6290   char *wantchrs;
6291
6292 /*  for (fn = 0; fn < mmbase; fn++) { */  /* ignore MM base fonts for now */
6293   for (fn = 0; fn < fnext; fn++) {    
6294 /*    if (fontproper[k] & C_MULTIPLE) continue; */ /* ignore MM base fonts */
6295 //    wantchrs = fontchar + MAXCHRS * fn;
6296     wantchrs = fontchar[fn];
6297 /*    property = fontproper[fn]; */
6298 /*    count = 0;
6299     for (k = 0; k < MAXCHRS; k++) {
6300       if (wantchrs[(k + 32) % 255] != 0) {
6301         count++;  break;
6302       }
6303     } */
6304 /*    count = IsItUsed(wantchrs); */
6305 /*    if (count == 0) { */
6306     if (! IsItUsed(wantchrs)) {
6307       if (traceflag) {
6308 /*        strcpy (fontnamek, fontname + k * MAXTEXNAME);   */
6309 //        strcpy (fontnamek, fontname + fn * MAXTEXNAME); 
6310         if (fontname[fn] != NULL) strcpy (fontnamek, fontname[fn]); 
6311         else *fontnamek = '\0';
6312         sprintf(logline, "Marking %s as unused\n", fontnamek);
6313         showline(logline, 0);
6314       }
6315       fontproper[fn] |= C_UNUSED;
6316       flag++;
6317     }
6318   }
6319   return flag;
6320 }
6321
6322 /* following split off 95/May/13 to improve readability ... */
6323
6324 int extractafont (FILE *fp_out, int k)
6325 {
6326   FILE *fp_in;
6327   int flag=0;
6328   int proper;         /* 1992/Aug/23 */
6329 //  char fontnamek[MAXTEXNAME];
6330   char fontnamek[FNAMELEN];
6331 //  char subfontnamek[MAXFONTNAME];
6332   char subfontnamek[FNAMELEN];
6333
6334   proper = fontproper[k];
6335 //  strcpy(fontnamek, fontname + k * MAXTEXNAME);   /* 94/Feb/2 */
6336   if (fontname[k] != NULL) strcpy(fontnamek, fontname[k]);    /* 94/Feb/2 */
6337   else *fontnamek = '\0';
6338 /*  if ((proper & C_UNUSED) != 0) return;  */
6339   if (fontsubflag[k] < 0) {   /* not a font substituted for */
6340 /*    don't bother if font not used - no characters */
6341     if ((proper & C_UNUSED) != 0) return 0; 
6342 /*    don't bother if already known not to exist  */
6343     if ((proper & C_MISSING) != 0) return 0; 
6344     if ((proper & C_RESIDENT) != 0) return 0; /* never */
6345     if ((proper & C_DEPENDENT) != 0) return 0;  /* NEW */
6346 /*    if (strcmp(fontname[k], subfontname[k]) == 0) continue; */ /* ? */
6347 /*    if ((proper & C_ALIASED) != 0)  
6348         strcpy(filefontname, subfontname[k]); */
6349 /*    strcpy(filefontname, fontname[k]); */
6350 //    strcpy(filefontname, fontname + k * MAXTEXNAME);
6351     if (fontname[k] != NULL) strcpy(filefontname, fontname[k]);
6352     else *filefontname = '\0';
6353     if ((proper & C_REMAPIT) != 0) { /* remapped font */
6354 //      strcpy (subfontnamek, subfontname + k * MAXFONTNAME);
6355       if (subfontname[k] != NULL) strcpy (subfontnamek, subfontname[k]);
6356       else *subfontnamek = '\0';
6357 /*      printf("\n%s AND %s ", filefontname, subfontnamek); */
6358       if (proper & C_MULTIPLE) { /* kludge for remapped MM base 95/Jul/15 */
6359 //        strcpy (subfontnamek, fontname + k * MAXFONTNAME);
6360         if (fontname[k] != NULL)
6361           strcpy (subfontnamek, fontname[k]);
6362         else *subfontnamek = '\0';
6363       }
6364 /*      if ((fp_in = OpenFont(subfontname[k])) == NULL) {  */
6365       if ((fp_in = OpenFont(subfontnamek, 1)) == NULL) { 
6366 /*        fprintf(errout, " WARNING: "); */ /* REDUNDANT ? */
6367         sprintf(logline, " WARNING: %s ", subfontnamek);  /* REDUNDANT ? */
6368         showline(logline, 1);
6369 /*        perrormod(subfontname[k]);   */
6370         perrormod(subfontnamek);  
6371         errcount(0); 
6372         return 0;
6373       }
6374     }
6375     else { /* not a remapped font */
6376 /* can we assume fontnamek set correctly ? */
6377 /*      if ((fp_in = OpenFont(fontname[k])) == NULL) {  */
6378       if ((fp_in = OpenFont(fontnamek, 1)) == NULL) { 
6379 /*        fprintf(errout, " WARNING: "); */ /* REDUNDANT ? */
6380         sprintf(logline, " WARNING: %s ", fontnamek); /* REDUNDANT ? */
6381         showline(logline, 1);
6382 /*        perrormod(fontname[k]);  */
6383         perrormod(fontnamek); 
6384         errcount(0);
6385         return 0;
6386       } /* shouldn't happen ? */
6387     }
6388     if (verboseflag) {
6389 //      putc('[', stdout);  
6390 //      if (logfileflag) putc('[', logfile);  
6391       showline("[", 0);
6392     }
6393 /*    else putc('*', stdout); */          /* 95/Mar/1 */
6394
6395     if (proper & C_MULTIPLE) {
6396       mmflag = 1;
6397 /*      (void) FindMMBaseFile(k);  */ /* done earlier already */
6398 /*      strcpy (fontnamek, fontname + k * MAXTEXNAME);  */
6399     } 
6400     if (proper & C_INSTANCE) {    /* Is this MM Instance PSS stub ?*/
6401       if (verboseflag) showline(fontnamek, 0);    /* 95/May/13 */
6402       if ((proper & C_NOTBASE) != 0) 
6403         copyPSS (fp_out, fp_in, k);   /* 94/Dec/6 do later ? */
6404     }
6405     else if (type3flag != 0) {
6406 /* How would type3flag ever get set here ? - By font open mechanism */
6407       if (extracttype3(fp_out, fp_in, k, fontnamek) == 0) {
6408         if (extracttype1(fp_out, fp_in, k, fontnamek) == 0)
6409           copyunknown(fp_out, fp_in, k, fontnamek);
6410       }
6411     }
6412     else {
6413       if (extracttype1(fp_out, fp_in, k, fontnamek) == 0) {
6414         if(extracttype3(fp_out, fp_in, k, fontnamek) == 0)
6415           copyunknown(fp_out, fp_in, k, fontnamek); 
6416       }
6417     }
6418     if (abortflag) return -1;
6419 /*    extractfont(fp_out, fp_in, k); */
6420 /*    nfonts++; */
6421     flag = 1;
6422     fclose (fp_in);
6423     if (verboseflag) showline("] ", 0);
6424   }   /* if (fontsubflag[k] < 0) */
6425   return flag;
6426 }
6427
6428 /* main entry point - extract and decompress font files */
6429 /* once it has been verified this works correctly, strip out IGNORE part */
6430 /* present order is: MM base fonts, PSS stub files, other fonts ... */
6431
6432 int extractfonts (FILE *fp_out) /* was called by main */
6433 {
6434   int k;
6435   int proper;         /* 1992/Aug/23 */
6436 /*  int oldsuppress; */
6437
6438 /*  initializeencoding(); */  /* should be done earlier dvipsone.c */
6439
6440   nfonts=0; nsubstitute=0; nremapped=0; nansified=0;
6441   if (fnext == 0) return 0;     /* nothing to do ??? */
6442
6443 /*  fprintf(fp_out, "dvidict begin\n"); */
6444   writedvistart(fp_out);        /* 93/Sep/30 */
6445 /*  if (bMarkUnused) MarkUnusedFonts(); */    /* 95/March/5 */
6446   if (showfontflag) {
6447     showfonttable();  /* an experiment */
6448 //    if (logfileflag) showfonttable(logfile);
6449   }
6450
6451   task = "decompressing font files";
6452
6453 /*  some redundancy with code below */ /* download MM base fonts first */
6454 /*  if (fnext > mmbase && forcereside == 0) { */
6455   if (mmcount > 0 && forcereside == 0) {    /* ??? */
6456     mmflag = 1;               /* flag that these are MM */
6457 /*    oldsuppress = bSuppressPartial; */
6458 /*    if (bMMNewFlag == 0) bSuppressPartial = 1; *//* backward compat */
6459 /*    for (k = mmbase; k < fnext; k++) { */   /* do MM fonts first */
6460     for (k = 0; k < fnext; k++) {       /* do MM fonts first */
6461       proper = fontproper[k];
6462       if ((proper & C_MULTIPLE) == 0) continue;
6463       if (extractafont(fp_out, k) != 0) nfonts++;
6464       if (bAbort) abortjob();         /* 1992/Nov/24 */
6465       if (abortflag) return -1;
6466     }               /* end of for loop over MM fonts */
6467 /*    if (bMMNewFlag == 0) bSuppressPartial = oldsuppress;  */
6468     mmflag = 0;
6469   }
6470   
6471 /*  extract PSS stub files next */
6472
6473   for (k = 0; k < fnext; k++)
6474   {
6475     proper = fontproper[k];
6476     if ((proper & C_INSTANCE) == 0) continue;
6477     if (extractafont(fp_out, k) != 0) nfonts++; /* do we count these ? */
6478     if (bAbort) abortjob();         /* 1992/Nov/24 */
6479     if (abortflag) return -1;
6480   }
6481
6482 /*  finally do non MM fonts ... */    /* MM base fonts already done above */
6483
6484 /*  for (k = 0; k < mmbase; k++) { */
6485   for (k = 0; k < fnext; k++) {   /* 1994/Dec/6 */
6486     proper = fontproper[k];
6487     if (proper & C_MULTIPLE) continue;  /* MM base fonts already done */
6488     if (proper & C_INSTANCE) continue;  /* MM instances already done */
6489     if (extractafont(fp_out, k) != 0) nfonts++;
6490     if (bAbort) abortjob();         /* 1992/Nov/24 */
6491     if (abortflag) return -1;
6492   }     /* for (k=0; k < fnext; k++) */
6493   if (verboseflag) showline("\n", 0);
6494
6495   writedviend(fp_out);        /* 1992/Nov/17 */
6496
6497   if (verboseflag) {        /* rewrote 1993/Feb/6 */
6498     if (nfonts > 0) 
6499 /*      printf("Processed %d font files ", nfonts);  */
6500       sprintf(logline, "Processed %d font file%s ", nfonts,
6501         (nfonts == 1) ? "" : "s");    /* 1994/Feb/1 */
6502     else sprintf(logline, "No font files ");
6503     showline(logline, 0);
6504   }
6505   return 0;
6506 }
6507
6508 /* Note: fstart / fend can occur twice (% Font Remap and % Font Defs) */
6509 /* so checking for existing fonts may list only those remapped, miss others */
6510 /* Because `fend' terminates when it has found one or more bad fonts */
6511     
6512 /* separated out from the above 94/Mar/3 ************************** */
6513
6514 void fontsetup (FILE *fp_out)
6515 {
6516   int k, i, ne, f;
6517 /*  int n; */
6518   int count, flag;
6519   int property;           /* 1992/Aug/23 */
6520 //  char fname[MAXFONTNAME];    /* 1993/Feb/15 */
6521   char fname[FNAMELEN];
6522 //  char fontnamef[MAXTEXNAME];
6523   char fontnamef[FNAMELEN];
6524 //  char fontnamek[MAXTEXNAME];
6525   char fontnamek[FNAMELEN];
6526 //  char subfontnamek[MAXFONTNAME];
6527   char subfontnamek[FNAMELEN];
6528   static long widths[MAXCHRS];  /* why is this static ? */
6529 /*  long widths[MAXCHRS]; */    /* problem with stack space ? */
6530   char *fontptr;
6531
6532 /*  now for the substitutions */
6533   if (substituteflag && needsubstitute() != 0) {   
6534     task = "constructing substituted fonts";
6535     nsubstitute = 0;
6536     if (stripcomment == 0) {
6537 //      fputs("% Font Subs:\n", fp_out);
6538       PSputs("% Font Subs:\n", fp_out);
6539     }
6540 /*    fprintf(fp_out, "%s", "dvidict begin\n"); */    /* new */
6541 /*    fputs("dvidict begin\n", fp_out); */  /* 1992/July/18 */
6542     writedvistart(fp_out);        /* 93/Sep/30 */
6543     for (k = 0; k < fnext; k++) {
6544       property = fontproper[k];
6545 //      strcpy (fontnamek, fontname + k * MAXTEXNAME);  /* 1994/Feb/2 */
6546       if (fontname[k] != NULL) strcpy (fontnamek, fontname[k]); /* 1994/Feb/2 */
6547       else *fontnamek = '\0';
6548 //      strcpy (subfontnamek, subfontname + k * MAXFONTNAME); /* 1997/June/1 */
6549       if (subfontname[k] != NULL) strcpy (subfontnamek, subfontname[k]);  /* 1997/June/1 */
6550       else *subfontnamek = '\0';
6551       if ((property & C_REMAPIT) != 0) continue;    /* ? */
6552       if ((property & C_RESIDENT) != 0) continue;   /* ? */
6553       if ((property & C_DEPENDENT) != 0) continue;    /* NEW */
6554       if ((property & C_UNUSED) != 0) continue;     /* 95/Sep/9 ??? */
6555 /*      if (strcmp(fontname[k], subfontname[k]) == 0) continue; */ /* rep */
6556       if ((f = fontsubflag[k]) >= 0) { 
6557 //        strcpy (fontnamef, fontname + f * MAXTEXNAME); /* 94/Feb/2 */
6558         if (fontname[f] != NULL) strcpy (fontnamef, fontname[f]); /* 94/Feb/2 */
6559         else *fontnamef = '\0';
6560 /*        fprintf(output, "%% FONTSUBFLAG %d\n",
6561           fontsubflag[k]); */  /* debugging */
6562 /*        f = fontsubflag[k]; */
6563 /*        following moved out here 1995/Sep/9 so we can check usage */
6564 /*        fontptr = fontchar + MAXCHRS * k;
6565         count = 0;
6566         ne = MAXCHRS;
6567         for (i= 0; i < ne; i++) if (fontptr[i] != 0) count++;
6568         if (count == 0) {
6569           fontproper[k] |= C_UNUSED;
6570           continue;   
6571         } */ /* should not happen ! */
6572 /*        above moved out here 1995/Sep/9 so we can check usage */
6573
6574         if (stripcomment == 0) {
6575 /*          fprintf(fp_out, "%%%%BeginFont: %s\n", fontname[k]); */
6576 /*          fprintf(fp_out, "%% BeginFont: %s\n", fontname[k]);  */
6577           if (property & C_MULTIPLE) {        /* 97/June/1 */
6578             sprintf(logline, "%% BeginFont: %s\n", subfontnamek);
6579           }
6580           else {
6581             sprintf(logline, "%% BeginFont: %s\n", fontnamek);
6582           }
6583           PSputs(logline, fp_out);
6584         }
6585 /*        fprintf(fp_out, "/%s fs ", fontname[f]); */
6586 //        putc('/', fp_out);
6587         PSputc('/', fp_out);
6588 //        if (strcmp(fontprefix, "") != 0)    /* 1995/July/5 */
6589         if (fontprefix != NULL) {   /* 1995/July/5 */
6590           if (fontreside(f) == 0) {
6591 /*  possibly modify if bRandomPrefix is set ??? */
6592 //            fputs(fontprefix, fp_out);
6593             PSputs(fontprefix, fp_out);
6594           }
6595         }
6596 /* shouldn't this depend on whether it is a texfont or not ??? */
6597 /*        if (uppercaseflag) */           /* 1995/July/1 */
6598         if (uppercaseflag && istexfont(fontnamef))  /* 1996/June/20 */
6599           uppercase(fontnamef, fontnamef);
6600 /*        fprintf(fp_out, "/%s fs ", fontnamef); */
6601 //        fputs(fontnamef, fp_out);       /* 1995/July/5 */
6602         PSputs(fontnamef, fp_out);        /* 1995/July/5 */
6603 //        fputs(" fs ", fp_out);
6604         PSputs(" fs ", fp_out);
6605 /*  insert new font metrics - (and possibly new uniqueID ?) */
6606         if (insertmetrics != 0 && (property & C_MTMI) == 0) {
6607 /*          if ((ne = readwidths(fontname[k], widths)) != 0) { */
6608           if ((ne = readwidths(fontnamek, widths)) != 0) {
6609 /*            fontptr = fontchar[k]; */
6610 /*            following moved up above to avoid zero count fonts */
6611 //            fontptr = fontchar + MAXCHRS * k;
6612             fontptr = fontchar[k];
6613             count = 0;
6614             for (i= 0; i < ne; i++) if (fontptr[i] != 0) count++;
6615             if (count == 0) 
6616               showline(" zero count", 1); /* 95/Sep/9 */
6617
6618             sprintf(logline, "%d fa\n", count);
6619             PSputs(logline, fp_out);
6620             for (i = 0; i < ne; i++) {
6621               if (fontptr[i] != 0) {
6622 #ifdef ALLOWSCALE
6623 /* following flushed 95/June/6 because fm PS proc *not* scaled */
6624 /* character width in design size units * 2^20 */
6625 /*                if (outscaleflag) 
6626                   fprintf(fp_out, "%d %.9lg fm\n",
6627                     i, widths[i] / outscale);
6628                 else */
6629 #endif
6630                 sprintf(logline, "%d %ld fm\n", i, widths[i]);
6631                 PSputs(logline, fp_out);
6632               }
6633             }
6634             PSputs("fb ", fp_out);
6635           }
6636         }
6637 /*        fprintf(fp_out, "/%s fe\n", fontname[k]); */
6638 //        putc('/', fp_out);  
6639         PSputc('/', fp_out);  
6640 //        if (strcmp(fontprefix, "") != 0) 
6641         if (fontprefix != NULL) {
6642 /*          if ((fontproper[k] & C_RESIDENT) == 0) */ /* NO ? */
6643 /*  possibly modify if bRandomPrefix is set ??? */
6644 //            fputs(fontprefix, fp_out);    /* 1995/July/5 */
6645           PSputs(fontprefix, fp_out);   /* 1995/July/5 */
6646         }
6647 /* shouldn't this depend on whether it is a texfont or not ??? */
6648 /*        if (uppercaseflag) */           /* 1995/July/1 */
6649         if (uppercaseflag && istexfont(fontnamek))  /* 1996/June/20 */
6650           uppercase(fontnamek, fontnamek);          
6651 //        fputs(fontnamek, fp_out);
6652         PSputs(fontnamek, fp_out);
6653 //        fputs(" fe\n", fp_out);
6654         PSputs(" fe\n", fp_out);
6655         if (stripcomment == 0) 
6656 /*          fprintf(fp_out, "%%%%EndFont\n");  */
6657 /*          fprintf(fp_out, "%% EndFont\n");  */
6658 //          fputs("% EndFont\n", fp_out); 
6659           PSputs("% EndFont\n", fp_out); 
6660         nsubstitute++;
6661       }
6662     }
6663
6664     writedviend(fp_out);        /* 1992/Nov/17 */
6665
6666     if (verboseflag && nsubstitute != 0) {
6667 /*      printf("Substituted for %d fonts\n", nsubstitute); */
6668 /*      printf("- substituted for %d fonts ", nsubstitute); */
6669       sprintf(logline, "- substituted for %d font%s ",
6670          nsubstitute, (nsubstitute == 1) ? "" : "s"); /* 95/July/15 */
6671       showline(logline, 0);
6672     }
6673   }
6674     
6675 /*  if (needremap() != 0) {  */
6676   if ((flag = needremap()) != 0) { 
6677 /*    constructvectors(fp_out); */
6678     if (flag < 0) constructvectors(fp_out);
6679     task = "constructing remapped fonts";
6680     nremapped = 0;
6681     if (stripcomment == 0) {
6682 //      fputs("% Font Remap:\n", fp_out);
6683       PSputs("% Font Remap:\n", fp_out);
6684     }
6685 /*    fprintf(fp_out, "%s", "dvidict begin\n"); */    /* new */
6686 /*    fputs("dvidict begin\n", fp_out); */  /* 1992/July/18 */
6687     writedvistart(fp_out);          /* 93/Sep/30 */
6688 //    fputs("fstart\n", fp_out);
6689     PSputs("fstart\n", fp_out);
6690     for (k = 0; k < fnext; k++) {
6691       property = fontproper[k];
6692 //      strcpy (fontnamek, fontname + k * MAXTEXNAME);  /* 94/Feb/2 */
6693       if (fontname[k] != NULL) strcpy (fontnamek, fontname[k]); /* 94/Feb/2 */
6694       else *fontnamek = '\0';
6695 //      strcpy (subfontnamek, subfontname + k * MAXFONTNAME); /* 97/June/1 */
6696       if (subfontname[k] != NULL) strcpy (subfontnamek, subfontname[k]);  /* 97/June/1 */
6697       else *subfontnamek = '\0';
6698 /*      printf("k %d proper ", k); */       /* debugging */
6699       if ((property & C_DEPENDENT) != 0) continue;
6700       if ((property & C_UNUSED) != 0) continue;   /* 1995/Mar/27 */
6701 /*      if (strcmp(fontname[k], subfontname[k]) == 0) continue; */ /* ? */
6702 /*      if ((property & C_REMAPIT) != 0 &&
6703         (property & C_RESIDENT) != 0) { */
6704 /* Shouldn't really bother doing this for MM Base Font if it is resident */
6705 /* Since the PSS stub then refers to PS FontName, not this new name ... */
6706 /*      only do this for printer resident fonts */
6707 /*      if ((property & C_RESIDENT) == 0) continue; */
6708 /*      only do this for printer resident fonts and MM base fonts */
6709       if ((property & C_RESIDENT) == 0 && (property & C_MULTIPLE) == 0) continue;
6710 /*      only do this if font needs to be remapped */
6711       if ((property & C_REMAPIT) == 0 && bWindowsFlag == 0) continue;
6712 /*      if ((property & C_RESIDENT) != 0 &&
6713         ((property & C_REMAPIT) != 0 ||
6714           bWindowsFlag != 0)) { */
6715         if (stripcomment == 0) {
6716           if (property & C_MULTIPLE) {        /* 97/June/1 */
6717             sprintf(logline, "%% BeginFont: %s\n", subfontnamek);
6718           }
6719           else {
6720             sprintf(logline, "%% BeginFont: %s\n", fontnamek);
6721           }
6722           PSputs(logline, fp_out);
6723         }
6724 //        putc('/', fp_out);  
6725         PSputc('/', fp_out);
6726 /*        if (strcmp(fontprefix, "") != 0) fputs(fontprefix, fp_out); */
6727 //        if (strcmp(fontprefix, "") != 0)    /* 1995/July/5 */
6728         if (fontprefix != NULL) {   /* 1995/July/5 */
6729           if (fontreside(k) == 0) {
6730 /*            possibly modify if bRandomPrefix is set ??? */
6731 //            fputs(fontprefix, fp_out);
6732             PSputs(fontprefix, fp_out);
6733           }
6734         }
6735 /*        strcpy(fname, fontname + k * MAXTEXNAME); */  /* 1994/Feb/2 */
6736         if (property & C_MULTIPLE) {      /* 97/June/1 */
6737           *fname = '\0';
6738
6739 //          strcat(fname, subfontname + k * MAXFONTNAME);
6740           if (subfontname[k] != NULL) strcat(fname, subfontname[k]);
6741         }
6742         else {
6743 //          strcpy(fname, fontname + k * MAXTEXNAME); /* 1994/Feb/2 */
6744           if (fontname[k] != NULL) strcpy(fname, fontname[k]);  /* 1994/Feb/2 */
6745           else *fname = '\0';
6746         }
6747         if (uppercaseflag != 0 && istexfont(fname) != 0) 
6748           uppercase(fname, fname);
6749 /*        fprintf(fp_out, "/%s %s /%s rmf\n",  
6750           fontname[k], fontvector[k], subfontname[k]); */
6751 //        strcpy (subfontnamek, subfontname + k * MAXFONTNAME);/* 94/Feb/2 */
6752         if (subfontname[k] != NULL) strcpy (subfontnamek, subfontname[k]);/* 94/Feb/2 */
6753         else *subfontnamek = '\0';
6754         if ((property & C_REMAPIT) != 0) {
6755           sprintf(logline, "%s %s /%s rmf\n",
6756 /*            fname, fontvector[k], subfontname[k]); */
6757 //            fname, fontvector + k * MAXVECNAME, subfontnamek);
6758             fname, fontvector[k], subfontnamek);
6759         }
6760         else {          /* just due to Windows ANSI remap */
6761           sprintf(logline, "%s %s /%s amf\n",
6762 /*            fname, "ansinew", subfontname[k]); */ /* 93/Oct/4 */
6763 /*            fname, "ansinew", subfontnamek); */ /* 94/Feb/2 */
6764 /*            fname, textencoding, subfontnamek); */  /* 94/Dec/17 */
6765             fname, textenconame, subfontnamek);   /* 95/Feb/6 */
6766         }
6767         PSputs(logline, fp_out);
6768 /* copy font directory and insert new encoding vector */
6769         if (stripcomment == 0) {
6770 /*          fprintf(fp_out, "%%%%EndFont\n");  */
6771 /*          fprintf(fp_out, "%% EndFont\n"); */
6772 //          fputs("% EndFont\n", fp_out);
6773           PSputs("% EndFont\n", fp_out);
6774         }
6775         nremapped++; 
6776 /*      } */ /* end of resident and remapped */
6777     } /* end of for loop stepping through fonts */
6778
6779 //    fputs("fend\n", fp_out);
6780     PSputs("fend\n", fp_out);
6781     writedviend(fp_out);        /* 1992/Nov/17 */
6782   } /* end of need remapped */
6783
6784 /*  NOTE: this only counts the resident fonts that get remapped ? */
6785 /*  if (verboseflag && nremapped != 0)
6786       printf("- remapped %d fonts ", nremapped); */
6787 /*  n = nremapped + nansified; */
6788 /*  if (verboseflag && n != 0) */
6789   if (verboseflag) {
6790     if (nremapped > 0 || nansified > 0) {
6791       if (nremapped > 0) {
6792         sprintf(logline, " - remapped %d font%s", nremapped,
6793           (nremapped == 1) ? "" : "s");
6794         showline(logline, 0);
6795       }
6796       if (nansified) {
6797         sprintf(logline, " - remapped %d font%s to `%s' encoding", nansified,
6798           (nansified == 1) ? "" : "s", textencoding);
6799         showline(logline, 0);
6800       }
6801 /*      putc('.', stdout); */
6802 /*      putc('\n', stdout); */
6803       showline(".\n", 0);
6804     }
6805 /* suppress the above if remapped font is not resident ? */
6806   }
6807 /* now it is time to actually do the setfonts ! */
6808
6809   if (stripcomment == 0) {
6810 /*    fputs("%%BeginSetup\n, fp_out); */ /* ??? */
6811 //    fputs("% Font Defs\n", fp_out);
6812     PSputs("% Font Defs\n", fp_out);
6813   }
6814   
6815 /*  fprintf(fp_out, "dvidict begin\n"); */
6816   writedvistart(fp_out);        /* 93/Sep/30 */
6817 //  fprintf(fp_out, "fstart\n");    /* 93/Nov/2 */
6818   PSputs("fstart\n", fp_out);
6819 /*  if (bShortFont != 0) { */
6820   if (bShortFont != 0 && bUseInternal == 0) {   /* 1994/June/7 */
6821     for (f = 0; f < fnext; f++) dofont(fp_out, f, f);
6822   }
6823 /*  the first chunck of old code above came from here ... */
6824   else { /* not using short font numbers */  
6825     for (k=0; k < MAXFONTNUMBERS; k++) 
6826 /*      if ((f = finx[k]) >= 0) dofont(fp_out, f, k); */ /* 93/Dec/11 */
6827       if ((f = finx[k]) != BLANKFONT) dofont(fp_out, f, k);
6828   }
6829   
6830 /* the second chunck of old code above came from here ... */
6831 //  fprintf(fp_out, "fend\n");      /* 93/Nov/2 */
6832   PSputs("fend\n", fp_out);
6833
6834   writedviend(fp_out);        /* 1992/Nov/17 */
6835
6836 /*  fputs("%%EndSetup\n", fp_out); */ /* ??? */
6837 }
6838
6839 /* Following called from dvispeci.c */
6840 /* Don't expand %%IncludeFont for printer resident fonts */
6841 /* Use a fixed list ??? */
6842 /* tir, tii, tib, tibi, hv, hvo, hvb, hvbo, com, coo, cob, cobo, sy, zd */
6843
6844 int ResidentFont (char *FileName)       /* 1994/Feb/10 */
6845 {
6846   char *s, *t;
6847   int k;
6848
6849 #ifdef DEBUG
6850   if (traceflag)
6851   {
6852     sprintf(logline, "ResidentFont %s?\n", FileName); /* debugging 97/June/5 */
6853     showline(logline, 0);
6854   }
6855 #endif
6856 /*  extract just font file name - get rid of path */
6857 /*  if ((s = strrchr(FileName, '\\')) != NULL) s++;
6858   else if ((s = strrchr(FileName, '/')) != NULL) s++;
6859   else if ((s = strrchr(FileName, ':')) != NULL) s++;
6860   else s = FileName; */
6861   s = removepath(FileName);           /* 95/May/28 */
6862 /*  get rid of extension */
6863   if ((t = strrchr(s, '.')) != NULL) *t ='\0';
6864   t = s + strlen(s) - 1;
6865   while (*t == '_') *t-- = '\0';          /* strip underscores */
6866 #ifdef DEBUG
6867   if (traceflag) {
6868     sprintf(logline, "Looking for font file: `%s'\n", s);/* debugging 97/June/5 */
6869     showline(logline, 0);
6870   }
6871 #endif
6872   for (k = 0; k < ksubst; k++) {
6873     if (fontsubprop[k] & C_RESIDENT) {
6874 /*      if (strcmp (s, fontsubfrom + k * MAXTEXNAME) == 0) */
6875 //      if (stricmp (s, fontsubfrom + k * MAXTEXNAME) == 0)
6876       if (fontsubfrom[k] != NULL &&
6877           stricmp (s, fontsubfrom[k]) == 0)
6878         return 1; /* is resident in table */
6879     }
6880   }
6881   return 0;           /* not in table as resident font */
6882 }
6883
6884 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
6885
6886 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
6887
6888 /* should earlier BeginSetup and EndSetup be moved to after loading fonts ? */
6889
6890 /* should tokenize input ? - remove dependency on lines */
6891 /* definitely ignoring synthetic and hybrid fonts ? */
6892 /* change font dictionary allocation ? first line after end of FontInfo OK */
6893 /* abbreviate dup and put ? */
6894 /* flush space before ND or | - NOT SAFE ?, make selectable ? */
6895 /* flush \r both before encryption and after - make selectable ? */
6896
6897 /* extract actual FontName from font directory OK, not used */
6898 /* replace actual FontName with what was passed along from dvianal OK */
6899 /* make up copies of fonts with different metrics, if substituting OK */
6900 /* need to read tfm files for this OK */
6901
6902 /* need to check EOF in calls to getline */
6903
6904 /* RD could be -| and ND could be | OK */
6905 /* check on how this treats Subrs and OtherSubrs !!! */
6906
6907 /* do the right thing with StandardEncoding ? */
6908 /* will this every be used with fonts other than TeX fonts ? */
6909 /* distinguish TeX fonts ? */
6910
6911 /* possibly copy over that stuff from fontone.c */
6912 /* for constructing Encoding from StandardEncoding ? efficiency */
6913 /* break up big functions to allow global optimizations */
6914
6915 /* make default directory c:\psfonts instead of c:\cm ? */
6916
6917 /* allow for cmr10___.pfb format of file name OK */
6918
6919 /* make deletion of input files default - controlled by command line flag */
6920
6921 /* decrypt, remove first four bytes of each CharString reencrypt lenIV NO */
6922 /* allow for removal of four leading bytes in CharStrings ? NO */
6923
6924 /* make flushing of FontInfo optional ... */
6925
6926 /* give warning if ASCII section has wrong length ? */
6927
6928 /* send control D if output direct to printer, or if requested.  OK */
6929
6930 /* stick in %!PS-Adobe-2.0 etc etc at beginning ? OK */
6931
6932 /* in case only page interval output is selected, slight weirdness: */
6933 /* will set up fonts that are not used and hence not loaded */
6934 /* but no error results, Courier is substituted, but no one knows */
6935 /* since font never actually used ... */ /* to be fixed in merge OK ? */
6936
6937 /* may need facility to generate new uniqueIDs */
6938 /* better to leave uniqueID off copy of font ? YES */
6939 /* helpful generating new uniqueID ? NO */
6940
6941 /* distinguish force substitution from substitution when file not found */
6942 /* invoke substitution when file not found ? OK */
6943
6944 /* some time break up "extractfont" and "extract" */
6945
6946 /* use table for dehexing hex and for creating hex ? */
6947
6948 /* right now there is no check whether font substituted exists ! */
6949 /* if it is not found try using table again ? loops ? */
6950
6951 /* specify encoding vector in substitution file */
6952
6953 /* problems remain with remapping resident fonts ... */
6954
6955 /* deal with *force* in substitution table OK */
6956 /* deal with *remap* in substitution table OK */
6957
6958 /* maybe check whether font file already was .pfb before trying that ext OK */
6959
6960 /* search for *//* make parallel to above ! */
6961
6962 /* worry about possible problems from assumed font ending - breakearly ? */
6963 /* breakearly != 0 may be too risky - don't know what weird things happen */
6964
6965 /* should tokenize input ? - remove dependency on lines */
6966
6967 /* what about .pfb files that have return as line terminator ? OK */
6968 /* need to fix getline and getrealline to deal with this */
6969
6970 /* need to treat /Subr strings specially */
6971 /* particularly since they may be long */
6972
6973 /* output font file name in [..] always - even for remapped fonts ? */
6974
6975 /* major space user is charnames[MAXCHRS][MAXCHARNAME] = 8192 bytes */
6976 /* OK, cut in half by using pointers into namestring instead */
6977
6978 /* check if font is really needed before bothering to extract it OK */
6979
6980 /* `Substituting' Times-Roman for psmtr - isn't quite appropriate phrasing */
6981
6982 /* check that  long checksum = 0x424B5048; - add brownie points ? */
6983
6984 /* should *reside* imply *force* ? */ /* no, use *force* explicitely */
6985 /* should *remap* imply force ? */
6986
6987 /* maybe remove default font substitution table ? - always read it in ? */
6988
6989 /* don't reread font substitution table for each DVI file processed ? */
6990 /* NO, have to, since it may be on DVI file path ! */
6991
6992 /* simplify all that hair for making up encoding vectors ... */
6993
6994 /* don't use textext vec if output is to be previewed ? use flag to control */
6995
6996 /* assuming it is either RD or -| and ND or |- */
6997
6998 /* do we need to cripple UniqueID when reencoding and using dviencoding ? */
6999
7000 /* command line flag 'k' not tested (forces printer resident for all) */
7001
7002 /* Compound Fonts are `Oblique' and `Narrow' fonts.  Examples: */
7003 /* Courier-Oblique, Courier-BoldOblique */
7004 /* Helvetica-Oblique, Helvetica-BoldOblique */
7005 /* Helvetica-Narrow, Helvetica-Narrow-Bold */
7006 /* Helvetica-Narrow-Oblique, Helvetica-Narrow-BoldOblique */
7007 /* Typically these have Fontmatrix m11 != m22 or m21 != 0 */
7008
7009 /* What's the problem with synthetic fonts ? Why be paranoid ? */
7010 /* 1. They may pick up base font that is partial (but FontName changed?) */ 
7011 /* 2. They may create a font that is partial (but has original name) */
7012 /* 3. There may be a problem if font is remapped ? */
7013 /*    but only if the base font is picked up by some other font ... */
7014
7015 /* Some interpreters fail on textext encoding, cause its not 256 element */
7016 /* Some interpreters fail on shortened encoding, cause its not 256 element */
7017 /* examples: ALW II NTJ */
7018
7019 /* complain if `hires' so-called hybrid font ??? */
7020 /* ask user to use *synthetic* flag */ /* Not any more, hybrid font fixed */
7021
7022 /* problems with fonts that have wrappings mostly fixed */
7023 /* can handle wrapped synthetic fonts now */
7024 /* may be able to handle wrapped PFA fonts also */
7025
7026 /* Typical wrapping format: */
7027
7028 /* FontDirectory/Symbol known{/Symbol findfont dup/UniqueID known{dup */
7029 /* /UniqueID get 5016107 eq exch/FontType get 1 eq and}{pop false}ifelse */
7030 /* {save true}{false}ifelse}{false}ifelse */
7031
7032 /* cleartomark */
7033 /* {restore}if */
7034
7035 /* cleartomark{restore}if */
7036
7037 /* Note: In DOS, TFM file names are not case sensitive in TeX */
7038 /* however, here in dealing with font substitution file, things ARE */
7039 /* So, its possible to get confused because a font is found by TeX */
7040 /* but not matched in substitution table */
7041
7042 /* Note `k' turns on *force* and *reside* which may not be desirable for */
7043 /* lines like `cmr8 cmr7' which should only trigger if cmr8 is not found */
7044 /* However, the new scheme for getting FontNames from PFB files solves */
7045 /* this problem ... */
7046
7047 /* MM font support incomplete */
7048 /* presently downloads full font - need to provide for partial font */
7049 /* collect wantchrs contributions from MM instances for base */
7050 /* remap / encoding not checked out */
7051
7052 /* if forcereside on, we should still download/expand the PSS stubs ... */
7053
7054 /* extracttype3, does fontname get printed ? */
7055 /* mac style font, does fontname get printed ? */
7056 /* what is font can't be found does font name get printed ? */
7057 /* what is some error in extraction does font name get printed ? */
7058 /* repeated output of font name if switch between type3 and type1 */
7059
7060 /* Presently we reencode the PSS stub files if needed */
7061 /* We do not reencode the MM master file */
7062 /* Which means we can't do selected down loading quite yet */
7063 /* Also seems like we are reencoding to ENCODING the PSS stub */
7064 /* without knowing whether the base font is a text font! */
7065
7066 /*  if we want to use partial font downloading, then need to reencode */
7067 /*  and then we have to assume that all instances encoded the same ? */
7068 /*  we also then need to set up wantchrs[] as or of instances ... */