#include <string.h>
#include <stdio.h>
#include <ctype.h>
+#ifdef ENABLE_PLUGINS
+# ifndef WIN32
+# include <dlfcn.h>
+# endif
+#endif
+#ifdef WIN32
+# include <shlobj.h>
+#endif
#if HAVE_PAPER_H
#include <paper.h>
#endif
#include "CMap.h"
#include "BuiltinFontTables.h"
#include "FontEncodingTables.h"
+#ifdef ENABLE_PLUGINS
+# include "XpdfPluginAPI.h"
+#endif
#include "GlobalParams.h"
#if MULTITHREADED
#include "UnicodeMapTables.h"
#include "UTF8.h"
+#ifdef ENABLE_PLUGINS
+# ifdef WIN32
+extern XpdfPluginVecTable xpdfPluginVecTable;
+# endif
+#endif
+
//------------------------------------------------------------------------
#define cidToUnicodeCacheSize 4
static struct {
char *name;
- char *fileName;
+ char *t1FileName;
+ char *ttFileName;
} displayFontTab[] = {
- {"Courier", "n022003l.pfb"},
- {"Courier-Bold", "n022004l.pfb"},
- {"Courier-BoldOblique", "n022024l.pfb"},
- {"Courier-Oblique", "n022023l.pfb"},
- {"Helvetica", "n019003l.pfb"},
- {"Helvetica-Bold", "n019004l.pfb"},
- {"Helvetica-BoldOblique", "n019024l.pfb"},
- {"Helvetica-Oblique", "n019023l.pfb"},
- {"Symbol", "s050000l.pfb"},
- {"Times-Bold", "n021004l.pfb"},
- {"Times-BoldItalic", "n021024l.pfb"},
- {"Times-Italic", "n021023l.pfb"},
- {"Times-Roman", "n021003l.pfb"},
- {"ZapfDingbats", "d050000l.pfb"},
+ {"Courier", "n022003l.pfb", "cour.ttf"},
+ {"Courier-Bold", "n022004l.pfb", "courbd.ttf"},
+ {"Courier-BoldOblique", "n022024l.pfb", "courbi.ttf"},
+ {"Courier-Oblique", "n022023l.pfb", "couri.ttf"},
+ {"Helvetica", "n019003l.pfb", "arial.ttf"},
+ {"Helvetica-Bold", "n019004l.pfb", "arialbd.ttf"},
+ {"Helvetica-BoldOblique", "n019024l.pfb", "arialbi.ttf"},
+ {"Helvetica-Oblique", "n019023l.pfb", "ariali.ttf"},
+ {"Symbol", "s050000l.pfb", NULL},
+ {"Times-Bold", "n021004l.pfb", "timesbd.ttf"},
+ {"Times-BoldItalic", "n021024l.pfb", "timesbi.ttf"},
+ {"Times-Italic", "n021023l.pfb", "timesi.ttf"},
+ {"Times-Roman", "n021003l.pfb", "times.ttf"},
+ {"ZapfDingbats", "d050000l.pfb", NULL},
{NULL}
};
+#ifdef WIN32
+static char *displayFontDirs[] = {
+ "c:/windows/fonts",
+ "c:/winnt/fonts",
+ NULL
+};
+#else
static char *displayFontDirs[] = {
"/usr/share/ghostscript/fonts",
"/usr/local/share/ghostscript/fonts",
"/usr/share/fonts/default/Type1",
+ "/usr/share/fonts/default/ghostscript",
+ "/usr/share/fonts/type1/gsfonts",
NULL
};
+#endif
//------------------------------------------------------------------------
}
}
+#ifdef ENABLE_PLUGINS
+//------------------------------------------------------------------------
+// Plugin
+//------------------------------------------------------------------------
+
+class Plugin {
+public:
+
+ static Plugin *load(char *type, char *name);
+ ~Plugin();
+
+private:
+
+#ifdef WIN32
+ Plugin(HMODULE libA);
+ HMODULE lib;
+#else
+ Plugin(void *dlA);
+ void *dl;
+#endif
+};
+
+Plugin *Plugin::load(char *type, char *name) {
+ GString *path;
+ Plugin *plugin;
+ XpdfPluginVecTable *vt;
+ XpdfBool (*xpdfInitPlugin)(void);
+#ifdef WIN32
+ HMODULE libA;
+#else
+ void *dlA;
+#endif
+
+ path = globalParams->getBaseDir();
+ appendToPath(path, "plugins");
+ appendToPath(path, type);
+ appendToPath(path, name);
+
+#ifdef WIN32
+ path->append(".dll");
+ if (!(libA = LoadLibrary(path->getCString()))) {
+ error(-1, "Failed to load plugin '%s'",
+ path->getCString());
+ goto err1;
+ }
+ if (!(vt = (XpdfPluginVecTable *)
+ GetProcAddress(libA, "xpdfPluginVecTable"))) {
+ error(-1, "Failed to find xpdfPluginVecTable in plugin '%s'",
+ path->getCString());
+ goto err2;
+ }
+#else
+ //~ need to deal with other extensions here
+ path->append(".so");
+ if (!(dlA = dlopen(path->getCString(), RTLD_NOW))) {
+ error(-1, "Failed to load plugin '%s': %s",
+ path->getCString(), dlerror());
+ goto err1;
+ }
+ if (!(vt = (XpdfPluginVecTable *)dlsym(dlA, "xpdfPluginVecTable"))) {
+ error(-1, "Failed to find xpdfPluginVecTable in plugin '%s'",
+ path->getCString());
+ goto err2;
+ }
+#endif
+
+ if (vt->version != xpdfPluginVecTable.version) {
+ error(-1, "Plugin '%s' is wrong version", path->getCString());
+ goto err2;
+ }
+ memcpy(vt, &xpdfPluginVecTable, sizeof(xpdfPluginVecTable));
+
+#ifdef WIN32
+ if (!(xpdfInitPlugin = (XpdfBool (*)(void))
+ GetProcAddress(libA, "xpdfInitPlugin"))) {
+ error(-1, "Failed to find xpdfInitPlugin in plugin '%s'",
+ path->getCString());
+ goto err2;
+ }
+#else
+ if (!(xpdfInitPlugin = (XpdfBool (*)(void))dlsym(dlA, "xpdfInitPlugin"))) {
+ error(-1, "Failed to find xpdfInitPlugin in plugin '%s'",
+ path->getCString());
+ goto err2;
+ }
+#endif
+
+ if (!(*xpdfInitPlugin)()) {
+ error(-1, "Initialization of plugin '%s' failed",
+ path->getCString());
+ goto err2;
+ }
+
+#ifdef WIN32
+ plugin = new Plugin(libA);
+#else
+ plugin = new Plugin(dlA);
+#endif
+
+ delete path;
+ return plugin;
+
+ err2:
+#ifdef WIN32
+ FreeLibrary(libA);
+#else
+ dlclose(dlA);
+#endif
+ err1:
+ delete path;
+ return NULL;
+}
+
+#ifdef WIN32
+Plugin::Plugin(HMODULE libA) {
+ lib = libA;
+}
+#else
+Plugin::Plugin(void *dlA) {
+ dl = dlA;
+}
+#endif
+
+Plugin::~Plugin() {
+ void (*xpdfFreePlugin)(void);
+
+#ifdef WIN32
+ if ((xpdfFreePlugin = (void (*)(void))
+ GetProcAddress(lib, "xpdfFreePlugin"))) {
+ (*xpdfFreePlugin)();
+ }
+ FreeLibrary(lib);
+#else
+ if ((xpdfFreePlugin = (void (*)(void))dlsym(dl, "xpdfFreePlugin"))) {
+ (*xpdfFreePlugin)();
+ }
+ dlclose(dl);
+#endif
+}
+
+#endif // ENABLE_PLUGINS
+
//------------------------------------------------------------------------
// parsing
//------------------------------------------------------------------------
}
}
+#ifdef WIN32
+ // baseDir will be set by a call to setBaseDir
+ baseDir = new GString();
+#else
+ baseDir = appendToPath(getHomeDir(), ".xpdf");
+#endif
nameToUnicode = new NameToCharCode();
cidToUnicodes = new GHash(gTrue);
unicodeToUnicodes = new GHash(gTrue);
textKeepTinyChars = gFalse;
fontDirs = new GList();
initialZoom = new GString("125");
+ continuousView = gFalse;
enableT1lib = gTrue;
enableFreeType = gTrue;
antialias = gTrue;
unicodeMapCache = new UnicodeMapCache();
cMapCache = new CMapCache();
+#ifdef ENABLE_PLUGINS
+ plugins = new GList();
+ securityHandlers = new GList();
+#endif
+
// set up the initial nameToUnicode table
for (i = 0; nameToUnicodeTab[i].name; ++i) {
nameToUnicode->add(nameToUnicodeTab[i].name, nameToUnicodeTab[i].u);
char buf[512];
FILE *f2;
+ /* extract path */
+ if(fileName) {
+ char* cfgFileName = fileName->getCString();
+ char* pos1 = strrchr(cfgFileName, '/');
+ char* pos2 = strrchr(cfgFileName, '\\');
+ char* p = pos1>pos2?pos1:pos2;
+ int pos = p ? p-cfgFileName : -1;
+ GString*path = new GString(new GString(cfgFileName), 0, (pos < 0 ? strlen(cfgFileName): pos));
+ if(pos1>=0)
+ path->append('/');
+ else if(pos2>=0)
+ path->append('\\');
+ else
+#ifdef WIN32
+ path->append('\\');
+#else
+ path->append('/');
+#endif
+ this->path = path;
+ } else {
+ this->path = new GString();
+ }
+
line = 1;
while (getLine(buf, sizeof(buf) - 1, f)) {
parseFontDir(tokens, fileName, line);
} else if (!cmd->cmp("initialZoom")) {
parseInitialZoom(tokens, fileName, line);
+ } else if (!cmd->cmp("continuousView")) {
+ parseYesNo("continuousView", &continuousView, tokens, fileName, line);
} else if (!cmd->cmp("enableT1lib")) {
parseYesNo("enableT1lib", &enableT1lib, tokens, fileName, line);
} else if (!cmd->cmp("enableFreeType")) {
}
}
+static GString* qualify_filename(GString*path, GString*filename)
+{
+ GString*fullpath = 0;
+ char*prefix = "/usr/local/share/xpdf/";
+
+ if (filename->getChar(0) != '\\' && filename->getChar(0) != '/') {
+ /* relative path */
+ fullpath = path->copy();
+ fullpath->append(filename);
+ } else if (!strncmp(filename->getCString(), prefix, strlen(prefix))) {
+ /* xpdf default path */
+ char*s = strchr(filename->getCString()+strlen(prefix), '/');
+ if(s) {
+ fullpath = path->copy();
+ fullpath->append(s+1);
+ } else {
+ fullpath = filename->copy();
+ }
+ } else {
+ /* absolute path */
+ fullpath = filename->copy();
+ }
+ //printf("%s -%s-> %s\n", filename->getCString(), path->getCString(), fullpath->getCString());
+ return fullpath;
+}
+
void GlobalParams::parseNameToUnicode(GList *tokens, GString *fileName,
int line) {
GString *name;
fileName->getCString(), line);
return;
}
- name = (GString *)tokens->get(1);
+ name = qualify_filename(this->path, (GString *)tokens->get(1));
if (!(f = fopen(name->getCString(), "r"))) {
error(-1, "Couldn't open 'nameToUnicode' file '%s'",
name->getCString());
}
collection = (GString *)tokens->get(1);
name = (GString *)tokens->get(2);
+
if ((old = (GString *)cidToUnicodes->remove(collection))) {
delete old;
}
- cidToUnicodes->add(collection->copy(), name->copy());
+
+ cidToUnicodes->add(collection->copy(), qualify_filename(this->path, name));
}
void GlobalParams::parseUnicodeToUnicode(GList *tokens, GString *fileName,
if ((old = (GString *)unicodeToUnicodes->remove(font))) {
delete old;
}
- unicodeToUnicodes->add(font->copy(), file->copy());
+
+ unicodeToUnicodes->add(font->copy(), qualify_filename(this->path, file));
}
void GlobalParams::parseUnicodeMap(GList *tokens, GString *fileName,
if ((old = (GString *)unicodeMaps->remove(encodingName))) {
delete old;
}
- unicodeMaps->add(encodingName->copy(), name->copy());
+
+ unicodeMaps->add(encodingName->copy(), qualify_filename(this->path, name));
}
void GlobalParams::parseCMapDir(GList *tokens, GString *fileName, int line) {
list = new GList();
cMapDirs->add(collection->copy(), list);
}
- list->append(dir->copy());
+
+ list->append(qualify_filename(this->path, dir));
}
void GlobalParams::parseToUnicodeDir(GList *tokens, GString *fileName,
int line) {
+ GString *dir;
+
if (tokens->getLength() != 2) {
error(-1, "Bad 'toUnicodeDir' config file command (%s:%d)",
fileName->getCString(), line);
return;
}
- toUnicodeDirs->append(((GString *)tokens->get(1))->copy());
+
+ dir = (GString *)tokens->get(1);
+
+ toUnicodeDirs->append(qualify_filename(this->path, dir));
}
void GlobalParams::parseDisplayFont(GList *tokens, GHash *fontHash,
DisplayFontParamKind kind,
GString *fileName, int line) {
DisplayFontParam *param, *old;
+ GString *file;
if (tokens->getLength() < 2) {
goto err1;
if (tokens->getLength() != 3) {
goto err2;
}
- param->t1.fileName = ((GString *)tokens->get(2))->copy();
+ file = (GString *)tokens->get(2);
+ param->t1.fileName = qualify_filename(this->path, file);
break;
case displayFontTT:
if (tokens->getLength() != 3) {
goto err2;
}
- param->tt.fileName = ((GString *)tokens->get(2))->copy();
+ file = (GString *)tokens->get(2);
+ param->tt.fileName = qualify_filename(this->path, file);
break;
}
delete macRomanReverseMap;
+ delete baseDir;
delete nameToUnicode;
deleteGHash(cidToUnicodes, GString);
deleteGHash(unicodeToUnicodes, GString);
delete unicodeMapCache;
delete cMapCache;
+#ifdef ENABLE_PLUGINS
+ delete securityHandlers;
+ deleteGList(plugins, Plugin);
+#endif
+
#if MULTITHREADED
gDestroyMutex(&mutex);
gDestroyMutex(&unicodeMapCacheMutex);
//------------------------------------------------------------------------
+void GlobalParams::setBaseDir(char *dir) {
+ delete baseDir;
+ baseDir = new GString(dir);
+}
+
void GlobalParams::setupBaseFonts(char *dir) {
GString *fontName;
GString *fileName;
+#ifdef WIN32
+ HMODULE shell32Lib;
+ BOOL (__stdcall *SHGetSpecialFolderPathFunc)(HWND hwndOwner,
+ LPTSTR lpszPath,
+ int nFolder,
+ BOOL fCreate);
+ char winFontDir[MAX_PATH];
+#endif
FILE *f;
+ DisplayFontParamKind kind;
DisplayFontParam *dfp;
int i, j;
+#ifdef WIN32
+ // SHGetSpecialFolderPath isn't available in older versions of
+ // shell32.dll (Win95 and WinNT4), so do a dynamic load
+ winFontDir[0] = '\0';
+ if ((shell32Lib = LoadLibrary("shell32.dll"))) {
+ if ((SHGetSpecialFolderPathFunc =
+ (BOOL (__stdcall *)(HWND hwndOwner, LPTSTR lpszPath,
+ int nFolder, BOOL fCreate))
+ GetProcAddress(shell32Lib, "SHGetSpecialFolderPath"))) {
+ if (!(*SHGetSpecialFolderPathFunc)(NULL, winFontDir,
+ CSIDL_FONTS, FALSE)) {
+ winFontDir[0] = '\0';
+ }
+ }
+ }
+#endif
for (i = 0; displayFontTab[i].name; ++i) {
fontName = new GString(displayFontTab[i].name);
if (getDisplayFont(fontName)) {
continue;
}
fileName = NULL;
+ kind = displayFontT1; // make gcc happy
if (dir) {
- fileName = appendToPath(new GString(dir), displayFontTab[i].fileName);
+ fileName = appendToPath(new GString(dir), displayFontTab[i].t1FileName);
+ kind = displayFontT1;
+ if ((f = fopen(fileName->getCString(), "rb"))) {
+ fclose(f);
+ } else {
+ delete fileName;
+ fileName = NULL;
+ }
+ }
+#ifdef WIN32
+ if (!fileName && winFontDir[0] && displayFontTab[i].ttFileName) {
+ fileName = appendToPath(new GString(winFontDir),
+ displayFontTab[i].ttFileName);
+ kind = displayFontTT;
if ((f = fopen(fileName->getCString(), "rb"))) {
fclose(f);
} else {
fileName = NULL;
}
}
-#ifndef WIN32
+ // SHGetSpecialFolderPath(CSIDL_FONTS) doesn't work on Win 2k Server
+ // or Win2003 Server, or with older versions of shell32.dll, so check
+ // the "standard" directories
+ if (displayFontTab[i].ttFileName) {
+ for (j = 0; !fileName && displayFontDirs[j]; ++j) {
+ fileName = appendToPath(new GString(displayFontDirs[j]),
+ displayFontTab[i].ttFileName);
+ kind = displayFontTT;
+ if ((f = fopen(fileName->getCString(), "rb"))) {
+ fclose(f);
+ } else {
+ delete fileName;
+ fileName = NULL;
+ }
+ }
+ }
+#else
for (j = 0; !fileName && displayFontDirs[j]; ++j) {
fileName = appendToPath(new GString(displayFontDirs[j]),
- displayFontTab[i].fileName);
+ displayFontTab[i].t1FileName);
+ kind = displayFontT1;
if ((f = fopen(fileName->getCString(), "rb"))) {
fclose(f);
} else {
delete fontName;
continue;
}
- dfp = new DisplayFontParam(fontName, displayFontT1);
+ dfp = new DisplayFontParam(fontName, kind);
dfp->t1.fileName = fileName;
globalParams->addDisplayFont(dfp);
}
return macRomanReverseMap->lookup(charName);
}
+GString *GlobalParams::getBaseDir() {
+ GString *s;
+
+ lockGlobalParams;
+ s = baseDir->copy();
+ unlockGlobalParams;
+ return s;
+}
+
Unicode GlobalParams::mapNameToUnicode(char *charName) {
// no need to lock - nameToUnicode is constant
return nameToUnicode->lookup(charName);
return s;
}
+GBool GlobalParams::getContinuousView() {
+ GBool f;
+
+ lockGlobalParams;
+ f = continuousView;
+ unlockGlobalParams;
+ return f;
+}
+
GBool GlobalParams::getEnableT1lib() {
GBool f;
unlockGlobalParams;
}
+void GlobalParams::setContinuousView(GBool cont) {
+ lockGlobalParams;
+ continuousView = cont;
+ unlockGlobalParams;
+}
+
GBool GlobalParams::setEnableT1lib(char *s) {
GBool ok;
errQuiet = errQuietA;
unlockGlobalParams;
}
+
+void GlobalParams::addSecurityHandler(XpdfSecurityHandler *handler) {
+#ifdef ENABLE_PLUGINS
+ lockGlobalParams;
+ securityHandlers->append(handler);
+ unlockGlobalParams;
+#endif
+}
+
+XpdfSecurityHandler *GlobalParams::getSecurityHandler(char *name) {
+#ifdef ENABLE_PLUGINS
+ XpdfSecurityHandler *hdlr;
+ int i;
+
+ lockGlobalParams;
+ for (i = 0; i < securityHandlers->getLength(); ++i) {
+ hdlr = (XpdfSecurityHandler *)securityHandlers->get(i);
+ if (!stricmp(hdlr->name, name)) {
+ unlockGlobalParams;
+ return hdlr;
+ }
+ }
+ unlockGlobalParams;
+
+ if (!loadPlugin("security", name)) {
+ return NULL;
+ }
+
+ lockGlobalParams;
+ for (i = 0; i < securityHandlers->getLength(); ++i) {
+ hdlr = (XpdfSecurityHandler *)securityHandlers->get(i);
+ if (!strcmp(hdlr->name, name)) {
+ unlockGlobalParams;
+ return hdlr;
+ }
+ }
+ unlockGlobalParams;
+#endif
+
+ return NULL;
+}
+
+#ifdef ENABLE_PLUGINS
+//------------------------------------------------------------------------
+// plugins
+//------------------------------------------------------------------------
+
+GBool GlobalParams::loadPlugin(char *type, char *name) {
+ Plugin *plugin;
+
+ if (!(plugin = Plugin::load(type, name))) {
+ return gFalse;
+ }
+ lockGlobalParams;
+ plugins->append(plugin);
+ unlockGlobalParams;
+ return gTrue;
+}
+
+#endif // ENABLE_PLUGINS