From 7b52cc13af4e85f1ca2deb6b6c77de9c95ea0dcf Mon Sep 17 00:00:00 2001 From: scuri Date: Fri, 17 Oct 2008 06:10:33 +0000 Subject: First commit - moving from LuaForge to SourceForge --- src/pdflib/pdcore/pc_resource.c | 1906 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 1906 insertions(+) create mode 100644 src/pdflib/pdcore/pc_resource.c (limited to 'src/pdflib/pdcore/pc_resource.c') 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 + +#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 +#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(<ime); + 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(<ime); + 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(<ime); + 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"); +} + + -- cgit v1.2.3