"Fossies" - the Fresh Open Source Software Archive

Member "xpdf-4.04/xpdf/GlobalParams.cc" (18 Apr 2022, 103543 Bytes) of package /linux/misc/xpdf-4.04.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "GlobalParams.cc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.03_vs_4.04.

    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 <stdarg.h>
   18 #include <ctype.h>
   19 #include <time.h>
   20 #ifdef _WIN32
   21 #  include <shlobj.h>
   22 #endif
   23 #if HAVE_PAPER_H
   24 #include <paper.h>
   25 #endif
   26 #if HAVE_FONTCONFIG
   27 #  include <fontconfig/fontconfig.h>
   28 #endif
   29 #include "gmem.h"
   30 #include "gmempp.h"
   31 #include "GString.h"
   32 #include "GList.h"
   33 #include "GHash.h"
   34 #include "gfile.h"
   35 #include "FoFiIdentifier.h"
   36 #include "Error.h"
   37 #include "NameToCharCode.h"
   38 #include "CharCodeToUnicode.h"
   39 #include "UnicodeRemapping.h"
   40 #include "UnicodeMap.h"
   41 #include "CMap.h"
   42 #include "BuiltinFontTables.h"
   43 #include "FontEncodingTables.h"
   44 #include "GlobalParams.h"
   45 
   46 #ifdef _WIN32
   47 #  define strcasecmp stricmp
   48 #  define strncasecmp strnicmp
   49 #endif
   50 
   51 #if MULTITHREADED
   52 #  define lockGlobalParams            gLockMutex(&mutex)
   53 #  define lockUnicodeMapCache         gLockMutex(&unicodeMapCacheMutex)
   54 #  define lockCMapCache               gLockMutex(&cMapCacheMutex)
   55 #  define unlockGlobalParams          gUnlockMutex(&mutex)
   56 #  define unlockUnicodeMapCache       gUnlockMutex(&unicodeMapCacheMutex)
   57 #  define unlockCMapCache             gUnlockMutex(&cMapCacheMutex)
   58 #else
   59 #  define lockGlobalParams
   60 #  define lockUnicodeMapCache
   61 #  define lockCMapCache
   62 #  define unlockGlobalParams
   63 #  define unlockUnicodeMapCache
   64 #  define unlockCMapCache
   65 #endif
   66 
   67 #include "NameToUnicodeTable.h"
   68 #include "UnicodeMapTables.h"
   69 #include "UTF8.h"
   70 
   71 //------------------------------------------------------------------------
   72 
   73 #define cidToUnicodeCacheSize     4
   74 #define unicodeToUnicodeCacheSize 4
   75 
   76 //------------------------------------------------------------------------
   77 
   78 static struct {
   79   const char *name;
   80   const char *t1FileName;
   81   const char *ttFileName;
   82   const char *macFileName;  // may be .dfont, .ttf, or .ttc
   83   const char *macFontName;  // font name inside .dfont or .ttc
   84   const char *obliqueFont;  // name of font to oblique
   85   double obliqueFactor;     // oblique sheer factor
   86 } displayFontTab[] = {
   87   {"Courier",               "n022003l.pfb", "cour.ttf",    "Courier",      "Courier",                NULL,             0},
   88   {"Courier-Bold",          "n022004l.pfb", "courbd.ttf",  "Courier",      "Courier Bold",           NULL,             0},
   89   {"Courier-BoldOblique",   "n022024l.pfb", "courbi.ttf",  "Courier",      "Courier Bold Oblique",   "Courier-Bold",   0.212557},
   90   {"Courier-Oblique",       "n022023l.pfb", "couri.ttf",   "Courier",      "Courier Oblique",        "Courier",        0.212557},
   91   {"Helvetica",             "n019003l.pfb", "arial.ttf",   "Helvetica",    "Helvetica",              NULL,             0},
   92   {"Helvetica-Bold",        "n019004l.pfb", "arialbd.ttf", "Helvetica",    "Helvetica Bold",         NULL,             0},
   93   {"Helvetica-BoldOblique", "n019024l.pfb", "arialbi.ttf", "Helvetica",    "Helvetica Bold Oblique", "Helvetica-Bold", 0.212557},
   94   {"Helvetica-Oblique",     "n019023l.pfb", "ariali.ttf",  "Helvetica",    "Helvetica Oblique",      "Helvetica",      0.212557},
   95   {"Symbol",                "s050000l.pfb", NULL,          "Symbol",       "Symbol",                 NULL,             0},
   96   {"Times-Bold",            "n021004l.pfb", "timesbd.ttf", "Times",        "Times Bold",             NULL,             0},
   97   {"Times-BoldItalic",      "n021024l.pfb", "timesbi.ttf", "Times",        "Times Bold Italic",       NULL,             0},
   98   {"Times-Italic",          "n021023l.pfb", "timesi.ttf",  "Times",        "Times Italic",           NULL,             0},
   99   {"Times-Roman",           "n021003l.pfb", "times.ttf",   "Times",        "Times Roman",            NULL,             0},
  100   {"ZapfDingbats",          "d050000l.pfb", NULL,          "ZapfDingbats", "Zapf Dingbats",          NULL,             0},
  101   {NULL}
  102 };
  103 
  104 #ifdef _WIN32
  105 static const char *displayFontDirs[] = {
  106   "c:/windows/fonts",
  107   "c:/winnt/fonts",
  108   NULL
  109 };
  110 #else
  111 static const char *displayFontDirs[] = {
  112   "/usr/share/ghostscript/fonts",
  113   "/usr/local/share/ghostscript/fonts",
  114   "/usr/share/fonts/default/Type1",
  115   "/usr/share/fonts/default/ghostscript",
  116   "/usr/share/fonts/type1/gsfonts",
  117 #if defined(__sun) && defined(__SVR4)
  118   "/usr/sfw/share/ghostscript/fonts",
  119 #endif
  120   NULL
  121 };
  122 #endif
  123 
  124 #ifdef __APPLE__
  125 static const char *macSystemFontPath = "/System/Library/Fonts";
  126 #endif
  127 
  128 struct Base14FontInfo {
  129   Base14FontInfo(GString *fileNameA, int fontNumA, double obliqueA) {
  130     fileName = fileNameA;
  131     fontNum = fontNumA;
  132     oblique = obliqueA;
  133   }
  134   ~Base14FontInfo() {
  135     delete fileName;
  136   }
  137   GString *fileName;
  138   int fontNum;
  139   double oblique;
  140 };
  141 
  142 //------------------------------------------------------------------------
  143 
  144 GlobalParams *globalParams = NULL;
  145 
  146 const char *GlobalParams::defaultTextEncoding = "Latin1";
  147 
  148 //------------------------------------------------------------------------
  149 // PSFontParam16
  150 //------------------------------------------------------------------------
  151 
  152 PSFontParam16::PSFontParam16(GString *nameA, int wModeA,
  153                  GString *psFontNameA, GString *encodingA) {
  154   name = nameA;
  155   wMode = wModeA;
  156   psFontName = psFontNameA;
  157   encoding = encodingA;
  158 }
  159 
  160 PSFontParam16::~PSFontParam16() {
  161   delete name;
  162   delete psFontName;
  163   delete encoding;
  164 }
  165 
  166 //------------------------------------------------------------------------
  167 // SysFontInfo
  168 //------------------------------------------------------------------------
  169 
  170 class SysFontInfo {
  171 public:
  172 
  173   GString *name;
  174   GString *path;
  175   SysFontType type;
  176   int fontNum;          // for TrueType collections
  177 
  178   SysFontInfo(GString *nameA, GString *pathA, SysFontType typeA, int fontNumA);
  179   ~SysFontInfo();
  180   GString *mungeName1(GString *in);
  181   GString *mungeName2(GString *in);
  182   void mungeName3(GString *name, GBool *bold, GBool *italic);
  183   int match(GString *nameA);
  184 };
  185 
  186 SysFontInfo::SysFontInfo(GString *nameA, GString *pathA,
  187              SysFontType typeA, int fontNumA) {
  188   name = nameA;
  189   path = pathA;
  190   type = typeA;
  191   fontNum = fontNumA;
  192 }
  193 
  194 SysFontInfo::~SysFontInfo() {
  195   delete name;
  196   delete path;
  197 }
  198 
  199 // Remove space/comma/dash/underscore chars.
  200 // Uppercase the name.
  201 GString *SysFontInfo::mungeName1(GString *in) {
  202   GString *out = new GString();
  203   for (char *p = in->getCString(); *p; ++p) {
  204     if (*p == ' ' || *p == ',' || *p == '-' || *p == '_') {
  205       // skip
  206     } else if (*p >= 'a' && *p <= 'z') {
  207       out->append((char)(*p & 0xdf));
  208     } else {
  209       out->append(*p);
  210     }
  211   }
  212   return out;
  213 }
  214 
  215 // Remove trailing encoding tags from the name.
  216 // Split the name into tokens at space/comma/dash/underscore.
  217 // Remove trailing "MT" or "BT" from tokens.
  218 // Remove trailing "PS" and "WGL4" from tokens.
  219 // Uppercase each token.
  220 // Concatenate tokens (dropping the space/comma/dash chars).
  221 GString *SysFontInfo::mungeName2(GString *in) {
  222   GString *out = new GString();
  223   char *p0 = in->getCString();
  224   while (*p0) {
  225     if (!strcmp(p0, "Identity-H") || !strcmp(p0, "Identity-V") ||
  226     !strcmp(p0, "GB2312") ||
  227     !strcmp(p0, "UniGB-UCS2-H") || !strcmp(p0, "UniGB-UCS2-V")) {
  228       break;
  229     }
  230     char *p1;
  231     for (p1 = p0 + 1;
  232      *p1 && *p1 != ' ' && *p1 != ',' && *p1 != '-' && *p1 != '_';
  233      ++p1) ;
  234     char *p2 = p1;
  235     if (p2 - p0 >= 2 && (p2[-2] == 'B' || p2[-2] == 'M') && p2[-1] == 'T') {
  236       p2 -= 2;
  237     }
  238     if (p2 - p0 >= 2 && p2[-2] == 'P' && p2[-1] == 'S') {
  239       p2 -= 2;
  240     }
  241     if (p2 - p0 >= 4 &&
  242     p2[-4] == 'W' && p2[-3] == 'G' && p2[-2] == 'L' && p2[-1] == '4') {
  243       p2 -= 4;
  244     }
  245     for (; p0 < p2; ++p0) {
  246       if (*p0 >= 'a' && *p0 <= 'z') {
  247     out->append((char)(*p0 & 0xdf));
  248       } else {
  249     out->append(*p0);
  250       }
  251     }
  252     for (p0 = p1; *p0 == ' ' || *p0 == ',' || *p0 == '-' || *p0 == '_'; ++p0) ;
  253   }
  254   return out;
  255 }
  256 
  257 // Remove trailing bold/italic/regular/roman tags from the name.
  258 // (Note: the names have already been uppercased by mungeName1/2.)
  259 void SysFontInfo::mungeName3(GString *name, GBool *bold, GBool *italic) {
  260   *bold = gFalse;
  261   *italic = gFalse;
  262   int n = name->getLength();
  263   while (1) {
  264     if (n >= 4 && !strcmp(name->getCString() + n - 4, "BOLD")) {
  265       name->del(n - 4, 4);
  266       n -= 4;
  267       *bold = gTrue;
  268     } else if (n >= 6 && !strcmp(name->getCString() + n - 6, "ITALIC")) {
  269       name->del(n - 6, 6);
  270       n -= 6;
  271       *italic = gTrue;
  272     } else if (n >= 7 && !strcmp(name->getCString() + n - 7, "REGULAR")) {
  273       name->del(n - 7, 7);
  274       n -= 7;
  275     } else if (n >= 5 && !strcmp(name->getCString() + n - 5, "ROMAN")) {
  276       name->del(n - 5, 5);
  277       n -= 5;
  278     } else {
  279       break;
  280     }
  281   }
  282 }
  283 
  284 // Returns a score indicating how well this font matches [nameA].  A
  285 // higher score is better.  Zero indicates a non-match.
  286 int SysFontInfo::match(GString *nameA) {
  287   // fast fail: check if the first two letters match
  288   if (strncasecmp(name->getCString(), nameA->getCString(), 2)) {
  289     return 0;
  290   }
  291 
  292   GString *pdfName1 = mungeName1(nameA);
  293   GString *sysName1 = mungeName1(name);
  294   if (!pdfName1->cmp(sysName1)) {
  295     delete pdfName1;
  296     delete sysName1;
  297     return 8;
  298   }
  299 
  300   GString *pdfName2 = mungeName2(nameA);
  301   GString *sysName2 = mungeName2(name);
  302   if (!pdfName2->cmp(sysName2)) {
  303     delete pdfName1;
  304     delete sysName1;
  305     delete pdfName2;
  306     delete sysName2;
  307     return 7;
  308   }
  309 
  310   GBool pdfBold1, pdfItalic1, sysBold1, sysItalic1;
  311   mungeName3(pdfName1, &pdfBold1, &pdfItalic1);
  312   mungeName3(sysName1, &sysBold1, &sysItalic1);
  313   int eq1 = !pdfName1->cmp(sysName1);
  314 
  315   GBool pdfBold2, pdfItalic2, sysBold2, sysItalic2;
  316   mungeName3(pdfName2, &pdfBold2, &pdfItalic2);
  317   mungeName3(sysName2, &sysBold2, &sysItalic2);
  318   int eq2 =!pdfName2->cmp(sysName2);
  319 
  320   delete pdfName1;
  321   delete sysName1;
  322   delete pdfName2;
  323   delete sysName2;
  324 
  325   if (eq1 && pdfBold1 == sysBold1 && pdfItalic1 == sysItalic1) {
  326     return 6;
  327   }
  328   if (eq2 && pdfBold2 == sysBold2 && pdfItalic2 == sysItalic2) {
  329     return 5;
  330   }
  331   if (eq1 && pdfItalic1 == sysItalic1) {
  332     return 4;
  333   }
  334   if (eq2 && pdfItalic2 == sysItalic2) {
  335     return 3;
  336   }
  337   if (eq1) {
  338     return 2;
  339   }
  340   if (eq2) {
  341     return 1;
  342   }
  343 
  344   return 0;
  345 }
  346 
  347 //------------------------------------------------------------------------
  348 // SysFontList
  349 //------------------------------------------------------------------------
  350 
  351 class SysFontList {
  352 public:
  353 
  354   SysFontList();
  355   ~SysFontList();
  356   SysFontInfo *find(GString *name);
  357 
  358 #ifdef _WIN32
  359   void scanWindowsFonts(char *winFontDir);
  360 #endif
  361 
  362 #if HAVE_FONTCONFIG
  363   void scanFontconfigFonts();
  364 #endif
  365 
  366 private:
  367 
  368 #ifdef _WIN32
  369   SysFontInfo *makeWindowsFont(char *name, int fontNum,
  370                    char *path);
  371 #endif
  372 
  373   GList *fonts;         // [SysFontInfo]
  374 };
  375 
  376 SysFontList::SysFontList() {
  377   fonts = new GList();
  378 }
  379 
  380 SysFontList::~SysFontList() {
  381   deleteGList(fonts, SysFontInfo);
  382 }
  383 
  384 SysFontInfo *SysFontList::find(GString *name) {
  385   SysFontInfo *match = NULL;
  386   int score = 0;
  387   for (int i = 0; i < fonts->getLength(); ++i) {
  388     SysFontInfo *fi = (SysFontInfo *)fonts->get(i);
  389     int s = fi->match(name);
  390     if (s > score) {
  391       match = fi;
  392       score = s;
  393     }
  394   }
  395   return match;
  396 }
  397 
  398 #ifdef _WIN32
  399 void SysFontList::scanWindowsFonts(char *winFontDir) {
  400   OSVERSIONINFO version;
  401   const char *path;
  402   DWORD idx, valNameLen, dataLen, type;
  403   HKEY regKey;
  404   char valName[1024], data[1024];
  405   int n, fontNum;
  406   char *p0, *p1;
  407   GString *fontPath;
  408 
  409   version.dwOSVersionInfoSize = sizeof(version);
  410   GetVersionEx(&version);
  411   if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
  412     path = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts\\";
  413   } else {
  414     path = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts\\";
  415   }
  416   if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, path, 0,
  417             KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
  418             &regKey) == ERROR_SUCCESS) {
  419     idx = 0;
  420     while (1) {
  421       valNameLen = sizeof(valName) - 1;
  422       dataLen = sizeof(data) - 1;
  423       if (RegEnumValueA(regKey, idx, valName, &valNameLen, NULL,
  424             &type, (LPBYTE)data, &dataLen) != ERROR_SUCCESS) {
  425     break;
  426       }
  427       if (type == REG_SZ &&
  428       valNameLen > 0 && valNameLen < sizeof(valName) &&
  429       dataLen > 0 && dataLen < sizeof(data)) {
  430     valName[valNameLen] = '\0';
  431     data[dataLen] = '\0';
  432     n = (int)strlen(data);
  433     if (!strcasecmp(data + n - 4, ".ttf") ||
  434         !strcasecmp(data + n - 4, ".ttc") ||
  435         !strcasecmp(data + n - 4, ".otf")) {
  436       fontPath = new GString(data);
  437       if (!(dataLen >= 3 && data[1] == ':' && data[2] == '\\')) {
  438         fontPath->insert(0, '\\');
  439         fontPath->insert(0, winFontDir);
  440       }
  441       p0 = valName;
  442       fontNum = 0;
  443       while (*p0) {
  444         p1 = strstr(p0, " & ");
  445         if (p1) {
  446           *p1 = '\0';
  447           p1 = p1 + 3;
  448         } else {
  449           p1 = p0 + strlen(p0);
  450         }
  451         fonts->append(makeWindowsFont(p0, fontNum,
  452                       fontPath->getCString()));
  453         p0 = p1;
  454         ++fontNum;
  455       }
  456       delete fontPath;
  457     }
  458       }
  459       ++idx;
  460     }
  461     RegCloseKey(regKey);
  462   }
  463 }
  464 
  465 SysFontInfo *SysFontList::makeWindowsFont(char *name, int fontNum,
  466                       char *path) {
  467   int n = (int)strlen(name);
  468 
  469   // remove trailing ' (TrueType)' or ' (OpenType)'
  470   if (n > 11 && (!strncmp(name + n - 11, " (TrueType)", 11) ||
  471          !strncmp(name + n - 11, " (OpenType)", 11))) {
  472     n -= 11;
  473   }
  474 
  475   SysFontType type;
  476   if (!strcasecmp(path + strlen(path) - 4, ".ttc")) {
  477     type = sysFontTTC;
  478   } else if (!strcasecmp(path + strlen(path) - 4, ".otf")) {
  479     type = sysFontOTF;
  480   } else {
  481     type = sysFontTTF;
  482   }
  483 
  484   return new SysFontInfo(new GString(name, n), new GString(path),
  485              type, fontNum);
  486 }
  487 #endif // _WIN32
  488 
  489 #if HAVE_FONTCONFIG
  490 void SysFontList::scanFontconfigFonts() {
  491   FcConfig *cfg;
  492   FcPattern *pattern;
  493   FcObjectSet *objSet;
  494   FcFontSet *fontSet;
  495   char *name, *file;
  496   SysFontType type;
  497   int fontNum, i, n;
  498 
  499   if (!(cfg = FcInitLoadConfigAndFonts())) {
  500     return;
  501   }
  502 
  503   pattern = FcPatternBuild(NULL,
  504                FC_OUTLINE, FcTypeBool, FcTrue,
  505                FC_SCALABLE, FcTypeBool, FcTrue,
  506                NULL);
  507   objSet = FcObjectSetBuild(FC_FULLNAME, FC_FILE, FC_INDEX, NULL);
  508   fontSet = FcFontList(cfg, pattern, objSet);
  509   FcPatternDestroy(pattern);
  510   FcObjectSetDestroy(objSet);
  511 
  512   if (fontSet) {
  513     for (i = 0; i < fontSet->nfont; ++i) {
  514 
  515       //--- font file, font type
  516       if (FcPatternGetString(fontSet->fonts[i], FC_FILE, 0,
  517                  (FcChar8 **)&file)
  518       != FcResultMatch) {
  519     continue;
  520       }
  521       n = (int)strlen(file);
  522       if (n > 4 && !strcasecmp(file + n - 4, ".pfa")) {
  523     type = sysFontPFA;
  524       } else if (n > 4 && !strcasecmp(file + n - 4, ".pfb")) {
  525     type = sysFontPFB;
  526       } else if (n > 4 && !strcasecmp(file + n - 4, ".ttf")) {
  527     type = sysFontTTF;
  528       } else if (n > 4 && !strcasecmp(file + n - 4, ".otf")) {
  529     type = sysFontOTF;
  530       } else {
  531     continue;
  532       }
  533 
  534       //--- font number
  535       if (FcPatternGetInteger(fontSet->fonts[i], FC_INDEX, 0, &fontNum)
  536       != FcResultMatch) {
  537     fontNum = 0;
  538       }
  539 
  540       //--- font name
  541       if (FcPatternGetString(fontSet->fonts[i], FC_FULLNAME, 0,
  542                  (FcChar8 **)&name)
  543       != FcResultMatch) {
  544     continue;
  545       }
  546 
  547       fonts->append(new SysFontInfo(new GString(name), new GString(file),
  548                     type, fontNum));
  549     }
  550 
  551     FcFontSetDestroy(fontSet);
  552   }
  553 
  554   FcConfigDestroy(cfg);
  555 }
  556 #endif // HAVE_FONTCONFIG
  557 
  558 //------------------------------------------------------------------------
  559 // KeyBinding
  560 //------------------------------------------------------------------------
  561 
  562 KeyBinding::KeyBinding(int codeA, int modsA, int contextA, const char *cmd0) {
  563   code = codeA;
  564   mods = modsA;
  565   context = contextA;
  566   cmds = new GList();
  567   cmds->append(new GString(cmd0));
  568 }
  569 
  570 KeyBinding::KeyBinding(int codeA, int modsA, int contextA,
  571                const char *cmd0, const char *cmd1) {
  572   code = codeA;
  573   mods = modsA;
  574   context = contextA;
  575   cmds = new GList();
  576   cmds->append(new GString(cmd0));
  577   cmds->append(new GString(cmd1));
  578 }
  579 
  580 KeyBinding::KeyBinding(int codeA, int modsA, int contextA, GList *cmdsA) {
  581   code = codeA;
  582   mods = modsA;
  583   context = contextA;
  584   cmds = cmdsA;
  585 }
  586 
  587 KeyBinding::~KeyBinding() {
  588   deleteGList(cmds, GString);
  589 }
  590 
  591 //------------------------------------------------------------------------
  592 // PopupMenuCmd
  593 //------------------------------------------------------------------------
  594 
  595 PopupMenuCmd::PopupMenuCmd(GString *labelA, GList *cmdsA) {
  596   label = labelA;
  597   cmds = cmdsA;
  598 }
  599 
  600 PopupMenuCmd::~PopupMenuCmd() {
  601   delete label;
  602   deleteGList(cmds, GString);
  603 }
  604 
  605 //------------------------------------------------------------------------
  606 // parsing
  607 //------------------------------------------------------------------------
  608 
  609 GlobalParams::GlobalParams(const char *cfgFileName) {
  610   UnicodeMap *map;
  611   GString *fileName;
  612   FILE *f;
  613   int i;
  614 
  615 #if MULTITHREADED
  616   gInitMutex(&mutex);
  617   gInitMutex(&unicodeMapCacheMutex);
  618   gInitMutex(&cMapCacheMutex);
  619 #endif
  620 
  621 #ifdef _WIN32
  622   tlsWin32ErrorInfo = TlsAlloc();
  623 #endif
  624 
  625   initBuiltinFontTables();
  626 
  627   // scan the encoding in reverse because we want the lowest-numbered
  628   // index for each char name ('space' is encoded twice)
  629   macRomanReverseMap = new NameToCharCode();
  630   for (i = 255; i >= 0; --i) {
  631     if (macRomanEncoding[i]) {
  632       macRomanReverseMap->add(macRomanEncoding[i], (CharCode)i);
  633     }
  634   }
  635 
  636 #ifdef _WIN32
  637   // baseDir will be set by a call to setBaseDir
  638   baseDir = new GString();
  639 #else
  640   baseDir = appendToPath(getHomeDir(), ".xpdf");
  641 #endif
  642   configFileVars = new GHash(gTrue);
  643   setDataDirVar();
  644   nameToUnicode = new NameToCharCode();
  645   cidToUnicodes = new GHash(gTrue);
  646   unicodeToUnicodes = new GHash(gTrue);
  647   residentUnicodeMaps = new GHash();
  648   unicodeMaps = new GHash(gTrue);
  649   cMapDirs = new GHash(gTrue);
  650   toUnicodeDirs = new GList();
  651   unicodeRemapping = new UnicodeRemapping();
  652   fontFiles = new GHash(gTrue);
  653   fontDirs = new GList();
  654   ccFontFiles = new GHash(gTrue);
  655   base14SysFonts = new GHash(gTrue);
  656   sysFonts = new SysFontList();
  657 #if HAVE_PAPER_H
  658   char *paperName;
  659   const struct paper *paperType;
  660   paperinit();
  661   if ((paperName = systempapername())) {
  662     paperType = paperinfo(paperName);
  663     psPaperWidth = (int)paperpswidth(paperType);
  664     psPaperHeight = (int)paperpsheight(paperType);
  665   } else {
  666     error(errConfig, -1, "No paper information available - using defaults");
  667     psPaperWidth = defPaperWidth;
  668     psPaperHeight = defPaperHeight;
  669   }
  670   paperdone();
  671 #else
  672   psPaperWidth = defPaperWidth;
  673   psPaperHeight = defPaperHeight;
  674 #endif
  675   psImageableLLX = psImageableLLY = 0;
  676   psImageableURX = psPaperWidth;
  677   psImageableURY = psPaperHeight;
  678   psCrop = gTrue;
  679   psUseCropBoxAsPage = gFalse;
  680   psExpandSmaller = gFalse;
  681   psShrinkLarger = gTrue;
  682   psCenter = gTrue;
  683   psDuplex = gFalse;
  684   psLevel = psLevel2;
  685   psResidentFonts = new GHash(gTrue);
  686   psResidentFonts16 = new GList();
  687   psResidentFontsCC = new GList();
  688   psEmbedType1 = gTrue;
  689   psEmbedTrueType = gTrue;
  690   psEmbedCIDPostScript = gTrue;
  691   psEmbedCIDTrueType = gTrue;
  692   psFontPassthrough = gFalse;
  693   psPreload = gFalse;
  694   psOPI = gFalse;
  695   psASCIIHex = gFalse;
  696   psLZW = gTrue;
  697   psUncompressPreloadedImages = gFalse;
  698   psMinLineWidth = 0;
  699   psRasterResolution = 300;
  700   psRasterMono = gFalse;
  701   psRasterSliceSize = 20000000;
  702   psAlwaysRasterize = gFalse;
  703   psNeverRasterize = gFalse;
  704   textEncoding = new GString(defaultTextEncoding);
  705 #if defined(_WIN32)
  706   textEOL = eolDOS;
  707 #else
  708   textEOL = eolUnix;
  709 #endif
  710   textPageBreaks = gTrue;
  711   textKeepTinyChars = gTrue;
  712   initialZoom = new GString("125");
  713   defaultFitZoom = 0;
  714   initialDisplayMode = new GString("continuous");
  715   initialToolbarState = gTrue;
  716   initialSidebarState = gTrue;
  717   initialSidebarWidth = 0;
  718   initialSelectMode = new GString("linear");
  719   maxTileWidth = 1500;
  720   maxTileHeight = 1500;
  721   tileCacheSize = 10;
  722   workerThreads = 1;
  723   enableFreeType = gTrue;
  724   disableFreeTypeHinting = gFalse;
  725   antialias = gTrue;
  726   vectorAntialias = gTrue;
  727   imageMaskAntialias = gTrue;
  728   antialiasPrinting = gFalse;
  729   strokeAdjust = strokeAdjustNormal;
  730   screenType = screenUnset;
  731   screenSize = -1;
  732   screenDotRadius = -1;
  733   screenGamma = 1.0;
  734   screenBlackThreshold = 0.0;
  735   screenWhiteThreshold = 1.0;
  736   minLineWidth = 0.0;
  737   enablePathSimplification = gFalse;
  738   drawAnnotations = gTrue;
  739   drawFormFields = gTrue;
  740   enableXFA = gTrue;
  741   overprintPreview = gFalse;
  742   paperColor = new GString("#ffffff");
  743   matteColor = new GString("#808080");
  744   fullScreenMatteColor = new GString("#000000");
  745   selectionColor = new GString("#8080ff");
  746   reverseVideoInvertImages = gFalse;
  747   launchCommand = NULL;
  748   movieCommand = NULL;
  749   defaultPrinter = NULL;
  750   mapNumericCharNames = gTrue;
  751   mapUnknownCharNames = gFalse;
  752   mapExtTrueTypeFontsViaUnicode = gTrue;
  753   useTrueTypeUnicodeMapping = gFalse;
  754   droppedFonts = new GHash(gTrue);
  755   createDefaultKeyBindings();
  756   popupMenuCmds = new GList();
  757   tabStateFile = appendToPath(getHomeDir(), ".xpdf.tab-state");
  758   savePageNumbers = gTrue;
  759   printCommands = gFalse;
  760   printStatusInfo = gFalse;
  761   errQuiet = gFalse;
  762   debugLogFile = NULL;
  763 
  764   cidToUnicodeCache = new CharCodeToUnicodeCache(cidToUnicodeCacheSize);
  765   unicodeToUnicodeCache =
  766       new CharCodeToUnicodeCache(unicodeToUnicodeCacheSize);
  767   unicodeMapCache = new UnicodeMapCache();
  768   cMapCache = new CMapCache();
  769 
  770   // set up the initial nameToUnicode table
  771   for (i = 0; nameToUnicodeTab[i].name; ++i) {
  772     nameToUnicode->add(nameToUnicodeTab[i].name, nameToUnicodeTab[i].u);
  773   }
  774 
  775   // set up the residentUnicodeMaps table
  776   map = new UnicodeMap("Latin1", gFalse,
  777                latin1UnicodeMapRanges, latin1UnicodeMapLen);
  778   residentUnicodeMaps->add(map->getEncodingName(), map);
  779   map = new UnicodeMap("ASCII7", gFalse,
  780                ascii7UnicodeMapRanges, ascii7UnicodeMapLen);
  781   residentUnicodeMaps->add(map->getEncodingName(), map);
  782   map = new UnicodeMap("Symbol", gFalse,
  783                symbolUnicodeMapRanges, symbolUnicodeMapLen);
  784   residentUnicodeMaps->add(map->getEncodingName(), map);
  785   map = new UnicodeMap("ZapfDingbats", gFalse, zapfDingbatsUnicodeMapRanges,
  786                zapfDingbatsUnicodeMapLen);
  787   residentUnicodeMaps->add(map->getEncodingName(), map);
  788   map = new UnicodeMap("UTF-8", gTrue, &mapUTF8);
  789   residentUnicodeMaps->add(map->getEncodingName(), map);
  790   map = new UnicodeMap("UCS-2", gTrue, &mapUCS2);
  791   residentUnicodeMaps->add(map->getEncodingName(), map);
  792 
  793   // look for a user config file, then a system-wide config file
  794   f = NULL;
  795   fileName = NULL;
  796   if (cfgFileName && cfgFileName[0]) {
  797     fileName = new GString(cfgFileName);
  798     if (!(f = fopen(fileName->getCString(), "r"))) {
  799       delete fileName;
  800     }
  801   }
  802   if (!f) {
  803     fileName = appendToPath(getHomeDir(), xpdfUserConfigFile);
  804     if (!(f = fopen(fileName->getCString(), "r"))) {
  805       delete fileName;
  806     }
  807   }
  808   if (!f) {
  809 #ifdef _WIN32
  810     char buf[512];
  811     i = GetModuleFileNameA(NULL, buf, sizeof(buf));
  812     if (i <= 0 || i >= sizeof(buf)) {
  813       // error or path too long for buffer - just use the current dir
  814       buf[0] = '\0';
  815     }
  816     fileName = grabPath(buf);
  817     appendToPath(fileName, xpdfSysConfigFile);
  818 #else
  819     fileName = new GString(xpdfSysConfigFile);
  820 #endif
  821     if (!(f = fopen(fileName->getCString(), "r"))) {
  822       delete fileName;
  823     }
  824   }
  825   if (f) {
  826     parseFile(fileName, f);
  827     delete fileName;
  828     fclose(f);
  829   }
  830 }
  831 
  832 void GlobalParams::setDataDirVar() {
  833   GString *dir;
  834 
  835 #if defined(XPDFRC_DATADIR)
  836   dir = new GString(XPDFRC_DATADIR);
  837 #elif defined(_WIN32)
  838   wchar_t buf[512];
  839   DWORD n = GetModuleFileNameW(NULL, buf, sizeof(buf) / sizeof(wchar_t));
  840   if (n <= 0 || n >= sizeof(buf)) {
  841     // error or path too long for buffer - just use the current dir
  842     buf[0] = L'\0';
  843   }
  844   GString *path = fileNameToUTF8(buf);
  845   dir = grabPath(path->getCString());
  846   delete path;
  847   appendToPath(dir, "data");
  848 #else
  849   //~ may be useful to allow the options of using the install dir
  850   //~   and/or the user's home dir (?)
  851   dir = new GString("./data");
  852 #endif
  853 
  854   configFileVars->add(new GString("DATADIR"), dir);
  855 }
  856 
  857 void GlobalParams::createDefaultKeyBindings() {
  858   keyBindings = new GList();
  859 
  860   //----- mouse buttons
  861   keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress1, xpdfKeyModNone,
  862                      xpdfKeyContextAny, "startSelection"));
  863   keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress1, xpdfKeyModShift,
  864                      xpdfKeyContextAny,
  865                      "startExtendedSelection"));
  866   keyBindings->append(new KeyBinding(xpdfKeyCodeMouseRelease1, xpdfKeyModNone,
  867                      xpdfKeyContextAny, "endSelection"));
  868   keyBindings->append(new KeyBinding(xpdfKeyCodeMouseRelease1, xpdfKeyModShift,
  869                      xpdfKeyContextAny,
  870                      "endSelection"));
  871   keyBindings->append(new KeyBinding(xpdfKeyCodeMouseDoubleClick1,
  872                      xpdfKeyModNone, xpdfKeyContextAny,
  873                      "selectWord"));
  874   keyBindings->append(new KeyBinding(xpdfKeyCodeMouseTripleClick1,
  875                      xpdfKeyModNone, xpdfKeyContextAny,
  876                      "selectLine"));
  877   keyBindings->append(new KeyBinding(xpdfKeyCodeMouseClick1, xpdfKeyModNone,
  878                      xpdfKeyContextAny, "followLinkNoSel"));
  879   keyBindings->append(new KeyBinding(xpdfKeyCodeMouseClick2, xpdfKeyModNone,
  880                      xpdfKeyContextOverLink,
  881                      "followLinkInNewTab"));
  882   keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress2, xpdfKeyModNone,
  883                      xpdfKeyContextAny, "startPan"));
  884   keyBindings->append(new KeyBinding(xpdfKeyCodeMouseRelease2, xpdfKeyModNone,
  885                      xpdfKeyContextAny, "endPan"));
  886   keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress3, xpdfKeyModNone,
  887                      xpdfKeyContextAny, "postPopupMenu"));
  888   keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress4, xpdfKeyModNone,
  889                      xpdfKeyContextAny,
  890                      "scrollUpPrevPage(16)"));
  891   keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress5, xpdfKeyModNone,
  892                      xpdfKeyContextAny,
  893                      "scrollDownNextPage(16)"));
  894   keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress6, xpdfKeyModNone,
  895                      xpdfKeyContextAny, "scrollLeft(16)"));
  896   keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress7, xpdfKeyModNone,
  897                      xpdfKeyContextAny, "scrollRight(16)"));
  898   keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress4, xpdfKeyModCtrl,
  899                      xpdfKeyContextAny, "zoomIn"));
  900   keyBindings->append(new KeyBinding(xpdfKeyCodeMousePress5, xpdfKeyModCtrl,
  901                      xpdfKeyContextAny, "zoomOut"));
  902 
  903   //----- control keys
  904   keyBindings->append(new KeyBinding('o', xpdfKeyModCtrl,
  905                      xpdfKeyContextAny, "open"));
  906   keyBindings->append(new KeyBinding('r', xpdfKeyModCtrl,
  907                      xpdfKeyContextAny, "reload"));
  908   keyBindings->append(new KeyBinding('f', xpdfKeyModCtrl,
  909                      xpdfKeyContextAny, "find"));
  910   keyBindings->append(new KeyBinding('g', xpdfKeyModCtrl,
  911                      xpdfKeyContextAny, "findNext"));
  912   keyBindings->append(new KeyBinding('c', xpdfKeyModCtrl,
  913                      xpdfKeyContextAny, "copy"));
  914   keyBindings->append(new KeyBinding('p', xpdfKeyModCtrl,
  915                      xpdfKeyContextAny, "print"));
  916   keyBindings->append(new KeyBinding('0', xpdfKeyModCtrl,
  917                      xpdfKeyContextAny, "zoomPercent(125)"));
  918   keyBindings->append(new KeyBinding('+', xpdfKeyModCtrl,
  919                      xpdfKeyContextAny, "zoomIn"));
  920   keyBindings->append(new KeyBinding('=', xpdfKeyModCtrl,
  921                      xpdfKeyContextAny, "zoomIn"));
  922   keyBindings->append(new KeyBinding('-', xpdfKeyModCtrl,
  923                      xpdfKeyContextAny, "zoomOut"));
  924   keyBindings->append(new KeyBinding('s', xpdfKeyModCtrl,
  925                      xpdfKeyContextAny, "saveAs"));
  926   keyBindings->append(new KeyBinding('t', xpdfKeyModCtrl,
  927                      xpdfKeyContextAny, "newTab"));
  928   keyBindings->append(new KeyBinding('n', xpdfKeyModCtrl,
  929                      xpdfKeyContextAny, "newWindow"));
  930   keyBindings->append(new KeyBinding('w', xpdfKeyModCtrl,
  931                      xpdfKeyContextAny, "closeTabOrQuit"));
  932   keyBindings->append(new KeyBinding('l', xpdfKeyModCtrl,
  933                      xpdfKeyContextAny,
  934                      "toggleFullScreenMode"));
  935   keyBindings->append(new KeyBinding('q', xpdfKeyModCtrl,
  936                      xpdfKeyContextAny, "quit"));
  937   keyBindings->append(new KeyBinding(xpdfKeyCodeTab, xpdfKeyModCtrl,
  938                      xpdfKeyContextAny, "nextTab"));
  939   keyBindings->append(new KeyBinding(xpdfKeyCodeTab,
  940                      xpdfKeyModShift | xpdfKeyModCtrl,
  941                      xpdfKeyContextAny, "prevTab"));
  942   keyBindings->append(new KeyBinding('?', xpdfKeyModCtrl,
  943                      xpdfKeyContextAny, "help"));
  944 
  945   //----- alt keys
  946   keyBindings->append(new KeyBinding(xpdfKeyCodeLeft, xpdfKeyModAlt,
  947                      xpdfKeyContextAny, "goBackward"));
  948   keyBindings->append(new KeyBinding(xpdfKeyCodeRight, xpdfKeyModAlt,
  949                      xpdfKeyContextAny, "goForward"));
  950 
  951   //----- home/end keys
  952   keyBindings->append(new KeyBinding(xpdfKeyCodeHome, xpdfKeyModCtrl,
  953                      xpdfKeyContextAny, "gotoPage(1)"));
  954   keyBindings->append(new KeyBinding(xpdfKeyCodeHome, xpdfKeyModNone,
  955                      xpdfKeyContextAny, "scrollToTopLeft"));
  956   keyBindings->append(new KeyBinding(xpdfKeyCodeEnd, xpdfKeyModCtrl,
  957                      xpdfKeyContextAny, "gotoLastPage"));
  958   keyBindings->append(new KeyBinding(xpdfKeyCodeEnd, xpdfKeyModNone,
  959                      xpdfKeyContextAny,
  960                      "scrollToBottomRight"));
  961 
  962   //----- pgup/pgdn keys
  963   keyBindings->append(new KeyBinding(xpdfKeyCodePgUp, xpdfKeyModNone,
  964                      xpdfKeyContextAny, "pageUp"));
  965   keyBindings->append(new KeyBinding(xpdfKeyCodePgDn, xpdfKeyModNone,
  966                      xpdfKeyContextAny, "pageDown"));
  967   keyBindings->append(new KeyBinding(xpdfKeyCodePgUp, xpdfKeyModCtrl,
  968                      xpdfKeyContextAny, "prevPage"));
  969   keyBindings->append(new KeyBinding(xpdfKeyCodePgDn, xpdfKeyModCtrl,
  970                      xpdfKeyContextAny, "nextPage"));
  971   keyBindings->append(new KeyBinding(xpdfKeyCodePgUp, xpdfKeyModCtrl,
  972                      xpdfKeyContextScrLockOn,
  973                      "prevPageNoScroll"));
  974   keyBindings->append(new KeyBinding(xpdfKeyCodePgDn, xpdfKeyModCtrl,
  975                      xpdfKeyContextScrLockOn,
  976                      "nextPageNoScroll"));
  977 
  978   //----- esc key
  979   keyBindings->append(new KeyBinding(xpdfKeyCodeEsc, xpdfKeyModNone,
  980                      xpdfKeyContextFullScreen,
  981                      "windowMode"));
  982 
  983   //----- arrow keys
  984   keyBindings->append(new KeyBinding(xpdfKeyCodeLeft, xpdfKeyModNone,
  985                      xpdfKeyContextAny, "scrollLeft(16)"));
  986   keyBindings->append(new KeyBinding(xpdfKeyCodeRight, xpdfKeyModNone,
  987                      xpdfKeyContextAny, "scrollRight(16)"));
  988   keyBindings->append(new KeyBinding(xpdfKeyCodeUp, xpdfKeyModNone,
  989                      xpdfKeyContextAny, "scrollUp(16)"));
  990   keyBindings->append(new KeyBinding(xpdfKeyCodeDown, xpdfKeyModNone,
  991                      xpdfKeyContextAny, "scrollDown(16)"));
  992   keyBindings->append(new KeyBinding(xpdfKeyCodeUp, xpdfKeyModCtrl,
  993                      xpdfKeyContextAny, "prevPage"));
  994   keyBindings->append(new KeyBinding(xpdfKeyCodeDown, xpdfKeyModCtrl,
  995                      xpdfKeyContextAny, "nextPage"));
  996   keyBindings->append(new KeyBinding(xpdfKeyCodeUp, xpdfKeyModCtrl,
  997                      xpdfKeyContextScrLockOn,
  998                      "prevPageNoScroll"));
  999   keyBindings->append(new KeyBinding(xpdfKeyCodeDown, xpdfKeyModCtrl,
 1000                      xpdfKeyContextScrLockOn,
 1001                      "nextPageNoScroll"));
 1002 
 1003   //----- letter keys
 1004   keyBindings->append(new KeyBinding(' ', xpdfKeyModNone,
 1005                      xpdfKeyContextAny, "pageDown"));
 1006   keyBindings->append(new KeyBinding('g', xpdfKeyModNone,
 1007                      xpdfKeyContextAny, "focusToPageNum"));
 1008   keyBindings->append(new KeyBinding('z', xpdfKeyModNone,
 1009                      xpdfKeyContextAny, "zoomFitPage"));
 1010   keyBindings->append(new KeyBinding('w', xpdfKeyModNone,
 1011                      xpdfKeyContextAny, "zoomFitWidth"));
 1012 }
 1013 
 1014 void GlobalParams::parseFile(GString *fileName, FILE *f) {
 1015   int line;
 1016   char buf[512];
 1017 
 1018   line = 1;
 1019   while (getLine(buf, sizeof(buf) - 1, f)) {
 1020     parseLine(buf, fileName, line);
 1021     ++line;
 1022   }
 1023 }
 1024 
 1025 void GlobalParams::parseLine(char *buf, GString *fileName, int line) {
 1026   GList *tokens;
 1027   GString *cmd, *incFile;
 1028   FILE *f2;
 1029 
 1030   // break the line into tokens
 1031   tokens = parseLineTokens(buf, fileName, line);
 1032 
 1033   // parse the line
 1034   if (tokens->getLength() > 0 &&
 1035       ((GString *)tokens->get(0))->getChar(0) != '#') {
 1036     cmd = (GString *)tokens->get(0);
 1037     if (!cmd->cmp("include")) {
 1038       if (tokens->getLength() == 2) {
 1039     incFile = (GString *)tokens->get(1);
 1040     if ((f2 = openFile(incFile->getCString(), "r"))) {
 1041       parseFile(incFile, f2);
 1042       fclose(f2);
 1043     } else {
 1044       error(errConfig, -1,
 1045         "Couldn't find included config file: '{0:t}' ({1:t}:{2:d})",
 1046         incFile, fileName, line);
 1047     }
 1048       } else {
 1049     error(errConfig, -1, "Bad 'include' config file command ({0:t}:{1:d})",
 1050           fileName, line);
 1051       }
 1052     } else if (!cmd->cmp("nameToUnicode")) {
 1053       parseNameToUnicode(tokens, fileName, line);
 1054     } else if (!cmd->cmp("cidToUnicode")) {
 1055       parseCIDToUnicode(tokens, fileName, line);
 1056     } else if (!cmd->cmp("unicodeToUnicode")) {
 1057       parseUnicodeToUnicode(tokens, fileName, line);
 1058     } else if (!cmd->cmp("unicodeMap")) {
 1059       parseUnicodeMap(tokens, fileName, line);
 1060     } else if (!cmd->cmp("cMapDir")) {
 1061       parseCMapDir(tokens, fileName, line);
 1062     } else if (!cmd->cmp("toUnicodeDir")) {
 1063       parseToUnicodeDir(tokens, fileName, line);
 1064     } else if (!cmd->cmp("unicodeRemapping")) {
 1065       parseUnicodeRemapping(tokens, fileName, line);
 1066     } else if (!cmd->cmp("fontFile")) {
 1067       parseFontFile(tokens, fileName, line);
 1068     } else if (!cmd->cmp("fontDir")) {
 1069       parseFontDir(tokens, fileName, line);
 1070     } else if (!cmd->cmp("fontFileCC")) {
 1071       parseFontFileCC(tokens, fileName, line);
 1072     } else if (!cmd->cmp("psPaperSize")) {
 1073       parsePSPaperSize(tokens, fileName, line);
 1074     } else if (!cmd->cmp("psImageableArea")) {
 1075       parsePSImageableArea(tokens, fileName, line);
 1076     } else if (!cmd->cmp("psCrop")) {
 1077       parseYesNo("psCrop", &psCrop, tokens, fileName, line);
 1078     } else if (!cmd->cmp("psUseCropBoxAsPage")) {
 1079       parseYesNo("psUseCropBoxAsPage", &psUseCropBoxAsPage,
 1080          tokens, fileName, line);
 1081     } else if (!cmd->cmp("psExpandSmaller")) {
 1082       parseYesNo("psExpandSmaller", &psExpandSmaller,
 1083          tokens, fileName, line);
 1084     } else if (!cmd->cmp("psShrinkLarger")) {
 1085       parseYesNo("psShrinkLarger", &psShrinkLarger, tokens, fileName, line);
 1086     } else if (!cmd->cmp("psCenter")) {
 1087       parseYesNo("psCenter", &psCenter, tokens, fileName, line);
 1088     } else if (!cmd->cmp("psDuplex")) {
 1089       parseYesNo("psDuplex", &psDuplex, tokens, fileName, line);
 1090     } else if (!cmd->cmp("psLevel")) {
 1091       parsePSLevel(tokens, fileName, line);
 1092     } else if (!cmd->cmp("psResidentFont")) {
 1093       parsePSResidentFont(tokens, fileName, line);
 1094     } else if (!cmd->cmp("psResidentFont16")) {
 1095       parsePSResidentFont16(tokens, fileName, line);
 1096     } else if (!cmd->cmp("psResidentFontCC")) {
 1097       parsePSResidentFontCC(tokens, fileName, line);
 1098     } else if (!cmd->cmp("psEmbedType1Fonts")) {
 1099       parseYesNo("psEmbedType1", &psEmbedType1, tokens, fileName, line);
 1100     } else if (!cmd->cmp("psEmbedTrueTypeFonts")) {
 1101       parseYesNo("psEmbedTrueType", &psEmbedTrueType,
 1102          tokens, fileName, line);
 1103     } else if (!cmd->cmp("psEmbedCIDPostScriptFonts")) {
 1104       parseYesNo("psEmbedCIDPostScript", &psEmbedCIDPostScript,
 1105          tokens, fileName, line);
 1106     } else if (!cmd->cmp("psEmbedCIDTrueTypeFonts")) {
 1107       parseYesNo("psEmbedCIDTrueType", &psEmbedCIDTrueType,
 1108          tokens, fileName, line);
 1109     } else if (!cmd->cmp("psFontPassthrough")) {
 1110       parseYesNo("psFontPassthrough", &psFontPassthrough,
 1111          tokens, fileName, line);
 1112     } else if (!cmd->cmp("psPreload")) {
 1113       parseYesNo("psPreload", &psPreload, tokens, fileName, line);
 1114     } else if (!cmd->cmp("psOPI")) {
 1115       parseYesNo("psOPI", &psOPI, tokens, fileName, line);
 1116     } else if (!cmd->cmp("psASCIIHex")) {
 1117       parseYesNo("psASCIIHex", &psASCIIHex, tokens, fileName, line);
 1118     } else if (!cmd->cmp("psLZW")) {
 1119       parseYesNo("psLZW", &psLZW, tokens, fileName, line);
 1120     } else if (!cmd->cmp("psUncompressPreloadedImages")) {
 1121       parseYesNo("psUncompressPreloadedImages", &psUncompressPreloadedImages,
 1122          tokens, fileName, line);
 1123     } else if (!cmd->cmp("psMinLineWidth")) {
 1124       parseFloat("psMinLineWidth", &psMinLineWidth,
 1125          tokens, fileName, line);
 1126     } else if (!cmd->cmp("psRasterResolution")) {
 1127       parseFloat("psRasterResolution", &psRasterResolution,
 1128          tokens, fileName, line);
 1129     } else if (!cmd->cmp("psRasterMono")) {
 1130       parseYesNo("psRasterMono", &psRasterMono, tokens, fileName, line);
 1131     } else if (!cmd->cmp("psRasterSliceSize")) {
 1132       parseInteger("psRasterSliceSize", &psRasterSliceSize,
 1133            tokens, fileName, line);
 1134     } else if (!cmd->cmp("psAlwaysRasterize")) {
 1135       parseYesNo("psAlwaysRasterize", &psAlwaysRasterize,
 1136          tokens, fileName, line);
 1137     } else if (!cmd->cmp("psNeverRasterize")) {
 1138       parseYesNo("psNeverRasterize", &psNeverRasterize,
 1139          tokens, fileName, line);
 1140     } else if (!cmd->cmp("textEncoding")) {
 1141       parseString("textEncoding", &textEncoding, tokens, fileName, line);
 1142     } else if (!cmd->cmp("textEOL")) {
 1143       parseTextEOL(tokens, fileName, line);
 1144     } else if (!cmd->cmp("textPageBreaks")) {
 1145       parseYesNo("textPageBreaks", &textPageBreaks,
 1146          tokens, fileName, line);
 1147     } else if (!cmd->cmp("textKeepTinyChars")) {
 1148       parseYesNo("textKeepTinyChars", &textKeepTinyChars,
 1149          tokens, fileName, line);
 1150     } else if (!cmd->cmp("initialZoom")) {
 1151       parseString("initialZoom", &initialZoom, tokens, fileName, line);
 1152     } else if (!cmd->cmp("defaultFitZoom")) {
 1153       parseInteger("defaultFitZoom", &defaultFitZoom, tokens, fileName, line);
 1154     } else if (!cmd->cmp("initialDisplayMode")) {
 1155       parseString("initialDisplayMode", &initialDisplayMode,
 1156           tokens, fileName, line);
 1157     } else if (!cmd->cmp("initialToolbarState")) {
 1158       parseYesNo("initialToolbarState", &initialToolbarState,
 1159          tokens, fileName, line);
 1160     } else if (!cmd->cmp("initialSidebarState")) {
 1161       parseYesNo("initialSidebarState", &initialSidebarState,
 1162          tokens, fileName, line);
 1163     } else if (!cmd->cmp("initialSidebarWidth")) {
 1164       parseInteger("initialSidebarWidth", &initialSidebarWidth,
 1165            tokens, fileName, line);
 1166     } else if (!cmd->cmp("initialSelectMode")) {
 1167       parseString("initialSelectMode", &initialSelectMode,
 1168           tokens, fileName, line);
 1169     } else if (!cmd->cmp("maxTileWidth")) {
 1170       parseInteger("maxTileWidth", &maxTileWidth, tokens, fileName, line);
 1171     } else if (!cmd->cmp("maxTileHeight")) {
 1172       parseInteger("maxTileHeight", &maxTileHeight, tokens, fileName, line);
 1173     } else if (!cmd->cmp("tileCacheSize")) {
 1174       parseInteger("tileCacheSize", &tileCacheSize, tokens, fileName, line);
 1175     } else if (!cmd->cmp("workerThreads")) {
 1176       parseInteger("workerThreads", &workerThreads, tokens, fileName, line);
 1177     } else if (!cmd->cmp("enableFreeType")) {
 1178       parseYesNo("enableFreeType", &enableFreeType, tokens, fileName, line);
 1179     } else if (!cmd->cmp("disableFreeTypeHinting")) {
 1180       parseYesNo("disableFreeTypeHinting", &disableFreeTypeHinting,
 1181          tokens, fileName, line);
 1182     } else if (!cmd->cmp("antialias")) {
 1183       parseYesNo("antialias", &antialias, tokens, fileName, line);
 1184     } else if (!cmd->cmp("vectorAntialias")) {
 1185       parseYesNo("vectorAntialias", &vectorAntialias,
 1186          tokens, fileName, line);
 1187     } else if (!cmd->cmp("imageMaskAntialias")) {
 1188       parseYesNo("imageMaskAntialias", &imageMaskAntialias,
 1189          tokens, fileName, line);
 1190     } else if (!cmd->cmp("antialiasPrinting")) {
 1191       parseYesNo("antialiasPrinting", &antialiasPrinting,
 1192          tokens, fileName, line);
 1193     } else if (!cmd->cmp("strokeAdjust")) {
 1194       parseStrokeAdjust(tokens, fileName, line);
 1195     } else if (!cmd->cmp("screenType")) {
 1196       parseScreenType(tokens, fileName, line);
 1197     } else if (!cmd->cmp("screenSize")) {
 1198       parseInteger("screenSize", &screenSize, tokens, fileName, line);
 1199     } else if (!cmd->cmp("screenDotRadius")) {
 1200       parseInteger("screenDotRadius", &screenDotRadius,
 1201            tokens, fileName, line);
 1202     } else if (!cmd->cmp("screenGamma")) {
 1203       parseFloat("screenGamma", &screenGamma,
 1204          tokens, fileName, line);
 1205     } else if (!cmd->cmp("screenBlackThreshold")) {
 1206       parseFloat("screenBlackThreshold", &screenBlackThreshold,
 1207          tokens, fileName, line);
 1208     } else if (!cmd->cmp("screenWhiteThreshold")) {
 1209       parseFloat("screenWhiteThreshold", &screenWhiteThreshold,
 1210          tokens, fileName, line);
 1211     } else if (!cmd->cmp("minLineWidth")) {
 1212       parseFloat("minLineWidth", &minLineWidth,
 1213          tokens, fileName, line);
 1214     } else if (!cmd->cmp("enablePathSimplification")) {
 1215       parseYesNo("enablePathSimplification", &enablePathSimplification,
 1216          tokens, fileName, line);
 1217     } else if (!cmd->cmp("drawAnnotations")) {
 1218       parseYesNo("drawAnnotations", &drawAnnotations,
 1219          tokens, fileName, line);
 1220     } else if (!cmd->cmp("drawFormFields")) {
 1221       parseYesNo("drawFormFields", &drawFormFields,
 1222          tokens, fileName, line);
 1223     } else if (!cmd->cmp("enableXFA")) {
 1224       parseYesNo("enableXFA", &enableXFA,
 1225          tokens, fileName, line);
 1226     } else if (!cmd->cmp("overprintPreview")) {
 1227       parseYesNo("overprintPreview", &overprintPreview,
 1228          tokens, fileName, line);
 1229     } else if (!cmd->cmp("paperColor")) {
 1230       parseString("paperColor", &paperColor, tokens, fileName, line);
 1231     } else if (!cmd->cmp("matteColor")) {
 1232       parseString("matteColor", &matteColor, tokens, fileName, line);
 1233     } else if (!cmd->cmp("fullScreenMatteColor")) {
 1234       parseString("fullScreenMatteColor", &fullScreenMatteColor,
 1235           tokens, fileName, line);
 1236     } else if (!cmd->cmp("selectionColor")) {
 1237       parseString("selectionColor", &selectionColor, tokens, fileName, line);
 1238     } else if (!cmd->cmp("reverseVideoInvertImages")) {
 1239       parseYesNo("reverseVideoInvertImages", &reverseVideoInvertImages,
 1240          tokens, fileName, line);
 1241     } else if (!cmd->cmp("launchCommand")) {
 1242       parseString("launchCommand", &launchCommand, tokens, fileName, line);
 1243     } else if (!cmd->cmp("movieCommand")) {
 1244       parseString("movieCommand", &movieCommand, tokens, fileName, line);
 1245     } else if (!cmd->cmp("defaultPrinter")) {
 1246       parseString("defaultPrinter", &defaultPrinter, tokens, fileName, line);
 1247     } else if (!cmd->cmp("mapNumericCharNames")) {
 1248       parseYesNo("mapNumericCharNames", &mapNumericCharNames,
 1249          tokens, fileName, line);
 1250     } else if (!cmd->cmp("mapUnknownCharNames")) {
 1251       parseYesNo("mapUnknownCharNames", &mapUnknownCharNames,
 1252          tokens, fileName, line);
 1253     } else if (!cmd->cmp("mapExtTrueTypeFontsViaUnicode")) {
 1254       parseYesNo("mapExtTrueTypeFontsViaUnicode",
 1255          &mapExtTrueTypeFontsViaUnicode,
 1256          tokens, fileName, line);
 1257     } else if (!cmd->cmp("useTrueTypeUnicodeMapping")) {
 1258       parseYesNo("useTrueTypeUnicodeMapping",
 1259          &useTrueTypeUnicodeMapping,
 1260          tokens, fileName, line);
 1261     } else if (!cmd->cmp("dropFont")) {
 1262       parseDropFont(tokens, fileName, line);
 1263     } else if (!cmd->cmp("bind")) {
 1264       parseBind(tokens, fileName, line);
 1265     } else if (!cmd->cmp("unbind")) {
 1266       parseUnbind(tokens, fileName, line);
 1267     } else if (!cmd->cmp("popupMenuCmd")) {
 1268       parsePopupMenuCmd(tokens, fileName, line);
 1269     } else if (!cmd->cmp("tabStateFile")) {
 1270       parseString("tabStateFile", &tabStateFile, tokens, fileName, line);
 1271     } else if (!cmd->cmp("savePageNumbers")) {
 1272       parseYesNo("savePageNumbers", &savePageNumbers, tokens, fileName, line);
 1273     } else if (!cmd->cmp("printCommands")) {
 1274       parseYesNo("printCommands", &printCommands, tokens, fileName, line);
 1275     } else if (!cmd->cmp("printStatusInfo")) {
 1276       parseYesNo("printStatusInfo", &printStatusInfo, tokens, fileName, line);
 1277     } else if (!cmd->cmp("errQuiet")) {
 1278       parseYesNo("errQuiet", &errQuiet, tokens, fileName, line);
 1279     } else if (!cmd->cmp("debugLogFile")) {
 1280       parseString("debugLogFile", &debugLogFile, tokens, fileName, line);
 1281     } else {
 1282       error(errConfig, -1, "Unknown config file command '{0:t}' ({1:t}:{2:d})",
 1283         cmd, fileName, line);
 1284       if (!cmd->cmp("displayFontX") ||
 1285       !cmd->cmp("displayNamedCIDFontX") ||
 1286       !cmd->cmp("displayCIDFontX")) {
 1287     error(errConfig, -1, "Xpdf no longer supports X fonts");
 1288       } else if (!cmd->cmp("enableT1lib")) {
 1289     error(errConfig, -1, "Xpdf no longer uses t1lib");
 1290       } else if (!cmd->cmp("t1libControl") || !cmd->cmp("freetypeControl")) {
 1291     error(errConfig, -1,
 1292           "The t1libControl and freetypeControl options have been replaced by the enableT1lib, enableFreeType, and antialias options");
 1293       } else if (!cmd->cmp("fontpath") || !cmd->cmp("fontmap")) {
 1294     error(errConfig, -1,
 1295           "The config file format has changed since Xpdf 0.9x");
 1296       }
 1297     }
 1298   }
 1299 
 1300   deleteGList(tokens, GString);
 1301 }
 1302 
 1303 // Split a line into a sequence of tokens.  Tokens are separated by
 1304 // whitespace.  Each token is one of:
 1305 //   - unquoted string, which can contain any char other than
 1306 //     whitespace, and which cannot start with a single quote, double
 1307 //     quote, or at-double-quote (xxxx)
 1308 //   - single-quoted string, which can contain any char other than the
 1309 //     single quote ('xxxx')
 1310 //   - double-quoted string, which can contain any char other than the
 1311 //     double quote ("xxxx")
 1312 //   - at-double-quoted string, which can contain variables and escape
 1313 //     chars (@"xxxx")
 1314 //     - variables look like ${name}
 1315 //     - special chars (${}") can be escaped with %, e.g.,
 1316 //       @"foo%"bar", @"foo%$bar", @"foo%%bar"
 1317 GList *GlobalParams::parseLineTokens(char *buf, GString *fileName, int line) {
 1318   GList *tokens = new GList();
 1319   char *p1 = buf;
 1320   while (*p1) {
 1321     for (; *p1 && isspace(*p1); ++p1) ;
 1322     if (!*p1) {
 1323       break;
 1324     }
 1325     if (*p1 == '"' || *p1 == '\'') {
 1326       char *p2;
 1327       for (p2 = p1 + 1; *p2 && *p2 != *p1; ++p2) ;
 1328       ++p1;
 1329       tokens->append(new GString(p1, (int)(p2 - p1)));
 1330       p1 = *p2 ? p2 + 1 : p2;
 1331     } else if (*p1 == '@' && p1[1] == '"') {
 1332       GString *token = new GString();
 1333       char *p2 = p1 + 2;
 1334       while (*p2 && *p2 != '"') {
 1335     if (*p2 == '%' && p2[1]) {
 1336       token->append(p2[1]);
 1337       p2 += 2;
 1338     } else if (*p2 == '$' && p2[1] == '{') {
 1339       p2 += 2;
 1340       char *p3;
 1341       for (p3 = p2; *p3 && *p3 != '}'; ++p3) ;
 1342       GString *varName = new GString(p2, (int)(p3 - p2));
 1343       GString *varValue = (GString *)configFileVars->lookup(varName);
 1344       if (varValue) {
 1345         token->append(varValue);
 1346       } else {
 1347         error(errConfig, -1, "Unknown config file variable '%t'", varName);
 1348       }
 1349       delete varName;
 1350       p2 = *p3 ? p3 + 1 : p3;
 1351     } else {
 1352       token->append(*p2);
 1353       ++p2;
 1354     }
 1355       }
 1356       tokens->append(token);
 1357       p1 = *p2 ? p2 + 1 : p2;
 1358     } else {
 1359       char *p2;
 1360       for (p2 = p1 + 1; *p2 && !isspace(*p2); ++p2) ;
 1361       tokens->append(new GString(p1, (int)(p2 - p1)));
 1362       p1 = p2;
 1363     }
 1364   }
 1365   return tokens;
 1366 }
 1367 
 1368 void GlobalParams::parseNameToUnicode(GList *tokens, GString *fileName,
 1369                       int line) {
 1370   GString *name;
 1371   char *tok1, *tok2;
 1372   FILE *f;
 1373   char buf[256];
 1374   int line2;
 1375   Unicode u;
 1376 
 1377   if (tokens->getLength() != 2) {
 1378     error(errConfig, -1,
 1379       "Bad 'nameToUnicode' config file command ({0:t}:{1:d})",
 1380       fileName, line);
 1381     return;
 1382   }
 1383   name = (GString *)tokens->get(1);
 1384   if (!(f = openFile(name->getCString(), "r"))) {
 1385     error(errConfig, -1, "Couldn't open 'nameToUnicode' file '{0:t}'", name);
 1386     return;
 1387   }
 1388   line2 = 1;
 1389   while (getLine(buf, sizeof(buf), f)) {
 1390     tok1 = strtok(buf, " \t\r\n");
 1391     tok2 = strtok(NULL, " \t\r\n");
 1392     if (tok1 && tok2) {
 1393       sscanf(tok1, "%x", &u);
 1394       nameToUnicode->add(tok2, u);
 1395     } else {
 1396       error(errConfig, -1, "Bad line in 'nameToUnicode' file ({0:t}:{1:d})",
 1397         name, line2);
 1398     }
 1399     ++line2;
 1400   }
 1401   fclose(f);
 1402 }
 1403 
 1404 void GlobalParams::parseCIDToUnicode(GList *tokens, GString *fileName,
 1405                      int line) {
 1406   GString *collection, *name, *old;
 1407 
 1408   if (tokens->getLength() != 3) {
 1409     error(errConfig, -1,
 1410       "Bad 'cidToUnicode' config file command ({0:t}:{1:d})",
 1411       fileName, line);
 1412     return;
 1413   }
 1414   collection = (GString *)tokens->get(1);
 1415   name = (GString *)tokens->get(2);
 1416   if ((old = (GString *)cidToUnicodes->remove(collection))) {
 1417     delete old;
 1418   }
 1419   cidToUnicodes->add(collection->copy(), name->copy());
 1420 }
 1421 
 1422 void GlobalParams::parseUnicodeToUnicode(GList *tokens, GString *fileName,
 1423                      int line) {
 1424   GString *font, *file, *old;
 1425 
 1426   if (tokens->getLength() != 3) {
 1427     error(errConfig, -1,
 1428       "Bad 'unicodeToUnicode' config file command ({0:t}:{1:d})",
 1429       fileName, line);
 1430     return;
 1431   }
 1432   font = (GString *)tokens->get(1);
 1433   file = (GString *)tokens->get(2);
 1434   if ((old = (GString *)unicodeToUnicodes->remove(font))) {
 1435     delete old;
 1436   }
 1437   unicodeToUnicodes->add(font->copy(), file->copy());
 1438 }
 1439 
 1440 void GlobalParams::parseUnicodeMap(GList *tokens, GString *fileName,
 1441                    int line) {
 1442   GString *encodingName, *name, *old;
 1443 
 1444   if (tokens->getLength() != 3) {
 1445     error(errConfig, -1, "Bad 'unicodeMap' config file command ({0:t}:{1:d})",
 1446       fileName, line);
 1447     return;
 1448   }
 1449   encodingName = (GString *)tokens->get(1);
 1450   name = (GString *)tokens->get(2);
 1451   if ((old = (GString *)unicodeMaps->remove(encodingName))) {
 1452     delete old;
 1453   }
 1454   unicodeMaps->add(encodingName->copy(), name->copy());
 1455 }
 1456 
 1457 void GlobalParams::parseCMapDir(GList *tokens, GString *fileName, int line) {
 1458   GString *collection, *dir;
 1459   GList *list;
 1460 
 1461   if (tokens->getLength() != 3) {
 1462     error(errConfig, -1, "Bad 'cMapDir' config file command ({0:t}:{1:d})",
 1463       fileName, line);
 1464     return;
 1465   }
 1466   collection = (GString *)tokens->get(1);
 1467   dir = (GString *)tokens->get(2);
 1468   if (!(list = (GList *)cMapDirs->lookup(collection))) {
 1469     list = new GList();
 1470     cMapDirs->add(collection->copy(), list);
 1471   }
 1472   list->append(dir->copy());
 1473 }
 1474 
 1475 void GlobalParams::parseToUnicodeDir(GList *tokens, GString *fileName,
 1476                      int line) {
 1477   if (tokens->getLength() != 2) {
 1478     error(errConfig, -1,
 1479       "Bad 'toUnicodeDir' config file command ({0:t}:{1:d})",
 1480       fileName, line);
 1481     return;
 1482   }
 1483   toUnicodeDirs->append(((GString *)tokens->get(1))->copy());
 1484 }
 1485 
 1486 void GlobalParams::parseUnicodeRemapping(GList *tokens, GString *fileName,
 1487                      int line) {
 1488   if (tokens->getLength() != 2) {
 1489     error(errConfig, -1,
 1490       "Bad 'unicodeRemapping' config file command ({0:t}:{1:d})",
 1491       fileName, line);
 1492     return;
 1493   }
 1494   unicodeRemapping->parseFile((GString *)tokens->get(1));
 1495 }
 1496 
 1497 void GlobalParams::parseFontFile(GList *tokens, GString *fileName, int line) {
 1498   if (tokens->getLength() != 3) {
 1499     error(errConfig, -1, "Bad 'fontFile' config file command ({0:t}:{1:d})",
 1500       fileName, line);
 1501     return;
 1502   }
 1503   fontFiles->add(((GString *)tokens->get(1))->copy(),
 1504          ((GString *)tokens->get(2))->copy());
 1505 }
 1506 
 1507 void GlobalParams::parseFontDir(GList *tokens, GString *fileName, int line) {
 1508   if (tokens->getLength() != 2) {
 1509     error(errConfig, -1, "Bad 'fontDir' config file command ({0:t}:{1:d})",
 1510       fileName, line);
 1511     return;
 1512   }
 1513   fontDirs->append(((GString *)tokens->get(1))->copy());
 1514 }
 1515 
 1516 void GlobalParams::parseFontFileCC(GList *tokens, GString *fileName,
 1517                    int line) {
 1518   if (tokens->getLength() != 3) {
 1519     error(errConfig, -1, "Bad 'fontFileCC' config file command ({0:t}:{1:d})",
 1520       fileName, line);
 1521     return;
 1522   }
 1523   ccFontFiles->add(((GString *)tokens->get(1))->copy(),
 1524            ((GString *)tokens->get(2))->copy());
 1525 }
 1526 
 1527 void GlobalParams::parsePSPaperSize(GList *tokens, GString *fileName,
 1528                     int line) {
 1529   GString *tok;
 1530 
 1531   if (tokens->getLength() == 2) {
 1532     tok = (GString *)tokens->get(1);
 1533     if (!setPSPaperSize(tok->getCString())) {
 1534       error(errConfig, -1,
 1535         "Bad 'psPaperSize' config file command ({0:s}:{1:d})",
 1536         fileName, line);
 1537     }
 1538   } else if (tokens->getLength() == 3) {
 1539     tok = (GString *)tokens->get(1);
 1540     psPaperWidth = atoi(tok->getCString());
 1541     tok = (GString *)tokens->get(2);
 1542     psPaperHeight = atoi(tok->getCString());
 1543     psImageableLLX = psImageableLLY = 0;
 1544     psImageableURX = psPaperWidth;
 1545     psImageableURY = psPaperHeight;
 1546   } else {
 1547     error(errConfig, -1, "Bad 'psPaperSize' config file command ({0:t}:{1:d})",
 1548       fileName, line);
 1549   }
 1550 }
 1551 
 1552 void GlobalParams::parsePSImageableArea(GList *tokens, GString *fileName,
 1553                     int line) {
 1554   if (tokens->getLength() != 5) {
 1555     error(errConfig, -1,
 1556       "Bad 'psImageableArea' config file command ({0:t}:{1:d})",
 1557       fileName, line);
 1558     return;
 1559   }
 1560   psImageableLLX = atoi(((GString *)tokens->get(1))->getCString());
 1561   psImageableLLY = atoi(((GString *)tokens->get(2))->getCString());
 1562   psImageableURX = atoi(((GString *)tokens->get(3))->getCString());
 1563   psImageableURY = atoi(((GString *)tokens->get(4))->getCString());
 1564 }
 1565 
 1566 void GlobalParams::parsePSLevel(GList *tokens, GString *fileName, int line) {
 1567   GString *tok;
 1568 
 1569   if (tokens->getLength() != 2) {
 1570     error(errConfig, -1, "Bad 'psLevel' config file command ({0:t}:{1:d})",
 1571       fileName, line);
 1572     return;
 1573   }
 1574   tok = (GString *)tokens->get(1);
 1575   if (!tok->cmp("level1")) {
 1576     psLevel = psLevel1;
 1577   } else if (!tok->cmp("level1sep")) {
 1578     psLevel = psLevel1Sep;
 1579   } else if (!tok->cmp("level2")) {
 1580     psLevel = psLevel2;
 1581   } else if (!tok->cmp("level2gray")) {
 1582     psLevel = psLevel2Gray;
 1583   } else if (!tok->cmp("level2sep")) {
 1584     psLevel = psLevel2Sep;
 1585   } else if (!tok->cmp("level3")) {
 1586     psLevel = psLevel3;
 1587   } else if (!tok->cmp("level3gray")) {
 1588     psLevel = psLevel3Gray;
 1589   } else if (!tok->cmp("level3Sep")) {
 1590     psLevel = psLevel3Sep;
 1591   } else {
 1592     error(errConfig, -1, "Bad 'psLevel' config file command ({0:t}:{1:d})",
 1593       fileName, line);
 1594   }
 1595 }
 1596 
 1597 void GlobalParams::parsePSResidentFont(GList *tokens, GString *fileName,
 1598                        int line) {
 1599   if (tokens->getLength() != 3) {
 1600     error(errConfig, -1, "Bad 'psResidentFont' config file command ({0:t}:{1:d})",
 1601       fileName, line);
 1602     return;
 1603   }
 1604   psResidentFonts->add(((GString *)tokens->get(1))->copy(),
 1605                ((GString *)tokens->get(2))->copy());
 1606 }
 1607 
 1608 void GlobalParams::parsePSResidentFont16(GList *tokens, GString *fileName,
 1609                      int line) {
 1610   PSFontParam16 *param;
 1611   int wMode;
 1612   GString *tok;
 1613 
 1614   if (tokens->getLength() != 5) {
 1615     error(errConfig, -1, "Bad 'psResidentFont16' config file command ({0:t}:{1:d})",
 1616       fileName, line);
 1617     return;
 1618   }
 1619   tok = (GString *)tokens->get(2);
 1620   if (!tok->cmp("H")) {
 1621     wMode = 0;
 1622   } else if (!tok->cmp("V")) {
 1623     wMode = 1;
 1624   } else {
 1625     error(errConfig, -1, "Bad wMode in psResidentFont16 config file command ({1:t}:{2:d})",
 1626       fileName, line);
 1627     return;
 1628   }
 1629   param = new PSFontParam16(((GString *)tokens->get(1))->copy(),
 1630                 wMode,
 1631                 ((GString *)tokens->get(3))->copy(),
 1632                 ((GString *)tokens->get(4))->copy());
 1633   psResidentFonts16->append(param);
 1634 }
 1635 
 1636 void GlobalParams::parsePSResidentFontCC(GList *tokens, GString *fileName,
 1637                      int line) {
 1638   PSFontParam16 *param;
 1639   int wMode;
 1640   GString *tok;
 1641 
 1642   if (tokens->getLength() != 5) {
 1643     error(errConfig, -1, "Bad 'psResidentFontCC' config file command ({0:t}:{1:d})",
 1644       fileName, line);
 1645     return;
 1646   }
 1647   tok = (GString *)tokens->get(2);
 1648   if (!tok->cmp("H")) {
 1649     wMode = 0;
 1650   } else if (!tok->cmp("V")) {
 1651     wMode = 1;
 1652   } else {
 1653     error(errConfig, -1, "Bad wMode in psResidentFontCC config file command ({1:t}:{2:d})",
 1654       fileName, line);
 1655     return;
 1656   }
 1657   param = new PSFontParam16(((GString *)tokens->get(1))->copy(),
 1658                 wMode,
 1659                 ((GString *)tokens->get(3))->copy(),
 1660                 ((GString *)tokens->get(4))->copy());
 1661   psResidentFontsCC->append(param);
 1662 }
 1663 
 1664 void GlobalParams::parseTextEOL(GList *tokens, GString *fileName, int line) {
 1665   GString *tok;
 1666 
 1667   if (tokens->getLength() != 2) {
 1668     error(errConfig, -1, "Bad 'textEOL' config file command ({0:t}:{1:d})",
 1669       fileName, line);
 1670     return;
 1671   }
 1672   tok = (GString *)tokens->get(1);
 1673   if (!tok->cmp("unix")) {
 1674     textEOL = eolUnix;
 1675   } else if (!tok->cmp("dos")) {
 1676     textEOL = eolDOS;
 1677   } else if (!tok->cmp("mac")) {
 1678     textEOL = eolMac;
 1679   } else {
 1680     error(errConfig, -1, "Bad 'textEOL' config file command ({0:t}:{1:d})",
 1681       fileName, line);
 1682   }
 1683 }
 1684 
 1685 void GlobalParams::parseStrokeAdjust(GList *tokens, GString *fileName,
 1686                      int line) {
 1687   GString *tok;
 1688 
 1689   if (tokens->getLength() != 2) {
 1690     error(errConfig, -1,
 1691       "Bad 'strokeAdjust' config file command ({0:t}:{1:d})",
 1692       fileName, line);
 1693     return;
 1694   }
 1695   tok = (GString *)tokens->get(1);
 1696   if (!tok->cmp("no")) {
 1697     strokeAdjust = strokeAdjustOff;
 1698   } else if (!tok->cmp("yes")) {
 1699     strokeAdjust = strokeAdjustNormal;
 1700   } else if (!tok->cmp("cad")) {
 1701     strokeAdjust = strokeAdjustCAD;
 1702   } else {
 1703     error(errConfig, -1,
 1704       "Bad 'strokeAdjust' config file command ({0:t}:{1:d})",
 1705       fileName, line);
 1706   }
 1707 }
 1708 
 1709 void GlobalParams::parseScreenType(GList *tokens, GString *fileName,
 1710                    int line) {
 1711   GString *tok;
 1712 
 1713   if (tokens->getLength() != 2) {
 1714     error(errConfig, -1, "Bad 'screenType' config file command ({0:t}:{1:d})",
 1715       fileName, line);
 1716     return;
 1717   }
 1718   tok = (GString *)tokens->get(1);
 1719   if (!tok->cmp("dispersed")) {
 1720     screenType = screenDispersed;
 1721   } else if (!tok->cmp("clustered")) {
 1722     screenType = screenClustered;
 1723   } else if (!tok->cmp("stochasticClustered")) {
 1724     screenType = screenStochasticClustered;
 1725   } else {
 1726     error(errConfig, -1, "Bad 'screenType' config file command ({0:t}:{1:d})",
 1727       fileName, line);
 1728   }
 1729 }
 1730 
 1731 void GlobalParams::parseDropFont(GList *tokens, GString *fileName, int line) {
 1732   if (tokens->getLength() != 2) {
 1733     error(errConfig, -1, "Bad 'dropFont' config file command ({0:t}:{1:d})",
 1734       fileName, line);
 1735     return;
 1736   }
 1737   droppedFonts->add(((GString *)tokens->get(1))->copy(), 1);
 1738 }
 1739 
 1740 void GlobalParams::parseBind(GList *tokens, GString *fileName, int line) {
 1741   KeyBinding *binding;
 1742   GList *cmds;
 1743   int code, mods, context, i;
 1744 
 1745   if (tokens->getLength() < 4) {
 1746     error(errConfig, -1, "Bad 'bind' config file command ({0:t}:{1:d})",
 1747       fileName, line);
 1748     return;
 1749   }
 1750   if (!parseKey((GString *)tokens->get(1), (GString *)tokens->get(2),
 1751         &code, &mods, &context,
 1752         "bind", tokens, fileName, line)) {
 1753     return;
 1754   }
 1755   for (i = 0; i < keyBindings->getLength(); ++i) {
 1756     binding = (KeyBinding *)keyBindings->get(i);
 1757     if (binding->code == code &&
 1758     binding->mods == mods &&
 1759     binding->context == context) {
 1760       delete (KeyBinding *)keyBindings->del(i);
 1761       break;
 1762     }
 1763   }
 1764   cmds = new GList();
 1765   for (i = 3; i < tokens->getLength(); ++i) {
 1766     cmds->append(((GString *)tokens->get(i))->copy());
 1767   }
 1768   keyBindings->append(new KeyBinding(code, mods, context, cmds));
 1769 }
 1770 
 1771 void GlobalParams::parseUnbind(GList *tokens, GString *fileName, int line) {
 1772   KeyBinding *binding;
 1773   int code, mods, context, i;
 1774 
 1775   if (tokens->getLength() != 3) {
 1776     error(errConfig, -1, "Bad 'unbind' config file command ({0:t}:{1:d})",
 1777       fileName, line);
 1778     return;
 1779   }
 1780   if (!parseKey((GString *)tokens->get(1), (GString *)tokens->get(2),
 1781         &code, &mods, &context,
 1782         "unbind", tokens, fileName, line)) {
 1783     return;
 1784   }
 1785   for (i = 0; i < keyBindings->getLength(); ++i) {
 1786     binding = (KeyBinding *)keyBindings->get(i);
 1787     if (binding->code == code &&
 1788     binding->mods == mods &&
 1789     binding->context == context) {
 1790       delete (KeyBinding *)keyBindings->del(i);
 1791       break;
 1792     }
 1793   }
 1794 }
 1795 
 1796 GBool GlobalParams::parseKey(GString *modKeyStr, GString *contextStr,
 1797                  int *code, int *mods, int *context,
 1798                  const char *cmdName,
 1799                  GList *tokens, GString *fileName, int line) {
 1800   char *p0;
 1801   int btn;
 1802 
 1803   *mods = xpdfKeyModNone;
 1804   p0 = modKeyStr->getCString();
 1805   while (1) {
 1806     if (!strncmp(p0, "shift-", 6)) {
 1807       *mods |= xpdfKeyModShift;
 1808       p0 += 6;
 1809     } else if (!strncmp(p0, "ctrl-", 5)) {
 1810       *mods |= xpdfKeyModCtrl;
 1811       p0 += 5;
 1812     } else if (!strncmp(p0, "alt-", 4)) {
 1813       *mods |= xpdfKeyModAlt;
 1814       p0 += 4;
 1815     } else {
 1816       break;
 1817     }
 1818   }
 1819 
 1820   if (!strcmp(p0, "space")) {
 1821     *code = ' ';
 1822   } else if (!strcmp(p0, "tab")) {
 1823     *code = xpdfKeyCodeTab;
 1824   } else if (!strcmp(p0, "return")) {
 1825     *code = xpdfKeyCodeReturn;
 1826   } else if (!strcmp(p0, "enter")) {
 1827     *code = xpdfKeyCodeEnter;
 1828   } else if (!strcmp(p0, "backspace")) {
 1829     *code = xpdfKeyCodeBackspace;
 1830   } else if (!strcmp(p0, "esc")) {
 1831     *code = xpdfKeyCodeEsc;
 1832   } else if (!strcmp(p0, "insert")) {
 1833     *code = xpdfKeyCodeInsert;
 1834   } else if (!strcmp(p0, "delete")) {
 1835     *code = xpdfKeyCodeDelete;
 1836   } else if (!strcmp(p0, "home")) {
 1837     *code = xpdfKeyCodeHome;
 1838   } else if (!strcmp(p0, "end")) {
 1839     *code = xpdfKeyCodeEnd;
 1840   } else if (!strcmp(p0, "pgup")) {
 1841     *code = xpdfKeyCodePgUp;
 1842   } else if (!strcmp(p0, "pgdn")) {
 1843     *code = xpdfKeyCodePgDn;
 1844   } else if (!strcmp(p0, "left")) {
 1845     *code = xpdfKeyCodeLeft;
 1846   } else if (!strcmp(p0, "right")) {
 1847     *code = xpdfKeyCodeRight;
 1848   } else if (!strcmp(p0, "up")) {
 1849     *code = xpdfKeyCodeUp;
 1850   } else if (!strcmp(p0, "down")) {
 1851     *code = xpdfKeyCodeDown;
 1852   } else if (p0[0] == 'f' && p0[1] >= '1' && p0[1] <= '9' && !p0[2]) {
 1853     *code = xpdfKeyCodeF1 + (p0[1] - '1');
 1854   } else if (p0[0] == 'f' &&
 1855          ((p0[1] >= '1' && p0[1] <= '2' && p0[2] >= '0' && p0[2] <= '9') ||
 1856           (p0[1] == '3' && p0[2] >= '0' && p0[2] <= '5')) &&
 1857          !p0[3]) {
 1858     *code = xpdfKeyCodeF1 + 10 * (p0[1] - '0') + (p0[2] - '0') - 1;
 1859   } else if (!strncmp(p0, "mousePress", 10) &&
 1860          p0[10] >= '0' && p0[10] <= '9' &&
 1861          (!p0[11] || (p0[11] >= '0' && p0[11] <= '9' && !p0[12])) &&
 1862          (btn = atoi(p0 + 10)) >= 1 && btn <= 32) {
 1863     *code = xpdfKeyCodeMousePress1 + btn - 1;
 1864   } else if (!strncmp(p0, "mouseRelease", 12) &&
 1865          p0[12] >= '0' && p0[12] <= '9' &&
 1866          (!p0[13] || (p0[13] >= '0' && p0[13] <= '9' && !p0[14])) &&
 1867          (btn = atoi(p0 + 12)) >= 1 && btn <= 32) {
 1868     *code = xpdfKeyCodeMouseRelease1 + btn - 1;
 1869   } else if (!strncmp(p0, "mouseClick", 10) &&
 1870          p0[10] >= '0' && p0[10] <= '9' &&
 1871          (!p0[11] || (p0[11] >= '0' && p0[11] <= '9' && !p0[12])) &&
 1872          (btn = atoi(p0 + 10)) >= 1 && btn <= 32) {
 1873     *code = xpdfKeyCodeMouseClick1 + btn - 1;
 1874   } else if (!strncmp(p0, "mouseDoubleClick", 16) &&
 1875          p0[16] >= '0' && p0[16] <= '9' &&
 1876          (!p0[17] || (p0[17] >= '0' && p0[17] <= '9' && !p0[18])) &&
 1877          (btn = atoi(p0 + 16)) >= 1 && btn <= 32) {
 1878     *code = xpdfKeyCodeMouseDoubleClick1 + btn - 1;
 1879   } else if (!strncmp(p0, "mouseTripleClick", 16) &&
 1880          p0[16] >= '0' && p0[16] <= '9' &&
 1881          (!p0[17] || (p0[17] >= '0' && p0[17] <= '9' && !p0[18])) &&
 1882          (btn = atoi(p0 + 16)) >= 1 && btn <= 32) {
 1883     *code = xpdfKeyCodeMouseTripleClick1 + btn - 1;
 1884   } else if (*p0 >= 0x20 && *p0 <= 0x7e && !p0[1]) {
 1885     *code = (int)*p0;
 1886   } else {
 1887     error(errConfig, -1,
 1888       "Bad key/modifier in '{0:s}' config file command ({1:t}:{2:d})",
 1889       cmdName, fileName, line);
 1890     return gFalse;
 1891   }
 1892 
 1893   p0 = contextStr->getCString();
 1894   if (!strcmp(p0, "any")) {
 1895     *context = xpdfKeyContextAny;
 1896   } else {
 1897     *context = xpdfKeyContextAny;
 1898     while (1) {
 1899       if (!strncmp(p0, "fullScreen", 10)) {
 1900     *context |= xpdfKeyContextFullScreen;
 1901     p0 += 10;
 1902       } else if (!strncmp(p0, "window", 6)) {
 1903     *context |= xpdfKeyContextWindow;
 1904     p0 += 6;
 1905       } else if (!strncmp(p0, "continuous", 10)) {
 1906     *context |= xpdfKeyContextContinuous;
 1907     p0 += 10;
 1908       } else if (!strncmp(p0, "singlePage", 10)) {
 1909     *context |= xpdfKeyContextSinglePage;
 1910     p0 += 10;
 1911       } else if (!strncmp(p0, "overLink", 8)) {
 1912     *context |= xpdfKeyContextOverLink;
 1913     p0 += 8;
 1914       } else if (!strncmp(p0, "offLink", 7)) {
 1915     *context |= xpdfKeyContextOffLink;
 1916     p0 += 7;
 1917       } else if (!strncmp(p0, "outline", 7)) {
 1918     *context |= xpdfKeyContextOutline;
 1919     p0 += 7;
 1920       } else if (!strncmp(p0, "mainWin", 7)) {
 1921     *context |= xpdfKeyContextMainWin;
 1922     p0 += 7;
 1923       } else if (!strncmp(p0, "scrLockOn", 9)) {
 1924     *context |= xpdfKeyContextScrLockOn;
 1925     p0 += 9;
 1926       } else if (!strncmp(p0, "scrLockOff", 10)) {
 1927     *context |= xpdfKeyContextScrLockOff;
 1928     p0 += 10;
 1929       } else {
 1930     error(errConfig, -1,
 1931           "Bad context in '{0:s}' config file command ({1:t}:{2:d})",
 1932           cmdName, fileName, line);
 1933     return gFalse;
 1934       }
 1935       if (!*p0) {
 1936     break;
 1937       }
 1938       if (*p0 != ',') {
 1939     error(errConfig, -1,
 1940           "Bad context in '{0:s}' config file command ({1:t}:{2:d})",
 1941           cmdName, fileName, line);
 1942     return gFalse;
 1943       }
 1944       ++p0;
 1945     }
 1946   }
 1947 
 1948   return gTrue;
 1949 }
 1950 
 1951 void GlobalParams::parsePopupMenuCmd(GList *tokens,
 1952                      GString *fileName, int line) {
 1953   GList *cmds;
 1954   int i;
 1955 
 1956   if (tokens->getLength() < 3) {
 1957     error(errConfig, -1,
 1958       "Bad 'popupMenuCmd' config file command ({0:t}:{1:d})",
 1959       fileName, line);
 1960     return;
 1961   }
 1962   cmds = new GList();
 1963   for (i = 2; i < tokens->getLength(); ++i) {
 1964     cmds->append(((GString *)tokens->get(i))->copy());
 1965   }
 1966   popupMenuCmds->append(new PopupMenuCmd(((GString *)tokens->get(1))->copy(),
 1967                      cmds));
 1968 }
 1969 
 1970 void GlobalParams::parseYesNo(const char *cmdName, GBool *flag,
 1971                   GList *tokens, GString *fileName, int line) {
 1972   GString *tok;
 1973 
 1974   if (tokens->getLength() != 2) {
 1975     error(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})",
 1976       cmdName, fileName, line);
 1977     return;
 1978   }
 1979   tok = (GString *)tokens->get(1);
 1980   if (!parseYesNo2(tok->getCString(), flag)) {
 1981     error(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})",
 1982       cmdName, fileName, line);
 1983   }
 1984 }
 1985 
 1986 GBool GlobalParams::parseYesNo2(char *token, GBool *flag) {
 1987   if (!strcmp(token, "yes")) {
 1988     *flag = gTrue;
 1989   } else if (!strcmp(token, "no")) {
 1990     *flag = gFalse;
 1991   } else {
 1992     return gFalse;
 1993   }
 1994   return gTrue;
 1995 }
 1996 
 1997 void GlobalParams::parseString(const char *cmdName, GString **s,
 1998                    GList *tokens, GString *fileName, int line) {
 1999   if (tokens->getLength() != 2) {
 2000     error(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})",
 2001       cmdName, fileName, line);
 2002     return;
 2003   }
 2004   if (*s) {
 2005     delete *s;
 2006   }
 2007   *s = ((GString *)tokens->get(1))->copy();
 2008 }
 2009 
 2010 void GlobalParams::parseInteger(const char *cmdName, int *val,
 2011                 GList *tokens, GString *fileName, int line) {
 2012   GString *tok;
 2013   int i;
 2014 
 2015   if (tokens->getLength() != 2) {
 2016     error(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})",
 2017       cmdName, fileName, line);
 2018     return;
 2019   }
 2020   tok = (GString *)tokens->get(1);
 2021   if (tok->getLength() == 0) {
 2022     error(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})",
 2023       cmdName, fileName, line);
 2024     return;
 2025   }
 2026   if (tok->getChar(0) == '-') {
 2027     i = 1;
 2028   } else {
 2029     i = 0;
 2030   }
 2031   for (; i < tok->getLength(); ++i) {
 2032     if (tok->getChar(i) < '0' || tok->getChar(i) > '9') {
 2033       error(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})",
 2034         cmdName, fileName, line);
 2035       return;
 2036     }
 2037   }
 2038   *val = atoi(tok->getCString());
 2039 }
 2040 
 2041 void GlobalParams::parseFloat(const char *cmdName, double *val,
 2042                   GList *tokens, GString *fileName, int line) {
 2043   GString *tok;
 2044   int i;
 2045 
 2046   if (tokens->getLength() != 2) {
 2047     error(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})",
 2048       cmdName, fileName, line);
 2049     return;
 2050   }
 2051   tok = (GString *)tokens->get(1);
 2052   if (tok->getLength() == 0) {
 2053     error(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})",
 2054       cmdName, fileName, line);
 2055     return;
 2056   }
 2057   if (tok->getChar(0) == '-') {
 2058     i = 1;
 2059   } else {
 2060     i = 0;
 2061   }
 2062   for (; i < tok->getLength(); ++i) {
 2063     if (!((tok->getChar(i) >= '0' && tok->getChar(i) <= '9') ||
 2064       tok->getChar(i) == '.')) {
 2065       error(errConfig, -1, "Bad '{0:s}' config file command ({1:t}:{2:d})",
 2066         cmdName, fileName, line);
 2067       return;
 2068     }
 2069   }
 2070   *val = atof(tok->getCString());
 2071 }
 2072 
 2073 GlobalParams::~GlobalParams() {
 2074   GHashIter *iter;
 2075   GString *key;
 2076   GList *list;
 2077 
 2078   freeBuiltinFontTables();
 2079 
 2080   delete macRomanReverseMap;
 2081 
 2082   delete baseDir;
 2083   deleteGHash(configFileVars, GString);
 2084   delete nameToUnicode;
 2085   deleteGHash(cidToUnicodes, GString);
 2086   deleteGHash(unicodeToUnicodes, GString);
 2087   deleteGHash(residentUnicodeMaps, UnicodeMap);
 2088   deleteGHash(unicodeMaps, GString);
 2089   deleteGList(toUnicodeDirs, GString);
 2090   delete unicodeRemapping;
 2091   deleteGHash(fontFiles, GString);
 2092   deleteGList(fontDirs, GString);
 2093   deleteGHash(ccFontFiles, GString);
 2094   deleteGHash(base14SysFonts, Base14FontInfo);
 2095   delete sysFonts;
 2096   deleteGHash(psResidentFonts, GString);
 2097   deleteGList(psResidentFonts16, PSFontParam16);
 2098   deleteGList(psResidentFontsCC, PSFontParam16);
 2099   delete textEncoding;
 2100   delete initialZoom;
 2101   delete initialDisplayMode;
 2102   delete initialSelectMode;
 2103   if (paperColor) {
 2104     delete paperColor;
 2105   }
 2106   if (matteColor) {
 2107     delete matteColor;
 2108   }
 2109   if (fullScreenMatteColor) {
 2110     delete fullScreenMatteColor;
 2111   }
 2112   if (selectionColor) {
 2113     delete selectionColor;
 2114   }
 2115   if (launchCommand) {
 2116     delete launchCommand;
 2117   }
 2118   if (movieCommand) {
 2119     delete movieCommand;
 2120   }
 2121   if (defaultPrinter) {
 2122     delete defaultPrinter;
 2123   }
 2124   delete droppedFonts;
 2125   deleteGList(keyBindings, KeyBinding);
 2126   deleteGList(popupMenuCmds, PopupMenuCmd);
 2127   delete tabStateFile;
 2128   delete debugLogFile;
 2129 
 2130   cMapDirs->startIter(&iter);
 2131   while (cMapDirs->getNext(&iter, &key, (void **)&list)) {
 2132     deleteGList(list, GString);
 2133   }
 2134   delete cMapDirs;
 2135 
 2136   delete cidToUnicodeCache;
 2137   delete unicodeToUnicodeCache;
 2138   delete unicodeMapCache;
 2139   delete cMapCache;
 2140 
 2141 #if MULTITHREADED
 2142   gDestroyMutex(&mutex);
 2143   gDestroyMutex(&unicodeMapCacheMutex);
 2144   gDestroyMutex(&cMapCacheMutex);
 2145 #endif
 2146 }
 2147 
 2148 //------------------------------------------------------------------------
 2149 
 2150 void GlobalParams::setBaseDir(const char *dir) {
 2151   delete baseDir;
 2152   baseDir = new GString(dir);
 2153 }
 2154 
 2155 #ifdef _WIN32
 2156 static void getWinFontDir(char *winFontDir) {
 2157   HMODULE shell32Lib;
 2158   BOOL (__stdcall *SHGetSpecialFolderPathFunc)(HWND hwndOwner,
 2159                            LPSTR lpszPath,
 2160                            int nFolder,
 2161                            BOOL fCreate);
 2162   char *p;
 2163   int i;
 2164 
 2165   // SHGetSpecialFolderPath isn't available in older versions of
 2166   // shell32.dll (Win95 and WinNT4), so do a dynamic load
 2167   winFontDir[0] = '\0';
 2168   if ((shell32Lib = LoadLibraryA("shell32.dll"))) {
 2169     if ((SHGetSpecialFolderPathFunc = 
 2170      (BOOL (__stdcall *)(HWND hwndOwner, LPSTR lpszPath,
 2171                  int nFolder, BOOL fCreate))
 2172      GetProcAddress(shell32Lib, "SHGetSpecialFolderPathA"))) {
 2173       if (!(*SHGetSpecialFolderPathFunc)(NULL, winFontDir,
 2174                      CSIDL_FONTS, FALSE)) {
 2175     winFontDir[0] = '\0';
 2176       }
 2177       // kludge: Terminal Server changes CSIDL_FONTS to something like
 2178       // "C:\Users\whatever\Windows\Fonts", which doesn't actually
 2179       // contain any fonts -- kill that, so we hit the fallback code
 2180       // below.
 2181       for (p = winFontDir; *p; ++p) {
 2182     if (!strncasecmp(p, "\\Users\\", 7)) {
 2183       winFontDir[0] = '\0';
 2184       break;
 2185     }
 2186       }
 2187     }
 2188     FreeLibrary(shell32Lib);
 2189   }
 2190   // if something went wrong, or we're on a Terminal Server, try using
 2191   // %SYSTEMROOT%\Fonts
 2192   if (!winFontDir[0]) {
 2193     GetSystemWindowsDirectoryA(winFontDir, MAX_PATH - 6);
 2194     winFontDir[MAX_PATH - 7] = '\0';
 2195     i = (int)strlen(winFontDir);
 2196     if (winFontDir[i-1] != '\\') {
 2197       winFontDir[i++] = '\\';
 2198     }
 2199     strcpy(winFontDir + i, "Fonts");
 2200   }
 2201 }
 2202 #endif
 2203 
 2204 #ifdef __APPLE__
 2205 // Apple dfonts and ttc fonts seem to randomly and interchangeably use
 2206 // space and hyphen, and sometimes drop the separator entirely.
 2207 static GBool macFontNameMatches(GString *name1, const char *name2) {
 2208   const char *p1, *p2;
 2209   char c1, c2;
 2210 
 2211   p1 = name1->getCString();
 2212   p2 = name2;
 2213   while (*p1 && *p2) {
 2214     c1 = *p1;
 2215     c2 = *p2;
 2216     if (c2 == ' ') {
 2217       // * space or hyphen matches a space in the pattern
 2218       // * separators can also be dropped, in which case we move to
 2219       //   the next char in the pattern
 2220       if (c1 == ' ' || c1 == '-') {
 2221     ++p1;
 2222       }
 2223     } else {
 2224       if (c1 != c2) {
 2225     return gFalse;
 2226       }
 2227       ++p1;
 2228     }
 2229     ++p2;
 2230   }
 2231   if (*p1 || *p2) {
 2232     return gFalse;
 2233   }
 2234   return gTrue;
 2235 }
 2236 #endif
 2237 
 2238 void GlobalParams::setupBaseFonts(const char *dir) {
 2239   GString *fontName;
 2240   GString *fileName;
 2241   int fontNum;
 2242   const char *s;
 2243   Base14FontInfo *base14;
 2244 #ifdef _WIN32
 2245   char winFontDir[MAX_PATH];
 2246 #endif
 2247 #ifdef __APPLE__
 2248   static const char *macFontExts[3] = { "dfont", "ttc", "ttf" };
 2249   GList *dfontFontNames;
 2250   GBool found;
 2251   int k;
 2252 #endif
 2253   FILE *f;
 2254   int i, j;
 2255 
 2256 #ifdef _WIN32
 2257   getWinFontDir(winFontDir);
 2258 #endif
 2259 #ifdef __APPLE__
 2260   dfontFontNames = NULL;
 2261 #endif
 2262   for (i = 0; displayFontTab[i].name; ++i) {
 2263     if (fontFiles->lookup(displayFontTab[i].name)) {
 2264       continue;
 2265     }
 2266     fontName = new GString(displayFontTab[i].name);
 2267     fileName = NULL;
 2268     fontNum = 0;
 2269     if (dir) {
 2270       fileName = appendToPath(new GString(dir), displayFontTab[i].t1FileName);
 2271       if ((f = fopen(fileName->getCString(), "rb"))) {
 2272     fclose(f);
 2273       } else {
 2274     delete fileName;
 2275     fileName = NULL;
 2276       }
 2277     }
 2278 #ifdef _WIN32
 2279     if (!fileName && winFontDir[0] && displayFontTab[i].ttFileName) {
 2280       fileName = appendToPath(new GString(winFontDir),
 2281                   displayFontTab[i].ttFileName);
 2282       if ((f = fopen(fileName->getCString(), "rb"))) {
 2283     fclose(f);
 2284       } else {
 2285     delete fileName;
 2286     fileName = NULL;
 2287       }
 2288     }
 2289 #endif
 2290 #ifdef __APPLE__
 2291     // Check for Mac OS X system fonts.
 2292     s = displayFontTab[i].macFileName;
 2293     if (dfontFontNames && i > 0 &&
 2294     (!s || strcmp(s, displayFontTab[i-1].macFileName))) {
 2295       deleteGList(dfontFontNames, GString);
 2296       dfontFontNames = NULL;
 2297     }
 2298     if (!fileName && s) {
 2299       for (j = 0; j < 3; ++j) {
 2300     fileName = GString::format("{0:s}/{1:s}.{2:s}",
 2301                    macSystemFontPath, s, macFontExts[j]);
 2302     if (!(f = fopen(fileName->getCString(), "rb"))) {
 2303       delete fileName;
 2304       fileName = NULL;
 2305     } else {
 2306       fclose(f);
 2307       found = gFalse;
 2308       // for .dfont or .ttc, we need to scan the font list
 2309       if (j < 2) {
 2310         if (!dfontFontNames) {
 2311           dfontFontNames =
 2312               FoFiIdentifier::getFontList(fileName->getCString());
 2313         }
 2314         if (dfontFontNames) {
 2315           for (k = 0; k < dfontFontNames->getLength(); ++k) {
 2316         if (macFontNameMatches((GString *)dfontFontNames->get(k),
 2317                        displayFontTab[i].macFontName)) {
 2318           fontNum = k;
 2319           found = gTrue;
 2320           break;
 2321         }
 2322           }
 2323         }
 2324       // for .ttf, we just use the font
 2325       } else {
 2326         found = gTrue;
 2327       }
 2328       if (!found) {
 2329         delete fileName;
 2330         fileName = NULL;
 2331       }
 2332       break;
 2333     }
 2334       }
 2335     }
 2336 #endif // __APPLE__
 2337     // On Linux, this checks the "standard" ghostscript font
 2338     // directories.  On Windows, it checks the "standard" system font
 2339     // directories (because SHGetSpecialFolderPath(CSIDL_FONTS)
 2340     // doesn't work on Win 2k Server or Win2003 Server, or with older
 2341     // versions of shell32.dll).
 2342 #ifdef _WIN32
 2343     s = displayFontTab[i].ttFileName;
 2344 #else
 2345     s = displayFontTab[i].t1FileName;
 2346 #endif
 2347     if (!fileName && s) {
 2348       for (j = 0; !fileName && displayFontDirs[j]; ++j) {
 2349     fileName = appendToPath(new GString(displayFontDirs[j]), s);
 2350     if ((f = fopen(fileName->getCString(), "rb"))) {
 2351       fclose(f);
 2352     } else {
 2353       delete fileName;
 2354       fileName = NULL;
 2355     }
 2356       }
 2357     }
 2358     if (!fileName) {
 2359       delete fontName;
 2360       continue;
 2361     }
 2362     base14SysFonts->add(fontName, new Base14FontInfo(fileName, fontNum, 0));
 2363   }
 2364 #ifdef __APPLE__
 2365   if (dfontFontNames) {
 2366     deleteGList(dfontFontNames, GString);
 2367   }
 2368 #endif
 2369   for (i = 0; displayFontTab[i].name; ++i) {
 2370     if (!base14SysFonts->lookup(displayFontTab[i].name) &&
 2371     !fontFiles->lookup(displayFontTab[i].name)) {
 2372       if (displayFontTab[i].obliqueFont &&
 2373       ((base14 = (Base14FontInfo *)base14SysFonts
 2374                      ->lookup(displayFontTab[i].obliqueFont)))) {
 2375     base14SysFonts->add(
 2376             new GString(displayFontTab[i].name),
 2377         new Base14FontInfo(base14->fileName->copy(),
 2378                    base14->fontNum,
 2379                    displayFontTab[i].obliqueFactor));
 2380       } else {
 2381     error(errConfig, -1, "No display font for '{0:s}'",
 2382           displayFontTab[i].name);
 2383       }
 2384     }
 2385   }
 2386 #ifdef _WIN32
 2387   if (winFontDir[0]) {
 2388     sysFonts->scanWindowsFonts(winFontDir);
 2389   }
 2390 #endif
 2391 #if HAVE_FONTCONFIG
 2392   sysFonts->scanFontconfigFonts();
 2393 #endif
 2394 }
 2395 
 2396 //------------------------------------------------------------------------
 2397 // accessors
 2398 //------------------------------------------------------------------------
 2399 
 2400 CharCode GlobalParams::getMacRomanCharCode(char *charName) {
 2401   // no need to lock - macRomanReverseMap is constant
 2402   return macRomanReverseMap->lookup(charName);
 2403 }
 2404 
 2405 GString *GlobalParams::getBaseDir() {
 2406   GString *s;
 2407 
 2408   lockGlobalParams;
 2409   s = baseDir->copy();
 2410   unlockGlobalParams;
 2411   return s;
 2412 }
 2413 
 2414 Unicode GlobalParams::mapNameToUnicode(const char *charName) {
 2415   // no need to lock - nameToUnicode is constant
 2416   return nameToUnicode->lookup(charName);
 2417 }
 2418 
 2419 UnicodeMap *GlobalParams::getResidentUnicodeMap(GString *encodingName) {
 2420   UnicodeMap *map;
 2421 
 2422   lockGlobalParams;
 2423   map = (UnicodeMap *)residentUnicodeMaps->lookup(encodingName);
 2424   unlockGlobalParams;
 2425   if (map) {
 2426     map->incRefCnt();
 2427   }
 2428   return map;
 2429 }
 2430 
 2431 FILE *GlobalParams::getUnicodeMapFile(GString *encodingName) {
 2432   GString *fileName;
 2433   FILE *f;
 2434 
 2435   lockGlobalParams;
 2436   if ((fileName = (GString *)unicodeMaps->lookup(encodingName))) {
 2437     f = openFile(fileName->getCString(), "r");
 2438   } else {
 2439     f = NULL;
 2440   }
 2441   unlockGlobalParams;
 2442   return f;
 2443 }
 2444 
 2445 FILE *GlobalParams::findCMapFile(GString *collection, GString *cMapName) {
 2446   GList *list;
 2447   GString *dir;
 2448   GString *fileName;
 2449   FILE *f;
 2450   int i;
 2451 
 2452   lockGlobalParams;
 2453   if (!(list = (GList *)cMapDirs->lookup(collection))) {
 2454     unlockGlobalParams;
 2455     return NULL;
 2456   }
 2457   for (i = 0; i < list->getLength(); ++i) {
 2458     dir = (GString *)list->get(i);
 2459     fileName = appendToPath(dir->copy(), cMapName->getCString());
 2460     f = openFile(fileName->getCString(), "r");
 2461     delete fileName;
 2462     if (f) {
 2463       unlockGlobalParams;
 2464       return f;
 2465     }
 2466   }
 2467   unlockGlobalParams;
 2468   return NULL;
 2469 }
 2470 
 2471 FILE *GlobalParams::findToUnicodeFile(GString *name) {
 2472   GString *dir, *fileName;
 2473   FILE *f;
 2474   int i;
 2475 
 2476   lockGlobalParams;
 2477   for (i = 0; i < toUnicodeDirs->getLength(); ++i) {
 2478     dir = (GString *)toUnicodeDirs->get(i);
 2479     fileName = appendToPath(dir->copy(), name->getCString());
 2480     f = openFile(fileName->getCString(), "r");
 2481     delete fileName;
 2482     if (f) {
 2483       unlockGlobalParams;
 2484       return f;
 2485     }
 2486   }
 2487   unlockGlobalParams;
 2488   return NULL;
 2489 }
 2490 
 2491 UnicodeRemapping *GlobalParams::getUnicodeRemapping() {
 2492   return unicodeRemapping;
 2493 }
 2494 
 2495 GString *GlobalParams::findFontFile(GString *fontName) {
 2496   static const char *exts[] = { ".pfa", ".pfb", ".ttf", ".ttc", ".otf" };
 2497   GString *path, *dir;
 2498 #ifdef _WIN32
 2499   GString *fontNameU;
 2500 #endif
 2501   const char *ext;
 2502   FILE *f;
 2503   int i, j;
 2504 
 2505   lockGlobalParams;
 2506   if ((path = (GString *)fontFiles->lookup(fontName))) {
 2507     path = path->copy();
 2508     unlockGlobalParams;
 2509     return path;
 2510   }
 2511   for (i = 0; i < fontDirs->getLength(); ++i) {
 2512     dir = (GString *)fontDirs->get(i);
 2513     for (j = 0; j < (int)(sizeof(exts) / sizeof(exts[0])); ++j) {
 2514       ext = exts[j];
 2515 #ifdef _WIN32
 2516       fontNameU = fileNameToUTF8(fontName->getCString());
 2517       path = appendToPath(dir->copy(), fontNameU->getCString());
 2518       delete fontNameU;
 2519 #else
 2520       path = appendToPath(dir->copy(), fontName->getCString());
 2521 #endif
 2522       path->append(ext);
 2523       if ((f = openFile(path->getCString(), "rb"))) {
 2524     fclose(f);
 2525     unlockGlobalParams;
 2526     return path;
 2527       }
 2528       delete path;
 2529     }
 2530   }
 2531   unlockGlobalParams;
 2532   return NULL;
 2533 }
 2534 
 2535 GString *GlobalParams::findBase14FontFile(GString *fontName, int *fontNum,
 2536                       double *oblique) {
 2537   Base14FontInfo *fi;
 2538   GString *path;
 2539 
 2540   lockGlobalParams;
 2541   if ((fi = (Base14FontInfo *)base14SysFonts->lookup(fontName))) {
 2542     path = fi->fileName->copy();
 2543     *fontNum = fi->fontNum;
 2544     *oblique = fi->oblique;
 2545     unlockGlobalParams;
 2546     return path;
 2547   }
 2548   unlockGlobalParams;
 2549   *fontNum = 0;
 2550   *oblique = 0;
 2551   return findFontFile(fontName);
 2552 }
 2553 
 2554 GString *GlobalParams::findSystemFontFile(GString *fontName,
 2555                       SysFontType *type,
 2556                       int *fontNum) {
 2557   SysFontInfo *fi;
 2558   GString *path;
 2559 
 2560   path = NULL;
 2561   lockGlobalParams;
 2562   if ((fi = sysFonts->find(fontName))) {
 2563     path = fi->path->copy();
 2564     *type = fi->type;
 2565     *fontNum = fi->fontNum;
 2566   }
 2567   unlockGlobalParams;
 2568   return path;
 2569 }
 2570 
 2571 GString *GlobalParams::findCCFontFile(GString *collection) {
 2572   GString *path;
 2573 
 2574   lockGlobalParams;
 2575   if ((path = (GString *)ccFontFiles->lookup(collection))) {
 2576     path = path->copy();
 2577   }
 2578   unlockGlobalParams;
 2579   return path;
 2580 }
 2581 
 2582 int GlobalParams::getPSPaperWidth() {
 2583   int w;
 2584 
 2585   lockGlobalParams;
 2586   w = psPaperWidth;
 2587   unlockGlobalParams;
 2588   return w;
 2589 }
 2590 
 2591 int GlobalParams::getPSPaperHeight() {
 2592   int h;
 2593 
 2594   lockGlobalParams;
 2595   h = psPaperHeight;
 2596   unlockGlobalParams;
 2597   return h;
 2598 }
 2599 
 2600 void GlobalParams::getPSImageableArea(int *llx, int *lly, int *urx, int *ury) {
 2601   lockGlobalParams;
 2602   *llx = psImageableLLX;
 2603   *lly = psImageableLLY;
 2604   *urx = psImageableURX;
 2605   *ury = psImageableURY;
 2606   unlockGlobalParams;
 2607 }
 2608 
 2609 GBool GlobalParams::getPSCrop() {
 2610   GBool f;
 2611 
 2612   lockGlobalParams;
 2613   f = psCrop;
 2614   unlockGlobalParams;
 2615   return f;
 2616 }
 2617 
 2618 GBool GlobalParams::getPSUseCropBoxAsPage() {
 2619   GBool f;
 2620 
 2621   lockGlobalParams;
 2622   f = psUseCropBoxAsPage;
 2623   unlockGlobalParams;
 2624   return f;
 2625 }
 2626 
 2627 GBool GlobalParams::getPSExpandSmaller() {
 2628   GBool f;
 2629 
 2630   lockGlobalParams;
 2631   f = psExpandSmaller;
 2632   unlockGlobalParams;
 2633   return f;
 2634 }
 2635 
 2636 GBool GlobalParams::getPSShrinkLarger() {
 2637   GBool f;
 2638 
 2639   lockGlobalParams;
 2640   f = psShrinkLarger;
 2641   unlockGlobalParams;
 2642   return f;
 2643 }
 2644 
 2645 GBool GlobalParams::getPSCenter() {
 2646   GBool f;
 2647 
 2648   lockGlobalParams;
 2649   f = psCenter;
 2650   unlockGlobalParams;
 2651   return f;
 2652 }
 2653 
 2654 GBool GlobalParams::getPSDuplex() {
 2655   GBool d;
 2656 
 2657   lockGlobalParams;
 2658   d = psDuplex;
 2659   unlockGlobalParams;
 2660   return d;
 2661 }
 2662 
 2663 PSLevel GlobalParams::getPSLevel() {
 2664   PSLevel level;
 2665 
 2666   lockGlobalParams;
 2667   level = psLevel;
 2668   unlockGlobalParams;
 2669   return level;
 2670 }
 2671 
 2672 GString *GlobalParams::getPSResidentFont(GString *fontName) {
 2673   GString *psName;
 2674 
 2675   lockGlobalParams;
 2676   if ((psName = (GString *)psResidentFonts->lookup(fontName))) {
 2677     psName = psName->copy();
 2678   }
 2679   unlockGlobalParams;
 2680   return psName;
 2681 }
 2682 
 2683 GList *GlobalParams::getPSResidentFonts() {
 2684   GList *names;
 2685   GHashIter *iter;
 2686   GString *name;
 2687   GString *psName;
 2688 
 2689   names = new GList();
 2690   lockGlobalParams;
 2691   psResidentFonts->startIter(&iter);
 2692   while (psResidentFonts->getNext(&iter, &name, (void **)&psName)) {
 2693     names->append(psName->copy());
 2694   }
 2695   unlockGlobalParams;
 2696   return names;
 2697 }
 2698 
 2699 PSFontParam16 *GlobalParams::getPSResidentFont16(GString *fontName,
 2700                          int wMode) {
 2701   PSFontParam16 *p;
 2702   int i;
 2703 
 2704   lockGlobalParams;
 2705   p = NULL;
 2706   for (i = 0; i < psResidentFonts16->getLength(); ++i) {
 2707     p = (PSFontParam16 *)psResidentFonts16->get(i);
 2708     if (!(p->name->cmp(fontName)) && p->wMode == wMode) {
 2709       break;
 2710     }
 2711     p = NULL;
 2712   }
 2713   unlockGlobalParams;
 2714   return p;
 2715 }
 2716 
 2717 PSFontParam16 *GlobalParams::getPSResidentFontCC(GString *collection,
 2718                          int wMode) {
 2719   PSFontParam16 *p;
 2720   int i;
 2721 
 2722   lockGlobalParams;
 2723   p = NULL;
 2724   for (i = 0; i < psResidentFontsCC->getLength(); ++i) {
 2725     p = (PSFontParam16 *)psResidentFontsCC->get(i);
 2726     if (!(p->name->cmp(collection)) && p->wMode == wMode) {
 2727       break;
 2728     }
 2729     p = NULL;
 2730   }
 2731   unlockGlobalParams;
 2732   return p;
 2733 }
 2734 
 2735 GBool GlobalParams::getPSEmbedType1() {
 2736   GBool e;
 2737 
 2738   lockGlobalParams;
 2739   e = psEmbedType1;
 2740   unlockGlobalParams;
 2741   return e;
 2742 }
 2743 
 2744 GBool GlobalParams::getPSEmbedTrueType() {
 2745   GBool e;
 2746 
 2747   lockGlobalParams;
 2748   e = psEmbedTrueType;
 2749   unlockGlobalParams;
 2750   return e;
 2751 }
 2752 
 2753 GBool GlobalParams::getPSEmbedCIDPostScript() {
 2754   GBool e;
 2755 
 2756   lockGlobalParams;
 2757   e = psEmbedCIDPostScript;
 2758   unlockGlobalParams;
 2759   return e;
 2760 }
 2761 
 2762 GBool GlobalParams::getPSEmbedCIDTrueType() {
 2763   GBool e;
 2764 
 2765   lockGlobalParams;
 2766   e = psEmbedCIDTrueType;
 2767   unlockGlobalParams;
 2768   return e;
 2769 }
 2770 
 2771 GBool GlobalParams::getPSFontPassthrough() {
 2772   GBool e;
 2773 
 2774   lockGlobalParams;
 2775   e = psFontPassthrough;
 2776   unlockGlobalParams;
 2777   return e;
 2778 }
 2779 
 2780 GBool GlobalParams::getPSPreload() {
 2781   GBool preload;
 2782 
 2783   lockGlobalParams;
 2784   preload = psPreload;
 2785   unlockGlobalParams;
 2786   return preload;
 2787 }
 2788 
 2789 GBool GlobalParams::getPSOPI() {
 2790   GBool opi;
 2791 
 2792   lockGlobalParams;
 2793   opi = psOPI;
 2794   unlockGlobalParams;
 2795   return opi;
 2796 }
 2797 
 2798 GBool GlobalParams::getPSASCIIHex() {
 2799   GBool ah;
 2800 
 2801   lockGlobalParams;
 2802   ah = psASCIIHex;
 2803   unlockGlobalParams;
 2804   return ah;
 2805 }
 2806 
 2807 GBool GlobalParams::getPSLZW() {
 2808   GBool ah;
 2809 
 2810   lockGlobalParams;
 2811   ah = psLZW;
 2812   unlockGlobalParams;
 2813   return ah;
 2814 }
 2815 
 2816 GBool GlobalParams::getPSUncompressPreloadedImages() {
 2817   GBool ah;
 2818 
 2819   lockGlobalParams;
 2820   ah = psUncompressPreloadedImages;
 2821   unlockGlobalParams;
 2822   return ah;
 2823 }
 2824 
 2825 double GlobalParams::getPSMinLineWidth() {
 2826   double w;
 2827 
 2828   lockGlobalParams;
 2829   w = psMinLineWidth;
 2830   unlockGlobalParams;
 2831   return w;
 2832 }
 2833 
 2834 double GlobalParams::getPSRasterResolution() {
 2835   double res;
 2836 
 2837   lockGlobalParams;
 2838   res = psRasterResolution;
 2839   unlockGlobalParams;
 2840   return res;
 2841 }
 2842 
 2843 GBool GlobalParams::getPSRasterMono() {
 2844   GBool mono;
 2845 
 2846   lockGlobalParams;
 2847   mono = psRasterMono;
 2848   unlockGlobalParams;
 2849   return mono;
 2850 }
 2851 
 2852 int GlobalParams::getPSRasterSliceSize() {
 2853   int slice;
 2854 
 2855   lockGlobalParams;
 2856   slice = psRasterSliceSize;
 2857   unlockGlobalParams;
 2858   return slice;
 2859 }
 2860 
 2861 GBool GlobalParams::getPSAlwaysRasterize() {
 2862   GBool rast;
 2863 
 2864   lockGlobalParams;
 2865   rast = psAlwaysRasterize;
 2866   unlockGlobalParams;
 2867   return rast;
 2868 }
 2869 
 2870 GBool GlobalParams::getPSNeverRasterize() {
 2871   GBool rast;
 2872 
 2873   lockGlobalParams;
 2874   rast = psNeverRasterize;
 2875   unlockGlobalParams;
 2876   return rast;
 2877 }
 2878 
 2879 GString *GlobalParams::getTextEncodingName() {
 2880   GString *s;
 2881 
 2882   lockGlobalParams;
 2883   s = textEncoding->copy();
 2884   unlockGlobalParams;
 2885   return s;
 2886 }
 2887 
 2888 GList *GlobalParams::getAvailableTextEncodings() {
 2889   GList *list;       // [GString]
 2890   GHashIter *iter;
 2891   GString *key;
 2892   void *val;
 2893 
 2894   list = new GList();
 2895   lockGlobalParams;
 2896   residentUnicodeMaps->startIter(&iter);
 2897   while (residentUnicodeMaps->getNext(&iter, &key, &val)) {
 2898     list->append(key->copy());
 2899   }
 2900   unicodeMaps->startIter(&iter);
 2901   while (unicodeMaps->getNext(&iter, &key, &val)) {
 2902     list->append(key->copy());
 2903   }
 2904   unlockGlobalParams;
 2905   return list;
 2906 }
 2907 
 2908 EndOfLineKind GlobalParams::getTextEOL() {
 2909   EndOfLineKind eol;
 2910 
 2911   lockGlobalParams;
 2912   eol = textEOL;
 2913   unlockGlobalParams;
 2914   return eol;
 2915 }
 2916 
 2917 GBool GlobalParams::getTextPageBreaks() {
 2918   GBool pageBreaks;
 2919 
 2920   lockGlobalParams;
 2921   pageBreaks = textPageBreaks;
 2922   unlockGlobalParams;
 2923   return pageBreaks;
 2924 }
 2925 
 2926 GBool GlobalParams::getTextKeepTinyChars() {
 2927   GBool tiny;
 2928 
 2929   lockGlobalParams;
 2930   tiny = textKeepTinyChars;
 2931   unlockGlobalParams;
 2932   return tiny;
 2933 }
 2934 
 2935 GString *GlobalParams::getInitialZoom() {
 2936   GString *s;
 2937 
 2938   lockGlobalParams;
 2939   s = initialZoom->copy();
 2940   unlockGlobalParams;
 2941   return s;
 2942 }
 2943 
 2944 int GlobalParams::getDefaultFitZoom() {
 2945   int z;
 2946 
 2947   lockGlobalParams;
 2948   z = defaultFitZoom;
 2949   unlockGlobalParams;
 2950   return z;
 2951 }
 2952 
 2953 GString *GlobalParams::getInitialDisplayMode() {
 2954   GString *s;
 2955 
 2956   lockGlobalParams;
 2957   s = initialDisplayMode->copy();
 2958   unlockGlobalParams;
 2959   return s;
 2960 }
 2961 
 2962 GBool GlobalParams::getInitialToolbarState() {
 2963   GBool state;
 2964 
 2965   lockGlobalParams;
 2966   state = initialToolbarState;
 2967   unlockGlobalParams;
 2968   return state;
 2969 }
 2970 
 2971 GBool GlobalParams::getInitialSidebarState() {
 2972   GBool state;
 2973 
 2974   lockGlobalParams;
 2975   state = initialSidebarState;
 2976   unlockGlobalParams;
 2977   return state;
 2978 }
 2979 
 2980 int GlobalParams::getInitialSidebarWidth() {
 2981   int w;
 2982 
 2983   lockGlobalParams;
 2984   w = initialSidebarWidth;
 2985   unlockGlobalParams;
 2986   return w;
 2987 }
 2988 
 2989 GString *GlobalParams::getInitialSelectMode() {
 2990   GString *s;
 2991 
 2992   lockGlobalParams;
 2993   s = initialSelectMode->copy();
 2994   unlockGlobalParams;
 2995   return s;
 2996 }
 2997 
 2998 int GlobalParams::getMaxTileWidth() {
 2999   int w;
 3000 
 3001   lockGlobalParams;
 3002   w = maxTileWidth;
 3003   unlockGlobalParams;
 3004   return w;
 3005 }
 3006 
 3007 int GlobalParams::getMaxTileHeight() {
 3008   int h;
 3009 
 3010   lockGlobalParams;
 3011   h = maxTileHeight;
 3012   unlockGlobalParams;
 3013   return h;
 3014 }
 3015 
 3016 int GlobalParams::getTileCacheSize() {
 3017   int n;
 3018 
 3019   lockGlobalParams;
 3020   n = tileCacheSize;
 3021   unlockGlobalParams;
 3022   return n;
 3023 }
 3024 
 3025 int GlobalParams::getWorkerThreads() {
 3026   int n;
 3027 
 3028   lockGlobalParams;
 3029   n = workerThreads;
 3030   unlockGlobalParams;
 3031   return n;
 3032 }
 3033 
 3034 GBool GlobalParams::getEnableFreeType() {
 3035   GBool f;
 3036 
 3037   lockGlobalParams;
 3038   f = enableFreeType;
 3039   unlockGlobalParams;
 3040   return f;
 3041 }
 3042 
 3043 GBool GlobalParams::getDisableFreeTypeHinting() {
 3044   GBool f;
 3045 
 3046   lockGlobalParams;
 3047   f = disableFreeTypeHinting;
 3048   unlockGlobalParams;
 3049   return f;
 3050 }
 3051 
 3052 
 3053 GBool GlobalParams::getAntialias() {
 3054   GBool f;
 3055 
 3056   lockGlobalParams;
 3057   f = antialias;
 3058   unlockGlobalParams;
 3059   return f;
 3060 }
 3061 
 3062 GBool GlobalParams::getVectorAntialias() {
 3063   GBool f;
 3064 
 3065   lockGlobalParams;
 3066   f = vectorAntialias;
 3067   unlockGlobalParams;
 3068   return f;
 3069 }
 3070 
 3071 GBool GlobalParams::getImageMaskAntialias() {
 3072   GBool f;
 3073 
 3074   lockGlobalParams;
 3075   f = imageMaskAntialias;
 3076   unlockGlobalParams;
 3077   return f;
 3078 }
 3079 
 3080 GBool GlobalParams::getAntialiasPrinting() {
 3081   GBool f;
 3082 
 3083   lockGlobalParams;
 3084   f = antialiasPrinting;
 3085   unlockGlobalParams;
 3086   return f;
 3087 }
 3088 
 3089 StrokeAdjustMode GlobalParams::getStrokeAdjust() {
 3090   StrokeAdjustMode mode;
 3091 
 3092   lockGlobalParams;
 3093   mode = strokeAdjust;
 3094   unlockGlobalParams;
 3095   return mode;
 3096 }
 3097 
 3098 ScreenType GlobalParams::getScreenType() {
 3099   ScreenType t;
 3100 
 3101   lockGlobalParams;
 3102   t = screenType;
 3103   unlockGlobalParams;
 3104   return t;
 3105 }
 3106 
 3107 int GlobalParams::getScreenSize() {
 3108   int size;
 3109 
 3110   lockGlobalParams;
 3111   size = screenSize;
 3112   unlockGlobalParams;
 3113   return size;
 3114 }
 3115 
 3116 int GlobalParams::getScreenDotRadius() {
 3117   int r;
 3118 
 3119   lockGlobalParams;
 3120   r = screenDotRadius;
 3121   unlockGlobalParams;
 3122   return r;
 3123 }
 3124 
 3125 double GlobalParams::getScreenGamma() {
 3126   double gamma;
 3127 
 3128   lockGlobalParams;
 3129   gamma = screenGamma;
 3130   unlockGlobalParams;
 3131   return gamma;
 3132 }
 3133 
 3134 double GlobalParams::getScreenBlackThreshold() {
 3135   double thresh;
 3136 
 3137   lockGlobalParams;
 3138   thresh = screenBlackThreshold;
 3139   unlockGlobalParams;
 3140   return thresh;
 3141 }
 3142 
 3143 double GlobalParams::getScreenWhiteThreshold() {
 3144   double thresh;
 3145 
 3146   lockGlobalParams;
 3147   thresh = screenWhiteThreshold;
 3148   unlockGlobalParams;
 3149   return thresh;
 3150 }
 3151 
 3152 double GlobalParams::getMinLineWidth() {
 3153   double w;
 3154 
 3155   lockGlobalParams;
 3156   w = minLineWidth;
 3157   unlockGlobalParams;
 3158   return w;
 3159 }
 3160 
 3161 GBool GlobalParams::getEnablePathSimplification() {
 3162   GBool en;
 3163 
 3164   lockGlobalParams;
 3165   en = enablePathSimplification;
 3166   unlockGlobalParams;
 3167   return en;
 3168 }
 3169 
 3170 GBool GlobalParams::getDrawAnnotations() {
 3171   GBool draw;
 3172 
 3173   lockGlobalParams;
 3174   draw = drawAnnotations;
 3175   unlockGlobalParams;
 3176   return draw;
 3177 }
 3178 
 3179 GBool GlobalParams::getDrawFormFields() {
 3180   GBool draw;
 3181 
 3182   lockGlobalParams;
 3183   draw = drawFormFields;
 3184   unlockGlobalParams;
 3185   return draw;
 3186 }
 3187 
 3188 GBool GlobalParams::getEnableXFA() {
 3189   GBool xfa;
 3190 
 3191   lockGlobalParams;
 3192   xfa = enableXFA;
 3193   unlockGlobalParams;
 3194   return xfa;
 3195 }
 3196 
 3197 
 3198 
 3199 GString *GlobalParams::getPaperColor() {
 3200   GString *s;
 3201 
 3202   lockGlobalParams;
 3203   s = paperColor->copy();
 3204   unlockGlobalParams;
 3205   return s;
 3206 }
 3207 
 3208 GString *GlobalParams::getMatteColor() {
 3209   GString *s;
 3210 
 3211   lockGlobalParams;
 3212   s = matteColor->copy();
 3213   unlockGlobalParams;
 3214   return s;
 3215 }
 3216 
 3217 GString *GlobalParams::getFullScreenMatteColor() {
 3218   GString *s;
 3219 
 3220   lockGlobalParams;
 3221   s = fullScreenMatteColor->copy();
 3222   unlockGlobalParams;
 3223   return s;
 3224 }
 3225 
 3226 GString *GlobalParams::getSelectionColor() {
 3227   GString *s;
 3228 
 3229   lockGlobalParams;
 3230   s = selectionColor->copy();
 3231   unlockGlobalParams;
 3232   return s;
 3233 }
 3234 
 3235 GBool GlobalParams::getReverseVideoInvertImages() {
 3236   GBool invert;
 3237 
 3238   lockGlobalParams;
 3239   invert = reverseVideoInvertImages;
 3240   unlockGlobalParams;
 3241   return invert;
 3242 }
 3243 
 3244 GString *GlobalParams::getDefaultPrinter() {
 3245   GString *s;
 3246 
 3247   lockGlobalParams;
 3248   s = defaultPrinter ? defaultPrinter->copy() : (GString *)NULL;
 3249   unlockGlobalParams;
 3250   return s;
 3251 }
 3252 
 3253 GBool GlobalParams::getMapNumericCharNames() {
 3254   GBool map;
 3255 
 3256   lockGlobalParams;
 3257   map = mapNumericCharNames;
 3258   unlockGlobalParams;
 3259   return map;
 3260 }
 3261 
 3262 GBool GlobalParams::getMapUnknownCharNames() {
 3263   GBool map;
 3264 
 3265   lockGlobalParams;
 3266   map = mapUnknownCharNames;
 3267   unlockGlobalParams;
 3268   return map;
 3269 }
 3270 
 3271 GBool GlobalParams::getMapExtTrueTypeFontsViaUnicode() {
 3272   GBool map;
 3273 
 3274   lockGlobalParams;
 3275   map = mapExtTrueTypeFontsViaUnicode;
 3276   unlockGlobalParams;
 3277   return map;
 3278 }
 3279 
 3280 GBool GlobalParams::getUseTrueTypeUnicodeMapping() {
 3281   GBool use;
 3282 
 3283   lockGlobalParams;
 3284   use = useTrueTypeUnicodeMapping;
 3285   unlockGlobalParams;
 3286   return use;
 3287 }
 3288 
 3289 GBool GlobalParams::isDroppedFont(const char *fontName) {
 3290   GBool isDropped;
 3291 
 3292   lockGlobalParams;
 3293   isDropped = droppedFonts->lookupInt(fontName) != 0;
 3294   unlockGlobalParams;
 3295   return isDropped;
 3296 }
 3297 
 3298 GList *GlobalParams::getKeyBinding(int code, int mods, int context) {
 3299   KeyBinding *binding;
 3300   GList *cmds;
 3301   int modMask;
 3302   int i, j;
 3303 
 3304   lockGlobalParams;
 3305   cmds = NULL;
 3306   // for ASCII chars, ignore the shift modifier
 3307   modMask = (code >= 0x21 && code <= 0xff) ? ~xpdfKeyModShift : ~0;
 3308   for (i = 0; i < keyBindings->getLength(); ++i) {
 3309     binding = (KeyBinding *)keyBindings->get(i);
 3310     if (binding->code == code &&
 3311     (binding->mods & modMask) == (mods & modMask) &&
 3312     (~binding->context | context) == ~0) {
 3313       cmds = new GList();
 3314       for (j = 0; j < binding->cmds->getLength(); ++j) {
 3315     cmds->append(((GString *)binding->cmds->get(j))->copy());
 3316       }
 3317       break;
 3318     }
 3319   }
 3320   unlockGlobalParams;
 3321   return cmds;
 3322 }
 3323 
 3324 GList *GlobalParams::getAllKeyBindings() {
 3325   return keyBindings;
 3326 }
 3327 
 3328 int GlobalParams::getNumPopupMenuCmds() {
 3329   int n;
 3330 
 3331   lockGlobalParams;
 3332   n = popupMenuCmds->getLength();
 3333   unlockGlobalParams;
 3334   return n;
 3335 }
 3336 
 3337 PopupMenuCmd *GlobalParams::getPopupMenuCmd(int idx) {
 3338   PopupMenuCmd *cmd;
 3339 
 3340   lockGlobalParams;
 3341   if (idx < popupMenuCmds->getLength()) {
 3342     cmd = (PopupMenuCmd *)popupMenuCmds->get(idx);
 3343   } else {
 3344     cmd = NULL;
 3345   }
 3346   unlockGlobalParams;
 3347   return cmd;
 3348 }
 3349 
 3350 GString *GlobalParams::getTabStateFile() {
 3351   GString *s;
 3352 
 3353   lockGlobalParams;
 3354   s = tabStateFile->copy();
 3355   unlockGlobalParams;
 3356   return s;
 3357 }
 3358 
 3359 GBool GlobalParams::getSavePageNumbers() {
 3360   GBool s;
 3361 
 3362   lockGlobalParams;
 3363   s = savePageNumbers;
 3364   unlockGlobalParams;
 3365   return s;
 3366 }
 3367 
 3368 GBool GlobalParams::getPrintCommands() {
 3369   GBool p;
 3370 
 3371   lockGlobalParams;
 3372   p = printCommands;
 3373   unlockGlobalParams;
 3374   return p;
 3375 }
 3376 
 3377 GBool GlobalParams::getPrintStatusInfo() {
 3378   GBool p;
 3379 
 3380   lockGlobalParams;
 3381   p = printStatusInfo;
 3382   unlockGlobalParams;
 3383   return p;
 3384 }
 3385 
 3386 GBool GlobalParams::getErrQuiet() {
 3387   // no locking -- this function may get called from inside a locked
 3388   // section
 3389   return errQuiet;
 3390 }
 3391 
 3392 GString *GlobalParams::getDebugLogFile() {
 3393   return debugLogFile;
 3394 }
 3395 
 3396 void GlobalParams::debugLogPrintf(const char *fmt, ...) {
 3397   GString *path;
 3398   FILE *f;
 3399   GBool needClose;
 3400   time_t t;
 3401   struct tm tm;
 3402   va_list args;
 3403 
 3404   if (!(path = getDebugLogFile())) {
 3405     return;
 3406   }
 3407   needClose = gFalse;
 3408   if (!path->cmp("-")) {
 3409     f = stdout;
 3410   } else if (!path->cmp("+")) {
 3411     f = stderr;
 3412   } else {
 3413     f = fopen(path->getCString(), "a");
 3414     needClose = gTrue;
 3415   }
 3416   if (!f) {
 3417     return;
 3418   }
 3419   t = time(NULL);
 3420 #ifdef _WIN32
 3421   localtime_s(&tm, &t);
 3422 #else
 3423   localtime_r(&t, &tm);
 3424 #endif
 3425   fprintf(f, "[%04d-%02d-%02d %02d:%02d:%02d] ",
 3426       tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
 3427       tm.tm_hour, tm.tm_min, tm.tm_sec);
 3428   va_start(args, fmt);
 3429   vfprintf(f, fmt, args);
 3430   va_end(args);
 3431   fflush(f);
 3432   if (needClose) {
 3433     fclose(f);
 3434   }
 3435 }
 3436 
 3437 CharCodeToUnicode *GlobalParams::getCIDToUnicode(GString *collection) {
 3438   GString *fileName;
 3439   CharCodeToUnicode *ctu;
 3440 
 3441   lockGlobalParams;
 3442   if (!(ctu = cidToUnicodeCache->getCharCodeToUnicode(collection))) {
 3443     if ((fileName = (GString *)cidToUnicodes->lookup(collection)) &&
 3444     (ctu = CharCodeToUnicode::parseCIDToUnicode(fileName, collection))) {
 3445       cidToUnicodeCache->add(ctu);
 3446     }
 3447   }
 3448   unlockGlobalParams;
 3449   return ctu;
 3450 }
 3451 
 3452 CharCodeToUnicode *GlobalParams::getUnicodeToUnicode(GString *fontName) {
 3453   CharCodeToUnicode *ctu;
 3454   GHashIter *iter;
 3455   GString *fontPattern, *fileName;
 3456 
 3457   lockGlobalParams;
 3458   fileName = NULL;
 3459   unicodeToUnicodes->startIter(&iter);
 3460   while (unicodeToUnicodes->getNext(&iter, &fontPattern, (void **)&fileName)) {
 3461     if (strstr(fontName->getCString(), fontPattern->getCString())) {
 3462       unicodeToUnicodes->killIter(&iter);
 3463       break;
 3464     }
 3465     fileName = NULL;
 3466   }
 3467   if (fileName) {
 3468     if (!(ctu = unicodeToUnicodeCache->getCharCodeToUnicode(fileName))) {
 3469       if ((ctu = CharCodeToUnicode::parseUnicodeToUnicode(fileName))) {
 3470     unicodeToUnicodeCache->add(ctu);
 3471       }
 3472     }
 3473   } else {
 3474     ctu = NULL;
 3475   }
 3476   unlockGlobalParams;
 3477   return ctu;
 3478 }
 3479 
 3480 UnicodeMap *GlobalParams::getUnicodeMap(GString *encodingName) {
 3481   return getUnicodeMap2(encodingName);
 3482 }
 3483 
 3484 UnicodeMap *GlobalParams::getUnicodeMap2(GString *encodingName) {
 3485   UnicodeMap *map;
 3486 
 3487   if (!(map = getResidentUnicodeMap(encodingName))) {
 3488     lockUnicodeMapCache;
 3489     map = unicodeMapCache->getUnicodeMap(encodingName);
 3490     unlockUnicodeMapCache;
 3491   }
 3492   return map;
 3493 }
 3494 
 3495 CMap *GlobalParams::getCMap(GString *collection, GString *cMapName) {
 3496   CMap *cMap;
 3497 
 3498   lockCMapCache;
 3499   cMap = cMapCache->getCMap(collection, cMapName);
 3500   unlockCMapCache;
 3501   return cMap;
 3502 }
 3503 
 3504 UnicodeMap *GlobalParams::getTextEncoding() {
 3505   return getUnicodeMap2(textEncoding);
 3506 }
 3507 
 3508 //------------------------------------------------------------------------
 3509 // functions to set parameters
 3510 //------------------------------------------------------------------------
 3511 
 3512 void GlobalParams::addUnicodeRemapping(Unicode in, Unicode *out, int len) {
 3513   unicodeRemapping->addRemapping(in, out, len);
 3514 }
 3515 
 3516 void GlobalParams::addFontFile(GString *fontName, GString *path) {
 3517   lockGlobalParams;
 3518   fontFiles->add(fontName, path);
 3519   unlockGlobalParams;
 3520 }
 3521 
 3522 GBool GlobalParams::setPSPaperSize(char *size) {
 3523   lockGlobalParams;
 3524   if (!strcmp(size, "match")) {
 3525     psPaperWidth = psPaperHeight = -1;
 3526   } else if (!strcmp(size, "letter")) {
 3527     psPaperWidth = 612;
 3528     psPaperHeight = 792;
 3529   } else if (!strcmp(size, "legal")) {
 3530     psPaperWidth = 612;
 3531     psPaperHeight = 1008;
 3532   } else if (!strcmp(size, "A4")) {
 3533     psPaperWidth = 595;
 3534     psPaperHeight = 842;
 3535   } else if (!strcmp(size, "A3")) {
 3536     psPaperWidth = 842;
 3537     psPaperHeight = 1190;
 3538   } else {
 3539     unlockGlobalParams;
 3540     return gFalse;
 3541   }
 3542   psImageableLLX = psImageableLLY = 0;
 3543   psImageableURX = psPaperWidth;
 3544   psImageableURY = psPaperHeight;
 3545   unlockGlobalParams;
 3546   return gTrue;
 3547 }
 3548 
 3549 void GlobalParams::setPSPaperWidth(int width) {
 3550   lockGlobalParams;
 3551   psPaperWidth = width;
 3552   psImageableLLX = 0;
 3553   psImageableURX = psPaperWidth;
 3554   unlockGlobalParams;
 3555 }
 3556 
 3557 void GlobalParams::setPSPaperHeight(int height) {
 3558   lockGlobalParams;
 3559   psPaperHeight = height;
 3560   psImageableLLY = 0;
 3561   psImageableURY = psPaperHeight;
 3562   unlockGlobalParams;
 3563 }
 3564 
 3565 void GlobalParams::setPSImageableArea(int llx, int lly, int urx, int ury) {
 3566   lockGlobalParams;
 3567   psImageableLLX = llx;
 3568   psImageableLLY = lly;
 3569   psImageableURX = urx;
 3570   psImageableURY = ury;
 3571   unlockGlobalParams;
 3572 }
 3573 
 3574 void GlobalParams::setPSCrop(GBool crop) {
 3575   lockGlobalParams;
 3576   psCrop = crop;
 3577   unlockGlobalParams;
 3578 }
 3579 
 3580 void GlobalParams::setPSUseCropBoxAsPage(GBool crop) {
 3581   lockGlobalParams;
 3582   psUseCropBoxAsPage = crop;
 3583   unlockGlobalParams;
 3584 }
 3585 
 3586 void GlobalParams::setPSExpandSmaller(GBool expand) {
 3587   lockGlobalParams;
 3588   psExpandSmaller = expand;
 3589   unlockGlobalParams;
 3590 }
 3591 
 3592 void GlobalParams::setPSShrinkLarger(GBool shrink) {
 3593   lockGlobalParams;
 3594   psShrinkLarger = shrink;
 3595   unlockGlobalParams;
 3596 }
 3597 
 3598 void GlobalParams::setPSCenter(GBool center) {
 3599   lockGlobalParams;
 3600   psCenter = center;
 3601   unlockGlobalParams;
 3602 }
 3603 
 3604 void GlobalParams::setPSDuplex(GBool duplex) {
 3605   lockGlobalParams;
 3606   psDuplex = duplex;
 3607   unlockGlobalParams;
 3608 }
 3609 
 3610 void GlobalParams::setPSLevel(PSLevel level) {
 3611   lockGlobalParams;
 3612   psLevel = level;
 3613   unlockGlobalParams;
 3614 }
 3615 
 3616 void GlobalParams::setPSEmbedType1(GBool embed) {
 3617   lockGlobalParams;
 3618   psEmbedType1 = embed;
 3619   unlockGlobalParams;
 3620 }
 3621 
 3622 void GlobalParams::setPSEmbedTrueType(GBool embed) {
 3623   lockGlobalParams;
 3624   psEmbedTrueType = embed;
 3625   unlockGlobalParams;
 3626 }
 3627 
 3628 void GlobalParams::setPSEmbedCIDPostScript(GBool embed) {
 3629   lockGlobalParams;
 3630   psEmbedCIDPostScript = embed;
 3631   unlockGlobalParams;
 3632 }
 3633 
 3634 void GlobalParams::setPSEmbedCIDTrueType(GBool embed) {
 3635   lockGlobalParams;
 3636   psEmbedCIDTrueType = embed;
 3637   unlockGlobalParams;
 3638 }
 3639 
 3640 void GlobalParams::setPSFontPassthrough(GBool passthrough) {
 3641   lockGlobalParams;
 3642   psFontPassthrough = passthrough;
 3643   unlockGlobalParams;
 3644 }
 3645 
 3646 void GlobalParams::setPSPreload(GBool preload) {
 3647   lockGlobalParams;
 3648   psPreload = preload;
 3649   unlockGlobalParams;
 3650 }
 3651 
 3652 void GlobalParams::setPSOPI(GBool opi) {
 3653   lockGlobalParams;
 3654   psOPI = opi;
 3655   unlockGlobalParams;
 3656 }
 3657 
 3658 void GlobalParams::setPSASCIIHex(GBool hex) {
 3659   lockGlobalParams;
 3660   psASCIIHex = hex;
 3661   unlockGlobalParams;
 3662 }
 3663 
 3664 void GlobalParams::setTextEncoding(const char *encodingName) {
 3665   lockGlobalParams;
 3666   delete textEncoding;
 3667   textEncoding = new GString(encodingName);
 3668   unlockGlobalParams;
 3669 }
 3670 
 3671 GBool GlobalParams::setTextEOL(char *s) {
 3672   lockGlobalParams;
 3673   if (!strcmp(s, "unix")) {
 3674     textEOL = eolUnix;
 3675   } else if (!strcmp(s, "dos")) {
 3676     textEOL = eolDOS;
 3677   } else if (!strcmp(s, "mac")) {
 3678     textEOL = eolMac;
 3679   } else {
 3680     unlockGlobalParams;
 3681     return gFalse;
 3682   }
 3683   unlockGlobalParams;
 3684   return gTrue;
 3685 }
 3686 
 3687 void GlobalParams::setTextPageBreaks(GBool pageBreaks) {
 3688   lockGlobalParams;
 3689   textPageBreaks = pageBreaks;
 3690   unlockGlobalParams;
 3691 }
 3692 
 3693 void GlobalParams::setTextKeepTinyChars(GBool keep) {
 3694   lockGlobalParams;
 3695   textKeepTinyChars = keep;
 3696   unlockGlobalParams;
 3697 }
 3698 
 3699 void GlobalParams::setInitialZoom(char *s) {
 3700   lockGlobalParams;
 3701   delete initialZoom;
 3702   initialZoom = new GString(s);
 3703   unlockGlobalParams;
 3704 }
 3705 
 3706 GBool GlobalParams::setEnableFreeType(char *s) {
 3707   GBool ok;
 3708 
 3709   lockGlobalParams;
 3710   ok = parseYesNo2(s, &enableFreeType);
 3711   unlockGlobalParams;
 3712   return ok;
 3713 }
 3714 
 3715 
 3716 GBool GlobalParams::setAntialias(char *s) {
 3717   GBool ok;
 3718 
 3719   lockGlobalParams;
 3720   ok = parseYesNo2(s, &antialias);
 3721   unlockGlobalParams;
 3722   return ok;
 3723 }
 3724 
 3725 GBool GlobalParams::setVectorAntialias(char *s) {
 3726   GBool ok;
 3727 
 3728   lockGlobalParams;
 3729   ok = parseYesNo2(s, &vectorAntialias);
 3730   unlockGlobalParams;
 3731   return ok;
 3732 }
 3733 
 3734 void GlobalParams::setScreenType(ScreenType t) {
 3735   lockGlobalParams;
 3736   screenType = t;
 3737   unlockGlobalParams;
 3738 }
 3739 
 3740 void GlobalParams::setScreenSize(int size) {
 3741   lockGlobalParams;
 3742   screenSize = size;
 3743   unlockGlobalParams;
 3744 }
 3745 
 3746 void GlobalParams::setScreenDotRadius(int r) {
 3747   lockGlobalParams;
 3748   screenDotRadius = r;
 3749   unlockGlobalParams;
 3750 }
 3751 
 3752 void GlobalParams::setScreenGamma(double gamma) {
 3753   lockGlobalParams;
 3754   screenGamma = gamma;
 3755   unlockGlobalParams;
 3756 }
 3757 
 3758 void GlobalParams::setScreenBlackThreshold(double thresh) {
 3759   lockGlobalParams;
 3760   screenBlackThreshold = thresh;
 3761   unlockGlobalParams;
 3762 }
 3763 
 3764 void GlobalParams::setScreenWhiteThreshold(double thresh) {
 3765   lockGlobalParams;
 3766   screenWhiteThreshold = thresh;
 3767   unlockGlobalParams;
 3768 }
 3769 
 3770 void GlobalParams::setDrawFormFields(GBool draw) {
 3771   lockGlobalParams;
 3772   drawFormFields = draw;
 3773   unlockGlobalParams;
 3774 }
 3775 
 3776 void GlobalParams::setOverprintPreview(GBool preview) {
 3777   lockGlobalParams;
 3778   overprintPreview = preview;
 3779   unlockGlobalParams;
 3780 }
 3781 
 3782 
 3783 
 3784 void GlobalParams::setMapNumericCharNames(GBool map) {
 3785   lockGlobalParams;
 3786   mapNumericCharNames = map;
 3787   unlockGlobalParams;
 3788 }
 3789 
 3790 void GlobalParams::setMapUnknownCharNames(GBool map) {
 3791   lockGlobalParams;
 3792   mapUnknownCharNames = map;
 3793   unlockGlobalParams;
 3794 }
 3795 
 3796 void GlobalParams::setMapExtTrueTypeFontsViaUnicode(GBool map) {
 3797   lockGlobalParams;
 3798   mapExtTrueTypeFontsViaUnicode = map;
 3799   unlockGlobalParams;
 3800 }
 3801 
 3802 void GlobalParams::setTabStateFile(char *tabStateFileA) {
 3803   lockGlobalParams;
 3804   delete tabStateFile;
 3805   tabStateFile = new GString(tabStateFileA);
 3806   unlockGlobalParams;
 3807 }
 3808 
 3809 void GlobalParams::setPrintCommands(GBool printCommandsA) {
 3810   lockGlobalParams;
 3811   printCommands = printCommandsA;
 3812   unlockGlobalParams;
 3813 }
 3814 
 3815 void GlobalParams::setPrintStatusInfo(GBool printStatusInfoA) {
 3816   lockGlobalParams;
 3817   printStatusInfo = printStatusInfoA;
 3818   unlockGlobalParams;
 3819 }
 3820 
 3821 void GlobalParams::setErrQuiet(GBool errQuietA) {
 3822   lockGlobalParams;
 3823   errQuiet = errQuietA;
 3824   unlockGlobalParams;
 3825 }
 3826 
 3827 #ifdef _WIN32
 3828 void GlobalParams::setWin32ErrorInfo(const char *func, DWORD code) {
 3829   XpdfWin32ErrorInfo *errorInfo;
 3830 
 3831   if (tlsWin32ErrorInfo == TLS_OUT_OF_INDEXES) {
 3832     return;
 3833   }
 3834   errorInfo = (XpdfWin32ErrorInfo *)TlsGetValue(tlsWin32ErrorInfo);
 3835   if (!errorInfo) {
 3836     errorInfo = new XpdfWin32ErrorInfo();
 3837     TlsSetValue(tlsWin32ErrorInfo, errorInfo);
 3838   }
 3839   errorInfo->func = func;
 3840   errorInfo->code = code;
 3841 }
 3842 
 3843 XpdfWin32ErrorInfo *GlobalParams::getWin32ErrorInfo() {
 3844   XpdfWin32ErrorInfo *errorInfo;
 3845 
 3846   if (tlsWin32ErrorInfo == TLS_OUT_OF_INDEXES) {
 3847     return NULL;
 3848   }
 3849   errorInfo = (XpdfWin32ErrorInfo *)TlsGetValue(tlsWin32ErrorInfo);
 3850   if (!errorInfo) {
 3851     errorInfo = new XpdfWin32ErrorInfo();
 3852     TlsSetValue(tlsWin32ErrorInfo, errorInfo);
 3853     errorInfo->func = NULL;
 3854     errorInfo->code = 0;
 3855   }
 3856   return errorInfo;
 3857 }
 3858 #endif