summaryrefslogtreecommitdiff
path: root/src/pdflib/pdcore/pc_resource.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pdflib/pdcore/pc_resource.c')
-rw-r--r--src/pdflib/pdcore/pc_resource.c1906
1 files changed, 1906 insertions, 0 deletions
diff --git a/src/pdflib/pdcore/pc_resource.c b/src/pdflib/pdcore/pc_resource.c
new file mode 100644
index 0000000..727df4e
--- /dev/null
+++ b/src/pdflib/pdcore/pc_resource.c
@@ -0,0 +1,1906 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_resource.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * Resource routines
+ *
+ */
+
+#define PC_RESOURCE_C
+
+#include <errno.h>
+
+#include "pc_util.h"
+#include "pc_file.h"
+#include "pc_resource.h"
+#include "pc_ctype.h"
+
+#if defined(WIN32)
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+
+/* -------------------------- resource handling ----------------------------- */
+
+struct pdc_res_s
+{
+ char *name;
+ char *value;
+ pdc_res *prev;
+ pdc_res *next;
+};
+
+struct pdc_category_s
+{
+ char *category;
+ pdc_res *kids;
+ pdc_category *next;
+};
+
+struct pdc_reslist_s
+{
+ pdc_category *resources; /* anchor for the category resource list */
+ pdc_bool filepending; /* to read resource file is pending */
+ char *filename; /* name of the resource file */
+};
+
+typedef enum
+{
+ pdc_FontOutline,
+ pdc_FontAFM,
+ pdc_FontPFM,
+ pdc_HostFont,
+ pdc_Encoding,
+ pdc_ICCProfile,
+ pdc_StandardOutputIntent,
+ pdc_SearchPath,
+ pdc_CMap,
+ pdc_GlyphList,
+ pdc_CodeList
+}
+pdc_rescategory;
+
+static const pdc_keyconn pdc_rescategories[] =
+{
+ {"FontOutline", pdc_FontOutline},
+ {"FontAFM", pdc_FontAFM},
+ {"FontPFM", pdc_FontPFM},
+ {"HostFont", pdc_HostFont},
+ {"Encoding", pdc_Encoding},
+ {"ICCProfile", pdc_ICCProfile},
+ {"StandardOutputIntent", pdc_StandardOutputIntent},
+ {"SearchPath", pdc_SearchPath},
+ {"CMap", pdc_CMap},
+ {"GlyphList", pdc_GlyphList},
+ {"CodeList", pdc_CodeList},
+ {NULL, 0}
+};
+
+#define RESOURCEFILEENVNAME "%sRESOURCEFILE"
+
+#ifndef MVS
+#define DEFAULTRESOURCEFILE "%s.upr"
+#else
+#define DEFAULTRESOURCEFILE "upr"
+#endif
+
+#ifdef WIN32
+#define REGISTRYKEY "Software\\PDFlib\\%s\\%s"
+#endif
+
+pdc_reslist *
+pdc_new_reslist(pdc_core *pdc)
+{
+ static const char fn[] = "pdc_new_reslist";
+
+ pdc_reslist *resl = (pdc_reslist *) pdc_malloc(pdc, sizeof(pdc_reslist),fn);
+
+ resl->resources = NULL;
+ resl->filepending = pdc_true;
+ resl->filename = NULL;
+
+ pdc->reslist = resl;
+
+ return resl;
+}
+
+static pdc_category *
+pdc_delete_rescategory(pdc_core *pdc, pdc_category *prevcat, pdc_category *cat,
+ pdc_bool empty)
+{
+ pdc_category *nextcat;
+ pdc_res *res, *lastres;
+
+ for (res = cat->kids; res != NULL; /* */)
+ {
+ lastres = res;
+ res = lastres->next;
+ pdc_free(pdc, lastres->name);
+ lastres->name = NULL;
+ if (lastres->value)
+ {
+ pdc_free(pdc, lastres->value);
+ lastres->value = NULL;
+ }
+ pdc_free(pdc, lastres);
+ }
+ nextcat = cat->next;
+
+ if (empty)
+ {
+ cat->kids = NULL;
+ }
+ else
+ {
+ pdc_free(pdc, cat->category);
+ cat->category = NULL;
+ pdc_free(pdc, cat);
+ cat = NULL;
+
+ if (prevcat != NULL)
+ {
+ pdc_reslist *resl = pdc->reslist;
+
+ if (prevcat != cat)
+ prevcat->next = nextcat;
+ else
+ resl->resources = nextcat;
+ }
+ }
+
+ return nextcat;
+}
+
+void
+pdc_delete_reslist(pdc_core *pdc)
+{
+ pdc_reslist *resl = pdc->reslist;
+
+ if (resl != NULL)
+ {
+ pdc_category *cat;
+
+ for (cat = resl->resources; cat != NULL; /* */)
+ cat = pdc_delete_rescategory(pdc, NULL, cat, pdc_false);
+
+ if (resl->filename)
+ pdc_free(pdc, resl->filename);
+
+ pdc_free(pdc, resl);
+ pdc->reslist = NULL;
+ }
+}
+
+static pdc_reslist *
+pdc_get_reslist(pdc_core *pdc)
+{
+ pdc_reslist *resl = pdc->reslist;
+
+ if (resl == NULL)
+ resl = pdc_new_reslist(pdc);
+
+ return resl;
+}
+
+void
+pdc_set_resourcefile(pdc_core *pdc, const char *filename)
+{
+ if (filename != NULL && *filename)
+ {
+ pdc_reslist *resl = pdc_get_reslist(pdc);
+
+ if (resl->filename)
+ pdc_free(pdc, resl->filename);
+
+ resl->filename = pdc_strdup(pdc, filename);
+ resl->filepending = pdc_true;
+ }
+}
+
+const char *
+pdc_get_resourcefile(pdc_core *pdc)
+{
+ pdc_reslist *resl = pdc_get_reslist(pdc);
+
+ return (resl->filename);
+}
+
+static void
+pdc_read_resourcefile(pdc_core *pdc, const char *filename)
+{
+ pdc_reslist *resl = pdc_get_reslist(pdc);
+ pdc_file *fp = NULL;
+ char **linelist;
+ char *line;
+ char *category = NULL;
+ char *uprfilename = NULL;
+ char tmpname[PDC_FILENAMELEN];
+#if defined(AS400) || defined(WIN32)
+#define BUFSIZE 2048
+ char buffer[BUFSIZE];
+#ifdef WIN32
+ char regkey[128];
+ HKEY hKey = NULL;
+ DWORD size, lType;
+#endif
+#endif
+ int il, nlines = 0, nextcat, begin;
+
+ pdc_logg_cond(pdc, 1, trc_resource,
+ "\n\tSearching for resource file...\n");
+
+#ifdef WIN32
+
+/* don't add patchlevel's to registry searchpath */
+#define stringiz1(x) #x
+#define stringiz(x) stringiz1(x)
+
+ sprintf(regkey, REGISTRYKEY, pdc->prodname, pdc->version);
+
+#endif /* WIN32 */
+
+#ifdef AS400
+ pdc_logg_cond(pdc, 1, trc_resource,
+ "\tSet AS400 default resources\n");
+ strcpy (buffer, "/pdflib/");
+ strcat (buffer, pdc->version);
+ il = (int) strlen(buffer);
+ strcat (buffer, "/fonts");
+ pdc_add_resource(pdc, "SearchPath", buffer, "");
+ strcpy(&buffer[il], "/bind/data");
+ pdc_add_resource(pdc, "SearchPath", buffer, "");
+#endif /* AS400 */
+
+#ifdef WIN32
+ /* process registry entries */
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, regkey, 0L,
+ (REGSAM) KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
+ {
+ pdc_logg_cond(pdc, 1, trc_resource,
+ "\tRead registry key \"%s\":\n", REGISTRYKEY);
+
+ size = BUFSIZE - 2;
+ if (RegQueryValueExA(hKey, "searchpath", (LPDWORD) NULL,
+ &lType, (LPBYTE) buffer, &size)
+ == ERROR_SUCCESS && *buffer)
+ {
+ char **pathlist;
+ int ip, np;
+
+ np = pdc_split_stringlist(pdc, buffer, ";", 0, &pathlist);
+ for (ip = 0; ip < np; ip++)
+ pdc_add_resource(pdc, "SearchPath", pathlist[ip], "");
+ pdc_cleanup_stringlist(pdc, pathlist);
+ }
+
+ RegCloseKey(hKey);
+ }
+#endif /* WIN32 */
+
+ /* searching for name of upr file */
+ uprfilename = (char *)filename;
+ if (uprfilename == NULL || *uprfilename == '\0')
+ {
+ /* upr file name via environment variable */
+ sprintf(tmpname, RESOURCEFILEENVNAME, pdc->prodname);
+ pdc_strtoupper(tmpname);
+ uprfilename = pdc_getenv(tmpname);
+
+#ifdef WIN32
+ /* registry upr file name */
+ if (uprfilename == NULL || *uprfilename == '\0')
+ {
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, regkey, 0L,
+ (REGSAM) KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
+ {
+ size = BUFSIZE - 2;
+ if (RegQueryValueExA(hKey, "resourcefile", (LPDWORD) NULL,
+ &lType, (LPBYTE) buffer, &size)
+ == ERROR_SUCCESS && *buffer)
+ {
+ uprfilename = buffer;
+ }
+
+ RegCloseKey(hKey);
+ }
+ }
+#endif /* WIN32 */
+
+ /* default upr file name */
+ if (uprfilename == NULL || *uprfilename == '\0')
+ {
+ sprintf(tmpname, DEFAULTRESOURCEFILE, pdc->prodname);
+ uprfilename = pdc_strtolower(tmpname);
+
+ /* user-supplied upr file */
+ fp = pdc_fsearch_fopen(pdc, uprfilename, NULL, NULL, 0);
+ if (fp == NULL)
+ {
+ uprfilename = NULL;
+ }
+ }
+ }
+
+ if (uprfilename != NULL && *uprfilename != '\0')
+ {
+ char *resfilename = resl->filename;
+
+ pdc_logg_cond(pdc, 1, trc_resource,
+ "\tRead resource file \"%s\":\n", uprfilename);
+
+ resl->filename = pdc_strdup(pdc, uprfilename);
+ if (resfilename)
+ pdc_free(pdc, resfilename);
+
+ /* read upr file */
+ if (fp == NULL)
+ {
+ fp = pdc_fsearch_fopen(pdc, resl->filename, NULL, "UPR ",
+ PDC_FILE_TEXT);
+ if (fp == NULL)
+ pdc_error(pdc, -1, 0, 0, 0, 0);
+ }
+
+ nlines = pdc_read_textfile(pdc, fp, 0, &linelist);
+ pdc_fclose(fp);
+
+ if (nlines)
+ {
+ /* Lines loop */
+ begin = 1;
+ nextcat = 0;
+ for (il = 0; il < nlines; il++)
+ {
+ line = linelist[il];
+
+ /* Next category */
+ if (line[0] == '.' && strlen(line) == 1)
+ {
+ begin = 0;
+ nextcat = 1;
+ continue;
+ }
+
+ /* Skip category list */
+ if (begin) continue;
+
+ /* Category expected */
+ if (nextcat)
+ {
+ /* Ressource Category */
+ category = line;
+ nextcat = 0;
+ continue;
+ }
+
+ /* Add resource */
+ if (strlen(line))
+ pdc_add_resource(pdc, category, line, NULL);
+ }
+
+ pdc_cleanup_stringlist(pdc, linelist);
+ }
+ }
+}
+
+/*
+ * pdc_add_resource_ext add a new resource to the resource data base
+ * for specified resource category.
+ *
+ * resvalue == NULL:
+ * resname string has the format "resname [= resvalue]"
+ * Then string splitting has to be performed.
+ * [EBCDIC-]UTF-8 must be specified by a BOM: resname = resvalue
+ *
+ * Otherwise resname and resvalue are [EBCDIC-]UTF-8 encoded.
+ *
+ */
+void
+pdc_add_resource_ext(pdc_core *pdc, const char *category, const char *resname,
+ const char *resvalue, pdc_encoding enc, int codepage)
+{
+ static const char fn[] = "pdc_add_resource";
+ pdc_reslist *resl = pdc_get_reslist(pdc);
+ pdc_rescategory rescat;
+ pdc_category *cat = NULL, *lastcat = NULL;
+ pdc_res *res = NULL, *lastres = NULL;
+ char *resnamutf8 = NULL;
+ char *resvalutf8 = NULL;
+ int resnamflags = PDC_CONV_EBCDIC;
+ int resvalflags = PDC_CONV_EBCDIC;
+ int k;
+
+ if (!resvalue || !strlen(resvalue))
+ pdc_logg_cond(pdc, 1, trc_resource,
+ "\tAdd \"%s\" to resource category \"%s\"\n", resname, category);
+ else
+ pdc_logg_cond(pdc, 1, trc_resource,
+ "\tAdd \"%s=%s\" to resource category \"%s\"\n",
+ resname, resvalue, category);
+
+ /* We no longer raise an error but silently ignore unknown categories */
+ k = pdc_get_keycode_ci(category, pdc_rescategories);
+ if (k == PDC_KEY_NOTFOUND)
+ {
+ pdc_warning(pdc, PDC_E_RES_BADCAT, category, 0, 0, 0);
+ return;
+ }
+ rescat = (pdc_rescategory) k;
+
+ /* Read resource configuration file if it is pending */
+ if (resl->filepending)
+ {
+ resl->filepending = pdc_false;
+ pdc_read_resourcefile(pdc, resl->filename);
+ }
+
+ /* Find start of this category's resource list, if the category exists */
+ lastcat = resl->resources;
+ for (cat = lastcat; cat != NULL; cat = cat->next)
+ {
+ if (!pdc_stricmp(cat->category, category))
+ break;
+ lastcat = cat;
+ }
+ if (cat == NULL)
+ {
+ cat = (pdc_category *) pdc_malloc(pdc, sizeof(pdc_category), fn);
+ cat->category = pdc_strdup(pdc, category);
+ cat->kids = NULL;
+ cat->next = NULL;
+ if (lastcat != NULL)
+ lastcat->next = cat;
+ else
+ resl->resources = cat;
+ }
+
+ /* resvalue */
+ if (resvalue == NULL)
+ {
+ char **strlist = NULL;
+
+ /* splitting of resname string */
+ int ns = pdc_split_stringlist(pdc, resname, "=", 0, &strlist);
+
+ if (ns >= 1)
+ pdc_str2trim(strlist[0]);
+ if (ns == 2)
+ pdc_str2trim(strlist[1]);
+ if (ns > 2 ||
+ (rescat != pdc_SearchPath && (ns == 0 || !strlen(strlist[0]))))
+ {
+ pdc_cleanup_stringlist(pdc, strlist);
+ pdc_error(pdc, PDC_E_RES_BADRES, resname, category, 0, 0);
+ }
+
+ /* resource name */
+ if (ns > 0)
+ {
+ if (pdc_is_utf8_bytecode(resname))
+ resnamflags |= PDC_CONV_ISUTF8;
+ resnamutf8 = pdc_convert_name_ext(pdc, strlist[0], 0,
+ enc, codepage, resnamflags);
+ }
+
+ /* resource value */
+ if (ns == 2)
+ {
+ resvalflags = resnamflags;
+ resvalutf8 = pdc_convert_name_ext(pdc, strlist[1], 0,
+ enc, codepage, resvalflags);
+ }
+ else
+ {
+ resvalutf8 = pdc_strdup(pdc, "");
+ }
+ pdc_cleanup_stringlist(pdc, strlist);
+ }
+ else
+ {
+ resnamflags |= PDC_CONV_ISUTF8;
+ resnamutf8 = pdc_convert_name_ext(pdc, resname, 0,
+ enc, codepage, resnamflags);
+
+ resvalflags |= PDC_CONV_ISUTF8;
+ resvalutf8 = pdc_convert_name_ext(pdc, resvalue, 0,
+ enc, codepage, resvalflags);
+ }
+
+ switch (rescat)
+ {
+ case pdc_FontOutline:
+ case pdc_FontAFM:
+ case pdc_FontPFM:
+ case pdc_HostFont:
+ case pdc_Encoding:
+ case pdc_ICCProfile:
+ case pdc_CMap:
+ case pdc_GlyphList:
+ case pdc_CodeList:
+ {
+ if (!strlen(resnamutf8) || !strlen(resvalutf8))
+ {
+ pdc_free(pdc, resnamutf8);
+ pdc_free(pdc, resvalutf8);
+ if (resvalue == NULL)
+ pdc_error(pdc, PDC_E_RES_BADRES, resname, category, 0, 0);
+ else
+ pdc_error(pdc, PDC_E_RES_BADRES2, resname, resvalue,
+ category, 0);
+ }
+
+ /* file name check */
+ resvalutf8 = pdc_check_filename(pdc, resvalutf8);
+ }
+ break;
+
+ case pdc_SearchPath:
+ {
+ if (strlen(resvalutf8))
+ {
+ if (resnamutf8 != NULL)
+ pdc_free(pdc, resnamutf8);
+ pdc_free(pdc, resvalutf8);
+ pdc_error(pdc, PDC_E_RES_BADRES, resname, category, 0, 0);
+ }
+
+ if (resvalutf8 != NULL)
+ {
+ pdc_free(pdc, resvalutf8);
+ resvalutf8 = NULL;
+ }
+
+ /* file name check */
+ if (resnamutf8 != NULL && strlen(resnamutf8))
+ {
+ resnamutf8 = pdc_check_filename(pdc, resnamutf8);
+ }
+ else
+ {
+ /* delete all entries */
+ if (resnamutf8 != NULL)
+ pdc_free(pdc, resnamutf8);
+ pdc_delete_rescategory(pdc, lastcat, cat, pdc_true);
+
+ pdc_logg_cond(pdc, 1, trc_resource,
+ "\tResource category \"%s\" removed\n", category);
+
+ return;
+ }
+ }
+ break;
+
+ case pdc_StandardOutputIntent:
+ break;
+ }
+
+ /* Find resource name in resource list */
+ lastres = NULL;
+ for (res = cat->kids; res != NULL; res = res->next)
+ {
+ if (!strcmp(res->name, resnamutf8))
+ break;
+ lastres = res;
+ }
+
+ /* New resource */
+ if (res == NULL)
+ {
+ res = (pdc_res *) pdc_calloc(pdc, sizeof(pdc_res), fn);
+ if (lastres)
+ lastres->next = res;
+ else
+ cat->kids = res;
+ res->prev = lastres;
+ res->name = resnamutf8;
+ }
+ else
+ {
+ pdc_free(pdc, resnamutf8);
+ }
+
+ /* New value */
+ if (res->value)
+ pdc_free(pdc, res->value);
+ res->value = resvalutf8;
+
+ if (res->value && strlen(res->value))
+ pdc_logg_cond(pdc, 1, trc_resource,
+ "\tNew category.resource: \"%s.%s = %s\"\n",
+ category, res->name, res->value);
+ else
+ pdc_logg_cond(pdc, 1, trc_resource,
+ "\tNew category.resource: \"%s.%s\"\n",
+ category, res->name);
+}
+
+void
+pdc_add_resource(pdc_core *pdc, const char *category, const char *resname,
+ const char *resvalue)
+{
+ pdc_add_resource_ext(pdc, category, resname, resvalue, pdc_invalidenc, 0);
+}
+
+const char *
+pdc_find_resource(pdc_core *pdc, const char *category, const char *name)
+{
+ pdc_reslist *resl = pdc_get_reslist(pdc);
+ pdc_category *cat;
+ pdc_res *res;
+
+ /* Read resource configuration file if it is pending */
+ if (resl->filepending)
+ {
+ resl->filepending = pdc_false;
+ pdc_read_resourcefile(pdc, resl->filename);
+ }
+
+ for (cat = resl->resources; cat != (pdc_category *) NULL; cat = cat->next)
+ {
+ if (!pdc_stricmp(cat->category, category))
+ {
+ for (res = cat->kids; res != (pdc_res *)NULL; res = res->next)
+ {
+ if (!strcmp(res->name, name))
+ {
+ if (pdc_logg_is_enabled(pdc, 1, trc_resource))
+ {
+ const char *resval = res->name, *separ = "";
+
+ if (res->value && strlen(res->value))
+ {
+ resval = res->value;
+ separ = " = ";
+ }
+
+ pdc_logg(pdc,
+ "\tFound category.resource: \"%s.%s%s%s\"\n",
+ category, res->name, separ, resval);
+ }
+
+ return res->value;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+const char *
+pdc_find_resource_nr(pdc_core *pdc, const char *category, int nr)
+{
+ pdc_reslist *resl = pdc_get_reslist(pdc);
+ pdc_category *cat;
+ pdc_rescategory rescat;
+ pdc_res *res;
+ int n = 0;
+
+ /* Read resource configuration file if it is pending */
+ if (resl->filepending)
+ {
+ resl->filepending = pdc_false;
+ pdc_read_resourcefile(pdc, resl->filename);
+ }
+
+ rescat = (pdc_rescategory) pdc_get_keycode_ci(category, pdc_rescategories);
+
+ for (cat = resl->resources; cat != (pdc_category *) NULL; cat = cat->next)
+ {
+ if (!pdc_stricmp(cat->category, category))
+ {
+ for (res = cat->kids; res != (pdc_res *)NULL; res = res->next)
+ {
+ n++;
+ if (n == nr)
+ {
+ char *resname = (char *) "", *resval = res->name;
+ const char *separ = "", *retval;
+ pdc_bool tobefree = pdc_false;
+
+ if (res->value && strlen(res->value))
+ {
+ resname = res->name;
+ resval = res->value;
+ separ = "=";
+ }
+
+ pdc_logg_cond(pdc, 1, trc_resource,
+ "\tFound %d. category.resource: "
+ "\"%s.%s%s%s\"\n",
+ nr, category, resname, separ, resval);
+
+ /* conversion of host encoded file names back to UTF-8 */
+ switch (rescat)
+ {
+ case pdc_StandardOutputIntent:
+ break;
+
+ default:
+ resval = pdc_get_filename(pdc, resval);
+ tobefree = pdc_true;
+ break;
+ }
+
+ retval =
+ pdc_errprintf(pdc, "%s%s%s", resname, separ, resval);
+
+ if (tobefree)
+ pdc_free(pdc, resval);
+
+ return retval;
+ }
+ }
+ }
+ }
+
+ return "";
+}
+
+
+/* ----------------------- virtual file handling ---------------------------- */
+
+struct pdc_virtfile_s
+{
+ char *name;
+ const void *data;
+ size_t size;
+ pdc_bool iscopy;
+ int lockcount;
+ pdc_virtfile *next;
+};
+
+static pdc_virtfile *
+pdc_find_pvf(pdc_core *pdc, const char *filename, pdc_virtfile **lastvfile)
+{
+ pdc_virtfile *vfile;
+ pdc_virtfile *filesystem = pdc->filesystem;
+
+ if (lastvfile != NULL)
+ *lastvfile = NULL;
+ for (vfile = filesystem; vfile != NULL; vfile = vfile->next)
+ {
+ if (!strcmp(vfile->name, filename))
+ {
+ pdc_logg_cond(pdc, 1, trc_filesearch,
+ "\n\tVirtual file \"%s\" found\n", filename);
+ return vfile;
+ }
+ if (lastvfile != NULL)
+ *lastvfile = vfile;
+ }
+ return NULL;
+}
+
+/* definitions of pvf options */
+static const pdc_defopt pdc_create_pvf_options[] =
+{
+ {"copy", pdc_booleanlist, 0, 1, 1, 0.0, 0.0, NULL},
+
+ PDC_OPT_TERMINATE
+};
+
+void
+pdc__create_pvf(pdc_core *pdc, const char *filename,
+ const void *data, size_t size, const char *optlist)
+{
+ static const char fn[] = "pdc__create_pvf";
+ pdc_bool iscopy = pdc_false;
+ pdc_virtfile *vfile, *lastvfile = NULL;
+ pdc_resopt *results;
+
+ if (!data)
+ pdc_error(pdc, PDC_E_ILLARG_EMPTY, "data", 0, 0, 0);
+
+ if (!size)
+ pdc_error(pdc, PDC_E_ILLARG_EMPTY, "size", 0, 0, 0);
+
+ /* Parse optlist */
+ results = pdc_parse_optionlist(pdc, optlist, pdc_create_pvf_options,
+ NULL, pdc_true);
+ pdc_get_optvalues("copy", results, &iscopy, NULL);
+ pdc_cleanup_optionlist(pdc, results);
+
+ /* Find virtual file in file system */
+ vfile = pdc_find_pvf(pdc, filename, &lastvfile);
+
+ /* Name already exists */
+ if (vfile != NULL)
+ pdc_error(pdc, PDC_E_PVF_NAMEEXISTS, filename, 0, 0, 0);
+
+ /* New virtual file */
+ vfile = (pdc_virtfile *) pdc_calloc(pdc, sizeof(pdc_virtfile), fn);
+ if (lastvfile)
+ lastvfile->next = vfile;
+ else
+ pdc->filesystem = vfile;
+
+ /* Fill up file struct */
+ vfile->name = pdc_strdup(pdc, filename);
+ if (iscopy == pdc_true)
+ {
+ vfile->data = (const void *) pdc_malloc(pdc, size, fn);
+ memcpy((void *) vfile->data, data, size);
+ }
+ else
+ {
+ vfile->data = data;
+ }
+ vfile->size = size;
+ vfile->iscopy = iscopy;
+ vfile->lockcount = 0;
+ vfile->next = NULL;
+
+ pdc_logg_cond(pdc, 1, trc_filesearch,
+ "\n\tVirtual file \"%s\" created\n", filename);
+}
+
+int
+pdc__delete_pvf(pdc_core *pdc, const char *filename)
+{
+ pdc_virtfile *vfile, *lastvfile = NULL;
+
+ /* Find virtual file in file system */
+ vfile = pdc_find_pvf(pdc, filename, &lastvfile);
+ if (vfile)
+ {
+ /* File exists but locked */
+ if (vfile->lockcount > 0)
+ {
+ return pdc_undef;
+ }
+
+ /* Delete */
+ if (vfile->iscopy == pdc_true)
+ {
+ pdc_free(pdc, (void *) vfile->data);
+ vfile->data = NULL;
+ }
+ pdc_free(pdc, vfile->name);
+ if (lastvfile)
+ lastvfile->next = vfile->next;
+ else
+ pdc->filesystem = vfile->next;
+ pdc_free(pdc, vfile);
+
+ pdc_logg_cond(pdc, 1, trc_filesearch,
+ "\tVirtual file \"%s\" deleted\n", filename);
+ }
+
+ return pdc_true;
+}
+
+void
+pdc_lock_pvf(pdc_core *pdc, const char *filename)
+{
+ pdc_virtfile *vfile = pdc_find_pvf(pdc, filename, NULL);
+ if (vfile)
+ {
+ (vfile->lockcount)++;
+
+ pdc_logg_cond(pdc, 1, trc_filesearch,
+ "\tVirtual file \"%s\" locked\n", filename);
+ }
+}
+
+void
+pdc_unlock_pvf(pdc_core *pdc, const char *filename)
+{
+ pdc_virtfile *vfile = pdc_find_pvf(pdc, filename, NULL);
+ if (vfile)
+ {
+ (vfile->lockcount)--;
+
+ pdc_logg_cond(pdc, 1, trc_filesearch,
+ "\tVirtual file \"%s\" unlocked\n", filename);
+ }
+}
+
+void
+pdc_delete_filesystem(pdc_core *pdc)
+{
+ pdc_virtfile *vfile, *nextvfile;
+ pdc_virtfile *filesystem = pdc->filesystem;
+
+ for (vfile = filesystem; vfile != NULL; /* */)
+ {
+ nextvfile = vfile->next;
+ if (vfile->iscopy == pdc_true && vfile->data)
+ pdc_free(pdc, (void *) vfile->data);
+ if (vfile->name)
+ pdc_free(pdc, vfile->name);
+ pdc_free(pdc, vfile);
+ vfile = nextvfile;
+ }
+ pdc->filesystem = NULL;
+}
+
+
+/* ------------------------ file search handling ---------------------------- */
+
+#if defined(_MSC_VER) && defined(_MANAGED)
+#pragma unmanaged
+#endif
+pdc_file *
+pdc_fsearch_fopen(pdc_core *pdc, const char *filename, char *fullname,
+ const char *qualifier, int flags)
+{
+ pdc_reslist *resl = pdc_get_reslist(pdc);
+ char fullname_s[PDC_FILENAMELEN];
+ const pdc_byte *data = NULL;
+ pdc_file *sfp = NULL;
+ size_t size = 0;
+ pdc_virtfile *vfile;
+
+ if (fullname == NULL)
+ fullname = fullname_s;
+ strcpy(fullname, filename);
+
+ vfile = pdc_find_pvf(pdc, filename, NULL);
+ if (vfile)
+ {
+ size = vfile->size;
+ data = (const pdc_byte *) vfile->data;
+ sfp = pdc_fopen(pdc, filename, qualifier, data, size, flags);
+ }
+ else
+ {
+ pdc_category *cat;
+
+ /* Bad filename */
+ if (!*filename || !strcmp(filename, ".") || !strcmp(filename, ".."))
+ {
+ pdc_set_errmsg(pdc, PDC_E_IO_ILLFILENAME, filename, 0, 0, 0);
+ return NULL;
+ }
+
+
+ /* Read resource configuration file if it is pending */
+ if (resl->filepending)
+ {
+ resl->filepending = pdc_false;
+ pdc_read_resourcefile(pdc, resl->filename);
+ }
+
+ pdc_logg_cond(pdc, 1, trc_filesearch,
+ "\n\tSearching for file \"%s\":\n", filename);
+
+ /* Searching resource category */
+ for (cat = resl->resources;
+ cat != (pdc_category *) NULL;
+ cat = cat->next)
+ if (!pdc_stricmp(cat->category, "SearchPath")) break;
+
+ if (!cat)
+ {
+ /* No resource category */
+ sfp = pdc_fopen(pdc, filename, qualifier, NULL, 0, flags);
+ }
+ else
+ {
+ pdc_res *res = cat->kids;
+ pdc_res *lastres = cat->kids;
+ char *pathname = NULL;
+ FILE *fp = NULL;
+ int errnum = PDC_E_IO_RDOPEN_NF;
+ pdc_bool fatal = pdc_false;
+
+ /* Find last SearchPath entry */
+ while (res != (pdc_res *) NULL)
+ {
+ lastres = res;
+ res = res->next;
+ }
+
+ /* First local search and then search with concatenated
+ * filename with search paths one after another backwards
+ */
+ while (1)
+ {
+ /* Test opening */
+ pdc_file_fullname(pathname, filename, fullname);
+
+ if (pathname != NULL)
+ pdc_logg_cond(pdc, 1, trc_filesearch,
+ "\tin directory \"%s\": \"%s\"\n", pathname, fullname);
+
+ fp = pdc_fopen_logg(pdc, fullname, READBMODE);
+ if (fp)
+ {
+ /* File found */
+ pdc_fclose_logg(pdc, fp);
+ sfp = pdc_fopen(pdc, fullname, qualifier, NULL, 0,flags);
+ break;
+ }
+ errnum = pdc_get_fopen_errnum(pdc, PDC_E_IO_RDOPEN);
+ if (errno != 0 && errnum != PDC_E_IO_RDOPEN_NF)
+ {
+ fatal = pdc_true;
+ pdc_set_fopen_errmsg(pdc, PDC_E_IO_RDOPEN,
+ qualifier, fullname);
+ }
+
+#if defined(WIN32)
+ /* file name beginning with a drive letter: 'x:'
+ * is already full specified.
+ */
+ if (pdc_isalpha(filename[0]) && filename[1] == ':')
+ break;
+#endif
+
+ if (lastres == (pdc_res *) NULL)
+ break;
+
+ pathname = lastres->name;
+ lastres = lastres->prev;
+ }
+
+ if (sfp == NULL && !fatal)
+ pdc_set_fopen_errmsg(pdc, PDC_E_IO_RDOPEN,
+ qualifier, filename);
+ else
+ filename = fullname;
+ }
+ }
+
+ pdc_logg_cond(pdc, 1, trc_filesearch,
+ "\tFile \"%s\" %sfound\n", fullname, sfp == NULL ? "not " : "");
+ return sfp;
+}
+#if defined(_MSC_VER) && defined(_MANAGED)
+#pragma managed
+#endif
+
+
+/* ----------------------- logging file handling ---------------------------- */
+
+# ifndef DEFAULTLOGFILE
+# if defined(MVS)
+# define DEFAULTLOGFILE "pdflog"
+# elif defined(MAC) || defined(AS400)
+# define DEFAULTLOGFILE "/%s.log"
+# elif defined(WIN32)
+# define DEFAULTLOGFILE "\\%s.log"
+# else
+# define DEFAULTLOGFILE "/tmp/%s.log"
+# endif
+# endif
+
+#define LOGFILEENVNAME "%sLOGFILE"
+#define LOGGINGENVNAME "%sLOGGING"
+
+#define PDC_CLASSLIST_SIZE 32
+#define PDC_CLASSLIST_MAX 10
+
+struct pdc_loggdef_s
+{
+ pdc_bool enabled; /* logging enabled */
+ char *filename; /* name of the logging file */
+ pdc_bool fromenviron; /* logging file name defined environment */
+ pdc_bool header; /* with header and separation line */
+ pdc_bool flush; /* logging file will be opened and
+ * and closed immediately */
+ FILE *fp; /* flush = false: file handle */
+ pdc_strform_kind strform; /* format for logging strings */
+ int maxchar; /* maximal number of characters
+ * of logging strings */
+ int sri; /* first index in classlist for save/restore */
+ char classlist[PDC_CLASSLIST_MAX][PDC_CLASSLIST_SIZE];
+ /* list array of levels for logging classes */
+ pdc_bool classapi; /* only api class has level = 1
+ * and warning class has level = 1 */
+};
+
+static pdc_loggdef *
+pdc_new_logg(pdc_core *pdc)
+{
+ static const char fn[] = "pdc_new_logg";
+ char envname[32];
+ const char *envval = NULL;
+
+ pdc_loggdef *logg = (pdc_loggdef *)
+ pdc_malloc(pdc, sizeof(pdc_loggdef), fn);
+
+ logg->enabled = pdc_false;
+ logg->filename = NULL;
+ logg->fromenviron = pdc_false;
+ logg->header = pdc_true;
+ logg->flush = pdc_false;
+ logg->fp = NULL;
+ logg->strform = strform_readable;
+ logg->maxchar = 0;
+ logg->sri = 0;
+ memset(logg->classlist[0], 0, PDC_CLASSLIST_SIZE);
+ logg->classlist[0][trc_api] = 1;
+ logg->classlist[0][trc_warning] = 1;
+ logg->classapi = pdc_true;
+
+ pdc->logg = logg;
+
+ /* logging file name defined by environment variable */
+ sprintf(envname, LOGFILEENVNAME, pdc->prodname);
+ pdc_strtoupper(envname);
+ envval = pdc_getenv(envname);
+ if (envval != NULL)
+ {
+ logg->filename = pdc_strdup(pdc, envval);
+ logg->fromenviron = pdc_true;
+ }
+
+ return logg;
+}
+
+void
+pdc_delete_logg(pdc_core *pdc)
+{
+ if (pdc->logg != NULL)
+ {
+ pdc_loggdef *logg = pdc->logg;
+
+ logg->enabled = pdc_false;
+
+ /* close file */
+ if (logg->fp != NULL && logg->fp != stdout && logg->fp != stderr)
+ {
+ fclose(logg->fp);
+ logg->fp = NULL;
+ }
+
+ if (logg->filename != NULL)
+ {
+ pdc_free(pdc, logg->filename);
+ logg->filename = NULL;
+ }
+
+ pdc_free(pdc, logg);
+ pdc->logg = NULL;
+ }
+}
+
+static pdc_loggdef *
+pdc_get_logg(pdc_core *pdc)
+{
+ pdc_loggdef *logg = pdc->logg;
+
+ if (logg == NULL)
+ logg = pdc_new_logg(pdc);
+
+ return logg;
+}
+
+static const pdc_keyconn pdc_strform_keylist[] =
+{
+ {"readable", strform_readable},
+ {"readable0", strform_readable0},
+ {"octal", strform_octal},
+ {"hex", strform_hexa},
+ {"java", strform_java},
+ {NULL, 0}
+};
+
+static const pdc_keyconn pdf_protoclass_keylist[] =
+{
+ {"api", trc_api},
+ {"encoding", trc_encoding},
+ {"digsig", trc_digsig},
+ {"filesearch", trc_filesearch},
+ {"font", trc_font},
+ {"image", trc_image},
+ {"memory", trc_memory},
+ {"optlist", trc_optlist},
+ {"other", trc_other},
+ {"pcos", trc_pcos},
+ {"pdi", trc_pdi},
+ {"resource", trc_resource},
+ {"shadow", trc_shadow},
+ {"table", trc_table},
+ {"text", trc_text},
+ {"textflow", trc_textflow},
+ {"user", trc_user},
+ {"warning", trc_warning},
+ {"wordfinder", trc_wordfinder},
+ {"xmp", trc_xmp},
+ {"zones", trc_zones},
+ {NULL, 0}
+};
+
+#define PDC_FILENAMELEN 1024
+
+static const pdc_defopt pdc_logg_options[] =
+{
+ {"header", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"enable", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"disable", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"flush", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"remove", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"filename", pdc_stringlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_FILENAMELEN, NULL},
+
+ {"restore", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"save", pdc_booleanlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, NULL},
+
+ {"stringformat", pdc_keywordlist, PDC_OPT_NONE, 1, 1,
+ 0.0, 0.0, pdc_strform_keylist},
+
+ {"stringlimit", pdc_integerlist, PDC_OPT_NONE, 1, 1,
+ 0.0, PDC_INT_MAX, NULL},
+
+ {"classes", pdc_stringlist, PDC_OPT_EVENNUM |PDC_OPT_SUBOPTLIST,
+ 1, 2 * PDC_CLASSLIST_SIZE, 1.0, 64, NULL},
+
+ PDC_OPT_TERMINATE
+};
+
+static const char *separstr =
+ "[ --------------------------------------------------------- ]\n";
+
+void
+pdc_set_logg_options(pdc_core *pdc, const char *optlist)
+{
+ pdc_loggdef *logg = pdc_get_logg(pdc);
+ pdc_resopt *resopts = NULL;
+ char **strlist, *keyword;
+ char filename[PDC_FILENAMELEN+1];
+ pdc_bool sare = pdc_false;
+ pdc_bool enable = pdc_true;
+ pdc_bool remfile = pdc_false;
+ pdc_char level;
+ int inum, i, pclass = 0, sumlevel = 0;
+
+ filename[0] = 0;
+ if (optlist && strlen(optlist))
+ {
+ resopts = pdc_parse_optionlist(pdc, optlist, pdc_logg_options,
+ NULL, pdc_true);
+
+ if (pdc_get_optvalues("save", resopts, &sare, NULL) && sare)
+ {
+ i = logg->sri + 1;
+ if (i >= PDC_CLASSLIST_MAX)
+ pdc_error(pdc, PDC_E_INT_TOOMUCH_SARE, 0, 0, 0, 0);
+ memcpy(logg->classlist[i], logg->classlist[logg->sri],
+ PDC_CLASSLIST_SIZE);
+ logg->sri = i;
+ }
+
+ if (pdc_get_optvalues("restore", resopts, &sare, NULL) && sare)
+ {
+ i = logg->sri - 1;
+ if (i < 0)
+ pdc_error(pdc, PDC_E_INT_TOOMUCH_SARE, 0, 0, 0, 0);
+ logg->sri = i;
+ }
+
+ if (pdc_get_optvalues("disable", resopts, &inum, NULL))
+ enable = inum ? pdc_false : pdc_true;
+
+ pdc_get_optvalues("header", resopts, &logg->header, NULL);
+
+ pdc_get_optvalues("flush", resopts, &logg->flush, NULL);
+
+ pdc_get_optvalues("remove", resopts, &remfile, NULL);
+
+ if (!logg->fromenviron)
+ pdc_get_optvalues("filename", resopts, filename, NULL);
+
+ if (pdc_get_optvalues("stringformat", resopts, &inum, NULL))
+ logg->strform = (pdc_strform_kind) inum;
+
+ pdc_get_optvalues("stringlimit", resopts, &logg->maxchar, NULL);
+
+ inum = pdc_get_optvalues("classes", resopts, NULL, &strlist);
+ if (inum)
+ {
+ for (i = 0; i < inum; i++, i++)
+ {
+ if (!pdc_stricmp(strlist[i], "other"))
+ {
+ i++;
+ if (pdc_str2integer(strlist[i],
+ PDC_INT_CHAR | PDC_INT_UNSIGNED,
+ &level))
+ {
+ memset(logg->classlist[logg->sri], (int)level,
+ PDC_CLASSLIST_SIZE);
+ }
+ break;
+ }
+ }
+ for (i = 0; i < inum; i++)
+ {
+ keyword = strlist[i];
+ pclass = pdc_get_keycode_ci(keyword, pdf_protoclass_keylist);
+ if (pclass == PDC_KEY_NOTFOUND)
+ pdc_error(pdc, PDC_E_OPT_ILLKEYWORD,
+ "classes", keyword, 0, 0);
+ i++;
+ if (!pdc_str2integer(strlist[i],
+ PDC_INT_CHAR | PDC_INT_UNSIGNED,
+ &level))
+ pdc_error(pdc, PDC_E_OPT_ILLINTEGER,
+ keyword, strlist[i], 0, 0);
+
+ logg->classlist[logg->sri][pclass] = level;
+ }
+
+ for (i = 0; i < PDC_CLASSLIST_SIZE; i++)
+ sumlevel += (int) logg->classlist[logg->sri][i];
+ logg->classapi =
+ (sumlevel == 2 &&
+ logg->classlist[logg->sri][trc_api] &&
+ logg->classlist[logg->sri][trc_warning]) ?
+ pdc_true : pdc_false;
+ }
+
+ pdc_cleanup_optionlist(pdc, resopts);
+ }
+
+ /* disable */
+ if (logg->enabled && logg->header && !enable)
+ {
+ pdc_logg(pdc, "\n");
+ pdc_logg(pdc, separstr);
+ }
+
+ /* no new logging file name specified */
+ if (!strlen(filename))
+ {
+ if (logg->filename == NULL)
+ {
+ char tmpname[PDC_FILENAMELEN];
+
+ sprintf(tmpname, DEFAULTLOGFILE, pdc->prodname);
+ pdc_strtolower(tmpname);
+ strcpy(filename, tmpname);
+ }
+ else
+ {
+ strcpy(filename, logg->filename);
+ }
+ }
+
+ /* new logging file */
+ if (logg->filename == NULL || strcmp(logg->filename, filename))
+ {
+ pdc_time ltime;
+
+ /* close file */
+ if (logg->fp != stdout && logg->fp != stderr && logg->filename)
+ {
+ pdc_localtime(&ltime);
+ pdc_logg(pdc, "[%04d-%02d-%02d %02d:%02d:%02d]\n",
+ ltime.year + 1900, ltime.month + 1, ltime.mday,
+ ltime.hour, ltime.minute, ltime.second);
+ if (logg->fp != NULL)
+ fclose(logg->fp);
+ }
+ logg->enabled = pdc_false;
+
+ /* remove file */
+ if (remfile && strcmp(filename, "stdout") && strcmp(filename, "stderr"))
+ remove(filename);
+
+ /* file name */
+ if (logg->filename != NULL)
+ pdc_free(pdc, logg->filename);
+ logg->filename = pdc_strdup(pdc, filename);
+
+ /* open file */
+ if (!logg->flush)
+ {
+ if (!strcmp(logg->filename, "stdout"))
+ logg->fp = stdout;
+ else if (!strcmp(logg->filename, "stderr"))
+ logg->fp = stderr;
+ else
+ logg->fp = fopen(logg->filename, APPENDMODE);
+ if (logg->fp == NULL)
+ {
+ pdc_error(pdc, PDC_E_IO_WROPEN, "log ", logg->filename,
+ 0, 0);
+ }
+ }
+ else
+ {
+ logg->fp = NULL;
+ }
+
+
+ /* header line */
+ logg->enabled = enable;
+ if (logg->enabled && logg->header && pdc->prodname != NULL)
+ {
+ char binding[64];
+
+ pdc_localtime(&ltime);
+ binding[0] = 0;
+ if (pdc->binding)
+ {
+ strcat(binding, pdc->binding);
+ strcat(binding, " binding ");
+ }
+ pdc_logg(pdc, separstr);
+ pdc_logg(pdc, "[ %s %s %son %s (%s) ",
+ pdc->prodname, pdc->version, binding,
+ PDF_PLATFORM, PDC_ISBIGENDIAN ? "be" : "le");
+ pdc_logg(pdc, "%04d-%02d-%02d %02d:%02d:%02d ]\n",
+ ltime.year + 1900, ltime.month + 1, ltime.mday,
+ ltime.hour, ltime.minute, ltime.second);
+
+ if (logg->classapi)
+ pdc_logg(pdc, "[ Use %%s/\\[[^]]*\\]//g and %%s/)$/);"
+ "/ in vi to compile it ]\n");
+ pdc_logg(pdc, separstr);
+ }
+ }
+ else
+ {
+ logg->enabled = enable;
+ }
+}
+
+const char *
+pdc_print_loggstring(pdc_core *pdc, const char *str, int len)
+{
+ if (pdc->logg != NULL && pdc->logg->enabled)
+ {
+
+ str = pdc_strprint(pdc, str, len, pdc->logg->maxchar,
+ pdc->logg->strform);
+
+
+ return str;
+ }
+ else
+ return "";
+}
+
+/* logging function without any class level check and decorations
+ */
+static void
+pdc_logg_output(pdc_core *pdc, const char *fmt, va_list ap)
+{
+ pdc_loggdef *logg = pdc->logg;
+
+ if (logg->flush)
+ {
+ FILE *fp = NULL;
+
+ if (!strcmp(logg->filename, "stdout"))
+ fp = stdout;
+ else if (!strcmp(logg->filename, "stderr"))
+ fp = stderr;
+ else
+ fp = fopen(logg->filename, APPENDMODE);
+
+ if (fp == NULL)
+ {
+ logg->enabled = pdc_false;
+ pdc_error(pdc, PDC_E_IO_WROPEN, "log ", logg->filename,
+ 0, 0);
+ }
+
+ pdc_vfprintf(pdc, pdc_false, fp, fmt, ap);
+
+ if (fp != stdout && fp != stderr)
+ fclose(fp);
+ }
+ else
+ {
+ pdc_vfprintf(pdc, pdc_false, logg->fp, fmt, ap);
+ fflush(logg->fp);
+ }
+}
+
+
+/* standard logging protocol functions for api function calls
+ */
+pdc_bool
+pdc_enter_api_logg(pdc_core *pdc, const char *funame, pdc_bool enter_api,
+ const char *fmt, va_list args)
+{
+ pdc_bool retval = pdc_true;
+
+ if (enter_api)
+ retval = pdc_enter_api(pdc, funame);
+
+ if (retval)
+ {
+ /* logging option list defined by environment variable */
+ if (pdc->loggenv == pdc_false)
+ {
+ char envname[32];
+ const char *envval = NULL;
+
+ pdc->loggenv = pdc_true;
+ sprintf(envname, LOGGINGENVNAME, pdc->prodname);
+ pdc_strtoupper(envname);
+ envval = pdc_getenv(envname);
+ if (envval != NULL)
+ {
+ pdc_set_logg_options(pdc, envval);
+ }
+#if defined(WIN32)
+ else
+ {
+ char buffer[BUFSIZE];
+ char regkey[128];
+ HKEY hKey = NULL;
+ DWORD size, lType;
+
+ sprintf(regkey, REGISTRYKEY, pdc->prodname, pdc->version);
+
+ /* process registry entries */
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, regkey, 0L,
+ (REGSAM) KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
+ {
+ size = BUFSIZE - 2;
+ pdc_strtolower(envname);
+ if (RegQueryValueExA(hKey, envname, (LPDWORD) NULL,
+ &lType, (LPBYTE) buffer, &size)
+ == ERROR_SUCCESS && *buffer)
+ {
+ pdc_set_logg_options(pdc, buffer);
+ }
+
+ RegCloseKey(hKey);
+ }
+ }
+ #endif
+ }
+
+ if (pdc->logg != NULL &&
+ pdc->logg->enabled &&
+ pdc->logg->classlist[pdc->logg->sri][trc_api])
+ {
+ /* time stamp */
+ if (pdc->logg->classlist[pdc->logg->sri][trc_api] > 1)
+ {
+ pdc_time ltime;
+
+ if (funame[0] == '\n')
+ {
+ pdc_logg(pdc, "\n");
+ funame++;
+ }
+
+ pdc_localtime(&ltime);
+ pdc_logg(pdc, "[%02d:%02d:%02d] ",
+ ltime.hour, ltime.minute, ltime.second);
+ }
+
+ /* function name */
+ pdc_logg(pdc, "%s", funame);
+
+ /* function arg list */
+ pdc_logg_output(pdc, fmt, args);
+ }
+ }
+
+ return retval;
+}
+
+void
+pdc_logg_exit_api(pdc_core *pdc, pdc_bool cleanup, const char *fmt, ...)
+{
+ if (fmt != NULL && pdc != NULL &&
+ pdc->logg != NULL &&
+ pdc->logg->enabled &&
+ pdc->logg->classlist[pdc->logg->sri][trc_api])
+ {
+ va_list ap;
+
+ va_start(ap, fmt);
+ pdc_logg_output(pdc, fmt, ap);
+ va_end(ap);
+ }
+
+ if (cleanup)
+ pdc_tmlist_cleanup(pdc);
+}
+
+/*
+ * General logging functions
+ */
+
+/*
+ * pdc_logg_enable() enables/disables logging
+ */
+void
+pdc_logg_enable(pdc_core *pdc, pdc_bool enable)
+{
+ if (pdc != NULL && pdc->logg != NULL)
+ pdc->logg->enabled = enable;
+}
+
+/*
+ * pdc_logg_is_enabled() returns pdc_true
+ * if logging is enabled for logging class 'pclass' and level 'level'.
+ * Otherwise pdc_false will be returned.
+ */
+pdc_bool
+pdc_logg_is_enabled(pdc_core *pdc, int level, int pclass)
+{
+ return pdc->logg != NULL &&
+ pdc->logg->enabled &&
+ level <= pdc->logg->classlist[pdc->logg->sri][pclass];
+}
+
+
+/*
+ * pdc_logg() writes formatted text in the current logging file
+ * without checking whether logging is enabled.
+ * This function should only be used in connection with
+ * pdc_logg_is_enabled():
+ */
+void
+pdc_logg(pdc_core *pdc, const char *fmt, ...)
+{
+ if (pdc != NULL && pdc->logg != NULL && pdc->logg->enabled)
+ {
+ va_list ap;
+
+ va_start(ap, fmt);
+ pdc_logg_output(pdc, fmt, ap);
+ va_end(ap);
+ }
+}
+
+/*
+ * pdc_logg_cond() writes formatted text in the current logging file
+ * if logging is enabled for logging class 'pclass' and level 'level'.
+ */
+void
+pdc_logg_cond(pdc_core *pdc, int level, int pclass, const char *fmt, ...)
+{
+ if (pdc != NULL && pdc->logg != NULL &&
+ pdc->logg->enabled &&
+ level <= pdc->logg->classlist[pdc->logg->sri][pclass])
+ {
+ va_list ap;
+
+ va_start(ap, fmt);
+ pdc_logg_output(pdc, fmt, ap);
+ va_end(ap);
+ }
+}
+
+
+/*
+ * pdc_logg_getlevel() returns the current level for a logging class
+ */
+int
+pdc_logg_getlevel(pdc_core *pdc, int pclass)
+{
+ if (pdc->logg != NULL && pdc->logg->enabled)
+ return (int) pdc->logg->classlist[pdc->logg->sri][pclass];
+ else
+ return 0;
+}
+
+/*
+ * pdc_logg_bitarr() writes the literal representation of a bit array
+ (including a descriptive message) in 1 line in the current logging file.
+ variable nbit must be <=32.
+ */
+void
+pdc_logg_bitarr(pdc_core *pdc, const char *msg, const char *bitarr, int nbit)
+{
+ int i;
+
+ pdc_logg(pdc,"%s = ", msg);
+
+ nbit = MIN(nbit, 32);
+ for (i = 0; i <= nbit; i++)
+ {
+ if (!(i%8))
+ {
+ pdc_logg(pdc, "|");
+ }
+ if (i == nbit)
+ {
+ if (nbit == 8)
+ pdc_logg(pdc, " (%02X)", bitarr[0]);
+ else if (nbit == 16)
+ pdc_logg(pdc, " (%04X)", *((pdc_uint16 *) &bitarr[0]));
+ else if (nbit == 32)
+ pdc_logg(pdc, " (%08X)", *((pdc_uint32 *) &bitarr[0]));
+ pdc_logg(pdc, "\n");
+ }
+ else
+ {
+ pdc_logg(pdc, "%s", pdc_getbit(bitarr, i) ? "1" : "0");
+ }
+ }
+}
+
+
+/*
+ * pdc_logg_hexdump() writes the hexadecimal output of the specified buffer
+ (including a descriptive message) in the current logging file.
+ */
+void
+pdc_logg_hexdump(pdc_core *pdc, const char *msg, const char *prefix,
+ const char *text, int tlen)
+{
+ int i, k;
+ pdc_byte ct;
+
+ if (tlen == 1)
+ {
+ ct = (pdc_byte) text[0];
+ pdc_logg(pdc, "%s%s: %02X '%c'\n", prefix, msg, ct,
+ pdc_logg_isprint((int) ct) ? ct : '.');
+ }
+ else
+ {
+ pdc_logg(pdc,"%s%s:\n", prefix, msg);
+
+ for (i = 0; i < tlen; i += 16)
+ {
+ pdc_logg(pdc,"%s", prefix);
+ for (k = 0; k < 16; ++k)
+ {
+ if (i + k < tlen)
+ {
+ ct = (pdc_byte) text[i + k];
+ pdc_logg(pdc,"%02X ", ct);
+ }
+ else
+ pdc_logg(pdc," ");
+ }
+
+ pdc_logg(pdc," ");
+ for (k = 0; k < 16; ++k)
+ {
+ if (i + k < tlen)
+ {
+ ct = (pdc_byte) text[i + k];
+ pdc_logg(pdc,"%c", pdc_logg_isprint((int)ct) ? ct : '.');
+ }
+ else
+ pdc_logg(pdc," ");
+ }
+
+ pdc_logg(pdc,"\n");
+ }
+ }
+}
+
+/*
+ * pdc_warning() is the former function of PDFlib exception handling.
+ * Now, pdc_warning() calls the function pdc_set_warnmsg(), which writes
+ * only a warning message generated from a xx_generr.h file into the logfile,
+ * if warning = 1.
+ */
+void
+pdc_warning(pdc_core *pdc, int errnum, const char *parm1, const char *parm2,
+ const char *parm3, const char *parm4)
+{
+ if (!pdc->smokerun)
+ pdc_set_warnmsg(pdc, errnum, parm1, parm2, parm3, parm4);
+}
+
+/*
+ * utility function for logging a Unicode character
+ *
+ */
+void
+pdc_logg_unichar(pdc_core *pdc, int unichar, pdc_bool kfill, pdc_bool newline)
+{
+ if (unichar > 0xFFFF)
+ {
+ pdc_logg(pdc, "U+%05X", unichar);
+ }
+ else
+ {
+ pdc_logg(pdc, "U+%04X", unichar);
+
+ if ((unichar >= PDC_UNICODE_SPACE && unichar <= PDC_UNICODE_DELETE) ||
+ (unichar >= PDC_UNICODE_NBSP && unichar <= PDC_UNICODE_MAXLATIN1))
+ {
+ char c = (char) unichar;
+
+
+ pdc_logg(pdc, " [%c]", c);
+ }
+ else if (kfill)
+ {
+ pdc_logg(pdc, " ");
+ }
+ }
+
+ if (newline)
+ pdc_logg(pdc, "\n");
+}
+
+/*
+ * utility function for logging a Unicode string
+ *
+ */
+static const pdc_keyconn pdc_ascii_escape_keylist[] =
+{
+ {"a", 0x07},
+ {"b", 0x08},
+ {"e", 0x1B},
+ {"f", 0x0C},
+ {"n", 0x0A},
+ {"r", 0x0D},
+ {"t", 0x09},
+ {"v", 0x0B},
+ {NULL, 0}
+};
+
+void
+pdc_logg_unitext(pdc_core *pdc, pdc_ushort *ustext, int len, pdc_bool newline)
+{
+ int i;
+ pdc_ushort usv;
+ const char *s;
+ char c;
+
+ pdc_logg(pdc, "\"");
+ for (i = 0; i < len; i++)
+ {
+ usv = ustext[i];
+ if (usv > PDC_UNICODE_MAXLATIN1)
+ {
+ pdc_logg(pdc, "\\u%04X", usv);
+ }
+ else
+ {
+ if (usv < PDC_UNICODE_SPACE)
+ {
+ s = pdc_get_keyword((int) usv, pdc_ascii_escape_keylist);
+ if (s != NULL)
+ {
+ pdc_logg(pdc, "\\%s", s);
+ continue;
+ }
+ }
+
+ if ((usv >= PDC_UNICODE_SPACE && usv <= PDC_UNICODE_DELETE) ||
+ (usv >= PDC_UNICODE_NBSP && usv <= PDC_UNICODE_MAXLATIN1))
+ {
+ c = (char) usv;
+
+
+ pdc_logg(pdc, "%c", c);
+ }
+ else
+ {
+ pdc_logg(pdc, "\\x%02X", usv);
+ }
+ }
+ }
+
+ pdc_logg(pdc, "\"");
+ if (newline)
+ pdc_logg(pdc, "\n");
+}
+
+