ee05db1d88bb9edbdbe21283be11305b278d54ec
[swftools.git] / pdf2swf / xpdf / GlobalParams.cc
1 //========================================================================
2 //
3 // GlobalParams.cc
4 //
5 // Copyright 2001-2003 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 <stdio.h>
17 #include <ctype.h>
18 #if HAVE_PAPER_H
19 #include <paper.h>
20 #endif
21 #include "gmem.h"
22 #include "GString.h"
23 #include "GList.h"
24 #include "GHash.h"
25 #include "gfile.h"
26 #include "Error.h"
27 #include "NameToCharCode.h"
28 #include "CharCodeToUnicode.h"
29 #include "UnicodeMap.h"
30 #include "CMap.h"
31 #include "BuiltinFontTables.h"
32 #include "FontEncodingTables.h"
33 #include "GlobalParams.h"
34
35 #if MULTITHREADED
36 #  define lockGlobalParams            gLockMutex(&mutex)
37 #  define lockUnicodeMapCache         gLockMutex(&unicodeMapCacheMutex)
38 #  define lockCMapCache               gLockMutex(&cMapCacheMutex)
39 #  define unlockGlobalParams          gUnlockMutex(&mutex)
40 #  define unlockUnicodeMapCache       gUnlockMutex(&unicodeMapCacheMutex)
41 #  define unlockCMapCache             gUnlockMutex(&cMapCacheMutex)
42 #else
43 #  define lockGlobalParams
44 #  define lockUnicodeMapCache
45 #  define lockCMapCache
46 #  define unlockGlobalParams
47 #  define unlockUnicodeMapCache
48 #  define unlockCMapCache
49 #endif
50
51 #include "NameToUnicodeTable.h"
52 #include "UnicodeMapTables.h"
53 #include "UTF8.h"
54
55 //------------------------------------------------------------------------
56
57 #define cidToUnicodeCacheSize     4
58 #define unicodeToUnicodeCacheSize 4
59
60 //------------------------------------------------------------------------
61
62 static struct {
63   char *name;
64   char *fileName;
65 } displayFontTab[] = {
66   {"Courier",               "n022003l.pfb"},
67   {"Courier-Bold",          "n022004l.pfb"},
68   {"Courier-BoldOblique",   "n022024l.pfb"},
69   {"Courier-Oblique",       "n022023l.pfb"},
70   {"Helvetica",             "n019003l.pfb"},
71   {"Helvetica-Bold",        "n019004l.pfb"},
72   {"Helvetica-BoldOblique", "n019024l.pfb"},
73   {"Helvetica-Oblique",     "n019023l.pfb"},
74   {"Symbol",                "s050000l.pfb"},
75   {"Times-Bold",            "n021004l.pfb"},
76   {"Times-BoldItalic",      "n021024l.pfb"},
77   {"Times-Italic",          "n021023l.pfb"},
78   {"Times-Roman",           "n021003l.pfb"},
79   {"ZapfDingbats",          "d050000l.pfb"},
80   {NULL}
81 };
82
83 static char *displayFontDirs[] = {
84   "/usr/share/ghostscript/fonts",
85   "/usr/local/share/ghostscript/fonts",
86   "/usr/share/fonts/default/Type1",
87   NULL
88 };
89
90 //------------------------------------------------------------------------
91
92 GlobalParams *globalParams = NULL;
93
94 //------------------------------------------------------------------------
95 // DisplayFontParam
96 //------------------------------------------------------------------------
97
98 DisplayFontParam::DisplayFontParam(GString *nameA,
99                                    DisplayFontParamKind kindA) {
100   name = nameA;
101   kind = kindA;
102   switch (kind) {
103   case displayFontT1:
104     t1.fileName = NULL;
105     break;
106   case displayFontTT:
107     tt.fileName = NULL;
108     break;
109   }
110 }
111
112 DisplayFontParam::~DisplayFontParam() {
113   delete name;
114   switch (kind) {
115   case displayFontT1:
116     if (t1.fileName) {
117       delete t1.fileName;
118     }
119     break;
120   case displayFontTT:
121     if (tt.fileName) {
122       delete tt.fileName;
123     }
124     break;
125   }
126 }
127
128 //------------------------------------------------------------------------
129 // PSFontParam
130 //------------------------------------------------------------------------
131
132 PSFontParam::PSFontParam(GString *pdfFontNameA, int wModeA,
133                          GString *psFontNameA, GString *encodingA) {
134   pdfFontName = pdfFontNameA;
135   wMode = wModeA;
136   psFontName = psFontNameA;
137   encoding = encodingA;
138 }
139
140 PSFontParam::~PSFontParam() {
141   delete pdfFontName;
142   delete psFontName;
143   if (encoding) {
144     delete encoding;
145   }
146 }
147
148 //------------------------------------------------------------------------
149 // parsing
150 //------------------------------------------------------------------------
151
152 GlobalParams::GlobalParams(char *cfgFileName) {
153   UnicodeMap *map;
154   GString *fileName;
155   FILE *f;
156   int i;
157
158 #if MULTITHREADED
159   gInitMutex(&mutex);
160   gInitMutex(&unicodeMapCacheMutex);
161   gInitMutex(&cMapCacheMutex);
162 #endif
163
164   initBuiltinFontTables();
165
166   // scan the encoding in reverse because we want the lowest-numbered
167   // index for each char name ('space' is encoded twice)
168   macRomanReverseMap = new NameToCharCode();
169   for (i = 255; i >= 0; --i) {
170     if (macRomanEncoding[i]) {
171       macRomanReverseMap->add(macRomanEncoding[i], (CharCode)i);
172     }
173   }
174
175   nameToUnicode = new NameToCharCode();
176   cidToUnicodes = new GHash(gTrue);
177   unicodeToUnicodes = new GHash(gTrue);
178   residentUnicodeMaps = new GHash();
179   unicodeMaps = new GHash(gTrue);
180   cMapDirs = new GHash(gTrue);
181   toUnicodeDirs = new GList();
182   displayFonts = new GHash();
183   displayCIDFonts = new GHash();
184   displayNamedCIDFonts = new GHash();
185 #if HAVE_PAPER_H
186   char *paperName;
187   const struct paper *paperType;
188   paperinit();
189   if ((paperName = systempapername())) {
190     paperType = paperinfo(paperName);
191     psPaperWidth = (int)paperpswidth(paperType);
192     psPaperHeight = (int)paperpsheight(paperType);
193   } else {
194     error(-1, "No paper information available - using defaults");
195     psPaperWidth = defPaperWidth;
196     psPaperHeight = defPaperHeight;
197   }
198   paperdone();
199 #else
200   psPaperWidth = defPaperWidth;
201   psPaperHeight = defPaperHeight;
202 #endif
203   psImageableLLX = psImageableLLY = 0;
204   psImageableURX = psPaperWidth;
205   psImageableURY = psPaperHeight;
206   psCrop = gTrue;
207   psExpandSmaller = gFalse;
208   psShrinkLarger = gTrue;
209   psCenter = gTrue;
210   psDuplex = gFalse;
211   psLevel = psLevel2;
212   psFile = NULL;
213   psFonts = new GHash();
214   psNamedFonts16 = new GList();
215   psFonts16 = new GList();
216   psEmbedType1 = gTrue;
217   psEmbedTrueType = gTrue;
218   psEmbedCIDPostScript = gTrue;
219   psEmbedCIDTrueType = gTrue;
220   psOPI = gFalse;
221   psASCIIHex = gFalse;
222   textEncoding = new GString("Latin1");
223 #if defined(WIN32)
224   textEOL = eolDOS;
225 #elif defined(MACOS)
226   textEOL = eolMac;
227 #else
228   textEOL = eolUnix;
229 #endif
230   textPageBreaks = gTrue;
231   textKeepTinyChars = gFalse;
232   fontDirs = new GList();
233   initialZoom = new GString("125");
234   enableT1lib = gTrue;
235   enableFreeType = gTrue;
236   antialias = gTrue;
237   urlCommand = NULL;
238   movieCommand = NULL;
239   mapNumericCharNames = gTrue;
240   printCommands = gFalse;
241   errQuiet = gFalse;
242
243   cidToUnicodeCache = new CharCodeToUnicodeCache(cidToUnicodeCacheSize);
244   unicodeToUnicodeCache =
245       new CharCodeToUnicodeCache(unicodeToUnicodeCacheSize);
246   unicodeMapCache = new UnicodeMapCache();
247   cMapCache = new CMapCache();
248
249   // set up the initial nameToUnicode table
250   for (i = 0; nameToUnicodeTab[i].name; ++i) {
251     nameToUnicode->add(nameToUnicodeTab[i].name, nameToUnicodeTab[i].u);
252   }
253
254   // set up the residentUnicodeMaps table
255   map = new UnicodeMap("Latin1", gFalse,
256                        latin1UnicodeMapRanges, latin1UnicodeMapLen);
257   residentUnicodeMaps->add(map->getEncodingName(), map);
258   map = new UnicodeMap("ASCII7", gFalse,
259                        ascii7UnicodeMapRanges, ascii7UnicodeMapLen);
260   residentUnicodeMaps->add(map->getEncodingName(), map);
261   map = new UnicodeMap("Symbol", gFalse,
262                        symbolUnicodeMapRanges, symbolUnicodeMapLen);
263   residentUnicodeMaps->add(map->getEncodingName(), map);
264   map = new UnicodeMap("ZapfDingbats", gFalse, zapfDingbatsUnicodeMapRanges,
265                        zapfDingbatsUnicodeMapLen);
266   residentUnicodeMaps->add(map->getEncodingName(), map);
267   map = new UnicodeMap("UTF-8", gTrue, &mapUTF8);
268   residentUnicodeMaps->add(map->getEncodingName(), map);
269   map = new UnicodeMap("UCS-2", gTrue, &mapUCS2);
270   residentUnicodeMaps->add(map->getEncodingName(), map);
271
272   // look for a user config file, then a system-wide config file
273   f = NULL;
274   fileName = NULL;
275   if (cfgFileName && cfgFileName[0]) {
276     fileName = new GString(cfgFileName);
277     if (!(f = fopen(fileName->getCString(), "r"))) {
278       delete fileName;
279     }
280   }
281   if (!f) {
282     fileName = appendToPath(getHomeDir(), xpdfUserConfigFile);
283     if (!(f = fopen(fileName->getCString(), "r"))) {
284       delete fileName;
285     }
286   }
287   if (!f) {
288 #if defined(WIN32) && !defined(__CYGWIN32__)
289     char buf[512];
290     i = GetModuleFileName(NULL, buf, sizeof(buf));
291     if (i <= 0 || i >= sizeof(buf)) {
292       // error or path too long for buffer - just use the current dir
293       buf[0] = '\0';
294     }
295     fileName = grabPath(buf);
296     appendToPath(fileName, xpdfSysConfigFile);
297 #else
298     fileName = new GString(xpdfSysConfigFile);
299 #endif
300     if (!(f = fopen(fileName->getCString(), "r"))) {
301       delete fileName;
302     }
303   }
304   if (f) {
305     parseFile(fileName, f);
306     delete fileName;
307     fclose(f);
308   }
309 }
310
311 void GlobalParams::parseFile(GString *fileName, FILE *f) {
312   int line;
313   GList *tokens;
314   GString *cmd, *incFile;
315   char *p1, *p2;
316   char buf[512];
317   FILE *f2;
318   
319   /* extract path */
320   if(fileName) {
321     char* cfgFileName = fileName->getCString();
322     char* pos1 = strrchr(cfgFileName, '/');
323     char* pos2 = strrchr(cfgFileName, '\\');
324     char* p = pos1>pos2?pos1:pos2;
325     int pos = p ? p-cfgFileName : -1;
326     GString*path = new GString(new GString(cfgFileName), 0, (pos < 0 ? strlen(cfgFileName): pos));
327     if(pos1>=0)
328         path->append('/');
329     else if(pos2>=0)
330         path->append('\\');
331     else
332 #ifdef WIN32
333         path->append('\\');
334 #else
335         path->append('/');
336 #endif
337     this->path = path;
338   } else {
339     this->path = new GString();
340   }
341   
342   line = 1;
343   while (getLine(buf, sizeof(buf) - 1, f)) {
344
345     // break the line into tokens
346     tokens = new GList();
347     p1 = buf;
348     while (*p1) {
349       for (; *p1 && isspace(*p1); ++p1) ;
350       if (!*p1) {
351         break;
352       }
353       if (*p1 == '"' || *p1 == '\'') {
354         for (p2 = p1 + 1; *p2 && *p2 != *p1; ++p2) ;
355         ++p1;
356       } else {
357         for (p2 = p1 + 1; *p2 && !isspace(*p2); ++p2) ;
358       }
359       tokens->append(new GString(p1, p2 - p1));
360       p1 = *p2 ? p2 + 1 : p2;
361     }
362
363     if (tokens->getLength() > 0 &&
364         ((GString *)tokens->get(0))->getChar(0) != '#') {
365       cmd = (GString *)tokens->get(0);
366       if (!cmd->cmp("include")) {
367         if (tokens->getLength() == 2) {
368           incFile = (GString *)tokens->get(1);
369           if ((f2 = fopen(incFile->getCString(), "r"))) {
370             parseFile(incFile, f2);
371             fclose(f2);
372           } else {
373             error(-1, "Couldn't find included config file: '%s' (%s:%d)",
374                   incFile->getCString(), fileName->getCString(), line);
375           }
376         } else {
377           error(-1, "Bad 'include' config file command (%s:%d)",
378                 fileName->getCString(), line);
379         }
380       } else if (!cmd->cmp("nameToUnicode")) {
381         parseNameToUnicode(tokens, fileName, line);
382       } else if (!cmd->cmp("cidToUnicode")) {
383         parseCIDToUnicode(tokens, fileName, line);
384       } else if (!cmd->cmp("unicodeToUnicode")) {
385         parseUnicodeToUnicode(tokens, fileName, line);
386       } else if (!cmd->cmp("unicodeMap")) {
387         parseUnicodeMap(tokens, fileName, line);
388       } else if (!cmd->cmp("cMapDir")) {
389         parseCMapDir(tokens, fileName, line);
390       } else if (!cmd->cmp("toUnicodeDir")) {
391         parseToUnicodeDir(tokens, fileName, line);
392       } else if (!cmd->cmp("displayFontT1")) {
393         parseDisplayFont(tokens, displayFonts, displayFontT1, fileName, line);
394       } else if (!cmd->cmp("displayFontTT")) {
395         parseDisplayFont(tokens, displayFonts, displayFontTT, fileName, line);
396       } else if (!cmd->cmp("displayNamedCIDFontT1")) {
397         parseDisplayFont(tokens, displayNamedCIDFonts,
398                          displayFontT1, fileName, line);
399       } else if (!cmd->cmp("displayCIDFontT1")) {
400         parseDisplayFont(tokens, displayCIDFonts,
401                          displayFontT1, fileName, line);
402       } else if (!cmd->cmp("displayNamedCIDFontTT")) {
403         parseDisplayFont(tokens, displayNamedCIDFonts,
404                          displayFontTT, fileName, line);
405       } else if (!cmd->cmp("displayCIDFontTT")) {
406         parseDisplayFont(tokens, displayCIDFonts,
407                          displayFontTT, fileName, line);
408       } else if (!cmd->cmp("psFile")) {
409         parsePSFile(tokens, fileName, line);
410       } else if (!cmd->cmp("psFont")) {
411         parsePSFont(tokens, fileName, line);
412       } else if (!cmd->cmp("psNamedFont16")) {
413         parsePSFont16("psNamedFont16", psNamedFonts16,
414                       tokens, fileName, line);
415       } else if (!cmd->cmp("psFont16")) {
416         parsePSFont16("psFont16", psFonts16, tokens, fileName, line);
417       } else if (!cmd->cmp("psPaperSize")) {
418         parsePSPaperSize(tokens, fileName, line);
419       } else if (!cmd->cmp("psImageableArea")) {
420         parsePSImageableArea(tokens, fileName, line);
421       } else if (!cmd->cmp("psCrop")) {
422         parseYesNo("psCrop", &psCrop, tokens, fileName, line);
423       } else if (!cmd->cmp("psExpandSmaller")) {
424         parseYesNo("psExpandSmaller", &psExpandSmaller,
425                    tokens, fileName, line);
426       } else if (!cmd->cmp("psShrinkLarger")) {
427         parseYesNo("psShrinkLarger", &psShrinkLarger, tokens, fileName, line);
428       } else if (!cmd->cmp("psCenter")) {
429         parseYesNo("psCenter", &psCenter, tokens, fileName, line);
430       } else if (!cmd->cmp("psDuplex")) {
431         parseYesNo("psDuplex", &psDuplex, tokens, fileName, line);
432       } else if (!cmd->cmp("psLevel")) {
433         parsePSLevel(tokens, fileName, line);
434       } else if (!cmd->cmp("psEmbedType1Fonts")) {
435         parseYesNo("psEmbedType1", &psEmbedType1, tokens, fileName, line);
436       } else if (!cmd->cmp("psEmbedTrueTypeFonts")) {
437         parseYesNo("psEmbedTrueType", &psEmbedTrueType,
438                    tokens, fileName, line);
439       } else if (!cmd->cmp("psEmbedCIDPostScriptFonts")) {
440         parseYesNo("psEmbedCIDPostScript", &psEmbedCIDPostScript,
441                    tokens, fileName, line);
442       } else if (!cmd->cmp("psEmbedCIDTrueTypeFonts")) {
443         parseYesNo("psEmbedCIDTrueType", &psEmbedCIDTrueType,
444                    tokens, fileName, line);
445       } else if (!cmd->cmp("psOPI")) {
446         parseYesNo("psOPI", &psOPI, tokens, fileName, line);
447       } else if (!cmd->cmp("psASCIIHex")) {
448         parseYesNo("psASCIIHex", &psASCIIHex, tokens, fileName, line);
449       } else if (!cmd->cmp("textEncoding")) {
450         parseTextEncoding(tokens, fileName, line);
451       } else if (!cmd->cmp("textEOL")) {
452         parseTextEOL(tokens, fileName, line);
453       } else if (!cmd->cmp("textPageBreaks")) {
454         parseYesNo("textPageBreaks", &textPageBreaks,
455                    tokens, fileName, line);
456       } else if (!cmd->cmp("textKeepTinyChars")) {
457         parseYesNo("textKeepTinyChars", &textKeepTinyChars,
458                    tokens, fileName, line);
459       } else if (!cmd->cmp("fontDir")) {
460         parseFontDir(tokens, fileName, line);
461       } else if (!cmd->cmp("initialZoom")) {
462         parseInitialZoom(tokens, fileName, line);
463       } else if (!cmd->cmp("enableT1lib")) {
464         parseYesNo("enableT1lib", &enableT1lib, tokens, fileName, line);
465       } else if (!cmd->cmp("enableFreeType")) {
466         parseYesNo("enableFreeType", &enableFreeType, tokens, fileName, line);
467       } else if (!cmd->cmp("antialias")) {
468         parseYesNo("antialias", &antialias, tokens, fileName, line);
469       } else if (!cmd->cmp("urlCommand")) {
470         parseCommand("urlCommand", &urlCommand, tokens, fileName, line);
471       } else if (!cmd->cmp("movieCommand")) {
472         parseCommand("movieCommand", &movieCommand, tokens, fileName, line);
473       } else if (!cmd->cmp("mapNumericCharNames")) {
474         parseYesNo("mapNumericCharNames", &mapNumericCharNames,
475                    tokens, fileName, line);
476       } else if (!cmd->cmp("printCommands")) {
477         parseYesNo("printCommands", &printCommands, tokens, fileName, line);
478       } else if (!cmd->cmp("errQuiet")) {
479         parseYesNo("errQuiet", &errQuiet, tokens, fileName, line);
480       } else {
481         error(-1, "Unknown config file command '%s' (%s:%d)",
482               cmd->getCString(), fileName->getCString(), line);
483         if (!cmd->cmp("displayFontX") ||
484             !cmd->cmp("displayNamedCIDFontX") ||
485             !cmd->cmp("displayCIDFontX")) {
486           error(-1, "-- Xpdf no longer supports X fonts");
487         } else if (!cmd->cmp("t1libControl") || !cmd->cmp("freetypeControl")) {
488           error(-1, "-- The t1libControl and freetypeControl options have been replaced");
489           error(-1, "   by the enableT1lib, enableFreeType, and antialias options");
490         } else if (!cmd->cmp("fontpath") || !cmd->cmp("fontmap")) {
491           error(-1, "-- the config file format has changed since Xpdf 0.9x");
492         }
493       }
494     }
495
496     deleteGList(tokens, GString);
497     ++line;
498   }
499 }
500
501 void GlobalParams::parseNameToUnicode(GList *tokens, GString *fileName,
502                                          int line) {
503   GString *name;
504   char *tok1, *tok2;
505   FILE *f;
506   char buf[256];
507   int line2;
508   Unicode u;
509
510   if (tokens->getLength() != 2) {
511     error(-1, "Bad 'nameToUnicode' config file command (%s:%d)",
512           fileName->getCString(), line);
513     return;
514   }
515   name = (GString *)tokens->get(1);
516   if (!(f = fopen(name->getCString(), "r"))) {
517     error(-1, "Couldn't open 'nameToUnicode' file '%s'",
518           name->getCString());
519     return;
520   }
521   line2 = 1;
522   while (getLine(buf, sizeof(buf), f)) {
523     tok1 = strtok(buf, " \t\r\n");
524     tok2 = strtok(NULL, " \t\r\n");
525     if (tok1 && tok2) {
526       sscanf(tok1, "%x", &u);
527       nameToUnicode->add(tok2, u);
528     } else {
529       error(-1, "Bad line in 'nameToUnicode' file (%s:%d)", name, line2);
530     }
531     ++line2;
532   }
533   fclose(f);
534 }
535
536 static GString* qualify_filename(GString*path, GString*filename)
537 {
538   GString*fullpath = 0;
539   char*prefix = "/usr/local/share/xpdf/";
540
541   if (filename->getChar(0) != '\\' && filename->getChar(0) != '/') {
542     /* relative path */
543     fullpath = path->copy();
544     fullpath->append(filename);
545   } else if (!strncmp(filename->getCString(), prefix, strlen(prefix))) {
546     /* xpdf default path */
547     char*s = strchr(filename->getCString()+strlen(prefix), '/');
548     if(s) {
549         fullpath = path->copy();
550         fullpath->append(s+1);
551     } else {
552         fullpath = filename->copy();
553     }
554   } else {
555     /* absolute path */
556     fullpath = filename->copy();
557   }
558   printf("%s -%s-> %s\n", filename->getCString(), path->getCString(), fullpath->getCString());
559   return fullpath;
560 }
561
562 void GlobalParams::parseCIDToUnicode(GList *tokens, GString *fileName,
563                                      int line) {
564   GString *collection, *name, *old;
565
566   if (tokens->getLength() != 3) {
567     error(-1, "Bad 'cidToUnicode' config file command (%s:%d)",
568           fileName->getCString(), line);
569     return;
570   }
571   collection = (GString *)tokens->get(1);
572   name = (GString *)tokens->get(2);
573
574   if ((old = (GString *)cidToUnicodes->remove(collection))) {
575     delete old;
576   }
577
578   cidToUnicodes->add(collection->copy(), qualify_filename(this->path, name));
579 }
580
581 void GlobalParams::parseUnicodeToUnicode(GList *tokens, GString *fileName,
582                                          int line) {
583   GString *font, *file, *old;
584
585   if (tokens->getLength() != 3) {
586     error(-1, "Bad 'unicodeToUnicode' config file command (%s:%d)",
587           fileName->getCString(), line);
588     return;
589   }
590   font = (GString *)tokens->get(1);
591   file = (GString *)tokens->get(2);
592   if ((old = (GString *)unicodeToUnicodes->remove(font))) {
593     delete old;
594   }
595
596   unicodeToUnicodes->add(font->copy(), qualify_filename(this->path, file));
597 }
598
599 void GlobalParams::parseUnicodeMap(GList *tokens, GString *fileName,
600                                    int line) {
601   GString *encodingName, *name, *old;
602
603   if (tokens->getLength() != 3) {
604     error(-1, "Bad 'unicodeMap' config file command (%s:%d)",
605           fileName->getCString(), line);
606     return;
607   }
608   encodingName = (GString *)tokens->get(1);
609   name = (GString *)tokens->get(2);
610   if ((old = (GString *)unicodeMaps->remove(encodingName))) {
611     delete old;
612   }
613
614   unicodeMaps->add(encodingName->copy(), qualify_filename(this->path, name));
615 }
616
617 void GlobalParams::parseCMapDir(GList *tokens, GString *fileName, int line) {
618   GString *collection, *dir;
619   GList *list;
620
621   if (tokens->getLength() != 3) {
622     error(-1, "Bad 'cMapDir' config file command (%s:%d)",
623           fileName->getCString(), line);
624     return;
625   }
626   collection = (GString *)tokens->get(1);
627   dir = (GString *)tokens->get(2);
628   if (!(list = (GList *)cMapDirs->lookup(collection))) {
629     list = new GList();
630     cMapDirs->add(collection->copy(), list);
631   }
632
633   list->append(qualify_filename(this->path, dir));
634 }
635
636 void GlobalParams::parseToUnicodeDir(GList *tokens, GString *fileName,
637                                      int line) {
638   GString *dir;
639
640   if (tokens->getLength() != 2) {
641     error(-1, "Bad 'toUnicodeDir' config file command (%s:%d)",
642           fileName->getCString(), line);
643     return;
644   }
645
646   dir = (GString *)tokens->get(1);
647
648   toUnicodeDirs->append(qualify_filename(this->path, dir));
649 }
650
651 void GlobalParams::parseDisplayFont(GList *tokens, GHash *fontHash,
652                                     DisplayFontParamKind kind,
653                                     GString *fileName, int line) {
654   DisplayFontParam *param, *old;
655   GString *file;
656
657   if (tokens->getLength() < 2) {
658     goto err1;
659   }
660   param = new DisplayFontParam(((GString *)tokens->get(1))->copy(), kind);
661   
662   switch (kind) {
663   case displayFontT1:
664     if (tokens->getLength() != 3) {
665       goto err2;
666     }
667     file = (GString *)tokens->get(2);
668     param->t1.fileName = qualify_filename(this->path, file);
669     break;
670   case displayFontTT:
671     if (tokens->getLength() != 3) {
672       goto err2;
673     }
674     file = (GString *)tokens->get(2);
675     param->tt.fileName = qualify_filename(this->path, file);
676     break;
677   }
678
679   if ((old = (DisplayFontParam *)fontHash->remove(param->name))) {
680     delete old;
681   }
682   fontHash->add(param->name, param);
683   return;
684
685  err2:
686   delete param;
687  err1:
688   error(-1, "Bad 'display*Font*' config file command (%s:%d)",
689         fileName->getCString(), line);
690 }
691
692 void GlobalParams::parsePSPaperSize(GList *tokens, GString *fileName,
693                                     int line) {
694   GString *tok;
695
696   if (tokens->getLength() == 2) {
697     tok = (GString *)tokens->get(1);
698     if (!setPSPaperSize(tok->getCString())) {
699       error(-1, "Bad 'psPaperSize' config file command (%s:%d)",
700             fileName->getCString(), line);
701     }
702   } else if (tokens->getLength() == 3) {
703     tok = (GString *)tokens->get(1);
704     psPaperWidth = atoi(tok->getCString());
705     tok = (GString *)tokens->get(2);
706     psPaperHeight = atoi(tok->getCString());
707     psImageableLLX = psImageableLLY = 0;
708     psImageableURX = psPaperWidth;
709     psImageableURY = psPaperHeight;
710   } else {
711     error(-1, "Bad 'psPaperSize' config file command (%s:%d)",
712           fileName->getCString(), line);
713   }
714 }
715
716 void GlobalParams::parsePSImageableArea(GList *tokens, GString *fileName,
717                                         int line) {
718   if (tokens->getLength() != 5) {
719     error(-1, "Bad 'psImageableArea' config file command (%s:%d)",
720           fileName->getCString(), line);
721     return;
722   }
723   psImageableLLX = atoi(((GString *)tokens->get(1))->getCString());
724   psImageableLLY = atoi(((GString *)tokens->get(2))->getCString());
725   psImageableURX = atoi(((GString *)tokens->get(3))->getCString());
726   psImageableURY = atoi(((GString *)tokens->get(4))->getCString());
727 }
728
729 void GlobalParams::parsePSLevel(GList *tokens, GString *fileName, int line) {
730   GString *tok;
731
732   if (tokens->getLength() != 2) {
733     error(-1, "Bad 'psLevel' config file command (%s:%d)",
734           fileName->getCString(), line);
735     return;
736   }
737   tok = (GString *)tokens->get(1);
738   if (!tok->cmp("level1")) {
739     psLevel = psLevel1;
740   } else if (!tok->cmp("level1sep")) {
741     psLevel = psLevel1Sep;
742   } else if (!tok->cmp("level2")) {
743     psLevel = psLevel2;
744   } else if (!tok->cmp("level2sep")) {
745     psLevel = psLevel2Sep;
746   } else if (!tok->cmp("level3")) {
747     psLevel = psLevel3;
748   } else if (!tok->cmp("level3Sep")) {
749     psLevel = psLevel3Sep;
750   } else {
751     error(-1, "Bad 'psLevel' config file command (%s:%d)",
752           fileName->getCString(), line);
753   }
754 }
755
756 void GlobalParams::parsePSFile(GList *tokens, GString *fileName, int line) {
757   if (tokens->getLength() != 2) {
758     error(-1, "Bad 'psFile' config file command (%s:%d)",
759           fileName->getCString(), line);
760     return;
761   }
762   if (psFile) {
763     delete psFile;
764   }
765   psFile = ((GString *)tokens->get(1))->copy();
766 }
767
768 void GlobalParams::parsePSFont(GList *tokens, GString *fileName, int line) {
769   PSFontParam *param;
770
771   if (tokens->getLength() != 3) {
772     error(-1, "Bad 'psFont' config file command (%s:%d)",
773           fileName->getCString(), line);
774     return;
775   }
776   param = new PSFontParam(((GString *)tokens->get(1))->copy(), 0,
777                           ((GString *)tokens->get(2))->copy(), NULL);
778   psFonts->add(param->pdfFontName, param);
779 }
780
781 void GlobalParams::parsePSFont16(char *cmdName, GList *fontList,
782                                  GList *tokens, GString *fileName, int line) {
783   PSFontParam *param;
784   int wMode;
785   GString *tok;
786
787   if (tokens->getLength() != 5) {
788     error(-1, "Bad '%s' config file command (%s:%d)",
789           cmdName, fileName->getCString(), line);
790     return;
791   }
792   tok = (GString *)tokens->get(2);
793   if (!tok->cmp("H")) {
794     wMode = 0;
795   } else if (!tok->cmp("V")) {
796     wMode = 1;
797   } else {
798     error(-1, "Bad '%s' config file command (%s:%d)",
799           cmdName, fileName->getCString(), line);
800     return;
801   }
802   param = new PSFontParam(((GString *)tokens->get(1))->copy(),
803                           wMode,
804                           ((GString *)tokens->get(3))->copy(),
805                           ((GString *)tokens->get(4))->copy());
806   fontList->append(param);
807 }
808
809 void GlobalParams::parseTextEncoding(GList *tokens, GString *fileName,
810                                      int line) {
811   if (tokens->getLength() != 2) {
812     error(-1, "Bad 'textEncoding' config file command (%s:%d)",
813           fileName->getCString(), line);
814     return;
815   }
816   delete textEncoding;
817   textEncoding = ((GString *)tokens->get(1))->copy();
818 }
819
820 void GlobalParams::parseTextEOL(GList *tokens, GString *fileName, int line) {
821   GString *tok;
822
823   if (tokens->getLength() != 2) {
824     error(-1, "Bad 'textEOL' config file command (%s:%d)",
825           fileName->getCString(), line);
826     return;
827   }
828   tok = (GString *)tokens->get(1);
829   if (!tok->cmp("unix")) {
830     textEOL = eolUnix;
831   } else if (!tok->cmp("dos")) {
832     textEOL = eolDOS;
833   } else if (!tok->cmp("mac")) {
834     textEOL = eolMac;
835   } else {
836     error(-1, "Bad 'textEOL' config file command (%s:%d)",
837           fileName->getCString(), line);
838   }
839 }
840
841 void GlobalParams::parseFontDir(GList *tokens, GString *fileName, int line) {
842   if (tokens->getLength() != 2) {
843     error(-1, "Bad 'fontDir' config file command (%s:%d)",
844           fileName->getCString(), line);
845     return;
846   }
847   fontDirs->append(((GString *)tokens->get(1))->copy());
848 }
849
850 void GlobalParams::parseInitialZoom(GList *tokens,
851                                     GString *fileName, int line) {
852   if (tokens->getLength() != 2) {
853     error(-1, "Bad 'initialZoom' config file command (%s:%d)",
854           fileName->getCString(), line);
855     return;
856   }
857   delete initialZoom;
858   initialZoom = ((GString *)tokens->get(1))->copy();
859 }
860
861 void GlobalParams::parseCommand(char *cmdName, GString **val,
862                                 GList *tokens, GString *fileName, int line) {
863   if (tokens->getLength() != 2) {
864     error(-1, "Bad '%s' config file command (%s:%d)",
865           cmdName, fileName->getCString(), line);
866     return;
867   }
868   if (*val) {
869     delete *val;
870   }
871   *val = ((GString *)tokens->get(1))->copy();
872 }
873
874 void GlobalParams::parseYesNo(char *cmdName, GBool *flag,
875                               GList *tokens, GString *fileName, int line) {
876   GString *tok;
877
878   if (tokens->getLength() != 2) {
879     error(-1, "Bad '%s' config file command (%s:%d)",
880           cmdName, fileName->getCString(), line);
881     return;
882   }
883   tok = (GString *)tokens->get(1);
884   if (!parseYesNo2(tok->getCString(), flag)) {
885     error(-1, "Bad '%s' config file command (%s:%d)",
886           cmdName, fileName->getCString(), line);
887   }
888 }
889
890 GBool GlobalParams::parseYesNo2(char *token, GBool *flag) {
891   if (!strcmp(token, "yes")) {
892     *flag = gTrue;
893   } else if (!strcmp(token, "no")) {
894     *flag = gFalse;
895   } else {
896     return gFalse;
897   }
898   return gTrue;
899 }
900
901 GlobalParams::~GlobalParams() {
902   GHashIter *iter;
903   GString *key;
904   GList *list;
905
906   freeBuiltinFontTables();
907
908   delete macRomanReverseMap;
909
910   delete nameToUnicode;
911   deleteGHash(cidToUnicodes, GString);
912   deleteGHash(unicodeToUnicodes, GString);
913   deleteGHash(residentUnicodeMaps, UnicodeMap);
914   deleteGHash(unicodeMaps, GString);
915   deleteGList(toUnicodeDirs, GString);
916   deleteGHash(displayFonts, DisplayFontParam);
917   deleteGHash(displayCIDFonts, DisplayFontParam);
918   deleteGHash(displayNamedCIDFonts, DisplayFontParam);
919   if (psFile) {
920     delete psFile;
921   }
922   deleteGHash(psFonts, PSFontParam);
923   deleteGList(psNamedFonts16, PSFontParam);
924   deleteGList(psFonts16, PSFontParam);
925   delete textEncoding;
926   deleteGList(fontDirs, GString);
927   delete initialZoom;
928   if (urlCommand) {
929     delete urlCommand;
930   }
931   if (movieCommand) {
932     delete movieCommand;
933   }
934
935   cMapDirs->startIter(&iter);
936   while (cMapDirs->getNext(&iter, &key, (void **)&list)) {
937     deleteGList(list, GString);
938   }
939   delete cMapDirs;
940
941   delete cidToUnicodeCache;
942   delete unicodeToUnicodeCache;
943   delete unicodeMapCache;
944   delete cMapCache;
945
946 #if MULTITHREADED
947   gDestroyMutex(&mutex);
948   gDestroyMutex(&unicodeMapCacheMutex);
949   gDestroyMutex(&cMapCacheMutex);
950 #endif
951 }
952
953 //------------------------------------------------------------------------
954
955 void GlobalParams::setupBaseFonts(char *dir) {
956   GString *fontName;
957   GString *fileName;
958   FILE *f;
959   DisplayFontParam *dfp;
960   int i, j;
961
962   for (i = 0; displayFontTab[i].name; ++i) {
963     fontName = new GString(displayFontTab[i].name);
964     if (getDisplayFont(fontName)) {
965       delete fontName;
966       continue;
967     }
968     fileName = NULL;
969     if (dir) {
970       fileName = appendToPath(new GString(dir), displayFontTab[i].fileName);
971       if ((f = fopen(fileName->getCString(), "rb"))) {
972         fclose(f);
973       } else {
974         delete fileName;
975         fileName = NULL;
976       }
977     }
978 #ifndef WIN32
979     for (j = 0; !fileName && displayFontDirs[j]; ++j) {
980       fileName = appendToPath(new GString(displayFontDirs[j]),
981                               displayFontTab[i].fileName);
982       if ((f = fopen(fileName->getCString(), "rb"))) {
983         fclose(f);
984       } else {
985         delete fileName;
986         fileName = NULL;
987       }
988     }
989 #endif
990     if (!fileName) {
991       error(-1, "No display font for '%s'", displayFontTab[i].name);
992       delete fontName;
993       continue;
994     }
995     dfp = new DisplayFontParam(fontName, displayFontT1);
996     dfp->t1.fileName = fileName;
997     globalParams->addDisplayFont(dfp);
998   }
999 }
1000
1001 //------------------------------------------------------------------------
1002 // accessors
1003 //------------------------------------------------------------------------
1004
1005 CharCode GlobalParams::getMacRomanCharCode(char *charName) {
1006   // no need to lock - macRomanReverseMap is constant
1007   return macRomanReverseMap->lookup(charName);
1008 }
1009
1010 Unicode GlobalParams::mapNameToUnicode(char *charName) {
1011   // no need to lock - nameToUnicode is constant
1012   return nameToUnicode->lookup(charName);
1013 }
1014
1015 UnicodeMap *GlobalParams::getResidentUnicodeMap(GString *encodingName) {
1016   UnicodeMap *map;
1017
1018   lockGlobalParams;
1019   map = (UnicodeMap *)residentUnicodeMaps->lookup(encodingName);
1020   unlockGlobalParams;
1021   if (map) {
1022     map->incRefCnt();
1023   }
1024   return map;
1025 }
1026
1027 FILE *GlobalParams::getUnicodeMapFile(GString *encodingName) {
1028   GString *fileName;
1029   FILE *f;
1030
1031   lockGlobalParams;
1032   if ((fileName = (GString *)unicodeMaps->lookup(encodingName))) {
1033     f = fopen(fileName->getCString(), "r");
1034   } else {
1035     f = NULL;
1036   }
1037   unlockGlobalParams;
1038   return f;
1039 }
1040
1041 FILE *GlobalParams::findCMapFile(GString *collection, GString *cMapName) {
1042   GList *list;
1043   GString *dir;
1044   GString *fileName;
1045   FILE *f;
1046   int i;
1047
1048   lockGlobalParams;
1049   if (!(list = (GList *)cMapDirs->lookup(collection))) {
1050     unlockGlobalParams;
1051     return NULL;
1052   }
1053   for (i = 0; i < list->getLength(); ++i) {
1054     dir = (GString *)list->get(i);
1055     fileName = appendToPath(dir->copy(), cMapName->getCString());
1056     f = fopen(fileName->getCString(), "r");
1057     delete fileName;
1058     if (f) {
1059       unlockGlobalParams;
1060       return f;
1061     }
1062   }
1063   unlockGlobalParams;
1064   return NULL;
1065 }
1066
1067 FILE *GlobalParams::findToUnicodeFile(GString *name) {
1068   GString *dir, *fileName;
1069   FILE *f;
1070   int i;
1071
1072   lockGlobalParams;
1073   for (i = 0; i < toUnicodeDirs->getLength(); ++i) {
1074     dir = (GString *)toUnicodeDirs->get(i);
1075     fileName = appendToPath(dir->copy(), name->getCString());
1076     f = fopen(fileName->getCString(), "r");
1077     delete fileName;
1078     if (f) {
1079       unlockGlobalParams;
1080       return f;
1081     }
1082   }
1083   unlockGlobalParams;
1084   return NULL;
1085 }
1086
1087 DisplayFontParam *GlobalParams::getDisplayFont(GString *fontName) {
1088   DisplayFontParam *dfp;
1089
1090   lockGlobalParams;
1091   dfp = (DisplayFontParam *)displayFonts->lookup(fontName);
1092   unlockGlobalParams;
1093   return dfp;
1094 }
1095
1096 DisplayFontParam *GlobalParams::getDisplayCIDFont(GString *fontName,
1097                                                   GString *collection) {
1098   DisplayFontParam *dfp;
1099
1100   lockGlobalParams;
1101   if (!fontName ||
1102       !(dfp = (DisplayFontParam *)displayNamedCIDFonts->lookup(fontName))) {
1103     dfp = (DisplayFontParam *)displayCIDFonts->lookup(collection);
1104   }
1105   unlockGlobalParams;
1106   return dfp;
1107 }
1108
1109 GString *GlobalParams::getPSFile() {
1110   GString *s;
1111
1112   lockGlobalParams;
1113   s = psFile ? psFile->copy() : (GString *)NULL;
1114   unlockGlobalParams;
1115   return s;
1116 }
1117
1118 int GlobalParams::getPSPaperWidth() {
1119   int w;
1120
1121   lockGlobalParams;
1122   w = psPaperWidth;
1123   unlockGlobalParams;
1124   return w;
1125 }
1126
1127 int GlobalParams::getPSPaperHeight() {
1128   int h;
1129
1130   lockGlobalParams;
1131   h = psPaperHeight;
1132   unlockGlobalParams;
1133   return h;
1134 }
1135
1136 void GlobalParams::getPSImageableArea(int *llx, int *lly, int *urx, int *ury) {
1137   lockGlobalParams;
1138   *llx = psImageableLLX;
1139   *lly = psImageableLLY;
1140   *urx = psImageableURX;
1141   *ury = psImageableURY;
1142   unlockGlobalParams;
1143 }
1144
1145 GBool GlobalParams::getPSCrop() {
1146   GBool f;
1147
1148   lockGlobalParams;
1149   f = psCrop;
1150   unlockGlobalParams;
1151   return f;
1152 }
1153
1154 GBool GlobalParams::getPSExpandSmaller() {
1155   GBool f;
1156
1157   lockGlobalParams;
1158   f = psExpandSmaller;
1159   unlockGlobalParams;
1160   return f;
1161 }
1162
1163 GBool GlobalParams::getPSShrinkLarger() {
1164   GBool f;
1165
1166   lockGlobalParams;
1167   f = psShrinkLarger;
1168   unlockGlobalParams;
1169   return f;
1170 }
1171
1172 GBool GlobalParams::getPSCenter() {
1173   GBool f;
1174
1175   lockGlobalParams;
1176   f = psCenter;
1177   unlockGlobalParams;
1178   return f;
1179 }
1180
1181 GBool GlobalParams::getPSDuplex() {
1182   GBool d;
1183
1184   lockGlobalParams;
1185   d = psDuplex;
1186   unlockGlobalParams;
1187   return d;
1188 }
1189
1190 PSLevel GlobalParams::getPSLevel() {
1191   PSLevel level;
1192
1193   lockGlobalParams;
1194   level = psLevel;
1195   unlockGlobalParams;
1196   return level;
1197 }
1198
1199 PSFontParam *GlobalParams::getPSFont(GString *fontName) {
1200   PSFontParam *p;
1201
1202   lockGlobalParams;
1203   p = (PSFontParam *)psFonts->lookup(fontName);
1204   unlockGlobalParams;
1205   return p;
1206 }
1207
1208 PSFontParam *GlobalParams::getPSFont16(GString *fontName,
1209                                        GString *collection, int wMode) {
1210   PSFontParam *p;
1211   int i;
1212
1213   lockGlobalParams;
1214   p = NULL;
1215   if (fontName) {
1216     for (i = 0; i < psNamedFonts16->getLength(); ++i) {
1217       p = (PSFontParam *)psNamedFonts16->get(i);
1218       if (!p->pdfFontName->cmp(fontName) &&
1219           p->wMode == wMode) {
1220         break;
1221       }
1222       p = NULL;
1223     }
1224   }
1225   if (!p && collection) {
1226     for (i = 0; i < psFonts16->getLength(); ++i) {
1227       p = (PSFontParam *)psFonts16->get(i);
1228       if (!p->pdfFontName->cmp(collection) &&
1229           p->wMode == wMode) {
1230         break;
1231       }
1232       p = NULL;
1233     }
1234   }
1235   unlockGlobalParams;
1236   return p;
1237 }
1238
1239 GBool GlobalParams::getPSEmbedType1() {
1240   GBool e;
1241
1242   lockGlobalParams;
1243   e = psEmbedType1;
1244   unlockGlobalParams;
1245   return e;
1246 }
1247
1248 GBool GlobalParams::getPSEmbedTrueType() {
1249   GBool e;
1250
1251   lockGlobalParams;
1252   e = psEmbedTrueType;
1253   unlockGlobalParams;
1254   return e;
1255 }
1256
1257 GBool GlobalParams::getPSEmbedCIDPostScript() {
1258   GBool e;
1259
1260   lockGlobalParams;
1261   e = psEmbedCIDPostScript;
1262   unlockGlobalParams;
1263   return e;
1264 }
1265
1266 GBool GlobalParams::getPSEmbedCIDTrueType() {
1267   GBool e;
1268
1269   lockGlobalParams;
1270   e = psEmbedCIDTrueType;
1271   unlockGlobalParams;
1272   return e;
1273 }
1274
1275 GBool GlobalParams::getPSOPI() {
1276   GBool opi;
1277
1278   lockGlobalParams;
1279   opi = psOPI;
1280   unlockGlobalParams;
1281   return opi;
1282 }
1283
1284 GBool GlobalParams::getPSASCIIHex() {
1285   GBool ah;
1286
1287   lockGlobalParams;
1288   ah = psASCIIHex;
1289   unlockGlobalParams;
1290   return ah;
1291 }
1292
1293 GString *GlobalParams::getTextEncodingName() {
1294   GString *s;
1295
1296   lockGlobalParams;
1297   s = textEncoding->copy();
1298   unlockGlobalParams;
1299   return s;
1300 }
1301
1302 EndOfLineKind GlobalParams::getTextEOL() {
1303   EndOfLineKind eol;
1304
1305   lockGlobalParams;
1306   eol = textEOL;
1307   unlockGlobalParams;
1308   return eol;
1309 }
1310
1311 GBool GlobalParams::getTextPageBreaks() {
1312   GBool pageBreaks;
1313
1314   lockGlobalParams;
1315   pageBreaks = textPageBreaks;
1316   unlockGlobalParams;
1317   return pageBreaks;
1318 }
1319
1320 GBool GlobalParams::getTextKeepTinyChars() {
1321   GBool tiny;
1322
1323   lockGlobalParams;
1324   tiny = textKeepTinyChars;
1325   unlockGlobalParams;
1326   return tiny;
1327 }
1328
1329 GString *GlobalParams::findFontFile(GString *fontName, char **exts) {
1330   GString *dir, *fileName;
1331   char **ext;
1332   FILE *f;
1333   int i;
1334
1335   lockGlobalParams;
1336   for (i = 0; i < fontDirs->getLength(); ++i) {
1337     dir = (GString *)fontDirs->get(i);
1338     for (ext = exts; *ext; ++ext) {
1339       fileName = appendToPath(dir->copy(), fontName->getCString());
1340       fileName->append(*ext);
1341       if ((f = fopen(fileName->getCString(), "rb"))) {
1342         fclose(f);
1343         unlockGlobalParams;
1344         return fileName;
1345       }
1346       delete fileName;
1347     }
1348   }
1349   unlockGlobalParams;
1350   return NULL;
1351 }
1352
1353 GString *GlobalParams::getInitialZoom() {
1354   GString *s;
1355
1356   lockGlobalParams;
1357   s = initialZoom->copy();
1358   unlockGlobalParams;
1359   return s;
1360 }
1361
1362 GBool GlobalParams::getEnableT1lib() {
1363   GBool f;
1364
1365   lockGlobalParams;
1366   f = enableT1lib;
1367   unlockGlobalParams;
1368   return f;
1369 }
1370
1371 GBool GlobalParams::getEnableFreeType() {
1372   GBool f;
1373
1374   lockGlobalParams;
1375   f = enableFreeType;
1376   unlockGlobalParams;
1377   return f;
1378 }
1379
1380
1381 GBool GlobalParams::getAntialias() {
1382   GBool f;
1383
1384   lockGlobalParams;
1385   f = antialias;
1386   unlockGlobalParams;
1387   return f;
1388 }
1389
1390 GBool GlobalParams::getMapNumericCharNames() {
1391   GBool map;
1392
1393   lockGlobalParams;
1394   map = mapNumericCharNames;
1395   unlockGlobalParams;
1396   return map;
1397 }
1398
1399 GBool GlobalParams::getPrintCommands() {
1400   GBool p;
1401
1402   lockGlobalParams;
1403   p = printCommands;
1404   unlockGlobalParams;
1405   return p;
1406 }
1407
1408 GBool GlobalParams::getErrQuiet() {
1409   GBool q;
1410
1411   lockGlobalParams;
1412   q = errQuiet;
1413   unlockGlobalParams;
1414   return q;
1415 }
1416
1417 CharCodeToUnicode *GlobalParams::getCIDToUnicode(GString *collection) {
1418   GString *fileName;
1419   CharCodeToUnicode *ctu;
1420
1421   lockGlobalParams;
1422   if (!(ctu = cidToUnicodeCache->getCharCodeToUnicode(collection))) {
1423     if ((fileName = (GString *)cidToUnicodes->lookup(collection)) &&
1424         (ctu = CharCodeToUnicode::parseCIDToUnicode(fileName, collection))) {
1425       cidToUnicodeCache->add(ctu);
1426     }
1427   }
1428   unlockGlobalParams;
1429   return ctu;
1430 }
1431
1432 CharCodeToUnicode *GlobalParams::getUnicodeToUnicode(GString *fontName) {
1433   CharCodeToUnicode *ctu;
1434   GHashIter *iter;
1435   GString *fontPattern, *fileName;
1436
1437   lockGlobalParams;
1438   fileName = NULL;
1439   unicodeToUnicodes->startIter(&iter);
1440   while (unicodeToUnicodes->getNext(&iter, &fontPattern, (void **)&fileName)) {
1441     if (strstr(fontName->getCString(), fontPattern->getCString())) {
1442       unicodeToUnicodes->killIter(&iter);
1443       break;
1444     }
1445     fileName = NULL;
1446   }
1447   if (fileName) {
1448     if (!(ctu = unicodeToUnicodeCache->getCharCodeToUnicode(fileName))) {
1449       if ((ctu = CharCodeToUnicode::parseUnicodeToUnicode(fileName))) {
1450         unicodeToUnicodeCache->add(ctu);
1451       }
1452     }
1453   } else {
1454     ctu = NULL;
1455   }
1456   unlockGlobalParams;
1457   return ctu;
1458 }
1459
1460 UnicodeMap *GlobalParams::getUnicodeMap(GString *encodingName) {
1461   return getUnicodeMap2(encodingName);
1462 }
1463
1464 UnicodeMap *GlobalParams::getUnicodeMap2(GString *encodingName) {
1465   UnicodeMap *map;
1466
1467   if (!(map = getResidentUnicodeMap(encodingName))) {
1468     lockUnicodeMapCache;
1469     map = unicodeMapCache->getUnicodeMap(encodingName);
1470     unlockUnicodeMapCache;
1471   }
1472   return map;
1473 }
1474
1475 CMap *GlobalParams::getCMap(GString *collection, GString *cMapName) {
1476   CMap *cMap;
1477
1478   lockCMapCache;
1479   cMap = cMapCache->getCMap(collection, cMapName);
1480   unlockCMapCache;
1481   return cMap;
1482 }
1483
1484 UnicodeMap *GlobalParams::getTextEncoding() {
1485   return getUnicodeMap2(textEncoding);
1486 }
1487
1488 //------------------------------------------------------------------------
1489 // functions to set parameters
1490 //------------------------------------------------------------------------
1491
1492 void GlobalParams::addDisplayFont(DisplayFontParam *param) {
1493   DisplayFontParam *old;
1494
1495   lockGlobalParams;
1496   if ((old = (DisplayFontParam *)displayFonts->remove(param->name))) {
1497     delete old;
1498   }
1499   displayFonts->add(param->name, param);
1500   unlockGlobalParams;
1501 }
1502
1503 void GlobalParams::setPSFile(char *file) {
1504   lockGlobalParams;
1505   if (psFile) {
1506     delete psFile;
1507   }
1508   psFile = new GString(file);
1509   unlockGlobalParams;
1510 }
1511
1512 GBool GlobalParams::setPSPaperSize(char *size) {
1513   lockGlobalParams;
1514   if (!strcmp(size, "match")) {
1515     psPaperWidth = psPaperHeight = -1;
1516   } else if (!strcmp(size, "letter")) {
1517     psPaperWidth = 612;
1518     psPaperHeight = 792;
1519   } else if (!strcmp(size, "legal")) {
1520     psPaperWidth = 612;
1521     psPaperHeight = 1008;
1522   } else if (!strcmp(size, "A4")) {
1523     psPaperWidth = 595;
1524     psPaperHeight = 842;
1525   } else if (!strcmp(size, "A3")) {
1526     psPaperWidth = 842;
1527     psPaperHeight = 1190;
1528   } else {
1529     unlockGlobalParams;
1530     return gFalse;
1531   }
1532   psImageableLLX = psImageableLLY = 0;
1533   psImageableURX = psPaperWidth;
1534   psImageableURY = psPaperHeight;
1535   unlockGlobalParams;
1536   return gTrue;
1537 }
1538
1539 void GlobalParams::setPSPaperWidth(int width) {
1540   lockGlobalParams;
1541   psPaperWidth = width;
1542   psImageableLLX = 0;
1543   psImageableURX = psPaperWidth;
1544   unlockGlobalParams;
1545 }
1546
1547 void GlobalParams::setPSPaperHeight(int height) {
1548   lockGlobalParams;
1549   psPaperHeight = height;
1550   psImageableLLY = 0;
1551   psImageableURY = psPaperHeight;
1552   unlockGlobalParams;
1553 }
1554
1555 void GlobalParams::setPSImageableArea(int llx, int lly, int urx, int ury) {
1556   lockGlobalParams;
1557   psImageableLLX = llx;
1558   psImageableLLY = lly;
1559   psImageableURX = urx;
1560   psImageableURY = ury;
1561   unlockGlobalParams;
1562 }
1563
1564 void GlobalParams::setPSCrop(GBool crop) {
1565   lockGlobalParams;
1566   psCrop = crop;
1567   unlockGlobalParams;
1568 }
1569
1570 void GlobalParams::setPSExpandSmaller(GBool expand) {
1571   lockGlobalParams;
1572   psExpandSmaller = expand;
1573   unlockGlobalParams;
1574 }
1575
1576 void GlobalParams::setPSShrinkLarger(GBool shrink) {
1577   lockGlobalParams;
1578   psShrinkLarger = shrink;
1579   unlockGlobalParams;
1580 }
1581
1582 void GlobalParams::setPSCenter(GBool center) {
1583   lockGlobalParams;
1584   psCenter = center;
1585   unlockGlobalParams;
1586 }
1587
1588 void GlobalParams::setPSDuplex(GBool duplex) {
1589   lockGlobalParams;
1590   psDuplex = duplex;
1591   unlockGlobalParams;
1592 }
1593
1594 void GlobalParams::setPSLevel(PSLevel level) {
1595   lockGlobalParams;
1596   psLevel = level;
1597   unlockGlobalParams;
1598 }
1599
1600 void GlobalParams::setPSEmbedType1(GBool embed) {
1601   lockGlobalParams;
1602   psEmbedType1 = embed;
1603   unlockGlobalParams;
1604 }
1605
1606 void GlobalParams::setPSEmbedTrueType(GBool embed) {
1607   lockGlobalParams;
1608   psEmbedTrueType = embed;
1609   unlockGlobalParams;
1610 }
1611
1612 void GlobalParams::setPSEmbedCIDPostScript(GBool embed) {
1613   lockGlobalParams;
1614   psEmbedCIDPostScript = embed;
1615   unlockGlobalParams;
1616 }
1617
1618 void GlobalParams::setPSEmbedCIDTrueType(GBool embed) {
1619   lockGlobalParams;
1620   psEmbedCIDTrueType = embed;
1621   unlockGlobalParams;
1622 }
1623
1624 void GlobalParams::setPSOPI(GBool opi) {
1625   lockGlobalParams;
1626   psOPI = opi;
1627   unlockGlobalParams;
1628 }
1629
1630 void GlobalParams::setPSASCIIHex(GBool hex) {
1631   lockGlobalParams;
1632   psASCIIHex = hex;
1633   unlockGlobalParams;
1634 }
1635
1636 void GlobalParams::setTextEncoding(char *encodingName) {
1637   lockGlobalParams;
1638   delete textEncoding;
1639   textEncoding = new GString(encodingName);
1640   unlockGlobalParams;
1641 }
1642
1643 GBool GlobalParams::setTextEOL(char *s) {
1644   lockGlobalParams;
1645   if (!strcmp(s, "unix")) {
1646     textEOL = eolUnix;
1647   } else if (!strcmp(s, "dos")) {
1648     textEOL = eolDOS;
1649   } else if (!strcmp(s, "mac")) {
1650     textEOL = eolMac;
1651   } else {
1652     unlockGlobalParams;
1653     return gFalse;
1654   }
1655   unlockGlobalParams;
1656   return gTrue;
1657 }
1658
1659 void GlobalParams::setTextPageBreaks(GBool pageBreaks) {
1660   lockGlobalParams;
1661   textPageBreaks = pageBreaks;
1662   unlockGlobalParams;
1663 }
1664
1665 void GlobalParams::setTextKeepTinyChars(GBool keep) {
1666   lockGlobalParams;
1667   textKeepTinyChars = keep;
1668   unlockGlobalParams;
1669 }
1670
1671 void GlobalParams::setInitialZoom(char *s) {
1672   lockGlobalParams;
1673   delete initialZoom;
1674   initialZoom = new GString(s);
1675   unlockGlobalParams;
1676 }
1677
1678 GBool GlobalParams::setEnableT1lib(char *s) {
1679   GBool ok;
1680
1681   lockGlobalParams;
1682   ok = parseYesNo2(s, &enableT1lib);
1683   unlockGlobalParams;
1684   return ok;
1685 }
1686
1687 GBool GlobalParams::setEnableFreeType(char *s) {
1688   GBool ok;
1689
1690   lockGlobalParams;
1691   ok = parseYesNo2(s, &enableFreeType);
1692   unlockGlobalParams;
1693   return ok;
1694 }
1695
1696
1697 GBool GlobalParams::setAntialias(char *s) {
1698   GBool ok;
1699
1700   lockGlobalParams;
1701   ok = parseYesNo2(s, &antialias);
1702   unlockGlobalParams;
1703   return ok;
1704 }
1705
1706 void GlobalParams::setMapNumericCharNames(GBool map) {
1707   lockGlobalParams;
1708   mapNumericCharNames = map;
1709   unlockGlobalParams;
1710 }
1711
1712 void GlobalParams::setPrintCommands(GBool printCommandsA) {
1713   lockGlobalParams;
1714   printCommands = printCommandsA;
1715   unlockGlobalParams;
1716 }
1717
1718 void GlobalParams::setErrQuiet(GBool errQuietA) {
1719   lockGlobalParams;
1720   errQuiet = errQuietA;
1721   unlockGlobalParams;
1722 }