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