added arts device
[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   /* extract path */
502   if(fileName) {
503     char* cfgFileName = fileName->getCString();
504     char* pos1 = strrchr(cfgFileName, '/');
505     char* pos2 = strrchr(cfgFileName, '\\');
506     char* p = pos1>pos2?pos1:pos2;
507     int pos = p ? p-cfgFileName : -1;
508     GString*path = new GString(new GString(cfgFileName), 0, (pos < 0 ? strlen(cfgFileName): pos));
509     if(pos1>=0)
510         path->append('/');
511     else if(pos2>=0)
512         path->append('\\');
513     else
514 #ifdef WIN32
515         path->append('\\');
516 #else
517         path->append('/');
518 #endif
519     this->path = path;
520   } else {
521     this->path = new GString();
522   }
523   
524   line = 1;
525   while (getLine(buf, sizeof(buf) - 1, f)) {
526
527     // break the line into tokens
528     tokens = new GList();
529     p1 = buf;
530     while (*p1) {
531       for (; *p1 && isspace(*p1); ++p1) ;
532       if (!*p1) {
533         break;
534       }
535       if (*p1 == '"' || *p1 == '\'') {
536         for (p2 = p1 + 1; *p2 && *p2 != *p1; ++p2) ;
537         ++p1;
538       } else {
539         for (p2 = p1 + 1; *p2 && !isspace(*p2); ++p2) ;
540       }
541       tokens->append(new GString(p1, p2 - p1));
542       p1 = *p2 ? p2 + 1 : p2;
543     }
544
545     if (tokens->getLength() > 0 &&
546         ((GString *)tokens->get(0))->getChar(0) != '#') {
547       cmd = (GString *)tokens->get(0);
548       if (!cmd->cmp("include")) {
549         if (tokens->getLength() == 2) {
550           incFile = (GString *)tokens->get(1);
551           if ((f2 = fopen(incFile->getCString(), "r"))) {
552             parseFile(incFile, f2);
553             fclose(f2);
554           } else {
555             error(-1, "Couldn't find included config file: '%s' (%s:%d)",
556                   incFile->getCString(), fileName->getCString(), line);
557           }
558         } else {
559           error(-1, "Bad 'include' config file command (%s:%d)",
560                 fileName->getCString(), line);
561         }
562       } else if (!cmd->cmp("nameToUnicode")) {
563         parseNameToUnicode(tokens, fileName, line);
564       } else if (!cmd->cmp("cidToUnicode")) {
565         parseCIDToUnicode(tokens, fileName, line);
566       } else if (!cmd->cmp("unicodeToUnicode")) {
567         parseUnicodeToUnicode(tokens, fileName, line);
568       } else if (!cmd->cmp("unicodeMap")) {
569         parseUnicodeMap(tokens, fileName, line);
570       } else if (!cmd->cmp("cMapDir")) {
571         parseCMapDir(tokens, fileName, line);
572       } else if (!cmd->cmp("toUnicodeDir")) {
573         parseToUnicodeDir(tokens, fileName, line);
574       } else if (!cmd->cmp("displayFontT1")) {
575         parseDisplayFont(tokens, displayFonts, displayFontT1, fileName, line);
576       } else if (!cmd->cmp("displayFontTT")) {
577         parseDisplayFont(tokens, displayFonts, displayFontTT, fileName, line);
578       } else if (!cmd->cmp("displayNamedCIDFontT1")) {
579         parseDisplayFont(tokens, displayNamedCIDFonts,
580                          displayFontT1, fileName, line);
581       } else if (!cmd->cmp("displayCIDFontT1")) {
582         parseDisplayFont(tokens, displayCIDFonts,
583                          displayFontT1, fileName, line);
584       } else if (!cmd->cmp("displayNamedCIDFontTT")) {
585         parseDisplayFont(tokens, displayNamedCIDFonts,
586                          displayFontTT, fileName, line);
587       } else if (!cmd->cmp("displayCIDFontTT")) {
588         parseDisplayFont(tokens, displayCIDFonts,
589                          displayFontTT, fileName, line);
590       } else if (!cmd->cmp("psFile")) {
591         parsePSFile(tokens, fileName, line);
592       } else if (!cmd->cmp("psFont")) {
593         parsePSFont(tokens, fileName, line);
594       } else if (!cmd->cmp("psNamedFont16")) {
595         parsePSFont16("psNamedFont16", psNamedFonts16,
596                       tokens, fileName, line);
597       } else if (!cmd->cmp("psFont16")) {
598         parsePSFont16("psFont16", psFonts16, tokens, fileName, line);
599       } else if (!cmd->cmp("psPaperSize")) {
600         parsePSPaperSize(tokens, fileName, line);
601       } else if (!cmd->cmp("psImageableArea")) {
602         parsePSImageableArea(tokens, fileName, line);
603       } else if (!cmd->cmp("psCrop")) {
604         parseYesNo("psCrop", &psCrop, tokens, fileName, line);
605       } else if (!cmd->cmp("psExpandSmaller")) {
606         parseYesNo("psExpandSmaller", &psExpandSmaller,
607                    tokens, fileName, line);
608       } else if (!cmd->cmp("psShrinkLarger")) {
609         parseYesNo("psShrinkLarger", &psShrinkLarger, tokens, fileName, line);
610       } else if (!cmd->cmp("psCenter")) {
611         parseYesNo("psCenter", &psCenter, tokens, fileName, line);
612       } else if (!cmd->cmp("psDuplex")) {
613         parseYesNo("psDuplex", &psDuplex, tokens, fileName, line);
614       } else if (!cmd->cmp("psLevel")) {
615         parsePSLevel(tokens, fileName, line);
616       } else if (!cmd->cmp("psEmbedType1Fonts")) {
617         parseYesNo("psEmbedType1", &psEmbedType1, tokens, fileName, line);
618       } else if (!cmd->cmp("psEmbedTrueTypeFonts")) {
619         parseYesNo("psEmbedTrueType", &psEmbedTrueType,
620                    tokens, fileName, line);
621       } else if (!cmd->cmp("psEmbedCIDPostScriptFonts")) {
622         parseYesNo("psEmbedCIDPostScript", &psEmbedCIDPostScript,
623                    tokens, fileName, line);
624       } else if (!cmd->cmp("psEmbedCIDTrueTypeFonts")) {
625         parseYesNo("psEmbedCIDTrueType", &psEmbedCIDTrueType,
626                    tokens, fileName, line);
627       } else if (!cmd->cmp("psOPI")) {
628         parseYesNo("psOPI", &psOPI, tokens, fileName, line);
629       } else if (!cmd->cmp("psASCIIHex")) {
630         parseYesNo("psASCIIHex", &psASCIIHex, tokens, fileName, line);
631       } else if (!cmd->cmp("textEncoding")) {
632         parseTextEncoding(tokens, fileName, line);
633       } else if (!cmd->cmp("textEOL")) {
634         parseTextEOL(tokens, fileName, line);
635       } else if (!cmd->cmp("textPageBreaks")) {
636         parseYesNo("textPageBreaks", &textPageBreaks,
637                    tokens, fileName, line);
638       } else if (!cmd->cmp("textKeepTinyChars")) {
639         parseYesNo("textKeepTinyChars", &textKeepTinyChars,
640                    tokens, fileName, line);
641       } else if (!cmd->cmp("fontDir")) {
642         parseFontDir(tokens, fileName, line);
643       } else if (!cmd->cmp("initialZoom")) {
644         parseInitialZoom(tokens, fileName, line);
645       } else if (!cmd->cmp("continuousView")) {
646         parseYesNo("continuousView", &continuousView, tokens, fileName, line);
647       } else if (!cmd->cmp("enableT1lib")) {
648         parseYesNo("enableT1lib", &enableT1lib, tokens, fileName, line);
649       } else if (!cmd->cmp("enableFreeType")) {
650         parseYesNo("enableFreeType", &enableFreeType, tokens, fileName, line);
651       } else if (!cmd->cmp("antialias")) {
652         parseYesNo("antialias", &antialias, tokens, fileName, line);
653       } else if (!cmd->cmp("urlCommand")) {
654         parseCommand("urlCommand", &urlCommand, tokens, fileName, line);
655       } else if (!cmd->cmp("movieCommand")) {
656         parseCommand("movieCommand", &movieCommand, tokens, fileName, line);
657       } else if (!cmd->cmp("mapNumericCharNames")) {
658         parseYesNo("mapNumericCharNames", &mapNumericCharNames,
659                    tokens, fileName, line);
660       } else if (!cmd->cmp("printCommands")) {
661         parseYesNo("printCommands", &printCommands, tokens, fileName, line);
662       } else if (!cmd->cmp("errQuiet")) {
663         parseYesNo("errQuiet", &errQuiet, tokens, fileName, line);
664       } else {
665         error(-1, "Unknown config file command '%s' (%s:%d)",
666               cmd->getCString(), fileName->getCString(), line);
667         if (!cmd->cmp("displayFontX") ||
668             !cmd->cmp("displayNamedCIDFontX") ||
669             !cmd->cmp("displayCIDFontX")) {
670           error(-1, "-- Xpdf no longer supports X fonts");
671         } else if (!cmd->cmp("t1libControl") || !cmd->cmp("freetypeControl")) {
672           error(-1, "-- The t1libControl and freetypeControl options have been replaced");
673           error(-1, "   by the enableT1lib, enableFreeType, and antialias options");
674         } else if (!cmd->cmp("fontpath") || !cmd->cmp("fontmap")) {
675           error(-1, "-- the config file format has changed since Xpdf 0.9x");
676         }
677       }
678     }
679
680     deleteGList(tokens, GString);
681     ++line;
682   }
683 }
684
685 static GString* qualify_filename(GString*path, GString*filename)
686 {
687   GString*fullpath = 0;
688   char*prefix = "/usr/local/share/xpdf/";
689
690   if (filename->getChar(0) != '\\' && filename->getChar(0) != '/') {
691     /* relative path */
692     fullpath = path->copy();
693     fullpath->append(filename);
694   } else if (!strncmp(filename->getCString(), prefix, strlen(prefix))) {
695     /* xpdf default path */
696     char*s = strchr(filename->getCString()+strlen(prefix), '/');
697     if(s) {
698         fullpath = path->copy();
699         fullpath->append(s+1);
700     } else {
701         fullpath = filename->copy();
702     }
703   } else {
704     /* absolute path */
705     fullpath = filename->copy();
706   }
707   //printf("%s -%s-> %s\n", filename->getCString(), path->getCString(), fullpath->getCString());
708   return fullpath;
709 }
710
711 void GlobalParams::parseNameToUnicode(GList *tokens, GString *fileName,
712                                          int line) {
713   GString *name;
714   char *tok1, *tok2;
715   FILE *f;
716   char buf[256];
717   int line2;
718   Unicode u;
719
720   if (tokens->getLength() != 2) {
721     error(-1, "Bad 'nameToUnicode' config file command (%s:%d)",
722           fileName->getCString(), line);
723     return;
724   }
725   name = qualify_filename(this->path, (GString *)tokens->get(1));
726   if (!(f = fopen(name->getCString(), "r"))) {
727     error(-1, "Couldn't open 'nameToUnicode' file '%s'",
728           name->getCString());
729     return;
730   }
731   line2 = 1;
732   while (getLine(buf, sizeof(buf), f)) {
733     tok1 = strtok(buf, " \t\r\n");
734     tok2 = strtok(NULL, " \t\r\n");
735     if (tok1 && tok2) {
736       sscanf(tok1, "%x", &u);
737       nameToUnicode->add(tok2, u);
738     } else {
739       error(-1, "Bad line in 'nameToUnicode' file (%s:%d)", name, line2);
740     }
741     ++line2;
742   }
743   fclose(f);
744 }
745
746 void GlobalParams::parseCIDToUnicode(GList *tokens, GString *fileName,
747                                      int line) {
748   GString *collection, *name, *old;
749
750   if (tokens->getLength() != 3) {
751     error(-1, "Bad 'cidToUnicode' config file command (%s:%d)",
752           fileName->getCString(), line);
753     return;
754   }
755   collection = (GString *)tokens->get(1);
756   name = (GString *)tokens->get(2);
757
758   if ((old = (GString *)cidToUnicodes->remove(collection))) {
759     delete old;
760   }
761
762   cidToUnicodes->add(collection->copy(), qualify_filename(this->path, name));
763 }
764
765 void GlobalParams::parseUnicodeToUnicode(GList *tokens, GString *fileName,
766                                          int line) {
767   GString *font, *file, *old;
768
769   if (tokens->getLength() != 3) {
770     error(-1, "Bad 'unicodeToUnicode' config file command (%s:%d)",
771           fileName->getCString(), line);
772     return;
773   }
774   font = (GString *)tokens->get(1);
775   file = (GString *)tokens->get(2);
776   if ((old = (GString *)unicodeToUnicodes->remove(font))) {
777     delete old;
778   }
779
780   unicodeToUnicodes->add(font->copy(), qualify_filename(this->path, file));
781 }
782
783 void GlobalParams::parseUnicodeMap(GList *tokens, GString *fileName,
784                                    int line) {
785   GString *encodingName, *name, *old;
786
787   if (tokens->getLength() != 3) {
788     error(-1, "Bad 'unicodeMap' config file command (%s:%d)",
789           fileName->getCString(), line);
790     return;
791   }
792   encodingName = (GString *)tokens->get(1);
793   name = (GString *)tokens->get(2);
794   if ((old = (GString *)unicodeMaps->remove(encodingName))) {
795     delete old;
796   }
797
798   unicodeMaps->add(encodingName->copy(), qualify_filename(this->path, name));
799 }
800
801 void GlobalParams::parseCMapDir(GList *tokens, GString *fileName, int line) {
802   GString *collection, *dir;
803   GList *list;
804
805   if (tokens->getLength() != 3) {
806     error(-1, "Bad 'cMapDir' config file command (%s:%d)",
807           fileName->getCString(), line);
808     return;
809   }
810   collection = (GString *)tokens->get(1);
811   dir = (GString *)tokens->get(2);
812   if (!(list = (GList *)cMapDirs->lookup(collection))) {
813     list = new GList();
814     cMapDirs->add(collection->copy(), list);
815   }
816
817   list->append(qualify_filename(this->path, dir));
818 }
819
820 void GlobalParams::parseToUnicodeDir(GList *tokens, GString *fileName,
821                                      int line) {
822   GString *dir;
823
824   if (tokens->getLength() != 2) {
825     error(-1, "Bad 'toUnicodeDir' config file command (%s:%d)",
826           fileName->getCString(), line);
827     return;
828   }
829
830   dir = (GString *)tokens->get(1);
831
832   toUnicodeDirs->append(qualify_filename(this->path, dir));
833 }
834
835 void GlobalParams::parseDisplayFont(GList *tokens, GHash *fontHash,
836                                     DisplayFontParamKind kind,
837                                     GString *fileName, int line) {
838   DisplayFontParam *param, *old;
839   GString *file;
840
841   if (tokens->getLength() < 2) {
842     goto err1;
843   }
844   param = new DisplayFontParam(((GString *)tokens->get(1))->copy(), kind);
845   
846   switch (kind) {
847   case displayFontT1:
848     if (tokens->getLength() != 3) {
849       goto err2;
850     }
851     file = (GString *)tokens->get(2);
852     param->t1.fileName = qualify_filename(this->path, file);
853     break;
854   case displayFontTT:
855     if (tokens->getLength() != 3) {
856       goto err2;
857     }
858     file = (GString *)tokens->get(2);
859     param->tt.fileName = qualify_filename(this->path, file);
860     break;
861   }
862
863   if ((old = (DisplayFontParam *)fontHash->remove(param->name))) {
864     delete old;
865   }
866   fontHash->add(param->name, param);
867   return;
868
869  err2:
870   delete param;
871  err1:
872   error(-1, "Bad 'display*Font*' config file command (%s:%d)",
873         fileName->getCString(), line);
874 }
875
876 void GlobalParams::parsePSPaperSize(GList *tokens, GString *fileName,
877                                     int line) {
878   GString *tok;
879
880   if (tokens->getLength() == 2) {
881     tok = (GString *)tokens->get(1);
882     if (!setPSPaperSize(tok->getCString())) {
883       error(-1, "Bad 'psPaperSize' config file command (%s:%d)",
884             fileName->getCString(), line);
885     }
886   } else if (tokens->getLength() == 3) {
887     tok = (GString *)tokens->get(1);
888     psPaperWidth = atoi(tok->getCString());
889     tok = (GString *)tokens->get(2);
890     psPaperHeight = atoi(tok->getCString());
891     psImageableLLX = psImageableLLY = 0;
892     psImageableURX = psPaperWidth;
893     psImageableURY = psPaperHeight;
894   } else {
895     error(-1, "Bad 'psPaperSize' config file command (%s:%d)",
896           fileName->getCString(), line);
897   }
898 }
899
900 void GlobalParams::parsePSImageableArea(GList *tokens, GString *fileName,
901                                         int line) {
902   if (tokens->getLength() != 5) {
903     error(-1, "Bad 'psImageableArea' config file command (%s:%d)",
904           fileName->getCString(), line);
905     return;
906   }
907   psImageableLLX = atoi(((GString *)tokens->get(1))->getCString());
908   psImageableLLY = atoi(((GString *)tokens->get(2))->getCString());
909   psImageableURX = atoi(((GString *)tokens->get(3))->getCString());
910   psImageableURY = atoi(((GString *)tokens->get(4))->getCString());
911 }
912
913 void GlobalParams::parsePSLevel(GList *tokens, GString *fileName, int line) {
914   GString *tok;
915
916   if (tokens->getLength() != 2) {
917     error(-1, "Bad 'psLevel' config file command (%s:%d)",
918           fileName->getCString(), line);
919     return;
920   }
921   tok = (GString *)tokens->get(1);
922   if (!tok->cmp("level1")) {
923     psLevel = psLevel1;
924   } else if (!tok->cmp("level1sep")) {
925     psLevel = psLevel1Sep;
926   } else if (!tok->cmp("level2")) {
927     psLevel = psLevel2;
928   } else if (!tok->cmp("level2sep")) {
929     psLevel = psLevel2Sep;
930   } else if (!tok->cmp("level3")) {
931     psLevel = psLevel3;
932   } else if (!tok->cmp("level3Sep")) {
933     psLevel = psLevel3Sep;
934   } else {
935     error(-1, "Bad 'psLevel' config file command (%s:%d)",
936           fileName->getCString(), line);
937   }
938 }
939
940 void GlobalParams::parsePSFile(GList *tokens, GString *fileName, int line) {
941   if (tokens->getLength() != 2) {
942     error(-1, "Bad 'psFile' config file command (%s:%d)",
943           fileName->getCString(), line);
944     return;
945   }
946   if (psFile) {
947     delete psFile;
948   }
949   psFile = ((GString *)tokens->get(1))->copy();
950 }
951
952 void GlobalParams::parsePSFont(GList *tokens, GString *fileName, int line) {
953   PSFontParam *param;
954
955   if (tokens->getLength() != 3) {
956     error(-1, "Bad 'psFont' config file command (%s:%d)",
957           fileName->getCString(), line);
958     return;
959   }
960   param = new PSFontParam(((GString *)tokens->get(1))->copy(), 0,
961                           ((GString *)tokens->get(2))->copy(), NULL);
962   psFonts->add(param->pdfFontName, param);
963 }
964
965 void GlobalParams::parsePSFont16(char *cmdName, GList *fontList,
966                                  GList *tokens, GString *fileName, int line) {
967   PSFontParam *param;
968   int wMode;
969   GString *tok;
970
971   if (tokens->getLength() != 5) {
972     error(-1, "Bad '%s' config file command (%s:%d)",
973           cmdName, fileName->getCString(), line);
974     return;
975   }
976   tok = (GString *)tokens->get(2);
977   if (!tok->cmp("H")) {
978     wMode = 0;
979   } else if (!tok->cmp("V")) {
980     wMode = 1;
981   } else {
982     error(-1, "Bad '%s' config file command (%s:%d)",
983           cmdName, fileName->getCString(), line);
984     return;
985   }
986   param = new PSFontParam(((GString *)tokens->get(1))->copy(),
987                           wMode,
988                           ((GString *)tokens->get(3))->copy(),
989                           ((GString *)tokens->get(4))->copy());
990   fontList->append(param);
991 }
992
993 void GlobalParams::parseTextEncoding(GList *tokens, GString *fileName,
994                                      int line) {
995   if (tokens->getLength() != 2) {
996     error(-1, "Bad 'textEncoding' config file command (%s:%d)",
997           fileName->getCString(), line);
998     return;
999   }
1000   delete textEncoding;
1001   textEncoding = ((GString *)tokens->get(1))->copy();
1002 }
1003
1004 void GlobalParams::parseTextEOL(GList *tokens, GString *fileName, int line) {
1005   GString *tok;
1006
1007   if (tokens->getLength() != 2) {
1008     error(-1, "Bad 'textEOL' config file command (%s:%d)",
1009           fileName->getCString(), line);
1010     return;
1011   }
1012   tok = (GString *)tokens->get(1);
1013   if (!tok->cmp("unix")) {
1014     textEOL = eolUnix;
1015   } else if (!tok->cmp("dos")) {
1016     textEOL = eolDOS;
1017   } else if (!tok->cmp("mac")) {
1018     textEOL = eolMac;
1019   } else {
1020     error(-1, "Bad 'textEOL' config file command (%s:%d)",
1021           fileName->getCString(), line);
1022   }
1023 }
1024
1025 void GlobalParams::parseFontDir(GList *tokens, GString *fileName, int line) {
1026   if (tokens->getLength() != 2) {
1027     error(-1, "Bad 'fontDir' config file command (%s:%d)",
1028           fileName->getCString(), line);
1029     return;
1030   }
1031   fontDirs->append(((GString *)tokens->get(1))->copy());
1032 }
1033
1034 void GlobalParams::parseInitialZoom(GList *tokens,
1035                                     GString *fileName, int line) {
1036   if (tokens->getLength() != 2) {
1037     error(-1, "Bad 'initialZoom' config file command (%s:%d)",
1038           fileName->getCString(), line);
1039     return;
1040   }
1041   delete initialZoom;
1042   initialZoom = ((GString *)tokens->get(1))->copy();
1043 }
1044
1045 void GlobalParams::parseCommand(char *cmdName, GString **val,
1046                                 GList *tokens, GString *fileName, int line) {
1047   if (tokens->getLength() != 2) {
1048     error(-1, "Bad '%s' config file command (%s:%d)",
1049           cmdName, fileName->getCString(), line);
1050     return;
1051   }
1052   if (*val) {
1053     delete *val;
1054   }
1055   *val = ((GString *)tokens->get(1))->copy();
1056 }
1057
1058 void GlobalParams::parseYesNo(char *cmdName, GBool *flag,
1059                               GList *tokens, GString *fileName, int line) {
1060   GString *tok;
1061
1062   if (tokens->getLength() != 2) {
1063     error(-1, "Bad '%s' config file command (%s:%d)",
1064           cmdName, fileName->getCString(), line);
1065     return;
1066   }
1067   tok = (GString *)tokens->get(1);
1068   if (!parseYesNo2(tok->getCString(), flag)) {
1069     error(-1, "Bad '%s' config file command (%s:%d)",
1070           cmdName, fileName->getCString(), line);
1071   }
1072 }
1073
1074 GBool GlobalParams::parseYesNo2(char *token, GBool *flag) {
1075   if (!strcmp(token, "yes")) {
1076     *flag = gTrue;
1077   } else if (!strcmp(token, "no")) {
1078     *flag = gFalse;
1079   } else {
1080     return gFalse;
1081   }
1082   return gTrue;
1083 }
1084
1085 GlobalParams::~GlobalParams() {
1086   GHashIter *iter;
1087   GString *key;
1088   GList *list;
1089
1090   freeBuiltinFontTables();
1091
1092   delete macRomanReverseMap;
1093
1094   delete baseDir;
1095   delete nameToUnicode;
1096   deleteGHash(cidToUnicodes, GString);
1097   deleteGHash(unicodeToUnicodes, GString);
1098   deleteGHash(residentUnicodeMaps, UnicodeMap);
1099   deleteGHash(unicodeMaps, GString);
1100   deleteGList(toUnicodeDirs, GString);
1101   deleteGHash(displayFonts, DisplayFontParam);
1102   deleteGHash(displayCIDFonts, DisplayFontParam);
1103   deleteGHash(displayNamedCIDFonts, DisplayFontParam);
1104   if (psFile) {
1105     delete psFile;
1106   }
1107   deleteGHash(psFonts, PSFontParam);
1108   deleteGList(psNamedFonts16, PSFontParam);
1109   deleteGList(psFonts16, PSFontParam);
1110   delete textEncoding;
1111   deleteGList(fontDirs, GString);
1112   delete initialZoom;
1113   if (urlCommand) {
1114     delete urlCommand;
1115   }
1116   if (movieCommand) {
1117     delete movieCommand;
1118   }
1119
1120   cMapDirs->startIter(&iter);
1121   while (cMapDirs->getNext(&iter, &key, (void **)&list)) {
1122     deleteGList(list, GString);
1123   }
1124   delete cMapDirs;
1125
1126   delete cidToUnicodeCache;
1127   delete unicodeToUnicodeCache;
1128   delete unicodeMapCache;
1129   delete cMapCache;
1130
1131 #ifdef ENABLE_PLUGINS
1132   delete securityHandlers;
1133   deleteGList(plugins, Plugin);
1134 #endif
1135
1136 #if MULTITHREADED
1137   gDestroyMutex(&mutex);
1138   gDestroyMutex(&unicodeMapCacheMutex);
1139   gDestroyMutex(&cMapCacheMutex);
1140 #endif
1141 }
1142
1143 //------------------------------------------------------------------------
1144
1145 void GlobalParams::setBaseDir(char *dir) {
1146   delete baseDir;
1147   baseDir = new GString(dir);
1148 }
1149
1150 void GlobalParams::setupBaseFonts(char *dir) {
1151   GString *fontName;
1152   GString *fileName;
1153 #ifdef WIN32
1154   HMODULE shell32Lib;
1155   BOOL (__stdcall *SHGetSpecialFolderPathFunc)(HWND hwndOwner,
1156                                                LPTSTR lpszPath,
1157                                                int nFolder,
1158                                                BOOL fCreate);
1159   char winFontDir[MAX_PATH];
1160 #endif
1161   FILE *f;
1162   DisplayFontParamKind kind;
1163   DisplayFontParam *dfp;
1164   int i, j;
1165
1166 #ifdef WIN32
1167   // SHGetSpecialFolderPath isn't available in older versions of
1168   // shell32.dll (Win95 and WinNT4), so do a dynamic load
1169   winFontDir[0] = '\0';
1170   if ((shell32Lib = LoadLibrary("shell32.dll"))) {
1171     if ((SHGetSpecialFolderPathFunc = 
1172          (BOOL (__stdcall *)(HWND hwndOwner, LPTSTR lpszPath,
1173                              int nFolder, BOOL fCreate))
1174          GetProcAddress(shell32Lib, "SHGetSpecialFolderPath"))) {
1175       if (!(*SHGetSpecialFolderPathFunc)(NULL, winFontDir,
1176                                          CSIDL_FONTS, FALSE)) {
1177         winFontDir[0] = '\0';
1178       }
1179     }
1180   }
1181 #endif
1182   for (i = 0; displayFontTab[i].name; ++i) {
1183     fontName = new GString(displayFontTab[i].name);
1184     if (getDisplayFont(fontName)) {
1185       delete fontName;
1186       continue;
1187     }
1188     fileName = NULL;
1189     kind = displayFontT1; // make gcc happy
1190     if (dir) {
1191       fileName = appendToPath(new GString(dir), displayFontTab[i].t1FileName);
1192       kind = displayFontT1;
1193       if ((f = fopen(fileName->getCString(), "rb"))) {
1194         fclose(f);
1195       } else {
1196         delete fileName;
1197         fileName = NULL;
1198       }
1199     }
1200 #ifdef WIN32
1201     if (!fileName && winFontDir[0] && displayFontTab[i].ttFileName) {
1202       fileName = appendToPath(new GString(winFontDir),
1203                               displayFontTab[i].ttFileName);
1204       kind = displayFontTT;
1205       if ((f = fopen(fileName->getCString(), "rb"))) {
1206         fclose(f);
1207       } else {
1208         delete fileName;
1209         fileName = NULL;
1210       }
1211     }
1212     // SHGetSpecialFolderPath(CSIDL_FONTS) doesn't work on Win 2k Server
1213     // or Win2003 Server, or with older versions of shell32.dll, so check
1214     // the "standard" directories
1215     if (displayFontTab[i].ttFileName) {
1216       for (j = 0; !fileName && displayFontDirs[j]; ++j) {
1217         fileName = appendToPath(new GString(displayFontDirs[j]),
1218                                 displayFontTab[i].ttFileName);
1219         kind = displayFontTT;
1220         if ((f = fopen(fileName->getCString(), "rb"))) {
1221           fclose(f);
1222         } else {
1223           delete fileName;
1224           fileName = NULL;
1225         }
1226       }
1227     }
1228 #else
1229     for (j = 0; !fileName && displayFontDirs[j]; ++j) {
1230       fileName = appendToPath(new GString(displayFontDirs[j]),
1231                               displayFontTab[i].t1FileName);
1232       kind = displayFontT1;
1233       if ((f = fopen(fileName->getCString(), "rb"))) {
1234         fclose(f);
1235       } else {
1236         delete fileName;
1237         fileName = NULL;
1238       }
1239     }
1240 #endif
1241     if (!fileName) {
1242       error(-1, "No display font for '%s'", displayFontTab[i].name);
1243       delete fontName;
1244       continue;
1245     }
1246     dfp = new DisplayFontParam(fontName, kind);
1247     dfp->t1.fileName = fileName;
1248     globalParams->addDisplayFont(dfp);
1249   }
1250 }
1251
1252 //------------------------------------------------------------------------
1253 // accessors
1254 //------------------------------------------------------------------------
1255
1256 CharCode GlobalParams::getMacRomanCharCode(char *charName) {
1257   // no need to lock - macRomanReverseMap is constant
1258   return macRomanReverseMap->lookup(charName);
1259 }
1260
1261 GString *GlobalParams::getBaseDir() {
1262   GString *s;
1263
1264   lockGlobalParams;
1265   s = baseDir->copy();
1266   unlockGlobalParams;
1267   return s;
1268 }
1269
1270 Unicode GlobalParams::mapNameToUnicode(char *charName) {
1271   // no need to lock - nameToUnicode is constant
1272   return nameToUnicode->lookup(charName);
1273 }
1274
1275 UnicodeMap *GlobalParams::getResidentUnicodeMap(GString *encodingName) {
1276   UnicodeMap *map;
1277
1278   lockGlobalParams;
1279   map = (UnicodeMap *)residentUnicodeMaps->lookup(encodingName);
1280   unlockGlobalParams;
1281   if (map) {
1282     map->incRefCnt();
1283   }
1284   return map;
1285 }
1286
1287 FILE *GlobalParams::getUnicodeMapFile(GString *encodingName) {
1288   GString *fileName;
1289   FILE *f;
1290
1291   lockGlobalParams;
1292   if ((fileName = (GString *)unicodeMaps->lookup(encodingName))) {
1293     f = fopen(fileName->getCString(), "r");
1294   } else {
1295     f = NULL;
1296   }
1297   unlockGlobalParams;
1298   return f;
1299 }
1300
1301 FILE *GlobalParams::findCMapFile(GString *collection, GString *cMapName) {
1302   GList *list;
1303   GString *dir;
1304   GString *fileName;
1305   FILE *f;
1306   int i;
1307
1308   lockGlobalParams;
1309   if (!(list = (GList *)cMapDirs->lookup(collection))) {
1310     unlockGlobalParams;
1311     return NULL;
1312   }
1313   for (i = 0; i < list->getLength(); ++i) {
1314     dir = (GString *)list->get(i);
1315     fileName = appendToPath(dir->copy(), cMapName->getCString());
1316     f = fopen(fileName->getCString(), "r");
1317     delete fileName;
1318     if (f) {
1319       unlockGlobalParams;
1320       return f;
1321     }
1322   }
1323   unlockGlobalParams;
1324   return NULL;
1325 }
1326
1327 FILE *GlobalParams::findToUnicodeFile(GString *name) {
1328   GString *dir, *fileName;
1329   FILE *f;
1330   int i;
1331
1332   lockGlobalParams;
1333   for (i = 0; i < toUnicodeDirs->getLength(); ++i) {
1334     dir = (GString *)toUnicodeDirs->get(i);
1335     fileName = appendToPath(dir->copy(), name->getCString());
1336     f = fopen(fileName->getCString(), "r");
1337     delete fileName;
1338     if (f) {
1339       unlockGlobalParams;
1340       return f;
1341     }
1342   }
1343   unlockGlobalParams;
1344   return NULL;
1345 }
1346
1347 DisplayFontParam *GlobalParams::getDisplayFont(GString *fontName) {
1348   DisplayFontParam *dfp;
1349
1350   lockGlobalParams;
1351   dfp = (DisplayFontParam *)displayFonts->lookup(fontName);
1352   unlockGlobalParams;
1353   return dfp;
1354 }
1355
1356 DisplayFontParam *GlobalParams::getDisplayCIDFont(GString *fontName,
1357                                                   GString *collection) {
1358   DisplayFontParam *dfp;
1359
1360   lockGlobalParams;
1361   if (!fontName ||
1362       !(dfp = (DisplayFontParam *)displayNamedCIDFonts->lookup(fontName))) {
1363     dfp = (DisplayFontParam *)displayCIDFonts->lookup(collection);
1364   }
1365   unlockGlobalParams;
1366   return dfp;
1367 }
1368
1369 GString *GlobalParams::getPSFile() {
1370   GString *s;
1371
1372   lockGlobalParams;
1373   s = psFile ? psFile->copy() : (GString *)NULL;
1374   unlockGlobalParams;
1375   return s;
1376 }
1377
1378 int GlobalParams::getPSPaperWidth() {
1379   int w;
1380
1381   lockGlobalParams;
1382   w = psPaperWidth;
1383   unlockGlobalParams;
1384   return w;
1385 }
1386
1387 int GlobalParams::getPSPaperHeight() {
1388   int h;
1389
1390   lockGlobalParams;
1391   h = psPaperHeight;
1392   unlockGlobalParams;
1393   return h;
1394 }
1395
1396 void GlobalParams::getPSImageableArea(int *llx, int *lly, int *urx, int *ury) {
1397   lockGlobalParams;
1398   *llx = psImageableLLX;
1399   *lly = psImageableLLY;
1400   *urx = psImageableURX;
1401   *ury = psImageableURY;
1402   unlockGlobalParams;
1403 }
1404
1405 GBool GlobalParams::getPSCrop() {
1406   GBool f;
1407
1408   lockGlobalParams;
1409   f = psCrop;
1410   unlockGlobalParams;
1411   return f;
1412 }
1413
1414 GBool GlobalParams::getPSExpandSmaller() {
1415   GBool f;
1416
1417   lockGlobalParams;
1418   f = psExpandSmaller;
1419   unlockGlobalParams;
1420   return f;
1421 }
1422
1423 GBool GlobalParams::getPSShrinkLarger() {
1424   GBool f;
1425
1426   lockGlobalParams;
1427   f = psShrinkLarger;
1428   unlockGlobalParams;
1429   return f;
1430 }
1431
1432 GBool GlobalParams::getPSCenter() {
1433   GBool f;
1434
1435   lockGlobalParams;
1436   f = psCenter;
1437   unlockGlobalParams;
1438   return f;
1439 }
1440
1441 GBool GlobalParams::getPSDuplex() {
1442   GBool d;
1443
1444   lockGlobalParams;
1445   d = psDuplex;
1446   unlockGlobalParams;
1447   return d;
1448 }
1449
1450 PSLevel GlobalParams::getPSLevel() {
1451   PSLevel level;
1452
1453   lockGlobalParams;
1454   level = psLevel;
1455   unlockGlobalParams;
1456   return level;
1457 }
1458
1459 PSFontParam *GlobalParams::getPSFont(GString *fontName) {
1460   PSFontParam *p;
1461
1462   lockGlobalParams;
1463   p = (PSFontParam *)psFonts->lookup(fontName);
1464   unlockGlobalParams;
1465   return p;
1466 }
1467
1468 PSFontParam *GlobalParams::getPSFont16(GString *fontName,
1469                                        GString *collection, int wMode) {
1470   PSFontParam *p;
1471   int i;
1472
1473   lockGlobalParams;
1474   p = NULL;
1475   if (fontName) {
1476     for (i = 0; i < psNamedFonts16->getLength(); ++i) {
1477       p = (PSFontParam *)psNamedFonts16->get(i);
1478       if (!p->pdfFontName->cmp(fontName) &&
1479           p->wMode == wMode) {
1480         break;
1481       }
1482       p = NULL;
1483     }
1484   }
1485   if (!p && collection) {
1486     for (i = 0; i < psFonts16->getLength(); ++i) {
1487       p = (PSFontParam *)psFonts16->get(i);
1488       if (!p->pdfFontName->cmp(collection) &&
1489           p->wMode == wMode) {
1490         break;
1491       }
1492       p = NULL;
1493     }
1494   }
1495   unlockGlobalParams;
1496   return p;
1497 }
1498
1499 GBool GlobalParams::getPSEmbedType1() {
1500   GBool e;
1501
1502   lockGlobalParams;
1503   e = psEmbedType1;
1504   unlockGlobalParams;
1505   return e;
1506 }
1507
1508 GBool GlobalParams::getPSEmbedTrueType() {
1509   GBool e;
1510
1511   lockGlobalParams;
1512   e = psEmbedTrueType;
1513   unlockGlobalParams;
1514   return e;
1515 }
1516
1517 GBool GlobalParams::getPSEmbedCIDPostScript() {
1518   GBool e;
1519
1520   lockGlobalParams;
1521   e = psEmbedCIDPostScript;
1522   unlockGlobalParams;
1523   return e;
1524 }
1525
1526 GBool GlobalParams::getPSEmbedCIDTrueType() {
1527   GBool e;
1528
1529   lockGlobalParams;
1530   e = psEmbedCIDTrueType;
1531   unlockGlobalParams;
1532   return e;
1533 }
1534
1535 GBool GlobalParams::getPSOPI() {
1536   GBool opi;
1537
1538   lockGlobalParams;
1539   opi = psOPI;
1540   unlockGlobalParams;
1541   return opi;
1542 }
1543
1544 GBool GlobalParams::getPSASCIIHex() {
1545   GBool ah;
1546
1547   lockGlobalParams;
1548   ah = psASCIIHex;
1549   unlockGlobalParams;
1550   return ah;
1551 }
1552
1553 GString *GlobalParams::getTextEncodingName() {
1554   GString *s;
1555
1556   lockGlobalParams;
1557   s = textEncoding->copy();
1558   unlockGlobalParams;
1559   return s;
1560 }
1561
1562 EndOfLineKind GlobalParams::getTextEOL() {
1563   EndOfLineKind eol;
1564
1565   lockGlobalParams;
1566   eol = textEOL;
1567   unlockGlobalParams;
1568   return eol;
1569 }
1570
1571 GBool GlobalParams::getTextPageBreaks() {
1572   GBool pageBreaks;
1573
1574   lockGlobalParams;
1575   pageBreaks = textPageBreaks;
1576   unlockGlobalParams;
1577   return pageBreaks;
1578 }
1579
1580 GBool GlobalParams::getTextKeepTinyChars() {
1581   GBool tiny;
1582
1583   lockGlobalParams;
1584   tiny = textKeepTinyChars;
1585   unlockGlobalParams;
1586   return tiny;
1587 }
1588
1589 GString *GlobalParams::findFontFile(GString *fontName, char **exts) {
1590   GString *dir, *fileName;
1591   char **ext;
1592   FILE *f;
1593   int i;
1594
1595   lockGlobalParams;
1596   for (i = 0; i < fontDirs->getLength(); ++i) {
1597     dir = (GString *)fontDirs->get(i);
1598     for (ext = exts; *ext; ++ext) {
1599       fileName = appendToPath(dir->copy(), fontName->getCString());
1600       fileName->append(*ext);
1601       if ((f = fopen(fileName->getCString(), "rb"))) {
1602         fclose(f);
1603         unlockGlobalParams;
1604         return fileName;
1605       }
1606       delete fileName;
1607     }
1608   }
1609   unlockGlobalParams;
1610   return NULL;
1611 }
1612
1613 GString *GlobalParams::getInitialZoom() {
1614   GString *s;
1615
1616   lockGlobalParams;
1617   s = initialZoom->copy();
1618   unlockGlobalParams;
1619   return s;
1620 }
1621
1622 GBool GlobalParams::getContinuousView() {
1623   GBool f;
1624
1625   lockGlobalParams;
1626   f = continuousView;
1627   unlockGlobalParams;
1628   return f;
1629 }
1630
1631 GBool GlobalParams::getEnableT1lib() {
1632   GBool f;
1633
1634   lockGlobalParams;
1635   f = enableT1lib;
1636   unlockGlobalParams;
1637   return f;
1638 }
1639
1640 GBool GlobalParams::getEnableFreeType() {
1641   GBool f;
1642
1643   lockGlobalParams;
1644   f = enableFreeType;
1645   unlockGlobalParams;
1646   return f;
1647 }
1648
1649
1650 GBool GlobalParams::getAntialias() {
1651   GBool f;
1652
1653   lockGlobalParams;
1654   f = antialias;
1655   unlockGlobalParams;
1656   return f;
1657 }
1658
1659 GBool GlobalParams::getMapNumericCharNames() {
1660   GBool map;
1661
1662   lockGlobalParams;
1663   map = mapNumericCharNames;
1664   unlockGlobalParams;
1665   return map;
1666 }
1667
1668 GBool GlobalParams::getPrintCommands() {
1669   GBool p;
1670
1671   lockGlobalParams;
1672   p = printCommands;
1673   unlockGlobalParams;
1674   return p;
1675 }
1676
1677 GBool GlobalParams::getErrQuiet() {
1678   GBool q;
1679
1680   lockGlobalParams;
1681   q = errQuiet;
1682   unlockGlobalParams;
1683   return q;
1684 }
1685
1686 CharCodeToUnicode *GlobalParams::getCIDToUnicode(GString *collection) {
1687   GString *fileName;
1688   CharCodeToUnicode *ctu;
1689
1690   lockGlobalParams;
1691   if (!(ctu = cidToUnicodeCache->getCharCodeToUnicode(collection))) {
1692     if ((fileName = (GString *)cidToUnicodes->lookup(collection)) &&
1693         (ctu = CharCodeToUnicode::parseCIDToUnicode(fileName, collection))) {
1694       cidToUnicodeCache->add(ctu);
1695     }
1696   }
1697   unlockGlobalParams;
1698   return ctu;
1699 }
1700
1701 CharCodeToUnicode *GlobalParams::getUnicodeToUnicode(GString *fontName) {
1702   CharCodeToUnicode *ctu;
1703   GHashIter *iter;
1704   GString *fontPattern, *fileName;
1705
1706   lockGlobalParams;
1707   fileName = NULL;
1708   unicodeToUnicodes->startIter(&iter);
1709   while (unicodeToUnicodes->getNext(&iter, &fontPattern, (void **)&fileName)) {
1710     if (strstr(fontName->getCString(), fontPattern->getCString())) {
1711       unicodeToUnicodes->killIter(&iter);
1712       break;
1713     }
1714     fileName = NULL;
1715   }
1716   if (fileName) {
1717     if (!(ctu = unicodeToUnicodeCache->getCharCodeToUnicode(fileName))) {
1718       if ((ctu = CharCodeToUnicode::parseUnicodeToUnicode(fileName))) {
1719         unicodeToUnicodeCache->add(ctu);
1720       }
1721     }
1722   } else {
1723     ctu = NULL;
1724   }
1725   unlockGlobalParams;
1726   return ctu;
1727 }
1728
1729 UnicodeMap *GlobalParams::getUnicodeMap(GString *encodingName) {
1730   return getUnicodeMap2(encodingName);
1731 }
1732
1733 UnicodeMap *GlobalParams::getUnicodeMap2(GString *encodingName) {
1734   UnicodeMap *map;
1735
1736   if (!(map = getResidentUnicodeMap(encodingName))) {
1737     lockUnicodeMapCache;
1738     map = unicodeMapCache->getUnicodeMap(encodingName);
1739     unlockUnicodeMapCache;
1740   }
1741   return map;
1742 }
1743
1744 CMap *GlobalParams::getCMap(GString *collection, GString *cMapName) {
1745   CMap *cMap;
1746
1747   lockCMapCache;
1748   cMap = cMapCache->getCMap(collection, cMapName);
1749   unlockCMapCache;
1750   return cMap;
1751 }
1752
1753 UnicodeMap *GlobalParams::getTextEncoding() {
1754   return getUnicodeMap2(textEncoding);
1755 }
1756
1757 //------------------------------------------------------------------------
1758 // functions to set parameters
1759 //------------------------------------------------------------------------
1760
1761 void GlobalParams::addDisplayFont(DisplayFontParam *param) {
1762   DisplayFontParam *old;
1763
1764   lockGlobalParams;
1765   if ((old = (DisplayFontParam *)displayFonts->remove(param->name))) {
1766     delete old;
1767   }
1768   displayFonts->add(param->name, param);
1769   unlockGlobalParams;
1770 }
1771
1772 void GlobalParams::setPSFile(char *file) {
1773   lockGlobalParams;
1774   if (psFile) {
1775     delete psFile;
1776   }
1777   psFile = new GString(file);
1778   unlockGlobalParams;
1779 }
1780
1781 GBool GlobalParams::setPSPaperSize(char *size) {
1782   lockGlobalParams;
1783   if (!strcmp(size, "match")) {
1784     psPaperWidth = psPaperHeight = -1;
1785   } else if (!strcmp(size, "letter")) {
1786     psPaperWidth = 612;
1787     psPaperHeight = 792;
1788   } else if (!strcmp(size, "legal")) {
1789     psPaperWidth = 612;
1790     psPaperHeight = 1008;
1791   } else if (!strcmp(size, "A4")) {
1792     psPaperWidth = 595;
1793     psPaperHeight = 842;
1794   } else if (!strcmp(size, "A3")) {
1795     psPaperWidth = 842;
1796     psPaperHeight = 1190;
1797   } else {
1798     unlockGlobalParams;
1799     return gFalse;
1800   }
1801   psImageableLLX = psImageableLLY = 0;
1802   psImageableURX = psPaperWidth;
1803   psImageableURY = psPaperHeight;
1804   unlockGlobalParams;
1805   return gTrue;
1806 }
1807
1808 void GlobalParams::setPSPaperWidth(int width) {
1809   lockGlobalParams;
1810   psPaperWidth = width;
1811   psImageableLLX = 0;
1812   psImageableURX = psPaperWidth;
1813   unlockGlobalParams;
1814 }
1815
1816 void GlobalParams::setPSPaperHeight(int height) {
1817   lockGlobalParams;
1818   psPaperHeight = height;
1819   psImageableLLY = 0;
1820   psImageableURY = psPaperHeight;
1821   unlockGlobalParams;
1822 }
1823
1824 void GlobalParams::setPSImageableArea(int llx, int lly, int urx, int ury) {
1825   lockGlobalParams;
1826   psImageableLLX = llx;
1827   psImageableLLY = lly;
1828   psImageableURX = urx;
1829   psImageableURY = ury;
1830   unlockGlobalParams;
1831 }
1832
1833 void GlobalParams::setPSCrop(GBool crop) {
1834   lockGlobalParams;
1835   psCrop = crop;
1836   unlockGlobalParams;
1837 }
1838
1839 void GlobalParams::setPSExpandSmaller(GBool expand) {
1840   lockGlobalParams;
1841   psExpandSmaller = expand;
1842   unlockGlobalParams;
1843 }
1844
1845 void GlobalParams::setPSShrinkLarger(GBool shrink) {
1846   lockGlobalParams;
1847   psShrinkLarger = shrink;
1848   unlockGlobalParams;
1849 }
1850
1851 void GlobalParams::setPSCenter(GBool center) {
1852   lockGlobalParams;
1853   psCenter = center;
1854   unlockGlobalParams;
1855 }
1856
1857 void GlobalParams::setPSDuplex(GBool duplex) {
1858   lockGlobalParams;
1859   psDuplex = duplex;
1860   unlockGlobalParams;
1861 }
1862
1863 void GlobalParams::setPSLevel(PSLevel level) {
1864   lockGlobalParams;
1865   psLevel = level;
1866   unlockGlobalParams;
1867 }
1868
1869 void GlobalParams::setPSEmbedType1(GBool embed) {
1870   lockGlobalParams;
1871   psEmbedType1 = embed;
1872   unlockGlobalParams;
1873 }
1874
1875 void GlobalParams::setPSEmbedTrueType(GBool embed) {
1876   lockGlobalParams;
1877   psEmbedTrueType = embed;
1878   unlockGlobalParams;
1879 }
1880
1881 void GlobalParams::setPSEmbedCIDPostScript(GBool embed) {
1882   lockGlobalParams;
1883   psEmbedCIDPostScript = embed;
1884   unlockGlobalParams;
1885 }
1886
1887 void GlobalParams::setPSEmbedCIDTrueType(GBool embed) {
1888   lockGlobalParams;
1889   psEmbedCIDTrueType = embed;
1890   unlockGlobalParams;
1891 }
1892
1893 void GlobalParams::setPSOPI(GBool opi) {
1894   lockGlobalParams;
1895   psOPI = opi;
1896   unlockGlobalParams;
1897 }
1898
1899 void GlobalParams::setPSASCIIHex(GBool hex) {
1900   lockGlobalParams;
1901   psASCIIHex = hex;
1902   unlockGlobalParams;
1903 }
1904
1905 void GlobalParams::setTextEncoding(char *encodingName) {
1906   lockGlobalParams;
1907   delete textEncoding;
1908   textEncoding = new GString(encodingName);
1909   unlockGlobalParams;
1910 }
1911
1912 GBool GlobalParams::setTextEOL(char *s) {
1913   lockGlobalParams;
1914   if (!strcmp(s, "unix")) {
1915     textEOL = eolUnix;
1916   } else if (!strcmp(s, "dos")) {
1917     textEOL = eolDOS;
1918   } else if (!strcmp(s, "mac")) {
1919     textEOL = eolMac;
1920   } else {
1921     unlockGlobalParams;
1922     return gFalse;
1923   }
1924   unlockGlobalParams;
1925   return gTrue;
1926 }
1927
1928 void GlobalParams::setTextPageBreaks(GBool pageBreaks) {
1929   lockGlobalParams;
1930   textPageBreaks = pageBreaks;
1931   unlockGlobalParams;
1932 }
1933
1934 void GlobalParams::setTextKeepTinyChars(GBool keep) {
1935   lockGlobalParams;
1936   textKeepTinyChars = keep;
1937   unlockGlobalParams;
1938 }
1939
1940 void GlobalParams::setInitialZoom(char *s) {
1941   lockGlobalParams;
1942   delete initialZoom;
1943   initialZoom = new GString(s);
1944   unlockGlobalParams;
1945 }
1946
1947 void GlobalParams::setContinuousView(GBool cont) {
1948   lockGlobalParams;
1949   continuousView = cont;
1950   unlockGlobalParams;
1951 }
1952
1953 GBool GlobalParams::setEnableT1lib(char *s) {
1954   GBool ok;
1955
1956   lockGlobalParams;
1957   ok = parseYesNo2(s, &enableT1lib);
1958   unlockGlobalParams;
1959   return ok;
1960 }
1961
1962 GBool GlobalParams::setEnableFreeType(char *s) {
1963   GBool ok;
1964
1965   lockGlobalParams;
1966   ok = parseYesNo2(s, &enableFreeType);
1967   unlockGlobalParams;
1968   return ok;
1969 }
1970
1971
1972 GBool GlobalParams::setAntialias(char *s) {
1973   GBool ok;
1974
1975   lockGlobalParams;
1976   ok = parseYesNo2(s, &antialias);
1977   unlockGlobalParams;
1978   return ok;
1979 }
1980
1981 void GlobalParams::setMapNumericCharNames(GBool map) {
1982   lockGlobalParams;
1983   mapNumericCharNames = map;
1984   unlockGlobalParams;
1985 }
1986
1987 void GlobalParams::setPrintCommands(GBool printCommandsA) {
1988   lockGlobalParams;
1989   printCommands = printCommandsA;
1990   unlockGlobalParams;
1991 }
1992
1993 void GlobalParams::setErrQuiet(GBool errQuietA) {
1994   lockGlobalParams;
1995   errQuiet = errQuietA;
1996   unlockGlobalParams;
1997 }
1998
1999 void GlobalParams::addSecurityHandler(XpdfSecurityHandler *handler) {
2000 #ifdef ENABLE_PLUGINS
2001   lockGlobalParams;
2002   securityHandlers->append(handler);
2003   unlockGlobalParams;
2004 #endif
2005 }
2006
2007 XpdfSecurityHandler *GlobalParams::getSecurityHandler(char *name) {
2008 #ifdef ENABLE_PLUGINS
2009   XpdfSecurityHandler *hdlr;
2010   int i;
2011
2012   lockGlobalParams;
2013   for (i = 0; i < securityHandlers->getLength(); ++i) {
2014     hdlr = (XpdfSecurityHandler *)securityHandlers->get(i);
2015     if (!stricmp(hdlr->name, name)) {
2016       unlockGlobalParams;
2017       return hdlr;
2018     }
2019   }
2020   unlockGlobalParams;
2021
2022   if (!loadPlugin("security", name)) {
2023     return NULL;
2024   }
2025
2026   lockGlobalParams;
2027   for (i = 0; i < securityHandlers->getLength(); ++i) {
2028     hdlr = (XpdfSecurityHandler *)securityHandlers->get(i);
2029     if (!strcmp(hdlr->name, name)) {
2030       unlockGlobalParams;
2031       return hdlr;
2032     }
2033   }
2034   unlockGlobalParams;
2035 #endif
2036
2037   return NULL;
2038 }
2039
2040 #ifdef ENABLE_PLUGINS
2041 //------------------------------------------------------------------------
2042 // plugins
2043 //------------------------------------------------------------------------
2044
2045 GBool GlobalParams::loadPlugin(char *type, char *name) {
2046   Plugin *plugin;
2047
2048   if (!(plugin = Plugin::load(type, name))) {
2049     return gFalse;
2050   }
2051   lockGlobalParams;
2052   plugins->append(plugin);
2053   unlockGlobalParams;
2054   return gTrue;
2055 }
2056
2057 #endif // ENABLE_PLUGINS