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