implemented bit depths.
[swftools.git] / pdf2swf / xpdf / GlobalParams.cc
1 //========================================================================
2 //
3 // GlobalParams.cc
4 //
5 // Copyright 2001-2002 Glyph & Cog, LLC
6 //
7 //========================================================================
8
9 #ifdef __GNUC__
10 #pragma implementation
11 #endif
12
13 #include <aconf.h>
14 #include <string.h>
15 #include <ctype.h>
16 #if HAVE_PAPER_H
17 #include <paper.h>
18 #endif
19 #include "gmem.h"
20 #include "GString.h"
21 #include "GList.h"
22 #include "GHash.h"
23 #include "gfile.h"
24 #include "Error.h"
25 #include "NameToCharCode.h"
26 #include "CharCodeToUnicode.h"
27 #include "UnicodeMap.h"
28 #include "CMap.h"
29 #include "BuiltinFontTables.h"
30 #include "FontEncodingTables.h"
31 #include "GlobalParams.h"
32
33 #include "NameToUnicodeTable.h"
34 #include "UnicodeMapTables.h"
35 #include "DisplayFontTable.h"
36 #include "UTF8.h"
37
38 //------------------------------------------------------------------------
39
40 GlobalParams *globalParams = NULL;
41
42 //------------------------------------------------------------------------
43 // DisplayFontParam
44 //------------------------------------------------------------------------
45
46 DisplayFontParam::DisplayFontParam(GString *nameA,
47                                    DisplayFontParamKind kindA) {
48   name = nameA;
49   kind = kindA;
50   switch (kind) {
51   case displayFontX:
52     x.xlfd = NULL;
53     x.encoding = NULL;
54     break;
55   case displayFontT1:
56     t1.fileName = NULL;
57     break;
58   case displayFontTT:
59     tt.fileName = NULL;
60     break;
61   }
62 }
63
64 DisplayFontParam::DisplayFontParam(char *nameA, char *xlfdA, char *encodingA) {
65   name = new GString(nameA);
66   kind = displayFontX;
67   x.xlfd = new GString(xlfdA);
68   x.encoding = new GString(encodingA);
69 }
70
71 DisplayFontParam::~DisplayFontParam() {
72   delete name;
73   switch (kind) {
74   case displayFontX:
75     if (x.xlfd) {
76       delete x.xlfd;
77     }
78     if (x.encoding) {
79       delete x.encoding;
80     }
81     break;
82   case displayFontT1:
83     if (t1.fileName) {
84       delete t1.fileName;
85     }
86     break;
87   case displayFontTT:
88     if (tt.fileName) {
89       delete tt.fileName;
90     }
91     break;
92   }
93 }
94
95 //------------------------------------------------------------------------
96 // PSFontParam
97 //------------------------------------------------------------------------
98
99 PSFontParam::PSFontParam(GString *pdfFontNameA, int wModeA,
100                          GString *psFontNameA, GString *encodingA) {
101   pdfFontName = pdfFontNameA;
102   wMode = wModeA;
103   psFontName = psFontNameA;
104   encoding = encodingA;
105 }
106
107 PSFontParam::~PSFontParam() {
108   delete pdfFontName;
109   delete psFontName;
110   if (encoding) {
111     delete encoding;
112   }
113 }
114
115 //------------------------------------------------------------------------
116 // parsing
117 //------------------------------------------------------------------------
118
119 GlobalParams::GlobalParams(char *cfgFileName) {
120   UnicodeMap *map;
121   DisplayFontParam *dfp;
122   GString *fileName;
123   FILE *f;
124   int i;
125
126   initBuiltinFontTables();
127
128   // scan the encoding in reverse because we want the lowest-numbered
129   // index for each char name ('space' is encoded twice)
130   macRomanReverseMap = new NameToCharCode();
131   for (i = 255; i >= 0; --i) {
132     if (macRomanEncoding[i]) {
133       macRomanReverseMap->add(macRomanEncoding[i], (CharCode)i);
134     }
135   }
136
137   nameToUnicode = new NameToCharCode();
138   cidToUnicodes = new GHash(gTrue);
139   residentUnicodeMaps = new GHash();
140   unicodeMaps = new GHash(gTrue);
141   cMapDirs = new GHash(gTrue);
142   toUnicodeDirs = new GList();
143   displayFonts = new GHash();
144   displayCIDFonts = new GHash();
145   displayNamedCIDFonts = new GHash();
146 #if HAVE_PAPER_H
147   const struct paper *paperType;
148   paperinit();
149   paperType = paperinfo(systempapername());
150   psPaperWidth = (int)paperpswidth(paperType);
151   psPaperHeight = (int)paperpsheight(paperType);
152   paperdone();
153 #else
154   psPaperWidth = defPaperWidth;
155   psPaperHeight = defPaperHeight;
156 #endif
157   psDuplex = gFalse;
158   psLevel = psLevel2;
159   psFile = NULL;
160   psFonts = new GHash();
161   psNamedFonts16 = new GList();
162   psFonts16 = new GList();
163   psEmbedType1 = gTrue;
164   psEmbedTrueType = gTrue;
165   psEmbedCIDPostScript = gTrue;
166   psEmbedCIDTrueType = gTrue;
167   psOPI = gFalse;
168   psASCIIHex = gFalse;
169   textEncoding = new GString("Latin1");
170 #if defined(WIN32)
171   textEOL = eolDOS;
172 #elif defined(MACOS)
173   textEOL = eolMac;
174 #else
175   textEOL = eolUnix;
176 #endif
177   fontDirs = new GList();
178   initialZoom = new GString("1");
179   t1libControl = fontRastAALow;
180   freetypeControl = fontRastAALow;
181   urlCommand = NULL;
182   mapNumericCharNames = gTrue;
183   errQuiet = gFalse;
184
185   cidToUnicodeCache = new CIDToUnicodeCache();
186   unicodeMapCache = new UnicodeMapCache();
187   cMapCache = new CMapCache();
188
189   // set up the initial nameToUnicode table
190   for (i = 0; nameToUnicodeTab[i].name; ++i) {
191     nameToUnicode->add(nameToUnicodeTab[i].name, nameToUnicodeTab[i].u);
192   }
193
194   // set up the residentUnicodeMaps table
195   map = new UnicodeMap("Latin1", latin1UnicodeMapRanges, latin1UnicodeMapLen);
196   residentUnicodeMaps->add(map->getEncodingName(), map);
197   map = new UnicodeMap("ASCII7", ascii7UnicodeMapRanges, ascii7UnicodeMapLen);
198   residentUnicodeMaps->add(map->getEncodingName(), map);
199   map = new UnicodeMap("Symbol", symbolUnicodeMapRanges, symbolUnicodeMapLen);
200   residentUnicodeMaps->add(map->getEncodingName(), map);
201   map = new UnicodeMap("ZapfDingbats", zapfDingbatsUnicodeMapRanges,
202                        zapfDingbatsUnicodeMapLen);
203   residentUnicodeMaps->add(map->getEncodingName(), map);
204   map = new UnicodeMap("UTF-8", &mapUTF8);
205   residentUnicodeMaps->add(map->getEncodingName(), map);
206   map = new UnicodeMap("UCS-2", &mapUCS2);
207   residentUnicodeMaps->add(map->getEncodingName(), map);
208
209   // default displayFonts table
210   for (i = 0; displayFontTab[i].name; ++i) {
211     dfp = new DisplayFontParam(displayFontTab[i].name,
212                                displayFontTab[i].xlfd,
213                                displayFontTab[i].encoding);
214     displayFonts->add(dfp->name, dfp);
215   }
216
217   // look for a user config file, then a system-wide config file
218   f = NULL;
219   fileName = NULL;
220   if (cfgFileName && cfgFileName[0]) {
221     fileName = new GString(cfgFileName);
222     if (!(f = fopen(fileName->getCString(), "r"))) {
223       delete fileName;
224     }
225   }
226   if (!f) {
227     fileName = appendToPath(getHomeDir(), xpdfUserConfigFile);
228     if (!(f = fopen(fileName->getCString(), "r"))) {
229       delete fileName;
230     }
231   }
232   if (!f) {
233 #if defined(WIN32) && !defined(__CYGWIN32__)
234     char buf[512];
235     i = GetModuleFileName(NULL, buf, sizeof(buf));
236     if (i <= 0 || i >= sizeof(buf)) {
237       // error or path too long for buffer - just use the current dir
238       buf[i] = '\0';
239     }
240     fileName = grabPath(buf);
241     appendToPath(fileName, xpdfSysConfigFile);
242 #else
243     fileName = new GString(xpdfSysConfigFile);
244 #endif
245     if (!(f = fopen(fileName->getCString(), "r"))) {
246       delete fileName;
247     }
248   }
249   if (f) {
250     parseFile(fileName, f);
251     delete fileName;
252   }
253 }
254
255 void GlobalParams::parseFile(GString *fileName, FILE *f) {
256   int line;
257   GList *tokens;
258   GString *cmd, *incFile;
259   char *p1, *p2;
260   char buf[512];
261   FILE *f2;
262
263   line = 1;
264   while (fgets(buf, sizeof(buf) - 1, f)) {
265
266     // break the line into tokens
267     tokens = new GList();
268     p1 = buf;
269     while (*p1) {
270       for (; *p1 && isspace(*p1); ++p1) ;
271       if (!*p1) {
272         break;
273       }
274       if (*p1 == '"' || *p1 == '\'') {
275         for (p2 = p1 + 1; *p2 && *p2 != *p1; ++p2) ;
276         ++p1;
277       } else {
278         for (p2 = p1 + 1; *p2 && !isspace(*p2); ++p2) ;
279       }
280       tokens->append(new GString(p1, p2 - p1));
281       p1 = p2 + 1;
282     }
283
284     if (tokens->getLength() > 0 &&
285         ((GString *)tokens->get(0))->getChar(0) != '#') {
286       cmd = (GString *)tokens->get(0);
287       if (!cmd->cmp("include")) {
288         if (tokens->getLength() == 2) {
289           incFile = (GString *)tokens->get(1);
290           if ((f2 = fopen(incFile->getCString(), "r"))) {
291             parseFile(incFile, f2);
292             fclose(f2);
293           } else {
294             error(-1, "Couldn't find included config file: '%s' (%s:%d)",
295                   incFile->getCString(), fileName->getCString(), line);
296           }
297         } else {
298           error(-1, "Bad 'include' config file command (%s:%d)",
299                 fileName->getCString(), line);
300         }
301       } else if (!cmd->cmp("nameToUnicode")) {
302         parseNameToUnicode(tokens, fileName, line);
303       } else if (!cmd->cmp("cidToUnicode")) {
304         parseCIDToUnicode(tokens, fileName, line);
305       } else if (!cmd->cmp("unicodeMap")) {
306         parseUnicodeMap(tokens, fileName, line);
307       } else if (!cmd->cmp("cMapDir")) {
308         parseCMapDir(tokens, fileName, line);
309       } else if (!cmd->cmp("toUnicodeDir")) {
310         parseToUnicodeDir(tokens, fileName, line);
311       } else if (!cmd->cmp("displayFontX")) {
312         parseDisplayFont(tokens, displayFonts, displayFontX, fileName, line);
313       } else if (!cmd->cmp("displayFontT1")) {
314         parseDisplayFont(tokens, displayFonts, displayFontT1, fileName, line);
315       } else if (!cmd->cmp("displayFontTT")) {
316         parseDisplayFont(tokens, displayFonts, displayFontTT, fileName, line);
317       } else if (!cmd->cmp("displayCIDFontX")) {
318         parseDisplayFont(tokens, displayCIDFonts,
319                          displayFontX, fileName, line);
320       } else if (!cmd->cmp("displayNamedCIDFontX")) {
321         parseDisplayFont(tokens, displayNamedCIDFonts,
322                          displayFontX, fileName, line);
323       } else if (!cmd->cmp("psFile")) {
324         parsePSFile(tokens, fileName, line);
325       } else if (!cmd->cmp("psFont")) {
326         parsePSFont(tokens, fileName, line);
327       } else if (!cmd->cmp("psNamedFont16")) {
328         parsePSFont16("psNamedFont16", psNamedFonts16,
329                       tokens, fileName, line);
330       } else if (!cmd->cmp("psFont16")) {
331         parsePSFont16("psFont16", psFonts16, tokens, fileName, line);
332       } else if (!cmd->cmp("psPaperSize")) {
333         parsePSPaperSize(tokens, fileName, line);
334       } else if (!cmd->cmp("psDuplex")) {
335         parseYesNo("psDuplex", &psDuplex, tokens, fileName, line);
336       } else if (!cmd->cmp("psLevel")) {
337         parsePSLevel(tokens, fileName, line);
338       } else if (!cmd->cmp("psEmbedType1Fonts")) {
339         parseYesNo("psEmbedType1", &psEmbedType1, tokens, fileName, line);
340       } else if (!cmd->cmp("psEmbedTrueTypeFonts")) {
341         parseYesNo("psEmbedTrueType", &psEmbedTrueType,
342                    tokens, fileName, line);
343       } else if (!cmd->cmp("psEmbedCIDPostScriptFonts")) {
344         parseYesNo("psEmbedCIDPostScript", &psEmbedCIDPostScript,
345                    tokens, fileName, line);
346       } else if (!cmd->cmp("psEmbedCIDTrueTypeFonts")) {
347         parseYesNo("psEmbedCIDTrueType", &psEmbedCIDTrueType,
348                    tokens, fileName, line);
349       } else if (!cmd->cmp("psOPI")) {
350         parseYesNo("psOPI", &psOPI, tokens, fileName, line);
351       } else if (!cmd->cmp("psASCIIHex")) {
352         parseYesNo("psASCIIHex", &psASCIIHex, tokens, fileName, line);
353       } else if (!cmd->cmp("textEncoding")) {
354         parseTextEncoding(tokens, fileName, line);
355       } else if (!cmd->cmp("textEOL")) {
356         parseTextEOL(tokens, fileName, line);
357       } else if (!cmd->cmp("fontDir")) {
358         parseFontDir(tokens, fileName, line);
359       } else if (!cmd->cmp("initialZoom")) {
360         parseInitialZoom(tokens, fileName, line);
361       } else if (!cmd->cmp("t1libControl")) {
362         parseFontRastControl("t1libControl", &t1libControl,
363                              tokens, fileName, line);
364       } else if (!cmd->cmp("freetypeControl")) {
365         parseFontRastControl("freetypeControl", &freetypeControl,
366                              tokens, fileName, line);
367       } else if (!cmd->cmp("urlCommand")) {
368         parseURLCommand(tokens, fileName, line);
369       } else if (!cmd->cmp("mapNumericCharNames")) {
370         parseYesNo("mapNumericCharNames", &mapNumericCharNames,
371                    tokens, fileName, line);
372       } else if (!cmd->cmp("errQuiet")) {
373         parseYesNo("errQuiet", &errQuiet, tokens, fileName, line);
374       } else if (!cmd->cmp("fontpath") || !cmd->cmp("fontmap")) {
375         error(-1, "Unknown config file command");
376         error(-1, "-- the config file format has changed since Xpdf 0.9x");
377       } else {
378         error(-1, "Unknown config file command '%s' (%s:%d)",
379               cmd->getCString(), fileName->getCString(), line);
380       }
381     }
382
383     deleteGList(tokens, GString);
384     ++line;
385   }
386 }
387
388 void GlobalParams::parseNameToUnicode(GList *tokens, GString *fileName,
389                                          int line) {
390   GString *name;
391   char *tok1, *tok2;
392   FILE *f;
393   char buf[256];
394   int line2;
395   Unicode u;
396
397   if (tokens->getLength() != 2) {
398     error(-1, "Bad 'nameToUnicode' config file command (%s:%d)",
399           fileName->getCString(), line);
400     return;
401   }
402   name = (GString *)tokens->get(1);
403   if (!(f = fopen(name->getCString(), "r"))) {
404     error(-1, "Couldn't open 'nameToUnicode' file '%s'",
405           name->getCString());
406     return;
407   }
408   line2 = 1;
409   while (fgets(buf, sizeof(buf), f)) {
410     tok1 = strtok(buf, " \t\r\n");
411     tok2 = strtok(NULL, " \t\r\n");
412     if (tok1 && tok2) {
413       sscanf(tok1, "%x", &u);
414       nameToUnicode->add(tok2, u);
415     } else {
416       error(-1, "Bad line in 'nameToUnicode' file (%s:%d)", name, line2);
417     }
418     ++line2;
419   }
420   fclose(f);
421 }
422
423 void GlobalParams::parseCIDToUnicode(GList *tokens, GString *fileName,
424                                      int line) {
425   GString *collection, *name, *old;
426
427   if (tokens->getLength() != 3) {
428     error(-1, "Bad 'cidToUnicode' config file command (%s:%d)",
429           fileName->getCString(), line);
430     return;
431   }
432   collection = (GString *)tokens->get(1);
433   name = (GString *)tokens->get(2);
434   if ((old = (GString *)cidToUnicodes->remove(collection))) {
435     delete old;
436   }
437   cidToUnicodes->add(collection->copy(), name->copy());
438 }
439
440 void GlobalParams::parseUnicodeMap(GList *tokens, GString *fileName,
441                                    int line) {
442   GString *encodingName, *name, *old;
443
444   if (tokens->getLength() != 3) {
445     error(-1, "Bad 'unicodeMap' config file command (%s:%d)",
446           fileName->getCString(), line);
447     return;
448   }
449   encodingName = (GString *)tokens->get(1);
450   name = (GString *)tokens->get(2);
451   if ((old = (GString *)unicodeMaps->remove(encodingName))) {
452     delete old;
453   }
454   unicodeMaps->add(encodingName->copy(), name->copy());
455 }
456
457 void GlobalParams::parseCMapDir(GList *tokens, GString *fileName, int line) {
458   GString *collection, *dir;
459   GList *list;
460
461   if (tokens->getLength() != 3) {
462     error(-1, "Bad 'cMapDir' config file command (%s:%d)",
463           fileName->getCString(), line);
464     return;
465   }
466   collection = (GString *)tokens->get(1);
467   dir = (GString *)tokens->get(2);
468   if (!(list = (GList *)cMapDirs->lookup(collection))) {
469     list = new GList();
470     cMapDirs->add(collection->copy(), list);
471   }
472   list->append(dir->copy());
473 }
474
475 void GlobalParams::parseToUnicodeDir(GList *tokens, GString *fileName,
476                                      int line) {
477   if (tokens->getLength() != 2) {
478     error(-1, "Bad 'toUnicodeDir' config file command (%s:%d)",
479           fileName->getCString(), line);
480     return;
481   }
482   toUnicodeDirs->append(((GString *)tokens->get(1))->copy());
483 }
484
485 void GlobalParams::parseDisplayFont(GList *tokens, GHash *fontHash,
486                                     DisplayFontParamKind kind,
487                                     GString *fileName, int line) {
488   DisplayFontParam *param, *old;
489
490   if (tokens->getLength() < 2) {
491     goto err1;
492   }
493   param = new DisplayFontParam(((GString *)tokens->get(1))->copy(), kind);
494   
495   switch (kind) {
496   case displayFontX:
497     if (tokens->getLength() != 4) {
498       goto err2;
499     }
500     param->x.xlfd = ((GString *)tokens->get(2))->copy();
501     param->x.encoding = ((GString *)tokens->get(3))->copy();
502     break;
503   case displayFontT1:
504     if (tokens->getLength() != 3) {
505       goto err2;
506     }
507     param->t1.fileName = ((GString *)tokens->get(2))->copy();
508     break;
509   case displayFontTT:
510     if (tokens->getLength() != 3) {
511       goto err2;
512     }
513     param->tt.fileName = ((GString *)tokens->get(2))->copy();
514     break;
515   }
516
517   if ((old = (DisplayFontParam *)fontHash->remove(param->name))) {
518     delete old;
519   }
520   fontHash->add(param->name, param);
521   return;
522
523  err2:
524   delete param;
525  err1:
526   error(-1, "Bad 'display*Font*' config file command (%s:%d)",
527         fileName->getCString(), line);
528 }
529
530 void GlobalParams::parsePSPaperSize(GList *tokens, GString *fileName,
531                                     int line) {
532   GString *tok;
533
534   if (tokens->getLength() == 2) {
535     tok = (GString *)tokens->get(1);
536     if (!setPSPaperSize(tok->getCString())) {
537       error(-1, "Bad 'psPaperSize' config file command (%s:%d)",
538             fileName->getCString(), line);
539     }
540   } else if (tokens->getLength() == 3) {
541     tok = (GString *)tokens->get(1);
542     psPaperWidth = atoi(tok->getCString());
543     tok = (GString *)tokens->get(2);
544     psPaperHeight = atoi(tok->getCString());
545   } else {
546     error(-1, "Bad 'psPaperSize' config file command (%s:%d)",
547           fileName->getCString(), line);
548   }
549 }
550
551 void GlobalParams::parsePSLevel(GList *tokens, GString *fileName, int line) {
552   GString *tok;
553
554   if (tokens->getLength() != 2) {
555     error(-1, "Bad 'psLevel' config file command (%s:%d)",
556           fileName->getCString(), line);
557     return;
558   }
559   tok = (GString *)tokens->get(1);
560   if (!tok->cmp("level1")) {
561     psLevel = psLevel1;
562   } else if (!tok->cmp("level1sep")) {
563     psLevel = psLevel1Sep;
564   } else if (!tok->cmp("level2")) {
565     psLevel = psLevel2;
566   } else if (!tok->cmp("level2sep")) {
567     psLevel = psLevel2Sep;
568   } else if (!tok->cmp("level3")) {
569     psLevel = psLevel3;
570   } else if (!tok->cmp("level3Sep")) {
571     psLevel = psLevel3Sep;
572   } else {
573     error(-1, "Bad 'psLevel' config file command (%s:%d)",
574           fileName->getCString(), line);
575   }
576 }
577
578 void GlobalParams::parsePSFile(GList *tokens, GString *fileName, int line) {
579   if (tokens->getLength() != 2) {
580     error(-1, "Bad 'psFile' config file command (%s:%d)",
581           fileName->getCString(), line);
582     return;
583   }
584   if (psFile) {
585     delete psFile;
586   }
587   psFile = ((GString *)tokens->get(1))->copy();
588 }
589
590 void GlobalParams::parsePSFont(GList *tokens, GString *fileName, int line) {
591   PSFontParam *param;
592
593   if (tokens->getLength() != 3) {
594     error(-1, "Bad 'psFont' config file command (%s:%d)",
595           fileName->getCString(), line);
596     return;
597   }
598   param = new PSFontParam(((GString *)tokens->get(1))->copy(), 0,
599                           ((GString *)tokens->get(2))->copy(), NULL);
600   psFonts->add(param->pdfFontName, param);
601 }
602
603 void GlobalParams::parsePSFont16(char *cmdName, GList *fontList,
604                                  GList *tokens, GString *fileName, int line) {
605   PSFontParam *param;
606   int wMode;
607   GString *tok;
608
609   if (tokens->getLength() != 5) {
610     error(-1, "Bad '%s' config file command (%s:%d)",
611           cmdName, fileName->getCString(), line);
612     return;
613   }
614   tok = (GString *)tokens->get(2);
615   if (!tok->cmp("H")) {
616     wMode = 0;
617   } else if (!tok->cmp("V")) {
618     wMode = 1;
619   } else {
620     error(-1, "Bad '%s' config file command (%s:%d)",
621           cmdName, fileName->getCString(), line);
622     return;
623   }
624   param = new PSFontParam(((GString *)tokens->get(1))->copy(),
625                           wMode,
626                           ((GString *)tokens->get(3))->copy(),
627                           ((GString *)tokens->get(4))->copy());
628   fontList->append(param);
629 }
630
631 void GlobalParams::parseTextEncoding(GList *tokens, GString *fileName,
632                                      int line) {
633   if (tokens->getLength() != 2) {
634     error(-1, "Bad 'textEncoding' config file command (%s:%d)",
635           fileName->getCString(), line);
636     return;
637   }
638   delete textEncoding;
639   textEncoding = ((GString *)tokens->get(1))->copy();
640 }
641
642 void GlobalParams::parseTextEOL(GList *tokens, GString *fileName, int line) {
643   GString *tok;
644
645   if (tokens->getLength() != 2) {
646     error(-1, "Bad 'textEOL' config file command (%s:%d)",
647           fileName->getCString(), line);
648     return;
649   }
650   tok = (GString *)tokens->get(1);
651   if (!tok->cmp("unix")) {
652     textEOL = eolUnix;
653   } else if (!tok->cmp("dos")) {
654     textEOL = eolDOS;
655   } else if (!tok->cmp("mac")) {
656     textEOL = eolMac;
657   } else {
658     error(-1, "Bad 'textEOL' config file command (%s:%d)",
659           fileName->getCString(), line);
660   }
661 }
662
663 void GlobalParams::parseFontDir(GList *tokens, GString *fileName, int line) {
664   if (tokens->getLength() != 2) {
665     error(-1, "Bad 'fontDir' config file command (%s:%d)",
666           fileName->getCString(), line);
667     return;
668   }
669   fontDirs->append(((GString *)tokens->get(1))->copy());
670 }
671
672 void GlobalParams::parseInitialZoom(GList *tokens,
673                                     GString *fileName, int line) {
674   if (tokens->getLength() != 2) {
675     error(-1, "Bad 'initialZoom' config file command (%s:%d)",
676           fileName->getCString(), line);
677     return;
678   }
679   delete initialZoom;
680   initialZoom = ((GString *)tokens->get(1))->copy();
681 }
682
683 void GlobalParams::parseFontRastControl(char *cmdName, FontRastControl *val,
684                                         GList *tokens, GString *fileName,
685                                         int line) {
686   GString *tok;
687
688   if (tokens->getLength() != 2) {
689     error(-1, "Bad '%s' config file command (%s:%d)",
690           cmdName, fileName->getCString(), line);
691     return;
692   }
693   tok = (GString *)tokens->get(1);
694   if (!setFontRastControl(val, tok->getCString())) {
695     error(-1, "Bad '%s' config file command (%s:%d)",
696           cmdName, fileName->getCString(), line);
697   }
698 }
699
700 void GlobalParams::parseURLCommand(GList *tokens, GString *fileName,
701                                    int line) {
702   if (tokens->getLength() != 2) {
703     error(-1, "Bad 'urlCommand' config file command (%s:%d)",
704           fileName->getCString(), line);
705     return;
706   }
707   if (urlCommand) {
708     delete urlCommand;
709   }
710   urlCommand = ((GString *)tokens->get(1))->copy();
711 }
712
713 void GlobalParams::parseYesNo(char *cmdName, GBool *flag,
714                               GList *tokens, GString *fileName, int line) {
715   GString *tok;
716
717   if (tokens->getLength() != 2) {
718     error(-1, "Bad '%s' config file command (%s:%d)",
719           cmdName, fileName->getCString(), line);
720     return;
721   }
722   tok = (GString *)tokens->get(1);
723   if (!tok->cmp("yes")) {
724     *flag = gTrue;
725   } else if (!tok->cmp("no")) {
726     *flag = gFalse;
727   } else {
728     error(-1, "Bad '%s' config file command (%s:%d)",
729           cmdName, fileName->getCString(), line);
730   }
731 }
732
733 GlobalParams::~GlobalParams() {
734   GHashIter *iter;
735   GString *key;
736   GList *list;
737
738   freeBuiltinFontTables();
739
740   delete macRomanReverseMap;
741
742   delete nameToUnicode;
743   deleteGHash(cidToUnicodes, GString);
744   deleteGHash(residentUnicodeMaps, UnicodeMap);
745   deleteGHash(unicodeMaps, GString);
746   deleteGList(toUnicodeDirs, GString);
747   deleteGHash(displayFonts, DisplayFontParam);
748   deleteGHash(displayCIDFonts, DisplayFontParam);
749   deleteGHash(displayNamedCIDFonts, DisplayFontParam);
750   if (psFile) {
751     delete psFile;
752   }
753   deleteGHash(psFonts, PSFontParam);
754   deleteGList(psNamedFonts16, PSFontParam);
755   deleteGList(psFonts16, PSFontParam);
756   delete textEncoding;
757   deleteGList(fontDirs, GString);
758   delete initialZoom;
759   if (urlCommand) {
760     delete urlCommand;
761   }
762
763   cMapDirs->startIter(&iter);
764   while (cMapDirs->getNext(&iter, &key, (void **)&list)) {
765     deleteGList(list, GString);
766   }
767   delete cMapDirs;
768
769   delete cidToUnicodeCache;
770   delete unicodeMapCache;
771   delete cMapCache;
772 }
773
774 //------------------------------------------------------------------------
775 // accessors
776 //------------------------------------------------------------------------
777
778 CharCode GlobalParams::getMacRomanCharCode(char *charName) {
779   return macRomanReverseMap->lookup(charName);
780 }
781
782 Unicode GlobalParams::mapNameToUnicode(char *charName) {
783   return nameToUnicode->lookup(charName);
784 }
785
786 FILE *GlobalParams::getCIDToUnicodeFile(GString *collection) {
787   GString *fileName;
788
789   if (!(fileName = (GString *)cidToUnicodes->lookup(collection))) {
790     return NULL;
791   }
792   return fopen(fileName->getCString(), "r");
793 }
794
795 UnicodeMap *GlobalParams::getResidentUnicodeMap(GString *encodingName) {
796   return (UnicodeMap *)residentUnicodeMaps->lookup(encodingName);
797 }
798
799 FILE *GlobalParams::getUnicodeMapFile(GString *encodingName) {
800   GString *fileName;
801
802   if (!(fileName = (GString *)unicodeMaps->lookup(encodingName))) {
803     return NULL;
804   }
805   return fopen(fileName->getCString(), "r");
806 }
807
808 FILE *GlobalParams::findCMapFile(GString *collection, GString *cMapName) {
809   GList *list;
810   GString *dir;
811   GString *fileName;
812   FILE *f;
813   int i;
814
815   if (!(list = (GList *)cMapDirs->lookup(collection))) {
816     return NULL;
817   }
818   for (i = 0; i < list->getLength(); ++i) {
819     dir = (GString *)list->get(i);
820     fileName = appendToPath(dir->copy(), cMapName->getCString());
821     f = fopen(fileName->getCString(), "r");
822     delete fileName;
823     if (f) {
824       return f;
825     }
826   }
827   return NULL;
828 }
829
830 FILE *GlobalParams::findToUnicodeFile(GString *name) {
831   GString *dir, *fileName;
832   FILE *f;
833   int i;
834
835   for (i = 0; i < toUnicodeDirs->getLength(); ++i) {
836     dir = (GString *)toUnicodeDirs->get(i);
837     fileName = appendToPath(dir->copy(), name->getCString());
838     f = fopen(fileName->getCString(), "r");
839     delete fileName;
840     if (f) {
841       return f;
842     }
843   }
844   return NULL;
845 }
846
847 DisplayFontParam *GlobalParams::getDisplayFont(GString *fontName) {
848   return (DisplayFontParam *)displayFonts->lookup(fontName);
849 }
850
851 DisplayFontParam *GlobalParams::getDisplayCIDFont(GString *fontName,
852                                                   GString *collection) {
853   DisplayFontParam *dfp;
854
855   if (!fontName ||
856       !(dfp = (DisplayFontParam *)displayNamedCIDFonts->lookup(fontName))) {
857     dfp = (DisplayFontParam *)displayCIDFonts->lookup(collection);
858   }
859   return dfp;
860 }
861
862 PSFontParam *GlobalParams::getPSFont(GString *fontName) {
863   return (PSFontParam *)psFonts->lookup(fontName);
864 }
865
866 PSFontParam *GlobalParams::getPSFont16(GString *fontName,
867                                        GString *collection, int wMode) {
868   PSFontParam *p;
869   int i;
870
871   p = NULL;
872   if (fontName) {
873     for (i = 0; i < psNamedFonts16->getLength(); ++i) {
874       p = (PSFontParam *)psNamedFonts16->get(i);
875       if (!p->pdfFontName->cmp(fontName) &&
876           p->wMode == wMode) {
877         break;
878       }
879       p = NULL;
880     }
881   }
882   if (!p && collection) {
883     for (i = 0; i < psFonts16->getLength(); ++i) {
884       p = (PSFontParam *)psFonts16->get(i);
885       if (!p->pdfFontName->cmp(collection) &&
886           p->wMode == wMode) {
887         break;
888       }
889       p = NULL;
890     }
891   }
892   return p;
893 }
894
895 GString *GlobalParams::findFontFile(GString *fontName,
896                                     char *ext1, char *ext2) {
897   GString *dir, *fileName;
898   FILE *f;
899   int i;
900
901   for (i = 0; i < fontDirs->getLength(); ++i) {
902     dir = (GString *)fontDirs->get(i);
903     if (ext1) {
904       fileName = appendToPath(dir->copy(), fontName->getCString());
905       fileName->append(ext1);
906       if ((f = fopen(fileName->getCString(), "r"))) {
907         fclose(f);
908         return fileName;
909       }
910       delete fileName;
911     }
912     if (ext2) {
913       fileName = appendToPath(dir->copy(), fontName->getCString());
914       fileName->append(ext2);
915       if ((f = fopen(fileName->getCString(), "r"))) {
916         fclose(f);
917         return fileName;
918       }
919       delete fileName;
920     }
921   }
922   return NULL;
923 }
924
925 CharCodeToUnicode *GlobalParams::getCIDToUnicode(GString *collection) {
926   return cidToUnicodeCache->getCIDToUnicode(collection);
927 }
928
929 UnicodeMap *GlobalParams::getUnicodeMap(GString *encodingName) {
930   UnicodeMap *map;
931
932   if ((map = getResidentUnicodeMap(encodingName))) {
933     map->incRefCnt();
934     return map;
935   }
936   return unicodeMapCache->getUnicodeMap(encodingName);
937 }
938
939 CMap *GlobalParams::getCMap(GString *collection, GString *cMapName) {
940   return cMapCache->getCMap(collection, cMapName);
941 }
942
943 UnicodeMap *GlobalParams::getTextEncoding() {
944   return getUnicodeMap(textEncoding);
945 }
946
947 //------------------------------------------------------------------------
948 // functions to set parameters
949 //------------------------------------------------------------------------
950
951 void GlobalParams::setPSFile(char *file) {
952   if (psFile) {
953     delete psFile;
954   }
955   psFile = new GString(file);
956 }
957
958 GBool GlobalParams::setPSPaperSize(char *size) {
959   if (!strcmp(size, "letter")) {
960     psPaperWidth = 612;
961     psPaperHeight = 792;
962   } else if (!strcmp(size, "legal")) {
963     psPaperWidth = 612;
964     psPaperHeight = 1008;
965   } else if (!strcmp(size, "A4")) {
966     psPaperWidth = 595;
967     psPaperHeight = 842;
968   } else if (!strcmp(size, "A3")) {
969     psPaperWidth = 842;
970     psPaperHeight = 1190;
971   } else {
972     return gFalse;
973   }
974   return gTrue;
975 }
976
977 void GlobalParams::setPSPaperWidth(int width) {
978   psPaperWidth = width;
979 }
980
981 void GlobalParams::setPSPaperHeight(int height) {
982   psPaperHeight = height;
983 }
984
985 void GlobalParams::setPSDuplex(GBool duplex) {
986   psDuplex = duplex;
987 }
988
989 void GlobalParams::setPSLevel(PSLevel level) {
990   psLevel = level;
991 }
992
993 void GlobalParams::setPSEmbedType1(GBool embed) {
994   psEmbedType1 = embed;
995 }
996
997 void GlobalParams::setPSEmbedTrueType(GBool embed) {
998   psEmbedTrueType = embed;
999 }
1000
1001 void GlobalParams::setPSEmbedCIDPostScript(GBool embed) {
1002   psEmbedCIDPostScript = embed;
1003 }
1004
1005 void GlobalParams::setPSEmbedCIDTrueType(GBool embed) {
1006   psEmbedCIDTrueType = embed;
1007 }
1008
1009 void GlobalParams::setPSOPI(GBool opi) {
1010   psOPI = opi;
1011 }
1012
1013 void GlobalParams::setPSASCIIHex(GBool hex) {
1014   psASCIIHex = hex;
1015 }
1016
1017 void GlobalParams::setTextEncoding(char *encodingName) {
1018   delete textEncoding;
1019   textEncoding = new GString(encodingName);
1020 }
1021
1022 GBool GlobalParams::setTextEOL(char *s) {
1023   if (!strcmp(s, "unix")) {
1024     textEOL = eolUnix;
1025   } else if (!strcmp(s, "dos")) {
1026     textEOL = eolDOS;
1027   } else if (!strcmp(s, "mac")) {
1028     textEOL = eolMac;
1029   } else {
1030     return gFalse;
1031   }
1032   return gTrue;
1033 }
1034
1035 void GlobalParams::setInitialZoom(char *s) {
1036   delete initialZoom;
1037   initialZoom = new GString(s);
1038 }
1039
1040 GBool GlobalParams::setT1libControl(char *s) {
1041   return setFontRastControl(&t1libControl, s);
1042 }
1043
1044 GBool GlobalParams::setFreeTypeControl(char *s) {
1045   return setFontRastControl(&freetypeControl, s);
1046 }
1047
1048 GBool GlobalParams::setFontRastControl(FontRastControl *val, char *s) {
1049   if (!strcmp(s, "none")) {
1050     *val = fontRastNone;
1051   } else if (!strcmp(s, "plain")) {
1052     *val = fontRastPlain;
1053   } else if (!strcmp(s, "low")) {
1054     *val = fontRastAALow;
1055   } else if (!strcmp(s, "high")) {
1056     *val = fontRastAAHigh;
1057   } else {
1058     return gFalse;
1059   }
1060   return gTrue;
1061 }
1062
1063 void GlobalParams::setErrQuiet(GBool errQuietA) {
1064   errQuiet = errQuietA;
1065 }