"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.

    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