]> www.fi.muni.cz Git - evince.git/blob - pdf/xpdf/GlobalParams.cc
ded583f5194fc1add9ea54575fb077f1db328b71
[evince.git] / pdf / xpdf / GlobalParams.cc
1 //========================================================================
2 //
3 // GlobalParams.cc
4 //
5 // Copyright 2001-2002 Glyph & Cog, LLC
6 //
7 //========================================================================
8
9 #include <aconf.h>
10
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
13 #endif
14
15 #include <string.h>
16 #include <ctype.h>
17 #if HAVE_PAPER_H
18 #include <paper.h>
19 #endif
20 #include "gmem.h"
21 #include "GString.h"
22 #include "GList.h"
23 #include "GHash.h"
24 #include "gfile.h"
25 #include "Error.h"
26 #include "NameToCharCode.h"
27 #include "CharCodeToUnicode.h"
28 #include "UnicodeMap.h"
29 #include "CMap.h"
30 #include "BuiltinFontTables.h"
31 #include "FontEncodingTables.h"
32 #include "GlobalParams.h"
33
34 #if MULTITHREADED
35 #  define globalParamsLock gLockMutex(&mutex)
36 #  define globalParamsUnlock gUnlockMutex(&mutex)
37 #else
38 #  define globalParamsLock
39 #  define globalParamsUnlock
40 #endif
41
42 #include "NameToUnicodeTable.h"
43 #include "UnicodeMapTables.h"
44 #include "DisplayFontTable.h"
45 #include "UTF8.h"
46
47 //------------------------------------------------------------------------
48
49 GlobalParams *globalParams = NULL;
50
51 //------------------------------------------------------------------------
52 // DisplayFontParam
53 //------------------------------------------------------------------------
54
55 DisplayFontParam::DisplayFontParam(GString *nameA,
56                                    DisplayFontParamKind kindA) {
57   name = nameA;
58   kind = kindA;
59   switch (kind) {
60   case displayFontX:
61     x.xlfd = NULL;
62     x.encoding = NULL;
63     break;
64   case displayFontT1:
65     t1.fileName = NULL;
66     break;
67   case displayFontTT:
68     tt.fileName = NULL;
69     break;
70   }
71 }
72
73 DisplayFontParam::DisplayFontParam(char *nameA, char *xlfdA, char *encodingA) {
74   name = new GString(nameA);
75   kind = displayFontX;
76   x.xlfd = new GString(xlfdA);
77   x.encoding = new GString(encodingA);
78 }
79
80 DisplayFontParam::~DisplayFontParam() {
81   delete name;
82   switch (kind) {
83   case displayFontX:
84     if (x.xlfd) {
85       delete x.xlfd;
86     }
87     if (x.encoding) {
88       delete x.encoding;
89     }
90     break;
91   case displayFontT1:
92     if (t1.fileName) {
93       delete t1.fileName;
94     }
95     break;
96   case displayFontTT:
97     if (tt.fileName) {
98       delete tt.fileName;
99     }
100     break;
101   }
102 }
103
104 //------------------------------------------------------------------------
105 // PSFontParam
106 //------------------------------------------------------------------------
107
108 PSFontParam::PSFontParam(GString *pdfFontNameA, int wModeA,
109                          GString *psFontNameA, GString *encodingA) {
110   pdfFontName = pdfFontNameA;
111   wMode = wModeA;
112   psFontName = psFontNameA;
113   encoding = encodingA;
114 }
115
116 PSFontParam::~PSFontParam() {
117   delete pdfFontName;
118   delete psFontName;
119   if (encoding) {
120     delete encoding;
121   }
122 }
123
124 //------------------------------------------------------------------------
125 // parsing
126 //------------------------------------------------------------------------
127
128 GlobalParams::GlobalParams(char *cfgFileName) {
129   UnicodeMap *map;
130   DisplayFontParam *dfp;
131   GString *fileName;
132   FILE *f;
133   int i;
134
135 #if MULTITHREADED
136   gInitMutex(&mutex);
137 #endif
138
139   initBuiltinFontTables();
140
141   // scan the encoding in reverse because we want the lowest-numbered
142   // index for each char name ('space' is encoded twice)
143   macRomanReverseMap = new NameToCharCode();
144   for (i = 255; i >= 0; --i) {
145     if (macRomanEncoding[i]) {
146       macRomanReverseMap->add(macRomanEncoding[i], (CharCode)i);
147     }
148   }
149
150   nameToUnicode = new NameToCharCode();
151   cidToUnicodes = new GHash(gTrue);
152   residentUnicodeMaps = new GHash();
153   unicodeMaps = new GHash(gTrue);
154   cMapDirs = new GHash(gTrue);
155   toUnicodeDirs = new GList();
156   displayFonts = new GHash();
157   displayCIDFonts = new GHash();
158   displayNamedCIDFonts = new GHash();
159 #if HAVE_PAPER_H
160   char *paperName;
161   const struct paper *paperType;
162   paperinit();
163   if ((paperName = systempapername())) {
164     paperType = paperinfo(paperName);
165     psPaperWidth = (int)paperpswidth(paperType);
166     psPaperHeight = (int)paperpsheight(paperType);
167   } else {
168     error(-1, "No paper information available - using defaults");
169     psPaperWidth = defPaperWidth;
170     psPaperHeight = defPaperHeight;
171   }
172   paperdone();
173 #else
174   psPaperWidth = defPaperWidth;
175   psPaperHeight = defPaperHeight;
176 #endif
177   psDuplex = gFalse;
178   psLevel = psLevel2;
179   psFile = NULL;
180   psFonts = new GHash();
181   psNamedFonts16 = new GList();
182   psFonts16 = new GList();
183   psEmbedType1 = gTrue;
184   psEmbedTrueType = gTrue;
185   psEmbedCIDPostScript = gTrue;
186   psEmbedCIDTrueType = gTrue;
187   psOPI = gFalse;
188   psASCIIHex = gFalse;
189   textEncoding = new GString("Latin1");
190 #if defined(WIN32)
191   textEOL = eolDOS;
192 #elif defined(MACOS)
193   textEOL = eolMac;
194 #else
195   textEOL = eolUnix;
196 #endif
197   textKeepTinyChars = gFalse;
198   fontDirs = new GList();
199   initialZoom = new GString("1");
200   t1libControl = fontRastAALow;
201   freetypeControl = fontRastAALow;
202   urlCommand = NULL;
203   movieCommand = NULL;
204   mapNumericCharNames = gTrue;
205   printCommands = gFalse;
206   errQuiet = gFalse;
207
208   cidToUnicodeCache = new CIDToUnicodeCache();
209   unicodeMapCache = new UnicodeMapCache();
210   cMapCache = new CMapCache();
211
212   // set up the initial nameToUnicode table
213   for (i = 0; nameToUnicodeTab[i].name; ++i) {
214     nameToUnicode->add(nameToUnicodeTab[i].name, nameToUnicodeTab[i].u);
215   }
216
217   // set up the residentUnicodeMaps table
218   map = new UnicodeMap("Latin1", gFalse,
219                        latin1UnicodeMapRanges, latin1UnicodeMapLen);
220   residentUnicodeMaps->add(map->getEncodingName(), map);
221   map = new UnicodeMap("ASCII7", gFalse,
222                        ascii7UnicodeMapRanges, ascii7UnicodeMapLen);
223   residentUnicodeMaps->add(map->getEncodingName(), map);
224   map = new UnicodeMap("Symbol", gFalse,
225                        symbolUnicodeMapRanges, symbolUnicodeMapLen);
226   residentUnicodeMaps->add(map->getEncodingName(), map);
227   map = new UnicodeMap("ZapfDingbats", gFalse, zapfDingbatsUnicodeMapRanges,
228                        zapfDingbatsUnicodeMapLen);
229   residentUnicodeMaps->add(map->getEncodingName(), map);
230   map = new UnicodeMap("UTF-8", gTrue, &mapUTF8);
231   residentUnicodeMaps->add(map->getEncodingName(), map);
232   map = new UnicodeMap("UCS-2", gTrue, &mapUCS2);
233   residentUnicodeMaps->add(map->getEncodingName(), map);
234
235   // default displayFonts table
236   for (i = 0; displayFontTab[i].name; ++i) {
237     dfp = new DisplayFontParam(displayFontTab[i].name,
238                                displayFontTab[i].xlfd,
239                                displayFontTab[i].encoding);
240     displayFonts->add(dfp->name, dfp);
241   }
242
243   // look for a user config file, then a system-wide config file
244   f = NULL;
245   fileName = NULL;
246   if (cfgFileName && cfgFileName[0]) {
247     fileName = new GString(cfgFileName);
248     if (!(f = fopen(fileName->getCString(), "r"))) {
249       delete fileName;
250     }
251   }
252   if (!f) {
253     fileName = appendToPath(getHomeDir(), xpdfUserConfigFile);
254     if (!(f = fopen(fileName->getCString(), "r"))) {
255       delete fileName;
256     }
257   }
258   if (!f) {
259 #if defined(WIN32) && !defined(__CYGWIN32__)
260     char buf[512];
261     i = GetModuleFileName(NULL, buf, sizeof(buf));
262     if (i <= 0 || i >= sizeof(buf)) {
263       // error or path too long for buffer - just use the current dir
264       buf[0] = '\0';
265     }
266     fileName = grabPath(buf);
267     appendToPath(fileName, xpdfSysConfigFile);
268 #else
269     fileName = new GString(xpdfSysConfigFile);
270 #endif
271     if (!(f = fopen(fileName->getCString(), "r"))) {
272       delete fileName;
273     }
274   }
275   if (f) {
276     parseFile(fileName, f);
277     delete fileName;
278     fclose(f);
279   }
280 }
281
282 void GlobalParams::parseFile(GString *fileName, FILE *f) {
283   int line;
284   GList *tokens;
285   GString *cmd, *incFile;
286   char *p1, *p2;
287   char buf[512];
288   FILE *f2;
289
290   line = 1;
291   while (getLine(buf, sizeof(buf) - 1, f)) {
292
293     // break the line into tokens
294     tokens = new GList();
295     p1 = buf;
296     while (*p1) {
297       for (; *p1 && isspace(*p1); ++p1) ;
298       if (!*p1) {
299         break;
300       }
301       if (*p1 == '"' || *p1 == '\'') {
302         for (p2 = p1 + 1; *p2 && *p2 != *p1; ++p2) ;
303         ++p1;
304       } else {
305         for (p2 = p1 + 1; *p2 && !isspace(*p2); ++p2) ;
306       }
307       tokens->append(new GString(p1, p2 - p1));
308       p1 = *p2 ? p2 + 1 : p2;
309     }
310
311     if (tokens->getLength() > 0 &&
312         ((GString *)tokens->get(0))->getChar(0) != '#') {
313       cmd = (GString *)tokens->get(0);
314       if (!cmd->cmp("include")) {
315         if (tokens->getLength() == 2) {
316           incFile = (GString *)tokens->get(1);
317           if ((f2 = fopen(incFile->getCString(), "r"))) {
318             parseFile(incFile, f2);
319             fclose(f2);
320           } else {
321             error(-1, "Couldn't find included config file: '%s' (%s:%d)",
322                   incFile->getCString(), fileName->getCString(), line);
323           }
324         } else {
325           error(-1, "Bad 'include' config file command (%s:%d)",
326                 fileName->getCString(), line);
327         }
328       } else if (!cmd->cmp("nameToUnicode")) {
329         parseNameToUnicode(tokens, fileName, line);
330       } else if (!cmd->cmp("cidToUnicode")) {
331         parseCIDToUnicode(tokens, fileName, line);
332       } else if (!cmd->cmp("unicodeMap")) {
333         parseUnicodeMap(tokens, fileName, line);
334       } else if (!cmd->cmp("cMapDir")) {
335         parseCMapDir(tokens, fileName, line);
336       } else if (!cmd->cmp("toUnicodeDir")) {
337         parseToUnicodeDir(tokens, fileName, line);
338       } else if (!cmd->cmp("displayFontX")) {
339         parseDisplayFont(tokens, displayFonts, displayFontX, fileName, line);
340       } else if (!cmd->cmp("displayFontT1")) {
341         parseDisplayFont(tokens, displayFonts, displayFontT1, fileName, line);
342       } else if (!cmd->cmp("displayFontTT")) {
343         parseDisplayFont(tokens, displayFonts, displayFontTT, fileName, line);
344       } else if (!cmd->cmp("displayNamedCIDFontX")) {
345         parseDisplayFont(tokens, displayNamedCIDFonts,
346                          displayFontX, fileName, line);
347       } else if (!cmd->cmp("displayCIDFontX")) {
348         parseDisplayFont(tokens, displayCIDFonts,
349                          displayFontX, fileName, line);
350       } else if (!cmd->cmp("displayNamedCIDFontT1")) {
351         parseDisplayFont(tokens, displayNamedCIDFonts,
352                          displayFontT1, fileName, line);
353       } else if (!cmd->cmp("displayCIDFontT1")) {
354         parseDisplayFont(tokens, displayCIDFonts,
355                          displayFontT1, fileName, line);
356       } else if (!cmd->cmp("psFile")) {
357         parsePSFile(tokens, fileName, line);
358       } else if (!cmd->cmp("psFont")) {
359         parsePSFont(tokens, fileName, line);
360       } else if (!cmd->cmp("psNamedFont16")) {
361         parsePSFont16("psNamedFont16", psNamedFonts16,
362                       tokens, fileName, line);
363       } else if (!cmd->cmp("psFont16")) {
364         parsePSFont16("psFont16", psFonts16, tokens, fileName, line);
365       } else if (!cmd->cmp("psPaperSize")) {
366         parsePSPaperSize(tokens, fileName, line);
367       } else if (!cmd->cmp("psDuplex")) {
368         parseYesNo("psDuplex", &psDuplex, tokens, fileName, line);
369       } else if (!cmd->cmp("psLevel")) {
370         parsePSLevel(tokens, fileName, line);
371       } else if (!cmd->cmp("psEmbedType1Fonts")) {
372         parseYesNo("psEmbedType1", &psEmbedType1, tokens, fileName, line);
373       } else if (!cmd->cmp("psEmbedTrueTypeFonts")) {
374         parseYesNo("psEmbedTrueType", &psEmbedTrueType,
375                    tokens, fileName, line);
376       } else if (!cmd->cmp("psEmbedCIDPostScriptFonts")) {
377         parseYesNo("psEmbedCIDPostScript", &psEmbedCIDPostScript,
378                    tokens, fileName, line);
379       } else if (!cmd->cmp("psEmbedCIDTrueTypeFonts")) {
380         parseYesNo("psEmbedCIDTrueType", &psEmbedCIDTrueType,
381                    tokens, fileName, line);
382       } else if (!cmd->cmp("psOPI")) {
383         parseYesNo("psOPI", &psOPI, tokens, fileName, line);
384       } else if (!cmd->cmp("psASCIIHex")) {
385         parseYesNo("psASCIIHex", &psASCIIHex, tokens, fileName, line);
386       } else if (!cmd->cmp("textEncoding")) {
387         parseTextEncoding(tokens, fileName, line);
388       } else if (!cmd->cmp("textEOL")) {
389         parseTextEOL(tokens, fileName, line);
390       } else if (!cmd->cmp("textKeepTinyChars")) {
391         parseYesNo("textKeepTinyChars", &textKeepTinyChars,
392                    tokens, fileName, line);
393       } else if (!cmd->cmp("fontDir")) {
394         parseFontDir(tokens, fileName, line);
395       } else if (!cmd->cmp("initialZoom")) {
396         parseInitialZoom(tokens, fileName, line);
397       } else if (!cmd->cmp("t1libControl")) {
398         parseFontRastControl("t1libControl", &t1libControl,
399                              tokens, fileName, line);
400       } else if (!cmd->cmp("freetypeControl")) {
401         parseFontRastControl("freetypeControl", &freetypeControl,
402                              tokens, fileName, line);
403       } else if (!cmd->cmp("urlCommand")) {
404         parseCommand("urlCommand", &urlCommand, tokens, fileName, line);
405       } else if (!cmd->cmp("movieCommand")) {
406         parseCommand("movieCommand", &movieCommand, tokens, fileName, line);
407       } else if (!cmd->cmp("mapNumericCharNames")) {
408         parseYesNo("mapNumericCharNames", &mapNumericCharNames,
409                    tokens, fileName, line);
410       } else if (!cmd->cmp("printCommands")) {
411         parseYesNo("printCommands", &printCommands, tokens, fileName, line);
412       } else if (!cmd->cmp("errQuiet")) {
413         parseYesNo("errQuiet", &errQuiet, tokens, fileName, line);
414       } else if (!cmd->cmp("fontpath") || !cmd->cmp("fontmap")) {
415         error(-1, "Unknown config file command");
416         error(-1, "-- the config file format has changed since Xpdf 0.9x");
417       } else {
418         error(-1, "Unknown config file command '%s' (%s:%d)",
419               cmd->getCString(), fileName->getCString(), line);
420       }
421     }
422
423     deleteGList(tokens, GString);
424     ++line;
425   }
426 }
427
428 void GlobalParams::parseNameToUnicode(GList *tokens, GString *fileName,
429                                          int line) {
430   GString *name;
431   char *tok1, *tok2;
432   FILE *f;
433   char buf[256];
434   int line2;
435   Unicode u;
436
437   if (tokens->getLength() != 2) {
438     error(-1, "Bad 'nameToUnicode' config file command (%s:%d)",
439           fileName->getCString(), line);
440     return;
441   }
442   name = (GString *)tokens->get(1);
443   if (!(f = fopen(name->getCString(), "r"))) {
444     error(-1, "Couldn't open 'nameToUnicode' file '%s'",
445           name->getCString());
446     return;
447   }
448   line2 = 1;
449   while (getLine(buf, sizeof(buf), f)) {
450     tok1 = strtok(buf, " \t\r\n");
451     tok2 = strtok(NULL, " \t\r\n");
452     if (tok1 && tok2) {
453       sscanf(tok1, "%x", &u);
454       nameToUnicode->add(tok2, u);
455     } else {
456       error(-1, "Bad line in 'nameToUnicode' file (%s:%d)", name, line2);
457     }
458     ++line2;
459   }
460   fclose(f);
461 }
462
463 void GlobalParams::parseCIDToUnicode(GList *tokens, GString *fileName,
464                                      int line) {
465   GString *collection, *name, *old;
466
467   if (tokens->getLength() != 3) {
468     error(-1, "Bad 'cidToUnicode' config file command (%s:%d)",
469           fileName->getCString(), line);
470     return;
471   }
472   collection = (GString *)tokens->get(1);
473   name = (GString *)tokens->get(2);
474   if ((old = (GString *)cidToUnicodes->remove(collection))) {
475     delete old;
476   }
477   cidToUnicodes->add(collection->copy(), name->copy());
478 }
479
480 void GlobalParams::parseUnicodeMap(GList *tokens, GString *fileName,
481                                    int line) {
482   GString *encodingName, *name, *old;
483
484   if (tokens->getLength() != 3) {
485     error(-1, "Bad 'unicodeMap' config file command (%s:%d)",
486           fileName->getCString(), line);
487     return;
488   }
489   encodingName = (GString *)tokens->get(1);
490   name = (GString *)tokens->get(2);
491   if ((old = (GString *)unicodeMaps->remove(encodingName))) {
492     delete old;
493   }
494   unicodeMaps->add(encodingName->copy(), name->copy());
495 }
496
497 void GlobalParams::parseCMapDir(GList *tokens, GString *fileName, int line) {
498   GString *collection, *dir;
499   GList *list;
500
501   if (tokens->getLength() != 3) {
502     error(-1, "Bad 'cMapDir' config file command (%s:%d)",
503           fileName->getCString(), line);
504     return;
505   }
506   collection = (GString *)tokens->get(1);
507   dir = (GString *)tokens->get(2);
508   if (!(list = (GList *)cMapDirs->lookup(collection))) {
509     list = new GList();
510     cMapDirs->add(collection->copy(), list);
511   }
512   list->append(dir->copy());
513 }
514
515 void GlobalParams::parseToUnicodeDir(GList *tokens, GString *fileName,
516                                      int line) {
517   if (tokens->getLength() != 2) {
518     error(-1, "Bad 'toUnicodeDir' config file command (%s:%d)",
519           fileName->getCString(), line);
520     return;
521   }
522   toUnicodeDirs->append(((GString *)tokens->get(1))->copy());
523 }
524
525 void GlobalParams::parseDisplayFont(GList *tokens, GHash *fontHash,
526                                     DisplayFontParamKind kind,
527                                     GString *fileName, int line) {
528   DisplayFontParam *param, *old;
529
530   if (tokens->getLength() < 2) {
531     goto err1;
532   }
533   param = new DisplayFontParam(((GString *)tokens->get(1))->copy(), kind);
534   
535   switch (kind) {
536   case displayFontX:
537     if (tokens->getLength() != 4) {
538       goto err2;
539     }
540     param->x.xlfd = ((GString *)tokens->get(2))->copy();
541     param->x.encoding = ((GString *)tokens->get(3))->copy();
542     break;
543   case displayFontT1:
544     if (tokens->getLength() != 3) {
545       goto err2;
546     }
547     param->t1.fileName = ((GString *)tokens->get(2))->copy();
548     break;
549   case displayFontTT:
550     if (tokens->getLength() != 3) {
551       goto err2;
552     }
553     param->tt.fileName = ((GString *)tokens->get(2))->copy();
554     break;
555   }
556
557   if ((old = (DisplayFontParam *)fontHash->remove(param->name))) {
558     delete old;
559   }
560   fontHash->add(param->name, param);
561   return;
562
563  err2:
564   delete param;
565  err1:
566   error(-1, "Bad 'display*Font*' config file command (%s:%d)",
567         fileName->getCString(), line);
568 }
569
570 void GlobalParams::parsePSPaperSize(GList *tokens, GString *fileName,
571                                     int line) {
572   GString *tok;
573
574   if (tokens->getLength() == 2) {
575     tok = (GString *)tokens->get(1);
576     if (!setPSPaperSize(tok->getCString())) {
577       error(-1, "Bad 'psPaperSize' config file command (%s:%d)",
578             fileName->getCString(), line);
579     }
580   } else if (tokens->getLength() == 3) {
581     tok = (GString *)tokens->get(1);
582     psPaperWidth = atoi(tok->getCString());
583     tok = (GString *)tokens->get(2);
584     psPaperHeight = atoi(tok->getCString());
585   } else {
586     error(-1, "Bad 'psPaperSize' config file command (%s:%d)",
587           fileName->getCString(), line);
588   }
589 }
590
591 void GlobalParams::parsePSLevel(GList *tokens, GString *fileName, int line) {
592   GString *tok;
593
594   if (tokens->getLength() != 2) {
595     error(-1, "Bad 'psLevel' config file command (%s:%d)",
596           fileName->getCString(), line);
597     return;
598   }
599   tok = (GString *)tokens->get(1);
600   if (!tok->cmp("level1")) {
601     psLevel = psLevel1;
602   } else if (!tok->cmp("level1sep")) {
603     psLevel = psLevel1Sep;
604   } else if (!tok->cmp("level2")) {
605     psLevel = psLevel2;
606   } else if (!tok->cmp("level2sep")) {
607     psLevel = psLevel2Sep;
608   } else if (!tok->cmp("level3")) {
609     psLevel = psLevel3;
610   } else if (!tok->cmp("level3Sep")) {
611     psLevel = psLevel3Sep;
612   } else {
613     error(-1, "Bad 'psLevel' config file command (%s:%d)",
614           fileName->getCString(), line);
615   }
616 }
617
618 void GlobalParams::parsePSFile(GList *tokens, GString *fileName, int line) {
619   if (tokens->getLength() != 2) {
620     error(-1, "Bad 'psFile' config file command (%s:%d)",
621           fileName->getCString(), line);
622     return;
623   }
624   if (psFile) {
625     delete psFile;
626   }
627   psFile = ((GString *)tokens->get(1))->copy();
628 }
629
630 void GlobalParams::parsePSFont(GList *tokens, GString *fileName, int line) {
631   PSFontParam *param;
632
633   if (tokens->getLength() != 3) {
634     error(-1, "Bad 'psFont' config file command (%s:%d)",
635           fileName->getCString(), line);
636     return;
637   }
638   param = new PSFontParam(((GString *)tokens->get(1))->copy(), 0,
639                           ((GString *)tokens->get(2))->copy(), NULL);
640   psFonts->add(param->pdfFontName, param);
641 }
642
643 void GlobalParams::parsePSFont16(char *cmdName, GList *fontList,
644                                  GList *tokens, GString *fileName, int line) {
645   PSFontParam *param;
646   int wMode;
647   GString *tok;
648
649   if (tokens->getLength() != 5) {
650     error(-1, "Bad '%s' config file command (%s:%d)",
651           cmdName, fileName->getCString(), line);
652     return;
653   }
654   tok = (GString *)tokens->get(2);
655   if (!tok->cmp("H")) {
656     wMode = 0;
657   } else if (!tok->cmp("V")) {
658     wMode = 1;
659   } else {
660     error(-1, "Bad '%s' config file command (%s:%d)",
661           cmdName, fileName->getCString(), line);
662     return;
663   }
664   param = new PSFontParam(((GString *)tokens->get(1))->copy(),
665                           wMode,
666                           ((GString *)tokens->get(3))->copy(),
667                           ((GString *)tokens->get(4))->copy());
668   fontList->append(param);
669 }
670
671 void GlobalParams::parseTextEncoding(GList *tokens, GString *fileName,
672                                      int line) {
673   if (tokens->getLength() != 2) {
674     error(-1, "Bad 'textEncoding' config file command (%s:%d)",
675           fileName->getCString(), line);
676     return;
677   }
678   delete textEncoding;
679   textEncoding = ((GString *)tokens->get(1))->copy();
680 }
681
682 void GlobalParams::parseTextEOL(GList *tokens, GString *fileName, int line) {
683   GString *tok;
684
685   if (tokens->getLength() != 2) {
686     error(-1, "Bad 'textEOL' config file command (%s:%d)",
687           fileName->getCString(), line);
688     return;
689   }
690   tok = (GString *)tokens->get(1);
691   if (!tok->cmp("unix")) {
692     textEOL = eolUnix;
693   } else if (!tok->cmp("dos")) {
694     textEOL = eolDOS;
695   } else if (!tok->cmp("mac")) {
696     textEOL = eolMac;
697   } else {
698     error(-1, "Bad 'textEOL' config file command (%s:%d)",
699           fileName->getCString(), line);
700   }
701 }
702
703 void GlobalParams::parseFontDir(GList *tokens, GString *fileName, int line) {
704   if (tokens->getLength() != 2) {
705     error(-1, "Bad 'fontDir' config file command (%s:%d)",
706           fileName->getCString(), line);
707     return;
708   }
709   fontDirs->append(((GString *)tokens->get(1))->copy());
710 }
711
712 void GlobalParams::parseInitialZoom(GList *tokens,
713                                     GString *fileName, int line) {
714   if (tokens->getLength() != 2) {
715     error(-1, "Bad 'initialZoom' config file command (%s:%d)",
716           fileName->getCString(), line);
717     return;
718   }
719   delete initialZoom;
720   initialZoom = ((GString *)tokens->get(1))->copy();
721 }
722
723 void GlobalParams::parseFontRastControl(char *cmdName, FontRastControl *val,
724                                         GList *tokens, GString *fileName,
725                                         int line) {
726   GString *tok;
727
728   if (tokens->getLength() != 2) {
729     error(-1, "Bad '%s' config file command (%s:%d)",
730           cmdName, fileName->getCString(), line);
731     return;
732   }
733   tok = (GString *)tokens->get(1);
734   if (!setFontRastControl(val, tok->getCString())) {
735     error(-1, "Bad '%s' config file command (%s:%d)",
736           cmdName, fileName->getCString(), line);
737   }
738 }
739
740 void GlobalParams::parseCommand(char *cmdName, GString **val,
741                                 GList *tokens, GString *fileName, int line) {
742   if (tokens->getLength() != 2) {
743     error(-1, "Bad '%s' config file command (%s:%d)",
744           cmdName, fileName->getCString(), line);
745     return;
746   }
747   if (*val) {
748     delete *val;
749   }
750   *val = ((GString *)tokens->get(1))->copy();
751 }
752
753 void GlobalParams::parseYesNo(char *cmdName, GBool *flag,
754                               GList *tokens, GString *fileName, int line) {
755   GString *tok;
756
757   if (tokens->getLength() != 2) {
758     error(-1, "Bad '%s' config file command (%s:%d)",
759           cmdName, fileName->getCString(), line);
760     return;
761   }
762   tok = (GString *)tokens->get(1);
763   if (!tok->cmp("yes")) {
764     *flag = gTrue;
765   } else if (!tok->cmp("no")) {
766     *flag = gFalse;
767   } else {
768     error(-1, "Bad '%s' config file command (%s:%d)",
769           cmdName, fileName->getCString(), line);
770   }
771 }
772
773 GlobalParams::~GlobalParams() {
774   GHashIter *iter;
775   GString *key;
776   GList *list;
777
778   freeBuiltinFontTables();
779
780   delete macRomanReverseMap;
781
782   delete nameToUnicode;
783   deleteGHash(cidToUnicodes, GString);
784   deleteGHash(residentUnicodeMaps, UnicodeMap);
785   deleteGHash(unicodeMaps, GString);
786   deleteGList(toUnicodeDirs, GString);
787   deleteGHash(displayFonts, DisplayFontParam);
788   deleteGHash(displayCIDFonts, DisplayFontParam);
789   deleteGHash(displayNamedCIDFonts, DisplayFontParam);
790   if (psFile) {
791     delete psFile;
792   }
793   deleteGHash(psFonts, PSFontParam);
794   deleteGList(psNamedFonts16, PSFontParam);
795   deleteGList(psFonts16, PSFontParam);
796   delete textEncoding;
797   deleteGList(fontDirs, GString);
798   delete initialZoom;
799   if (urlCommand) {
800     delete urlCommand;
801   }
802   if (movieCommand) {
803     delete movieCommand;
804   }
805
806   cMapDirs->startIter(&iter);
807   while (cMapDirs->getNext(&iter, &key, (void **)&list)) {
808     deleteGList(list, GString);
809   }
810   delete cMapDirs;
811
812   delete cidToUnicodeCache;
813   delete unicodeMapCache;
814   delete cMapCache;
815
816 #if MULTITHREADED
817   gDestroyMutex(&mutex);
818 #endif
819 }
820
821 //------------------------------------------------------------------------
822 // accessors
823 //------------------------------------------------------------------------
824
825 CharCode GlobalParams::getMacRomanCharCode(char *charName) {
826   return macRomanReverseMap->lookup(charName);
827 }
828
829 Unicode GlobalParams::mapNameToUnicode(char *charName) {
830   return nameToUnicode->lookup(charName);
831 }
832
833 FILE *GlobalParams::getCIDToUnicodeFile(GString *collection) {
834   GString *fileName;
835
836   if (!(fileName = (GString *)cidToUnicodes->lookup(collection))) {
837     return NULL;
838   }
839   return fopen(fileName->getCString(), "r");
840 }
841
842 UnicodeMap *GlobalParams::getResidentUnicodeMap(GString *encodingName) {
843   return (UnicodeMap *)residentUnicodeMaps->lookup(encodingName);
844 }
845
846 FILE *GlobalParams::getUnicodeMapFile(GString *encodingName) {
847   GString *fileName;
848
849   if (!(fileName = (GString *)unicodeMaps->lookup(encodingName))) {
850     return NULL;
851   }
852   return fopen(fileName->getCString(), "r");
853 }
854
855 FILE *GlobalParams::findCMapFile(GString *collection, GString *cMapName) {
856   GList *list;
857   GString *dir;
858   GString *fileName;
859   FILE *f;
860   int i;
861
862   if (!(list = (GList *)cMapDirs->lookup(collection))) {
863     return NULL;
864   }
865   for (i = 0; i < list->getLength(); ++i) {
866     dir = (GString *)list->get(i);
867     fileName = appendToPath(dir->copy(), cMapName->getCString());
868     f = fopen(fileName->getCString(), "r");
869     delete fileName;
870     if (f) {
871       return f;
872     }
873   }
874   return NULL;
875 }
876
877 FILE *GlobalParams::findToUnicodeFile(GString *name) {
878   GString *dir, *fileName;
879   FILE *f;
880   int i;
881
882   for (i = 0; i < toUnicodeDirs->getLength(); ++i) {
883     dir = (GString *)toUnicodeDirs->get(i);
884     fileName = appendToPath(dir->copy(), name->getCString());
885     f = fopen(fileName->getCString(), "r");
886     delete fileName;
887     if (f) {
888       return f;
889     }
890   }
891   return NULL;
892 }
893
894 DisplayFontParam *GlobalParams::getDisplayFont(GString *fontName) {
895   DisplayFontParam *dfp;
896
897   globalParamsLock;
898   dfp = (DisplayFontParam *)displayFonts->lookup(fontName);
899   globalParamsUnlock;
900   return dfp;
901 }
902
903 DisplayFontParam *GlobalParams::getDisplayCIDFont(GString *fontName,
904                                                   GString *collection) {
905   DisplayFontParam *dfp;
906
907   if (!fontName ||
908       !(dfp = (DisplayFontParam *)displayNamedCIDFonts->lookup(fontName))) {
909     dfp = (DisplayFontParam *)displayCIDFonts->lookup(collection);
910   }
911   return dfp;
912 }
913
914 GString *GlobalParams::getPSFile() {
915   GString *s;
916
917   globalParamsLock;
918   s = psFile ? psFile->copy() : (GString *)NULL;
919   globalParamsUnlock;
920   return s;
921 }
922
923 int GlobalParams::getPSPaperWidth() {
924   int w;
925
926   globalParamsLock;
927   w = psPaperWidth;
928   globalParamsUnlock;
929   return w;
930 }
931
932 int GlobalParams::getPSPaperHeight() {
933   int h;
934
935   globalParamsLock;
936   h = psPaperHeight;
937   globalParamsUnlock;
938   return h;
939 }
940
941 GBool GlobalParams::getPSDuplex() {
942   GBool d;
943
944   globalParamsLock;
945   d = psDuplex;
946   globalParamsUnlock;
947   return d;
948 }
949
950 PSLevel GlobalParams::getPSLevel() {
951   PSLevel level;
952
953   globalParamsLock;
954   level = psLevel;
955   globalParamsUnlock;
956   return level;
957 }
958
959 PSFontParam *GlobalParams::getPSFont(GString *fontName) {
960   return (PSFontParam *)psFonts->lookup(fontName);
961 }
962
963 PSFontParam *GlobalParams::getPSFont16(GString *fontName,
964                                        GString *collection, int wMode) {
965   PSFontParam *p;
966   int i;
967
968   p = NULL;
969   if (fontName) {
970     for (i = 0; i < psNamedFonts16->getLength(); ++i) {
971       p = (PSFontParam *)psNamedFonts16->get(i);
972       if (!p->pdfFontName->cmp(fontName) &&
973           p->wMode == wMode) {
974         break;
975       }
976       p = NULL;
977     }
978   }
979   if (!p && collection) {
980     for (i = 0; i < psFonts16->getLength(); ++i) {
981       p = (PSFontParam *)psFonts16->get(i);
982       if (!p->pdfFontName->cmp(collection) &&
983           p->wMode == wMode) {
984         break;
985       }
986       p = NULL;
987     }
988   }
989   return p;
990 }
991
992 GBool GlobalParams::getPSEmbedType1() {
993   GBool e;
994
995   globalParamsLock;
996   e = psEmbedType1;
997   globalParamsUnlock;
998   return e;
999 }
1000
1001 GBool GlobalParams::getPSEmbedTrueType() {
1002   GBool e;
1003
1004   globalParamsLock;
1005   e = psEmbedTrueType;
1006   globalParamsUnlock;
1007   return e;
1008 }
1009
1010 GBool GlobalParams::getPSEmbedCIDPostScript() {
1011   GBool e;
1012
1013   globalParamsLock;
1014   e = psEmbedCIDPostScript;
1015   globalParamsUnlock;
1016   return e;
1017 }
1018
1019 GBool GlobalParams::getPSEmbedCIDTrueType() {
1020   GBool e;
1021
1022   globalParamsLock;
1023   e = psEmbedCIDTrueType;
1024   globalParamsUnlock;
1025   return e;
1026 }
1027
1028 GBool GlobalParams::getPSOPI() {
1029   GBool opi;
1030
1031   globalParamsLock;
1032   opi = psOPI;
1033   globalParamsUnlock;
1034   return opi;
1035 }
1036
1037 GBool GlobalParams::getPSASCIIHex() {
1038   GBool ah;
1039
1040   globalParamsLock;
1041   ah = psASCIIHex;
1042   globalParamsUnlock;
1043   return ah;
1044 }
1045
1046 EndOfLineKind GlobalParams::getTextEOL() {
1047   EndOfLineKind eol;
1048
1049   globalParamsLock;
1050   eol = textEOL;
1051   globalParamsUnlock;
1052   return eol;
1053 }
1054
1055 GBool GlobalParams::getTextKeepTinyChars() {
1056   GBool tiny;
1057
1058   globalParamsLock;
1059   tiny = textKeepTinyChars;
1060   globalParamsUnlock;
1061   return tiny;
1062 }
1063
1064 GString *GlobalParams::findFontFile(GString *fontName,
1065                                     char *ext1, char *ext2) {
1066   GString *dir, *fileName;
1067   FILE *f;
1068   int i;
1069
1070   for (i = 0; i < fontDirs->getLength(); ++i) {
1071     dir = (GString *)fontDirs->get(i);
1072     if (ext1) {
1073       fileName = appendToPath(dir->copy(), fontName->getCString());
1074       fileName->append(ext1);
1075       if ((f = fopen(fileName->getCString(), "r"))) {
1076         fclose(f);
1077         return fileName;
1078       }
1079       delete fileName;
1080     }
1081     if (ext2) {
1082       fileName = appendToPath(dir->copy(), fontName->getCString());
1083       fileName->append(ext2);
1084       if ((f = fopen(fileName->getCString(), "r"))) {
1085         fclose(f);
1086         return fileName;
1087       }
1088       delete fileName;
1089     }
1090   }
1091   return NULL;
1092 }
1093
1094 GString *GlobalParams::getInitialZoom() {
1095   GString *s;
1096
1097   globalParamsLock;
1098   s = initialZoom->copy();
1099   globalParamsUnlock;
1100   return s;
1101 }
1102
1103 FontRastControl GlobalParams::getT1libControl() {
1104   FontRastControl c;
1105
1106   globalParamsLock;
1107   c = t1libControl;
1108   globalParamsUnlock;
1109   return c;
1110 }
1111
1112 FontRastControl GlobalParams::getFreeTypeControl() {
1113   FontRastControl c;
1114
1115   globalParamsLock;
1116   c = freetypeControl;
1117   globalParamsUnlock;
1118   return c;
1119 }
1120
1121 GBool GlobalParams::getMapNumericCharNames() {
1122   GBool map;
1123
1124   globalParamsLock;
1125   map = mapNumericCharNames;
1126   globalParamsUnlock;
1127   return map;
1128 }
1129
1130 GBool GlobalParams::getPrintCommands() {
1131   GBool p;
1132
1133   globalParamsLock;
1134   p = printCommands;
1135   globalParamsUnlock;
1136   return p;
1137 }
1138
1139 GBool GlobalParams::getErrQuiet() {
1140   GBool q;
1141
1142   globalParamsLock;
1143   q = errQuiet;
1144   globalParamsUnlock;
1145   return q;
1146 }
1147
1148 CharCodeToUnicode *GlobalParams::getCIDToUnicode(GString *collection) {
1149   CharCodeToUnicode *ctu;
1150
1151   globalParamsLock;
1152   ctu = cidToUnicodeCache->getCIDToUnicode(collection);
1153   globalParamsUnlock;
1154   return ctu;
1155 }
1156
1157 UnicodeMap *GlobalParams::getUnicodeMap(GString *encodingName) {
1158   UnicodeMap *map;
1159
1160   globalParamsLock;
1161   map = getUnicodeMap2(encodingName);
1162   globalParamsUnlock;
1163   return map;
1164 }
1165
1166 UnicodeMap *GlobalParams::getUnicodeMap2(GString *encodingName) {
1167   UnicodeMap *map;
1168
1169   if ((map = getResidentUnicodeMap(encodingName))) {
1170     map->incRefCnt();
1171   } else {
1172     map = unicodeMapCache->getUnicodeMap(encodingName);
1173   }
1174   return map;
1175 }
1176
1177 CMap *GlobalParams::getCMap(GString *collection, GString *cMapName) {
1178   CMap *cMap;
1179
1180   globalParamsLock;
1181   cMap = cMapCache->getCMap(collection, cMapName);
1182   globalParamsUnlock;
1183   return cMap;
1184 }
1185
1186 UnicodeMap *GlobalParams::getTextEncoding() {
1187   UnicodeMap *map;
1188
1189   globalParamsLock;
1190   map = getUnicodeMap2(textEncoding);
1191   globalParamsUnlock;
1192   return map;
1193 }
1194
1195 //------------------------------------------------------------------------
1196 // functions to set parameters
1197 //------------------------------------------------------------------------
1198
1199 void GlobalParams::addDisplayFont(DisplayFontParam *param) {
1200   DisplayFontParam *old;
1201
1202   globalParamsLock;
1203   if ((old = (DisplayFontParam *)displayFonts->remove(param->name))) {
1204     delete old;
1205   }
1206   displayFonts->add(param->name, param);
1207   globalParamsUnlock;
1208 }
1209
1210 void GlobalParams::setPSFile(char *file) {
1211   globalParamsLock;
1212   if (psFile) {
1213     delete psFile;
1214   }
1215   psFile = new GString(file);
1216   globalParamsUnlock;
1217 }
1218
1219 GBool GlobalParams::setPSPaperSize(char *size) {
1220   globalParamsLock;
1221   if (!strcmp(size, "letter")) {
1222     psPaperWidth = 612;
1223     psPaperHeight = 792;
1224   } else if (!strcmp(size, "legal")) {
1225     psPaperWidth = 612;
1226     psPaperHeight = 1008;
1227   } else if (!strcmp(size, "A4")) {
1228     psPaperWidth = 595;
1229     psPaperHeight = 842;
1230   } else if (!strcmp(size, "A3")) {
1231     psPaperWidth = 842;
1232     psPaperHeight = 1190;
1233   } else {
1234     globalParamsUnlock;
1235     return gFalse;
1236   }
1237   globalParamsUnlock;
1238   return gTrue;
1239 }
1240
1241 void GlobalParams::setPSPaperWidth(int width) {
1242   globalParamsLock;
1243   psPaperWidth = width;
1244   globalParamsUnlock;
1245 }
1246
1247 void GlobalParams::setPSPaperHeight(int height) {
1248   globalParamsLock;
1249   psPaperHeight = height;
1250   globalParamsUnlock;
1251 }
1252
1253 void GlobalParams::setPSDuplex(GBool duplex) {
1254   globalParamsLock;
1255   psDuplex = duplex;
1256   globalParamsUnlock;
1257 }
1258
1259 void GlobalParams::setPSLevel(PSLevel level) {
1260   globalParamsLock;
1261   psLevel = level;
1262   globalParamsUnlock;
1263 }
1264
1265 void GlobalParams::setPSEmbedType1(GBool embed) {
1266   globalParamsLock;
1267   psEmbedType1 = embed;
1268   globalParamsUnlock;
1269 }
1270
1271 void GlobalParams::setPSEmbedTrueType(GBool embed) {
1272   globalParamsLock;
1273   psEmbedTrueType = embed;
1274   globalParamsUnlock;
1275 }
1276
1277 void GlobalParams::setPSEmbedCIDPostScript(GBool embed) {
1278   globalParamsLock;
1279   psEmbedCIDPostScript = embed;
1280   globalParamsUnlock;
1281 }
1282
1283 void GlobalParams::setPSEmbedCIDTrueType(GBool embed) {
1284   globalParamsLock;
1285   psEmbedCIDTrueType = embed;
1286   globalParamsUnlock;
1287 }
1288
1289 void GlobalParams::setPSOPI(GBool opi) {
1290   globalParamsLock;
1291   psOPI = opi;
1292   globalParamsUnlock;
1293 }
1294
1295 void GlobalParams::setPSASCIIHex(GBool hex) {
1296   globalParamsLock;
1297   psASCIIHex = hex;
1298   globalParamsUnlock;
1299 }
1300
1301 void GlobalParams::setTextEncoding(char *encodingName) {
1302   globalParamsLock;
1303   delete textEncoding;
1304   textEncoding = new GString(encodingName);
1305   globalParamsUnlock;
1306 }
1307
1308 GBool GlobalParams::setTextEOL(char *s) {
1309   globalParamsLock;
1310   if (!strcmp(s, "unix")) {
1311     textEOL = eolUnix;
1312   } else if (!strcmp(s, "dos")) {
1313     textEOL = eolDOS;
1314   } else if (!strcmp(s, "mac")) {
1315     textEOL = eolMac;
1316   } else {
1317     globalParamsUnlock;
1318     return gFalse;
1319   }
1320   globalParamsUnlock;
1321   return gTrue;
1322 }
1323
1324 void GlobalParams::setTextKeepTinyChars(GBool keep) {
1325   globalParamsLock;
1326   textKeepTinyChars = keep;
1327   globalParamsUnlock;
1328 }
1329
1330 void GlobalParams::setInitialZoom(char *s) {
1331   globalParamsLock;
1332   delete initialZoom;
1333   initialZoom = new GString(s);
1334   globalParamsUnlock;
1335 }
1336
1337 GBool GlobalParams::setT1libControl(char *s) {
1338   GBool ok;
1339
1340   globalParamsLock;
1341   ok = setFontRastControl(&t1libControl, s);
1342   globalParamsUnlock;
1343   return ok;
1344 }
1345
1346 GBool GlobalParams::setFreeTypeControl(char *s) {
1347   GBool ok;
1348
1349   globalParamsLock;
1350   ok = setFontRastControl(&freetypeControl, s);
1351   globalParamsUnlock;
1352   return ok;
1353 }
1354
1355 GBool GlobalParams::setFontRastControl(FontRastControl *val, char *s) {
1356   if (!strcmp(s, "none")) {
1357     *val = fontRastNone;
1358   } else if (!strcmp(s, "plain")) {
1359     *val = fontRastPlain;
1360   } else if (!strcmp(s, "low")) {
1361     *val = fontRastAALow;
1362   } else if (!strcmp(s, "high")) {
1363     *val = fontRastAAHigh;
1364   } else {
1365     return gFalse;
1366   }
1367   return gTrue;
1368 }
1369
1370 void GlobalParams::setMapNumericCharNames(GBool map) {
1371   globalParamsLock;
1372   mapNumericCharNames = map;
1373   globalParamsUnlock;
1374 }
1375
1376 void GlobalParams::setPrintCommands(GBool printCommandsA) {
1377   globalParamsLock;
1378   printCommands = printCommandsA;
1379   globalParamsUnlock;
1380 }
1381
1382 void GlobalParams::setErrQuiet(GBool errQuietA) {
1383   globalParamsLock;
1384   errQuiet = errQuietA;
1385   globalParamsUnlock;
1386 }