summaryrefslogtreecommitdiff
path: root/support/dktools/dk3uc2l.ctr
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/dktools/dk3uc2l.ctr
Initial commit
Diffstat (limited to 'support/dktools/dk3uc2l.ctr')
-rw-r--r--support/dktools/dk3uc2l.ctr2062
1 files changed, 2062 insertions, 0 deletions
diff --git a/support/dktools/dk3uc2l.ctr b/support/dktools/dk3uc2l.ctr
new file mode 100644
index 0000000000..772373aa4a
--- /dev/null
+++ b/support/dktools/dk3uc2l.ctr
@@ -0,0 +1,2062 @@
+%% options
+
+copyright owner = Dirk Krause
+copyright year = 2011-xxxx
+license = bsd
+
+
+
+%% header
+
+/** @file dk3uc2l.h 32-bit character to LaTeX conversion.
+
+This module was rewritten in August 2015, so it uses the same *.t2l files
+as the dk4uc2l module.
+During this rewrite the functionality was stripped down to those functions
+used by the itadmin program.
+
+*/
+
+#include "dk3conf.h"
+#include "dk3types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Open LaTeX encoder.
+ @param d Directory containing the tables.
+ @param f_desc Flag: Attempt to load glyph descriptions.
+ @param f_utf8 Flag: UTF-8 output encoding.
+ @param app Application structure for diagnostics, may be NULL.
+ @return Pointer to new encoder on success, NULL on error.
+*/
+dk3_uc2lat_t *
+dk3uc2lat_open_app(dkChar const *d, int f_desc, int f_utf8, dk3_app_t *app);
+
+/** Close LaTeX encoder.
+ @param u Encoder to close.
+*/
+void
+dk3uc2lat_close(dk3_uc2lat_t *u);
+
+/** Retrieve LaTeX encoding for one 32-bit character.
+ @param u LaTeX encoder.
+ @param c32 Character to obtain LaTeX encoding for.
+ @param ismath Flag: In math mode.
+ @return Pointer to encoding on success, NULL on error.
+*/
+char const *
+dk3uc2lat_get(dk3_uc2lat_t *u, dk3_c32_t c32, int ismath);
+
+/** Check whether a character can be written to a LaTeX file directly.
+ @param c32 Character to check.
+ @return 1 for yes, 0 for no.
+*/
+int
+dk3uc2lat_direct(dk3_c32_t c32);
+
+/** Write LaTeX encoding for a string to a stream.
+ @param u LaTeX encoder.
+ @param st Stream to write to.
+ @param t Text to write (ASCII/ISO-LATIN-1 encoded).
+ @return 1 on success, 0 on error.
+*/
+int
+dk3uc2lat_c8_plain_stputs(dk3_uc2lat_t *u, dk3_stream_t *st, char const *t);
+
+/** Write LaTeX encoding for a string to a stream.
+ @param u LaTeX encoder.
+ @param st Stream to write to.
+ @param t Text to write (UTF-8 encoded).
+ @return 1 on success, 0 on error.
+*/
+int
+dk3uc2lat_c8_utf8_stputs(dk3_uc2lat_t *u, dk3_stream_t *st, char const *t);
+
+/** Write LaTeX encoding for a string to a stream.
+ @param u LaTeX encoder.
+ @param st Stream to write to.
+ @param t Text to write (UTF-16 encoded).
+ @return 1 on success, 0 on error.
+*/
+int
+dk3uc2lat_c16_stputs(dk3_uc2lat_t *u, dk3_stream_t *st, dk3_c16_t const *t);
+
+/** Write LaTeX encoding for a string to a stream.
+ @param u LaTeX encoder.
+ @param st Stream to write to.
+ @param t Text to write (32-bit characters).
+ @return 1 on success, 0 on error.
+*/
+int
+dk3uc2lat_c32_stputs(dk3_uc2lat_t *u, dk3_stream_t *st, dk3_c32_t const *t);
+
+/** Write LaTeX encoding for a string to a stream.
+ @param u LaTeX encoder.
+ @param st Stream to write to.
+ @param t Text to write (dkChar characters).
+ @param e Encoding (only used for 8-bit characters).
+ @return 1 on success, 0 on error.
+*/
+int
+dk3uc2lat_stputs(dk3_uc2lat_t *u, dk3_stream_t *st, dkChar const *t, int e);
+
+#if HAVE_PACKAGES
+
+/** Prepare LaTeX encoder to retrieve package information.
+ @param u LaTeX encoder.
+*/
+void
+dk3uc2lat_package_reset(dk3_uc2lat_t *u);
+
+/** Retrieve next package information from LaTeX encoder.
+ @param u LaTeX encoder.
+ @return Pointer to next package information or NULL.
+*/
+dk3_uc2lat_pkg_t *
+dk3uc2lat_package_next(dk3_uc2lat_t *u);
+
+#endif
+
+/** Reset font encoding information.
+ @param u LaTeX encoder.
+*/
+void
+dk3uc2lat_font_encoding_reset(dk3_uc2lat_t *u);
+
+/** Check for font encoding conflicts.
+ @param u LaTeX encoder.
+ @return 1 on conflicts, 0 otherwise (no problems).
+*/
+int
+dk3uc2lat_font_encoding_conflict(dk3_uc2lat_t *u);
+
+/** Report font encoding requirement conflicts.
+ @param u LaTeX encoder.
+*/
+void
+dk3uc2lat_font_encoding_report_conflict(dk3_uc2lat_t *u);
+
+/** Report font encoding requirement conflicts.
+ @param u LaTeX encoder.
+*/
+void
+dk3uc2lat_font_encoding_report(dk3_uc2lat_t *u);
+
+/** Write some final comments to output stream about
+ usable encdings and required packages.
+ @param u LaTeX encoder.
+ @param st Output stream.
+*/
+void
+dk3uc2lat_final_report(dk3_uc2lat_t *u, dk3_stream_t *st);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+%% module
+
+/** Enable or disable support for dk3_uc2l_pkg_t.
+*/
+#define HAVE_PACKAGES 1
+
+
+#include "dk3all.h"
+#include "dk3maih8.h"
+
+
+$!trace-include
+
+
+
+/** LaTeX commands to start and end math mode.
+*/
+static char const * const dk3uc2lat_mm[] = {
+"\\(",
+"\\)",
+"% font encodings:",
+"% package: ",
+"\n",
+};
+
+
+
+#if 0
+/** Font encoding names.
+*/
+static char const * const dk3uc2lat_font_encodings[] = {
+"ot1",
+"!ot1",
+"t1",
+"!t1",
+"t4",
+"!t4",
+"t5",
+"!t5",
+NULL
+};
+#endif
+
+
+
+/** Font encoding names, used in error messages.
+*/
+static dkChar const * const dk3uc2l_font_encoding_names[] = {
+dkT("OT1"),
+dkT("T1"),
+dkT("T4"),
+dkT("T5"),
+NULL
+};
+
+
+
+/** Font encoding names written at end of output file.
+*/
+static const char * const dk3uc2l_c8_font_encoding_names[] = {
+$!string-table
+ OT1
+ T1
+ T4
+ T5
+$!end
+};
+
+
+
+/** Allowed suffixes for conversion data files.
+*/
+static dkChar const * const dk3uc2l_suffixes[] = {
+dkT(".t2l"),
+#if DK3_HAVE_ZLIB_H && (DK3_CHAR_SIZE == 1)
+dkT(".t2l.gz"),
+#endif
+#if DK3_HAVE_BZLIB_H && (DK3_CHAR_SIZE == 1)
+dkT(".t2l.bz2"),
+#endif
+NULL
+};
+
+
+
+/** Compression suffixes.
+*/
+static dkChar const * const dk3uc2l_co_suf[] = {
+$!string-table macro=dkT
+.gz
+.bz2
+$!end
+};
+
+
+
+/** Attribute keywords.
+*/
+static const char * const dk3uc2l_kw[] = {
+$!string-table
+b$oth
+t$ext
+m$ath
+e$ncoding
+p$ackages
+$!end
+};
+
+
+
+/** Encoding names, used for reporting.
+*/
+static const char * const dk3uc2l_enco[] = {
+$!string-table
+ot1
+t1
+t4
+t5
+$!end
+};
+
+
+
+/** Release an array of string pointers.
+ @param ap Array base address.
+ @param ns Number of strings.
+*/
+static
+void
+dk3uc2lat_release_pointer_array(char const **ap, size_t ns)
+{
+ char const **ptr; /* Current string in array. */
+ size_t i; /* Current string index in array. */
+ $? "+ dk3uc2lat_release_pointer_array %lu", (unsigned long)ns
+ ptr = ap; i = ns;
+ while(i--) {
+ dk3_release(*ptr);
+ ptr++;
+ } $? "- dk3uc2lat_release_pointer_array"
+ dk3_delete(ap);
+}
+
+
+
+/** Destroy range structure, release memory.
+ @param rp Structure to destroy.
+*/
+static
+void
+dk3uc2lat_range_delete(dk3_uc2lat_range_t *rp)
+{
+ size_t numchar; /* Number of characters in this range. */
+ dkChar const **ptr; /* Release all descriptions. */
+ dk3_uc2lat_pkg_t ***pkgppp;
+ size_t i; /* Number of descriptions to release. */
+ $? "+ dk3uc2lat_range_delete %lx %lx", (unsigned long)(rp->start), (unsigned long)(rp->end)
+ if(rp) {
+ numchar = (size_t)(rp->end - rp->start + 1);
+ if(numchar > 0) {
+ rp->dir = NULL;
+ if(rp->f) {
+ dk3_release(rp->f);
+ } rp->f = NULL;
+ if(rp->dsc) {
+ ptr = rp->dsc;
+ i = (size_t)(rp->end - rp->start + 1);
+ while(i--) {
+ dk3_release(*ptr);
+ ptr++;
+ }
+ } rp->dsc = NULL;
+ if(rp->a) {
+ dk3uc2lat_release_pointer_array(rp->a, numchar);
+ } rp->a = NULL;
+ if(rp->t) {
+ dk3uc2lat_release_pointer_array(rp->t, numchar);
+ } rp->t = NULL;
+ if(rp->m) {
+ dk3uc2lat_release_pointer_array(rp->m, numchar);
+ } rp->m = NULL;
+ if(rp->p) {
+ pkgppp = rp->p;
+ i = (size_t)(rp->end - rp->start + 1);
+ while (i--) {
+ dk3_release(*pkgppp);
+ pkgppp++;
+ }
+ dk3_delete(rp->p);
+ } rp->p = NULL;
+ rp->start = (dk3_c32_t)0UL; rp->end = (dk3_c32_t)0UL;
+ rp->ia = 0x00;
+ }
+ dk3_delete(rp);
+ } $? "- dk3uc2lat_range_delete"
+}
+
+
+#if HAVE_PACKAGES
+
+/** Destroy package structure, release memory.
+ @param pp Structure to release.
+*/
+static
+void
+dk3uc2lat_pkg_delete(dk3_uc2lat_pkg_t *pp)
+{
+ $? "+ dk3uc2lat_pkg_delete %!8s", TR_8PTR(pp)
+ if(pp) { $? ". pkg name = \"%!8s\"", TR_8STR(pp->name)
+ dk3_release(pp->name);
+ pp->used = 0x00;
+ dk3_delete(pp);
+ } $? "- dk3uc2lat_pkg_delete"
+}
+
+#endif
+
+
+/** Destroy UC to LaTeX directory structure, release memory.
+ @param dp Structure to destroy.
+*/
+static
+void
+dk3uc2lat_dir_delete(dk3_uc2lat_dir_t *dp)
+{
+ $? "+ dk3uc2lat_dir_delete %!8s", TR_8PTR(dp)
+ if(dp) {
+ if(dp->s_ran) {
+ if(dp->i_ran) {
+ dk3sto_it_close(dp->i_ran);
+ } dp->i_ran = NULL;
+ dk3sto_close(dp->s_ran);
+ } dp->s_ran = NULL;
+ dk3_release(dp->sn);
+ dp->loaded = 0x00;
+ dk3_delete(dp);
+ } $? "- dk3uc2lat_dir_delete"
+}
+
+
+
+#if HAVE_PACKAGES
+
+/** Compare two package records.
+ @param l Left record.
+ @param r Right record or name.
+ @param cr Comparison criteria (0=record/record, 1=record/name).
+ @return Comparison result.
+*/
+static
+int
+dk3uc2lat_pkg_compare(void const *l, void const *r, int cr)
+{
+ int back = 0;
+ dk3_uc2lat_pkg_t const *pl; /* Left pointer. */
+ dk3_uc2lat_pkg_t const *pr; /* Right pointer. */
+
+ pl = (dk3_uc2lat_pkg_t const *)l;
+ pr = (dk3_uc2lat_pkg_t const *)r;
+ if(l) {
+ if(r) {
+ switch(cr) {
+ case 1: {
+ if(pl->name) {
+ back = dk3str_c8_cmp(pl->name, (char const *)r);
+ } else { back = -1; }
+ } break;
+ default: {
+ if(pl->name) {
+ if(pr->name) {
+ back = dk3str_c8_cmp(pl->name, pr->name);
+ } else { back = 1; }
+ } else {
+ if(pr->name) { back = -1; }
+ }
+ } break;
+ }
+ } else { back = 1; }
+ } else {
+ if(r) { back = -1; }
+ }
+ if(back < -1) { back = -1; }
+ if(back > 1) { back = 1; }
+ return back;
+}
+
+#endif
+
+
+
+/** Compare two range structures by start and end character.
+ @param l Left structure.
+ @param r Right structure/UC character.
+ @param cr Comparison criteria (0=struct/struct, 1=struct/char).
+ @return Comparison result.
+*/
+static
+int
+dk3uc2lat_range_compare(void const *l, void const *r, int cr)
+{
+ int back = 0;
+ dk3_uc2lat_range_t const *pl; /* Left pointer. */
+ dk3_uc2lat_range_t const *pr; /* Right pointer. */
+ dk3_c32_t *ucptr; /* Right pointer is a character pointer. */
+
+ pl = (dk3_uc2lat_range_t const *)l;
+ pr = (dk3_uc2lat_range_t const *)r;
+ if(l) {
+ if(r) {
+ switch(cr) {
+ case 1: {
+ ucptr = (dk3_c32_t *)r;
+ if(pl->start > (*ucptr)) {
+ back = 1;
+ } else {
+ if(pl->end < (*ucptr)) {
+ back = -1;
+ }
+ }
+ } break;
+ default: {
+ if(pl->start > pr->end) {
+ back = 1;
+ } else {
+ if(pl->end < pr->start) {
+ back = -1;
+ }
+ }
+ } break;
+ }
+ } else { back = 1; }
+ } else {
+ if(r) { back = -1; }
+ }
+ return back;
+}
+
+
+
+/** Compare two UC to LaTeX directory structures.
+ @param l Left structure.
+ @param r Right structure/name.
+ @param cr Comparison criteria (0=struct/struct, 1=struct/name).
+ @return Comparison result.
+*/
+static
+int
+dk3uc2lat_dir_compare(void const *l, void const *r, int cr)
+{
+ int back = 0;
+ dk3_uc2lat_dir_t const *pl; /* Left pointer. */
+ dk3_uc2lat_dir_t const *pr; /* Right pointer. */
+
+ pl = (dk3_uc2lat_dir_t const *)l;
+ pr = (dk3_uc2lat_dir_t const *)r;
+ if(l) {
+ if(r) {
+ switch(cr) {
+ case 1: {
+ if(pl->sn) {
+ back = dk3str_fncmp(pl->sn, (dkChar const *)r);
+ } else { back = -1; }
+ } break;
+ default: {
+ if(pl->sn) {
+ if(pr->sn) {
+ back = dk3str_fncmp(pl->sn, pr->sn);
+ } else { back = 1; }
+ } else {
+ if(pr->sn) { back = -1; }
+ }
+ } break;
+ }
+ } else { back = 1; }
+ } else {
+ if(r) { back = -1; }
+ }
+ return back;
+}
+
+
+
+void
+dk3uc2lat_close(dk3_uc2lat_t *u)
+{
+#if HAVE_PACKAGES
+ dk3_uc2lat_pkg_t *ppkg;
+#endif
+ dk3_uc2lat_dir_t *pdir;
+ dk3_uc2lat_range_t *pran;
+ $? "+ dk3uc2lat_close"
+ if (NULL != u) {
+ u->app = NULL;
+ dk3_release(u->dir);
+ dk3_release(u->buf);
+ if (NULL != u->s_ran) {
+ if (NULL != u->i_ran) {
+ dk3sto_it_reset(u->i_ran);
+ do {
+ pran = (dk3_uc2lat_range_t *)dk3sto_it_next(u->i_ran);
+ if (NULL != pran) {
+ dk3uc2lat_range_delete(pran);
+ }
+ } while (NULL != pran);
+ dk3sto_it_close(u->i_ran);
+ }
+ dk3sto_close(u->s_ran);
+ }
+ u->s_ran = NULL; u->i_ran = NULL;
+ if (NULL != u->s_dir) {
+ if (NULL != u->i_dir) {
+ dk3sto_it_reset(u->i_dir);
+ do {
+ pdir = (dk3_uc2lat_dir_t *)dk3sto_it_next(u->i_dir);
+ if (NULL != pdir) {
+ dk3uc2lat_dir_delete(pdir);
+ }
+ } while (NULL != pdir);
+ dk3sto_it_close(u->i_dir);
+ }
+ dk3sto_close(u->s_dir);
+ }
+ u->s_dir = NULL; u->i_dir = NULL;
+#if HAVE_PACKAGES
+ if (NULL != u->s_pkg) {
+ if (NULL != u->i_pkg) {
+ dk3sto_it_reset(u->i_pkg);
+ do {
+ ppkg = (dk3_uc2lat_pkg_t *)dk3sto_it_next(u->i_pkg);
+ if (NULL != ppkg) {
+ dk3uc2lat_pkg_delete(ppkg);
+ }
+ } while (NULL != ppkg);
+ dk3sto_it_close(u->i_pkg);
+ }
+ dk3sto_close(u->s_pkg);
+ }
+ u->s_pkg = NULL; u->i_pkg = NULL;
+#endif
+ u->rca = NULL;
+ u->szbuf = 0;
+ u->f_dsc = 0;
+ u->f_utf8 = 0;
+ u->fe = 0;
+ dk3_delete(u);
+ }
+ $? "- dk3uc2lat_close"
+}
+
+
+
+#if HAVE_PACKAGES
+
+/** Create package structure, allocate memory.
+ @param pn Package name.
+ @param app Application structure for diagnostics.
+ @return Pointer to new structure on success, NULL on error.
+*/
+static
+dk3_uc2lat_pkg_t *
+dk3uc2lat_pkg_new(char const *pn, dk3_app_t *app)
+{
+ dk3_uc2lat_pkg_t *back = NULL;
+ $? "+ dk3uc2lat_pkg_new \"%!8s\"", TR_8STR(pn)
+ back = dk3_new_app(dk3_uc2lat_pkg_t,1,app);
+ if(back) {
+ back->used = 0x00;
+ back->name = dk3str_c8_dup_app(pn,app);
+ if(!(back->name)) {
+ dk3uc2lat_pkg_delete(back);
+ back = NULL;
+ }
+ } $? "- dk3uc2lat_pkg_new %!8s", TR_8PTR(back)
+ return back;
+}
+
+#endif
+
+
+/** Create range structure, allocate memory.
+ @param start Start character of range.
+ @param end End character of range.
+ @param dir Directory structure (parent of this range).
+ @param app Application structure for diagnostics.
+ @return Pointer to new range structure on success, NULL on error.
+*/
+static
+dk3_uc2lat_range_t *
+dk3uc2lat_range_new(
+ dk3_c32_t start, dk3_c32_t end, dk3_uc2lat_dir_t *dir, dk3_app_t *app
+)
+{
+ dk3_uc2lat_range_t *back = NULL;
+ char range_text[32]; /* Buffer for number range. */
+ dkChar dk_range_text[32]; /* Buffer for number range. */
+ $? "+ dk3uc2lat_range_new %lx %lx", (unsigned long)(start), (unsigned long)(end)
+ if(dk3app_max_log_level(app) >= DK3_LL_DEBUG) {
+ sprintf(range_text, "%lx-%lx", (long)start, (long)end);
+ (void)dk3str_c8_to_str_simple_app(dk_range_text, 32, range_text, app);
+ dk3app_log_i3(app, DK3_LL_DEBUG, 238, 239, dk_range_text);
+ }
+ if(end >= start) {
+ back = dk3_new_app(dk3_uc2lat_range_t,1,app);
+ if(back) {
+ back->dir = dir;
+ back->dsc = NULL;
+ back->a = NULL;
+ back->t = NULL;
+ back->m = NULL;
+#if HAVE_PACKAGES
+ back->p = NULL;
+#endif
+ back->f = NULL;
+ back->start = start;
+ back->end = end;
+ back->ia = 0x00;
+ }
+ } else {
+ if(app) {
+ dk3app_log_i1(app, DK3_LL_ERROR, 220);
+ }
+ } $? "- dk3uc2lat_range_new %!8s", TR_8PTR(back)
+ return back;
+}
+
+
+
+/** Create UC to LaTeX directory structure, allocate memory.
+ @param sn Short directory file name.
+ @param app Application structure for diagnostics.
+ @return Pointer to new directory structure on success, NULL on error.
+*/
+static
+dk3_uc2lat_dir_t *
+dk3uc2lat_dir_new(dkChar const *sn, dk3_app_t *app)
+{
+ dk3_uc2lat_dir_t *back = NULL;
+ $? "+ dk3uc2lat_dir_new \"%!ds\"", TR_STR(sn)
+ back = dk3_new_app(dk3_uc2lat_dir_t,1,app);
+ if(back) {
+ back->s_ran = NULL; back->i_ran = NULL; back->sn = NULL;
+ back->loaded = 0x00;
+ back->s_ran = dk3sto_open_app(app);
+ if(back->s_ran) {
+ dk3sto_set_comp(back->s_ran, dk3uc2lat_range_compare, 0);
+ back->i_ran = dk3sto_it_open(back->s_ran);
+ if(back->i_ran) {
+ back->sn = dk3str_dup_app(sn,app);
+ }
+ }
+ if(!((back->s_ran) && (back->i_ran) && (back->sn))) {
+ dk3uc2lat_dir_delete(back); back = NULL;
+ }
+ } $? "- dk3uc2lat_dir_new PTR:%d", TR_IPTR(back)
+ return back;
+}
+
+
+
+/** Create new LaTeX encoder.
+ @param dn Directory containing the data files.
+ @param f_utf8 Flag: Allowed to write UTF-8 output.
+ @param app Application structure for diagnostics, may be NULL.
+ @return Pointer to new encoder on success, NULL on error.
+*/
+static
+dk3_uc2lat_t *
+dk3uc2lat_t_new(
+ const dkChar *dn,
+ int f_utf8,
+ dk3_app_t *app
+)
+{
+ dk3_uc2lat_t *back = NULL;
+ int ok = 0;
+ $? "+ dk3uc2lat_t_new %!ds", dn
+ back = dk3_new_app(dk3_uc2lat_t,1,app);
+ if (NULL != back) {
+ back->app = app;
+ back->dir = NULL;
+ back->buf = NULL;
+ back->s_ran = NULL;
+ back->i_ran = NULL;
+ back->s_dir = NULL;
+ back->i_dir = NULL;
+#if HAVE_PACKAGES
+ back->s_pkg = NULL;
+ back->i_pkg = NULL;
+#endif
+ back->rca = NULL;
+ back->szbuf = 0;
+ back->f_dsc = 0;
+ back->f_utf8 = f_utf8;
+ back->fe =
+ DK3_FONT_ENCODING_OT1 + DK3_FONT_ENCODING_T1
+ + DK3_FONT_ENCODING_T4 + DK3_FONT_ENCODING_T5;
+ back->dir = dk3str_dup_app(dn, app);
+ back->buf = dk3_new_app(char,16,app);
+ if (NULL != back->buf) { back->szbuf = 16; }
+ if ((NULL != back->dir) && (NULL != back->buf)) {
+ back->s_ran = dk3sto_open_app(app);
+ if (NULL != back->s_ran) {
+ dk3sto_set_comp(back->s_ran, dk3uc2lat_range_compare, 0);
+ back->s_dir = dk3sto_open_app(app);
+ if (NULL != back->s_dir) {
+ dk3sto_set_comp(back->s_dir, dk3uc2lat_dir_compare, 0);
+#if HAVE_PACKAGES
+ back->s_pkg = dk3sto_open_app(app);
+ if (NULL != back->s_pkg) {
+ dk3sto_set_comp(back->s_pkg, dk3uc2lat_pkg_compare, 0);
+#endif
+ back->i_ran = dk3sto_it_open(back->s_ran);
+ if (NULL != back->i_ran) {
+ back->i_dir = dk3sto_it_open(back->s_dir);
+ if (NULL != back->i_dir) {
+#if HAVE_PACKAGES
+ back->i_pkg = dk3sto_it_open(back->s_pkg);
+ if (NULL != back->i_pkg) {
+#endif
+ ok = 1;
+#if HAVE_PACKAGES
+ }
+#endif
+ }
+ }
+#if HAVE_PACKAGES
+ }
+#endif
+ }
+ }
+ }
+ if (0 == ok) {
+ dk3uc2lat_close(back);
+ back = NULL;
+ }
+ } $? "- dk3uc2lat_t_new PTR:%d", TR_IPTR(back)
+ return back;
+}
+
+
+
+/** Check the file name whether it contains LaTeX conversion data
+ and can be processed.
+ @param fn File name to check.
+ @return 1 if yes, 0 otherwise.
+*/
+static
+int
+dk3uc2lat_is_suitable_file(const dkChar *fn)
+{
+ const dkChar * const *ptr; /* Traverse allowed suffixes array */
+ size_t szfn = 0; /* File name size */
+ size_t szsu = 0; /* Allowed suffix size */
+ int back = 0;
+ $? "+ dk3uc2lat_is_suitable_file %!ds", fn
+ szfn = dk3str_len(fn);
+ ptr = dk3uc2l_suffixes;
+ while ((NULL != *ptr) && (0 == back)) {
+ szsu = dk3str_len(*ptr);
+ if (szfn > szsu) {
+ if (0 == dk3str_fncmp(&(fn[szfn - szsu]), *ptr)) {
+ back = 1;
+ }
+ }
+ ptr++;
+ } $? "- dk3uc2lat_is_suitable_file %d", back
+ return back;
+}
+
+
+
+/** Add one character to the range descriptions of a file directory.
+ @param uptr Conversion structure to set up.
+ @param pdir File directory to set up.
+ @param chr Character to add.
+ @param app Application structure for diagnostics, may be NULL.
+ @return 1 on success, 0 on error.
+*/
+static
+int
+dk3uc2l_add_char_to_dir(
+ dk3_uc2lat_t *uptr,
+ dk3_uc2lat_dir_t *pdir,
+ dk3_c32_t chr,
+ dk3_app_t *app
+)
+{
+ dkChar cbuf[64];
+ dk3_uc2lat_range_t *prange;
+ dk3_uc2lat_range_t *pr2;
+ size_t szcbuf = DK3_SIZEOF(cbuf,dkChar);
+ dk3_c32_t tchr;
+ int back = 0;
+ $? "+ dk3uc2l_add_char_to_dir %lx", (unsigned long)chr
+ prange = dk3sto_it_find_like(uptr->i_ran, &chr, 1);
+ if (NULL == prange) {
+ prange = dk3sto_it_find_like(pdir->i_ran, &chr, 1);
+ if (NULL == prange) {
+ if ((dk3_c32_t)0UL < chr) { $? ". try to append"
+ tchr = chr - 1;
+ prange = dk3sto_it_find_like(pdir->i_ran, &tchr, 1);
+ if (NULL != prange) { $? ". found %lx-%lx", (unsigned long)(prange->start), (unsigned long)(prange->end)
+ prange->end = chr;
+ back = 1; $? ". changed to %lx-%lx", (unsigned long)(prange->start), (unsigned long)(prange->end)
+ if (0xFFFFFFFFUL > (unsigned long)chr) {
+ tchr = chr + (dk3_c32_t)1UL;
+ pr2 = dk3sto_it_find_like(pdir->i_ran, &tchr, 1);
+ if (NULL != pr2) { $? ". found %lx-%lx", (unsigned long)(pr2->start), (unsigned long)(pr2->end)
+ tchr = pr2->end;
+ dk3sto_remove(pdir->s_ran, pr2);
+ dk3uc2lat_range_delete(pr2);
+ prange->end = tchr;
+ $? ". changed %lx-%lx", (unsigned long)(prange->start), (unsigned long)(prange->end)
+ }
+ }
+ }
+ }
+ if (0 == back) { $? ". try to prepend"
+ if (0xFFFFFFFFUL > (unsigned long)chr) { $? ". can"
+ tchr = chr + (dk3_c32_t)1UL;
+ prange = dk3sto_it_find_like(pdir->i_ran, &tchr, 1);
+ if (NULL != prange) { $? ". found %lx-%lx", (unsigned long)(prange->start), (unsigned long)(prange->end)
+ prange->start = chr;
+ back = 1; $? ". changed to %lx-%lx", (unsigned long)(prange->start), (unsigned long)(prange->end)
+ }
+ }
+ }
+ if (0 == back) { $? ". try to add"
+ prange = dk3uc2lat_range_new(chr, chr, pdir, app);
+ if (NULL != prange) {
+ if (dk3sto_add(pdir->s_ran, prange)) {
+ back = 1; $? ". added %lx-%lx", (unsigned long)(prange->start), (unsigned long)(prange->end)
+ } else {
+ dk3uc2lat_range_delete(prange);
+ }
+ }
+ }
+ } else { $? "! already found"
+ /* ERROR: Already found! */
+ if (0 != dk3ma_um_to_hex_string(cbuf, szcbuf, (dk3_um_t)chr, 8)) {
+ dk3app_log_i3(uptr->app, DK3_LL_ERROR, 395, 396, cbuf);
+ } else {
+ dk3app_log_i1(uptr->app, DK3_LL_ERROR, 397);
+ }
+ }
+ } else { $? "! already found"
+ /* ERROR: Already found ! */
+ if (0 != dk3ma_um_to_hex_string(cbuf, szcbuf, (dk3_um_t)chr, 8)) {
+ dk3app_log_i3(uptr->app, DK3_LL_ERROR, 395, 396, cbuf);
+ } else {
+ dk3app_log_i1(uptr->app, DK3_LL_ERROR, 397);
+ }
+ } $? "- dk3uc2l_add_char_to_dir %d", back
+ return back;
+}
+
+
+
+/** Apply data from stream to directory information for one file.
+ @param uptr Conversion structure to set up.
+ @param pdir File directory entry to configure.
+ @param istrm Input stream for file (normal or compressed).
+ @param fn Full path name.
+ @param sn Short file name.
+ @param app Application structure for diagnostics, may be NULL.
+ @return 1 on success, 0 on error.
+*/
+static
+int
+dk3uc2l_apply_1(
+ dk3_uc2lat_t *uptr,
+ dk3_uc2lat_dir_t *pdir,
+ dk3_stream_t *istrm,
+ const dkChar *fn,
+ const dkChar *sn,
+ dk3_app_t *app
+)
+{
+ char buf[512];
+ char *p1;
+ char *p2;
+ dk3_uc2lat_range_t *prange;
+ unsigned long lineno = 0UL;
+ unsigned long chr;
+ int back = 1;
+ $? "+ dk3uc2l_apply_1"
+ while ((1 == back) && (1 == dk3stream_c8_fgets(istrm, buf, sizeof(buf)))) {
+ dk3app_set_source_line(app, ++lineno);
+ buf[sizeof(buf) - 1] = '\0';
+ $? ". processing line %lu: %s", lineno, buf
+ p1 = dk3str_c8_start(buf, NULL);
+ if (NULL != p1) {
+ if ('#' != *p1) {
+ p2 = dk3str_c8_next(p1, NULL);
+ if (NULL != p2) {
+ if (0 != dk3ma_ul_from_c8_hex_string(&chr, p1, NULL)) {
+ if (0 == dk3uc2l_add_char_to_dir(uptr, pdir, chr, app)) {
+ back = 0; $? "! failed to add %lx", chr
+ }
+ } else {
+ /* ERROR: Syntax error, not a hexadecimal number */
+ dk3app_log_i1(uptr->app, DK3_LL_ERROR, 398);
+ }
+ } else {
+ /* ERROR: Syntax error, missing configuration */
+ dk3app_log_i1(uptr->app, DK3_LL_ERROR, 400);
+ }
+ }
+ }
+ }
+ if (1 == back) { $? ". copying ranges to global container"
+ dk3sto_it_reset(pdir->i_ran);
+ do {
+ prange = dk3sto_it_next(pdir->i_ran);
+ if (NULL != prange) { $? ". range %lx-%lx", (unsigned long)(prange->start), (unsigned long)(prange->end)
+ if (0 == dk3sto_add(uptr->s_ran, prange)) {
+ dk3uc2lat_range_delete(prange);
+ back = 0; $? "! failed to copy range"
+ }
+ }
+ } while (NULL != prange);
+ } else { $? "! deleting ranges due to error"
+ dk3sto_it_reset(pdir->i_ran);
+ do {
+ prange = dk3sto_it_next(pdir->i_ran);
+ if (NULL != prange) {
+ dk3uc2lat_range_delete(prange);
+ }
+ } while (NULL != prange);
+ } $? "- dk3uc2l_apply_1 %d", back
+ return back;
+}
+
+
+
+/** Apply directory information for a file.
+ @param uptr Conversion structure to set up.
+ @param fn File name containing conversion data.
+ @param app Application structure for diagnostics, may be NULL.
+ @return 1 on success, 0 on error.
+*/
+static
+int
+dk3uc2lat_pass_1(
+ dk3_uc2lat_t *uptr, const dkChar *fn, const dkChar *sn, dk3_app_t *app
+)
+{
+ dk3_uc2lat_dir_t *pdir = NULL;
+ dk3_stream_t *istrm = NULL;
+ FILE *fipo = NULL;
+ const dkChar *oldsrc = NULL;
+ const dkChar *fsuf = NULL;
+#if DK3_HAVE_ZLIB_H && (DK3_CHAR_SIZE == 1)
+ gzFile gzf = NULL;
+#endif
+#if DK3_HAVE_BZLIB_H && (DK3_CHAR_SIZE == 1)
+ BZFILE *bzf = NULL;
+#endif
+ unsigned long oldln = 0UL;
+#if DK3_HAVE_FNCASEINS
+ int fncs = 0;
+#else
+ int fncs = 1;
+#endif
+ int back = 0;
+ $? ". dk3uc2lat_pass_1 %!ds", fn
+ pdir = dk3uc2lat_dir_new(sn, app);
+ if (NULL != pdir) {
+ oldsrc = dk3app_get_source_file(app);
+ oldln = dk3app_get_source_line(app);
+ dk3app_set_source_file(app, fn);
+ dk3app_set_source_line(app, 0UL);
+ if (0 != dk3sto_add(uptr->s_dir, pdir)) {
+ fsuf = dk3str_get_suffix(fn);
+ switch (dk3str_array_index(dk3uc2l_co_suf, fsuf, fncs)) {
+ case 0: { /* gz */
+#if DK3_HAVE_ZLIB_H && (DK3_CHAR_SIZE == 1)
+ gzf = gzopen(fn, "r");
+ if (NULL != gzf) {
+ istrm = dk3stream_open_gz_app(gzf, DK3_STREAM_FLAG_READ, app);
+ if (NULL != istrm) {
+ back = dk3uc2l_apply_1(uptr, pdir, istrm, fn, sn, app);
+ (void)dk3stream_close(istrm);
+ }
+ gzclose(gzf);
+ } else {
+ /* ERROR: Failed to open file */
+ dk3app_log_i3(uptr->app, DK3_LL_ERROR, 143, 144, fn);
+ }
+#else
+ /* ERROR: No zlib support */
+ dk3app_log_i1(uptr->app, DK3_LL_ERROR, 401);
+#endif
+ } break;
+ case 1: { /* bz2 */
+#if DK3_HAVE_BZLIB_H && (DK3_CHAR_SIZE == 1)
+ bzf = BZ2_bzopen(fn, "r");
+ if (NULL != bzf) {
+ istrm = dk3stream_open_bz2_app(bzf, DK3_STREAM_FLAG_READ, app);
+ if (NULL != istrm) {
+ back = dk3uc2l_apply_1(uptr, pdir, istrm, fn, sn, app);
+ (void)dk3stream_close(istrm);
+ }
+ BZ2_bzclose(bzf);
+ } else {
+ /* ERROR: Failed to open file */
+ dk3app_log_i3(uptr->app, DK3_LL_ERROR, 143, 144, fn);
+ }
+#else
+ /* ERROR: No bzip2 support */
+ dk3app_log_i1(uptr->app, DK3_LL_ERROR, 402);
+#endif
+ } break;
+ default : { /* normal file */
+ fipo = dk3sf_fopen_app(fn, dkT("r"), app);
+ if (NULL != fipo) {
+ istrm = dk3stream_open_file_app(fipo, DK3_STREAM_FLAG_READ, app);
+ if (NULL != istrm) {
+ back = dk3uc2l_apply_1(uptr, pdir, istrm, fn, sn, app);
+ (void)dk3stream_close(istrm);
+ }
+ fclose(fipo);
+ }
+ } break;
+ }
+ } else {
+ dk3uc2lat_dir_delete(pdir);
+ }
+ dk3app_set_source_file(app, oldsrc);
+ dk3app_set_source_line(app, oldln);
+ } $? "- dk3uc2lat_pass_1 %d", back
+ return back;
+}
+
+
+
+/** Read directory information (check existing data files, retrieve ranges.
+ @param d Directory containing the data files.
+ @param uptr Conversion structure to initialize.
+ @param app Application structure for diagnostics, may be NULL.
+ @return 1 on success, 0 on error.
+*/
+static
+int
+dk3uc2lat_read_dir_info(dk3_uc2lat_t *uptr, dk3_app_t *app)
+{
+ dk3_dir_t *dir = NULL;
+ const dkChar *fn = NULL;
+ const dkChar *sn = NULL;
+ int back = 0;
+ int found = 0;
+ $? "+ dk3uc2lat_read_dir_info"
+ dir = dk3dir_open_app(uptr->dir, uptr->app);
+ if (NULL != dir) {
+ back = 1;
+ while (0 != dk3dir_get_next_file(dir)) {
+ sn = dk3dir_get_shortname(dir);
+ fn = dk3dir_get_fullname(dir);
+ if ((NULL != sn) && (NULL != fn)) {
+ if (0 != dk3uc2lat_is_suitable_file(fn)) {
+ found = 1;
+ if (0 == dk3uc2lat_pass_1(uptr, fn, sn, app)) {
+ back = 0;
+ }
+ }
+ }
+ }
+ dk3dir_close(dir);
+ if (0 == found) {
+ back = 0;
+ /* ERROR: No suitable files found */
+ dk3app_log_i1(uptr->app, DK3_LL_ERROR, 403);
+ }
+ }
+ $? "- dk3uc2lat_read_dir_info %d", back
+ return back;
+}
+
+
+
+/** Allocate memory for all ranges details for a file directory.
+ @param uptr Conversion structure to set up.
+ @param pdir Directory information to set up.
+ @return 1 on success, 0 on error.
+*/
+static
+int
+dk3uc2l_allocate_memory(
+ dk3_uc2lat_t *uptr,
+ dk3_uc2lat_dir_t *pdir
+)
+{
+ dk3_uc2lat_range_t *prange;
+ size_t sz;
+ size_t i;
+ int back = 1;
+ int allenc = 0;
+
+ dk3sto_it_reset(pdir->i_ran);
+ allenc = DK3_FONT_ENCODING_OT1
+ + DK3_FONT_ENCODING_T1
+ + DK3_FONT_ENCODING_T4
+ + DK3_FONT_ENCODING_T5;
+ do {
+ prange = (dk3_uc2lat_range_t *)dk3sto_it_next(pdir->i_ran);
+ if (NULL != prange) {
+ sz = (size_t)(prange->end - prange->start) + 1;
+ if (NULL == prange->a) {
+ prange->a = dk3_new_app(DK3_PCCHAR,sz,uptr->app);
+ if (NULL != prange->a) {
+ for (i = 0; i < sz; i++) { (prange->a)[i] = NULL; }
+ } else {
+ back = 0;
+ }
+ }
+ if (NULL == prange->t) {
+ prange->t = dk3_new_app(DK3_PCCHAR,sz,uptr->app);
+ if (NULL != prange->t) {
+ for (i = 0; i < sz; i++) { (prange->t)[i] = NULL; }
+ } else {
+ back = 0;
+ }
+ }
+ if (NULL == prange->m) {
+ prange->m = dk3_new_app(DK3_PCCHAR,sz,uptr->app);
+ if (NULL != prange->m) {
+ for (i = 0; i < sz; i++) { (prange->m)[i] = NULL; }
+ } else {
+ back = 0;
+ }
+ }
+#if HAVE_PACKAGES
+ if (NULL == prange->p) {
+ prange->p = dk3_new_app(dk3_uc2lat_pkg_pptr,sz,uptr->app);
+ if (NULL != prange->p) {
+ for (i = 0; i < sz; i++) { (prange->p)[i] = NULL; }
+ } else {
+ back = 0;
+ }
+ }
+#endif
+ if (NULL == prange->f) {
+ prange->f = dk3_new_app(dk3_font_encoding_t,sz,uptr->app);
+ if (NULL != prange->f) {
+ for(i = 0; i < sz; i++) { (prange->f)[i] = allenc; }
+ } else {
+ back = 0;
+ }
+ }
+ }
+ } while (NULL != prange);
+ return back;
+}
+
+
+
+static
+void
+dk3uc2l_apply_2(
+ dk3_uc2lat_t *uptr,
+ dk3_uc2lat_dir_t *pdir,
+ dk3_stream_t *istrm,
+ const dkChar *filename
+)
+{
+ char buf[512]; /* Input line buffer */
+#if HAVE_PACKAGES
+ char *parts[16]; /* Package names */
+#endif
+ char *p1; /* Hex value or next item */
+ char *p2; /* Current item key */
+ char *p3; /* Current item value */
+ char *p4; /* Dynamic value copy */
+ dk3_uc2lat_range_t *prange; /* Current range */
+#if HAVE_PACKAGES
+ dk3_uc2lat_pkg_t *ppkg; /* Current package */
+#endif
+ unsigned long lineno = 0UL; /* Current line number */
+ unsigned long chr; /* Current character */
+ size_t ind; /* Index of chr in range */
+#if HAVE_PACKAGES
+ size_t nparts; /* Number of packages */
+ size_t i; /* Traverse */
+ size_t j; /* Add new packages */
+#endif
+ int cc = 1; /* Flag: Can continue */
+ int action; /* Action to take */
+ int isneg; /* Flag: Deny encodings */
+ int encod; /* Encodings selection */
+ $? "+ dk3uc2l_apply_2"
+ while ((1 == cc) && (1 == dk3stream_c8_fgets(istrm, buf, sizeof(buf)))) {
+ dk3app_set_source_line(uptr->app, ++lineno);
+ buf[sizeof(buf) - 1] = '\0';
+ $? ". processing line %lu: %s", lineno, buf
+ p1 = dk3str_c8_start(buf, NULL);
+ if (NULL != p1) { $? ". p1=\"%!8s\"", p1
+ if ('#' != *p1) { $? ". normal line"
+ p2 = dk3str_c8_next(p1, NULL);
+ if (NULL != p2) { $? ". attributes=\"%!8s\"", p2
+ if (0 != dk3ma_ul_from_c8_hex_string(&chr, p1, NULL)) {
+ prange =
+ (dk3_uc2lat_range_t *)dk3sto_it_find_like(pdir->i_ran, &chr, 1);
+ if (NULL != prange) { $? ". range found"
+ ind = (size_t)(chr - prange->start);
+ while (NULL != p2) {
+ p1 = dk3str_c8_next(p2, NULL);
+ p3 = dk3str_c8_chr(p2, '=');
+ if (NULL != p3) {
+ *(p3++) = '\0';
+#if 0
+ /* 2015-08-10 Bugfix: Must be start */
+ p3 = dk3str_c8_next(p3, NULL);
+#endif
+ p3 = dk3str_c8_start(p3, NULL);
+ if (NULL != p3) { $? ". \"%!8s\"=\"%!8s\"", p2, p3
+ action = dk3str_c8_array_abbr(dk3uc2l_kw, p2, '$', 0);
+ $? ". action = %d", action
+ switch (action) {
+ case 0: { /* both */ $? ". both"
+ if (NULL != prange->a) {
+ p4 = dk3str_c8_dup_app(p3, uptr->app);
+ if (NULL != p4) {
+ dk3_release((prange->a)[ind]);
+ (prange->a)[ind] = p4;
+ }
+ }
+ } break;
+ case 1: { /* text */ $? ". text"
+ if (NULL != prange->t) {
+ p4 = dk3str_c8_dup_app(p3, uptr->app);
+ if (NULL != p4) {
+ dk3_release((prange->t)[ind]);
+ (prange->t)[ind] = p4;
+ }
+ }
+ } break;
+ case 2: { /* math */ $? ". math"
+ if (NULL != prange->m) {
+ p4 = dk3str_c8_dup_app(p3, uptr->app);
+ if (NULL != p4) {
+ dk3_release((prange->m)[ind]);
+ (prange->m)[ind] = p4;
+ }
+ }
+ } break;
+ case 3: { /* encoding */ $? ". encoding"
+ if (NULL != prange->f) {
+ isneg = 0; encod = 0;
+ if ('!' == *p3) {
+ isneg = 1; p3++;
+ }
+ while (NULL != p3) {
+ p4 = dk3str_c8_chr(p3, ',');
+ if (NULL != p4) {
+ *(p4++) = '\0';
+ p4 = dk3str_c8_start(p4, NULL);
+ }
+ switch (dk3str_c8_array_index(dk3uc2l_enco, p3, 0))
+ {
+ case 0: { /* OT1 */
+ encod |= DK3_FONT_ENCODING_OT1;
+ } break;
+ case 1: { /* T1 */
+ encod |= DK3_FONT_ENCODING_T1;
+ } break;
+ case 2: { /* T4 */
+ encod |= DK3_FONT_ENCODING_T4;
+ } break;
+ case 3: { /* T5 */
+ encod |= DK3_FONT_ENCODING_T5;
+ } break;
+ default : {
+ /* Syntax error, unknown encoding */
+ dk3app_log_i1(uptr->app, DK3_LL_DEBUG, 404);
+ } break;
+ }
+ p3 = p4;
+ }
+ if (0 != isneg) { encod = (~(encod)); }
+ (prange->f)[ind] = encod;
+ }
+ } break;
+ case 4: { /* packages */ $? ". packages"
+#if HAVE_PACKAGES
+ if (NULL != prange->p) {
+ nparts = dk3str_c8_explode(parts, 15, p3, ",");
+ if (0 < nparts) {
+ dk3_release((prange->p)[ind]);
+ (prange->p)[ind] =
+ dk3_new_app(dk3_uc2lat_pkg_ptr,(nparts+1),uptr->app);
+ if (NULL != (prange->p)[ind]) {
+ for (i = 0; i < (nparts+1); i++) {
+ ((prange->p)[ind])[i] = NULL;
+ }
+ j = 0;
+ for (i = 0; i < nparts; i++) {
+ ppkg = (dk3_uc2lat_pkg_t *)dk3sto_it_find_like(
+ uptr->i_pkg, parts[i], 1
+ );
+ if (NULL != ppkg) {
+ ((prange->p)[ind])[j++] = ppkg;
+ } else {
+ ppkg = dk3uc2lat_pkg_new(parts[i], uptr->app);
+ if (NULL != ppkg) {
+ if (dk3sto_add(uptr->s_pkg, ppkg)) {
+ ((prange->p)[ind])[j++] = ppkg;
+ } else {
+ dk3uc2lat_pkg_delete(ppkg);
+ }
+ }
+ }
+ }
+ }
+ } else {
+ /* ERROR: Syntax, no packages */
+ dk3app_log_i1(uptr->app, DK3_LL_DEBUG, 405);
+ }
+ }
+#endif
+ } break;
+ default: { $? "! unknown key"
+ } break;
+ }
+ } else { $? "! missing attribute value"
+ /* ERROR: Value missing */
+ dk3app_log_i1(uptr->app, DK3_LL_DEBUG, 406);
+ }
+ } else { $? "! missing attribute value"
+ /* ERROR: Syntax, not a key value pair */
+ dk3app_log_i1(uptr->app, DK3_LL_DEBUG, 406);
+ }
+ p2 = p1;
+ }
+ } else { $? "! bug: range not found"
+ /* BUG or file changed */
+ }
+ } else {
+ /* ERROR: Syntax error, not a hexadecimal number */
+ dk3app_log_i1(uptr->app, DK3_LL_ERROR, 398);
+ }
+ } else { $? "! missing attributes"
+ /* ERROR: Syntax error, missing configuration */
+ dk3app_log_i1(uptr->app, DK3_LL_ERROR, 401);
+ }
+ } else { $? ". ignore comment line"
+ }
+ } else { $? ". ignore empty line"
+ }
+ } $? "- dk3uc2l_apply_2"
+}
+
+
+
+static
+void
+dk3uc2lat_load_file(dk3_uc2lat_t *u, dk3_uc2lat_dir_t *pdir)
+{
+ dkChar fnb[DK3_MAX_PATH];
+ dk3_stream_t *istrm = NULL;
+ FILE *fipo = NULL;
+ const dkChar *oldsrc = NULL;
+ const dkChar *fsuf = NULL;
+#if DK3_HAVE_ZLIB_H && (DK3_CHAR_SIZE == 1)
+ gzFile gzf = NULL;
+#endif
+#if DK3_HAVE_BZLIB_H && (DK3_CHAR_SIZE == 1)
+ BZFILE *bzf = NULL;
+#endif
+ unsigned long oldln = 0UL;
+#if DK3_HAVE_FNCASEINS
+ int fncs = 0;
+#else
+ int fncs = 1;
+#endif
+ size_t sz;
+ $? "+ dk3uc2lat_load_file"
+ sz = dk3str_len(u->dir);
+ sz += dk3str_len(pdir->sn);
+ sz += 1;
+ if (sizeof(fnb) > sz) { $? ". file name length ok"
+ dk3str_cpy(fnb, u->dir);
+ dk3str_cat(fnb, dk3app_not_localized(20));
+ dk3str_cat(fnb, pdir->sn);
+ dk3str_correct_filename(fnb);
+ oldsrc = dk3app_get_source_file(u->app);
+ oldln = dk3app_get_source_line(u->app);
+ dk3app_set_source_file(u->app, fnb);
+ dk3app_set_source_line(u->app, 0UL);
+ if (0 != dk3uc2l_allocate_memory(u, pdir)) { $? ". memory allocated"
+ fsuf = dk3str_get_suffix(fnb);
+ switch (dk3str_array_index(dk3uc2l_co_suf, fsuf, fncs)) {
+ case 0: { $? ". zlib compressed"
+#if DK3_HAVE_ZLIB_H && (DK3_CHAR_SIZE == 1)
+ gzf = gzopen(fnb, "r");
+ if (NULL != gzf) {
+ istrm = dk3stream_open_gz_app(gzf, DK3_STREAM_FLAG_READ, u->app);
+ if (NULL != istrm) {
+ dk3uc2l_apply_2(u, pdir, istrm, fnb);
+ (void)dk3stream_close(istrm);
+ }
+ gzclose(gzf);
+ } else {
+ /* ERROR: Failed to open file */
+ dk3app_log_i3(u->app, DK3_LL_ERROR, 143, 144, fnb);
+ }
+#else
+ /* ERROR: No zlib support */
+ dk3app_log_i1(u->app, DK3_LL_ERROR, 401);
+#endif
+ } break;
+ case 1: { $? ". bzip2 compressed"
+#if DK3_HAVE_BZLIB_H && (DK3_CHAR_SIZE == 1)
+ bzf = BZ2_bzopen(fnb, "r");
+ if (NULL != bzf) {
+ istrm = dk3stream_open_bz2_app(bzf, DK3_STREAM_FLAG_READ, u->app);
+ if (NULL != istrm) {
+ dk3uc2l_apply_2(u, pdir, istrm, fnb);
+ (void)dk3stream_close(istrm);
+ }
+ BZ2_bzclose(bzf);
+ } else {
+ /* ERROR: Failed to open file */
+ dk3app_log_i3(u->app, DK3_LL_ERROR, 143, 144, fnb);
+ }
+#else
+ /* ERROR: No bzip2 support */
+ dk3app_log_i1(u->app, DK3_LL_ERROR, 402);
+#endif
+ } break;
+ default: { $? ". normal file"
+ fipo = dk3sf_fopen_app(fnb, dkT("r"), u->app);
+ if (NULL != fipo) {
+ istrm = dk3stream_open_file_app(fipo, DK3_STREAM_FLAG_READ, u->app);
+ if (NULL != istrm) {
+ dk3uc2l_apply_2(u, pdir, istrm, fnb);
+ (void)dk3stream_close(istrm);
+ }
+ fclose(fipo);
+ }
+ } break;
+ }
+ } else { $? "! memory allocation error"
+ }
+ dk3app_set_source_file(u->app, oldsrc);
+ dk3app_set_source_line(u->app, oldln);
+ } else { $? "! file name too long"
+ /* ERROR: Name too long */
+ dk3app_log_i3(u->app, DK3_LL_ERROR, 65, 66, pdir->sn);
+ }
+ pdir->loaded = 0x01;
+ $? "- dk3uc2lat_load_file"
+}
+
+
+
+/** Open conversion structure for a given directory.
+ @param d Directory containing conversion files.
+ @param f_desc Flag: Load glyph descriptions (ignored).
+ @param f_utf8 Flag: UTF-8 output allowed.
+ @param app Application structure for diagnostics, may be NULL.
+ @return Pointer to new structure on success, NULL on error.
+*/
+static
+dk3_uc2lat_t *
+dk3uc2lat_i_open_app(const dkChar *d, int f_desc, int f_utf8, dk3_app_t *app)
+{
+ dk3_uc2lat_t *back = NULL;
+ $? "+ dk3uc2lat_i_open_app %!ds", d
+ if (0 != dk3sf_is_dir_app(d, NULL)) {
+ back = dk3uc2lat_t_new(d, f_utf8, app);
+ if (NULL != back) {
+ if (0 == dk3uc2lat_read_dir_info(back, app)) {
+ dk3uc2lat_close(back);
+ back = NULL;
+ }
+ }
+ } else {
+ /* ERROR: Not a directory ... */
+ dk3app_log_i3(app, DK3_LL_ERROR, 202, 203, d);
+ }
+ $? "- dk3uc2lat_i_open_app PTR:%d", TR_IPTR(back)
+ return back;
+}
+
+
+
+dk3_uc2lat_t *
+dk3uc2lat_open_app(dkChar const *d, int f_desc, int f_utf8, dk3_app_t *app)
+{
+ dkChar fnb[DK3_MAX_PATH];
+ dk3_uc2lat_t *back = NULL;
+ const dkChar *shd = NULL;
+ const dkChar *dirn = NULL;
+ size_t szfnb = DK3_SIZEOF(fnb,dkChar);
+ size_t szshd = 0;
+ $? "+ dk3uc2lat_open_app %!ds", TR_DKSTR(d)
+ if (NULL != d) {
+ back = dk3uc2lat_i_open_app(d, f_desc, f_utf8, app);
+ } else {
+ if (NULL != app) {
+ if (dk3app_get_dir_from_pref(app,dk3app_not_localized(48),fnb,szfnb,1))
+ {
+ dk3str_correct_filename(fnb);
+ back = dk3uc2lat_i_open_app(fnb, f_desc, f_utf8, app);
+ } else
+ {
+ shd = dk3app_get_sharedir(app);
+ if (NULL != shd) {
+ szshd = dk3str_len(shd);
+ if (szfnb > szshd) {
+ dk3str_cpy_not_overlapped(fnb, shd);
+ dirn = dk3app_not_localized(49);
+ if (szfnb > (szshd + dk3str_len(dirn))) {
+ dk3str_cat(fnb, dirn);
+ dk3str_correct_filename(fnb);
+ back = dk3uc2lat_i_open_app(fnb, f_desc, f_utf8, app);
+ } else {
+ /* ERROR: Directory name too long! */
+ dk3app_log_i3(app, DK3_LL_ERROR, 64, 66, dirn);
+ }
+ } else {
+ /* ERROR: Share directory name too long! */
+ dk3app_log_i3(app, DK3_LL_ERROR, 64, 66, shd);
+ }
+ } else {
+ /* ERROR: Missing share directory */
+ dk3app_log_i1(app, DK3_LL_ERROR, 407);
+ }
+ }
+ }
+ } $? "- dk3uc2lat_open_app %d", TR_IPTR(back)
+ return back;
+}
+
+
+
+char const *
+dk3uc2lat_get(dk3_uc2lat_t *u, dk3_c32_t c32, int ismath)
+{
+ dkChar cbuf[64];
+ dk3_uc2lat_range_t *prange = NULL;
+ dk3_uc2lat_pkg_t **pkgpp;
+ const char *back = NULL;
+ size_t szcbuf = DK3_SIZEOF(cbuf,dkChar);
+ $? "+ dk3uc2lat_get"
+ if (NULL != u) {
+ if (NULL != u->rca) { $? ". range cache available"
+ if ((u->rca)->start <= c32) { $? ". start ok"
+ if ((u->rca)->end >= c32) { $? ". end ok"
+ prange = u->rca; $? ". use range cache"
+ }
+ }
+ }
+ if (NULL == prange) { $? ". find character"
+ prange = dk3sto_it_find_like(u->i_ran, &c32, 1);
+ if (NULL != prange) { $? ". range found"
+ u->rca = prange;
+ if (NULL != prange->p) { $? ". range->package"
+ pkgpp = (prange->p)[(size_t)(c32 - prange->start)];
+ if (NULL != pkgpp) {
+ while (NULL != *pkgpp) {
+ (*(pkgpp++))->used = 0x01;
+ } $? ". packages marked as used"
+ }
+ }
+ } else { $? "! no range found"
+ }
+ }
+ if (NULL != prange) { $? ". range found"
+ if (NULL != prange->dir) { $? ". range has dir entry"
+ if (0x00 == (prange->dir)->loaded) { $? ". must load"
+ dk3uc2lat_load_file(u, prange->dir);
+ }
+ }
+ if (0 != ismath) { $? ". math mode"
+ if (NULL != prange->m) { $? ". math"
+ back = (prange->m)[(size_t)(c32 - prange->start)];
+ }
+ if (NULL == back) {
+ if (NULL != prange->a) { $? ". all"
+ back = (prange->a)[(size_t)(c32 - prange->start)];
+ }
+ }
+ } else { $? ". normal mode"
+ if (NULL != prange->t) { $? ". text"
+ back = (prange->t)[(size_t)(c32 - prange->start)];
+ }
+ if (NULL == back) { $? ". all"
+ if (NULL != prange->a) {
+ back = (prange->a)[(size_t)(c32 - prange->start)];
+ }
+ }
+ }
+ if (NULL != prange->f) {
+ u->fe &= ((prange->f)[(size_t)(c32 - prange->start)]);
+ }
+ } else {
+ /* ERROR: Not found */
+ if (0 != dk3ma_um_to_hex_string(cbuf, szcbuf, (dk3_um_t)c32, 8)) {
+ dk3app_log_i3(u->app, DK3_LL_ERROR, 409, 410, cbuf);
+ } else {
+ dk3app_log_i1(u->app, DK3_LL_ERROR, 408);
+ }
+ }
+ } $? "- dk3uc2lat_get PTR:%d", TR_IPTR(back)
+ return back;
+}
+
+
+
+#if HAVE_PACKAGES
+
+void
+dk3uc2lat_package_reset(dk3_uc2lat_t *u)
+{
+ if (NULL != u) {
+ dk3sto_it_reset(u->i_pkg);
+ }
+}
+
+
+
+dk3_uc2lat_pkg_t *
+dk3uc2lat_package_next(dk3_uc2lat_t *u)
+{
+ dk3_uc2lat_pkg_t *back = NULL;
+ if (NULL != u) {
+ back = (dk3_uc2lat_pkg_t *)dk3sto_it_next(u->i_pkg);
+ }
+ return back;
+}
+
+#endif
+
+
+
+void
+dk3uc2lat_font_encoding_reset(dk3_uc2lat_t *u)
+{
+ /* UNUSED */
+}
+
+
+
+int
+dk3uc2lat_font_encoding_conflict(dk3_uc2lat_t *u)
+{
+ int back = 0;
+ /* UNUSED */
+ return back;
+}
+
+
+
+void
+dk3uc2lat_font_encoding_report_conflict(dk3_uc2lat_t *u)
+{
+ if (0x00 == u->fe) {
+ /* Error */
+ dk3app_log_i1(u->app, DK3_LL_ERROR, 411);
+ }
+}
+
+
+
+static
+void
+dk3uc2lat_report_for_encoding(dk3_uc2lat_t *u, const char *eptr)
+{
+#if DK3_CHAR_SIZE > 1
+ dkChar buffer[32];
+ dkChar *dkptr = NULL;
+ size_t szbu = DK3_SIZEOF(buffer,dkChar);
+ if (szbu > strlen(eptr)) {
+ dkptr = buffer;
+ while ('\0' != *eptr) {
+ *(dkptr++) = (dkChar)(*(eptr++));
+ }
+ *dkptr = dkT('\0');
+ dk3app_log_i3(u->app, DK3_LL_INFO, 381, 382, buffer);
+ }
+#else
+ dk3app_log_i3(u->app, DK3_LL_INFO, 381, 382, eptr);
+#endif
+}
+
+
+
+void
+dk3uc2lat_font_encoding_report(dk3_uc2lat_t *u)
+{
+ if (0 != ((u->fe) & DK3_FONT_ENCODING_OT1)) {
+ dk3uc2lat_report_for_encoding(u, dk3uc2l_enco[0]);
+ }
+ if (0 != ((u->fe) & DK3_FONT_ENCODING_T1)) {
+ dk3uc2lat_report_for_encoding(u, dk3uc2l_enco[1]);
+ }
+ if (0 != ((u->fe) & DK3_FONT_ENCODING_T4)) {
+ dk3uc2lat_report_for_encoding(u, dk3uc2l_enco[2]);
+ }
+ if (0 != ((u->fe) & DK3_FONT_ENCODING_T5)) {
+ dk3uc2lat_report_for_encoding(u, dk3uc2l_enco[3]);
+ }
+}
+
+
+
+int
+dk3uc2lat_direct(dk3_c32_t c32)
+{
+ int back = 0;
+ char c; /* 8-bit character version of c32. */
+ $? "+ dk3uc2lat_direct %lx", (unsigned long)c32
+ if((unsigned long)c32 < 128UL) {
+ c = (char)c32;
+ switch(c) {
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
+ case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
+ case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
+ case 'v': case 'w': case 'x': case 'y': case 'z': case 'A': case 'B':
+ case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I':
+ case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P':
+ case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W':
+ case 'X': case 'Y': case 'Z': case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7': case '8': case '9': case ',':
+ case '.': case ':': case ';': case '+': case '-': case '?': case '!':
+ case '|': case '@': case '(': case ')': case '/': case '=': case ' ':
+ case '\t':
+ {
+ back = 1;
+ }
+ break;
+ }
+ } $? "- dk3uc2lat_direct %d", back
+ return back;
+}
+
+
+
+static
+int
+dk3uc2lat_stputc(dk3_uc2lat_t *u, dk3_stream_t *st, dk3_c32_t ul, int *mmptr)
+{
+ char buf[16];
+ const char *ptr;
+ size_t sz;
+ int back = 0;
+
+ if (0 != dk3uc2lat_direct(ul)) {
+ if (0 != *mmptr) {
+ dk3stream_c8_fputs(st, dk3uc2lat_mm[1]);
+ *mmptr = 0;
+ }
+ if (u->f_utf8) {
+ sz = dk3enc_uc2utf8(ul, (unsigned char *)buf, sizeof(buf));
+ buf[sz] = '\0';
+ } else {
+ buf[0] = (char)ul;
+ buf[1] = '\0';
+ }
+ dk3stream_c8_fputs(st, buf);
+ back = 1;
+ } else {
+ ptr = dk3uc2lat_get(u, ul, 0);
+ if (NULL != ptr) {
+ if (0 != *mmptr) {
+ dk3stream_c8_fputs(st, dk3uc2lat_mm[1]);
+ *mmptr = 0;
+ }
+ dk3stream_c8_fputs(st, ptr);
+ } else {
+ ptr = dk3uc2lat_get(u, ul, 1);
+ if (NULL != ptr) {
+ if (0 == *mmptr) {
+ dk3stream_c8_fputs(st, dk3uc2lat_mm[0]);
+ *mmptr = 1;
+ }
+ dk3stream_c8_fputs(st, ptr);
+ } else {
+ /* ERROR: Not found, already reported */
+ }
+ }
+ }
+ return back;
+}
+
+
+
+int
+dk3uc2lat_c8_plain_stputs(dk3_uc2lat_t *u, dk3_stream_t *st, char const *t)
+{
+ int back = 0;
+ int mm = 0; /* Flag: In math mode. */
+ char const *ptr; /* Current position. */
+ dk3_c32_t ul; /* Output character. */
+ char c; /* Current character. */
+ $? "+ dk3uc2lat_c8_plain_stputs \"%!8s\"", TR_8STR(t)
+ if((u) && (st) && (t)) {
+ ptr = t; back = 1;
+ while(*ptr) {
+ c = *ptr;
+ ul = (unsigned long)c;
+ ul &= 0x000000FFUL;
+ if(!dk3uc2lat_stputc(u, st, ul, &mm)) { back = 0; }
+ ptr++;
+ }
+ if(mm) {
+ dk3stream_c8_fputs(st, dk3uc2lat_mm[1]);
+ }
+ }
+ $? "- dk3uc2lat_c8_plain_stputs %d", back
+ return back;
+}
+
+
+
+int
+dk3uc2lat_c8_utf8_stputs(dk3_uc2lat_t *u, dk3_stream_t *st, char const *t)
+{
+ int back = 0;
+ int mm = 0; /* Flag: Math mode. */
+ unsigned char const *sp; /* String pointer, current pos. */
+ size_t sl; /* Remaining bytes. */
+ size_t used; /* Bytes used for current c32. */
+ dk3_c32_t c32; /* Current character. */
+ $? "+ dk3uc2lat_c8_utf8_stputs \"%!8s\"", TR_8STR(t)
+ if((u) && (st) && (t)) {
+ sp = (unsigned char const *)t; sl = dk3str_c8_len(t); back = 1;
+ while(sl) {
+ used = 0;
+ if(dk3enc_utf82uc(&c32, sp, sl, &used)) {
+ if(!dk3uc2lat_stputc(u, st, c32, &mm)) {
+ back = 0;
+ }
+ if(used) {
+ if(sl >= used) {
+ sl = sl - used;
+ sp = &(sp[used]);
+ } else {
+ sl = 0; back = 0;
+ }
+ } else {
+ sl = 0; back = 0; /* No byte used, will appear again and again. */
+ }
+ } else {
+ sl = 0; back = 0;
+ if(u->app) {
+ /* ERROR: Decoding failed! */
+ dk3app_log_i1(u->app, DK3_LL_ERROR, 118);
+ }
+ }
+ }
+ if(mm) {
+ dk3stream_c8_fputs(st, dk3uc2lat_mm[1]);
+ }
+ }
+ $? "- dk3uc2lat_c8_utf8_stputs %d", back
+ return back;
+}
+
+
+
+int
+dk3uc2lat_c16_stputs(dk3_uc2lat_t *u, dk3_stream_t *st, dk3_c16_t const *t)
+{
+ int back = 0;
+ int mm = 0; /* Flag: Math mode. */
+ dk3_c16_t const *sp; /* Current position. */
+ size_t sl; /* Number of 16-bit characters remaining. */
+ size_t used; /* Number of 16-bit characters used. */
+ dk3_c32_t c32; /* Current output character. */
+ $? "+ dk3uc2lat_c16_stputs %!8s", TR_8PTR(t)
+ if((u) && (st) && (t)) {
+ sp = t; sl = dk3str_c16_len(t); back = 1;
+ while(sl) {
+ used = 0;
+ if(dk3enc_utf162uc(&c32, sp, sl, &used)) {
+ if(used) {
+ if(!dk3uc2lat_stputc(u, st, c32, &mm)) { back = 0; }
+ if(sl >= used) {
+ sl = sl - used;
+ sp = &(sp[used]);
+ } else {
+ sl = 0;
+ }
+ } else {
+ back = 0; sl = 0;
+ if(u->app) {
+ /* ERROR: Decoding */
+ dk3app_log_i1(u->app, DK3_LL_ERROR, 119);
+ }
+ }
+ } else {
+ sl = 0; back = 0;
+ if(u->app) {
+ /* Decoding error */
+ dk3app_log_i1(u->app, DK3_LL_ERROR, 119);
+ }
+ }
+ }
+ if(mm) {
+ dk3stream_c8_fputs(st, dk3uc2lat_mm[1]);
+ }
+ }
+ $? "- dk3uc2lat_c16_stputs %d", back
+ return back;
+}
+
+
+
+int
+dk3uc2lat_c32_stputs(dk3_uc2lat_t *u, dk3_stream_t *st, dk3_c32_t const *t)
+{
+ int back = 0;
+ int mm = 0; /* Flag: Math mode. */
+ dk3_c32_t const *ptr; /* Current position. */
+ $? "+ dk3uc2lat_c32_stputs %!8s", TR_8PTR(t)
+ if((u) && (st) && (t)) {
+ back = 1;
+ ptr = t;
+ while(*ptr) {
+ if(!dk3uc2lat_stputc(u, st, *(ptr++), &mm)) {
+ back = 0;
+ }
+ }
+ if(mm) {
+ dk3stream_c8_fputs(st, dk3uc2lat_mm[1]);
+ }
+ }
+ $? "- dk3uc2lat_c32_stputs %d", back
+ return back;
+}
+
+
+
+int
+dk3uc2lat_stputs(dk3_uc2lat_t *u, dk3_stream_t *st, dkChar const *t, int e)
+{
+ int back = 0;
+ $? "+ dk3uc2lat_stputs \"%!ds\"", TR_STR(t)
+#if DK3_CHAR_SIZE > 1
+#if DK3_CHAR_SIZE > 2
+ back = dk3uc2lat_c32_stputs(u, st, t);
+#else
+ back = dk3uc2lat_c16_stputs(u, st, t);
+#endif
+#else
+ switch(e) {
+ case DK3_ENCODING_UTF8: {
+ back = dk3uc2lat_c8_utf8_stputs(u, st, t);
+ } break;
+ default: {
+ back = dk3uc2lat_c8_plain_stputs(u, st, t);
+ } break;
+ }
+#endif
+ $? "- dk3uc2lat_stputs %d", back
+ return back;
+}
+
+
+
+void
+dk3uc2lat_final_report(dk3_uc2lat_t *u, dk3_stream_t *st)
+{
+ dk3_uc2lat_pkg_t *pkgp;
+ dk3stream_c8_fputs(st, dk3uc2lat_mm[2]);
+ if (0 != ((u->fe) & DK3_FONT_ENCODING_OT1)) {
+ dk3stream_c8_fputs(st, dk3uc2l_c8_font_encoding_names[0]);
+ }
+ if (0 != ((u->fe) & DK3_FONT_ENCODING_T1)) {
+ dk3stream_c8_fputs(st, dk3uc2l_c8_font_encoding_names[1]);
+ }
+ if (0 != ((u->fe) & DK3_FONT_ENCODING_T4)) {
+ dk3stream_c8_fputs(st, dk3uc2l_c8_font_encoding_names[2]);
+ }
+ if (0 != ((u->fe) & DK3_FONT_ENCODING_T5)) {
+ dk3stream_c8_fputs(st, dk3uc2l_c8_font_encoding_names[3]);
+ }
+ dk3stream_c8_fputs(st, dk3uc2lat_mm[4]);
+ dk3uc2lat_package_reset(u);
+ do {
+ pkgp = dk3uc2lat_package_next(u);
+ if (NULL != pkgp) {
+ $!trace-code if (NULL != pkgp->name) {
+ $!trace-code if (0x00 != pkgp->used) {
+ $? ". pkg used %!8s", pkgp->name
+ $!trace-code } else {
+ $? ". pkg not used %!8s", pkgp->name
+ $!trace-code }
+ $!trace-code }
+ if ((0x00 != pkgp->used) && (NULL != pkgp->name)) {
+ dk3stream_c8_fputs(st, dk3uc2lat_mm[3]);
+ dk3stream_c8_fputs(st, pkgp->name);
+ dk3stream_c8_fputs(st, dk3uc2lat_mm[4]);
+ }
+ }
+ } while (NULL != pkgp);
+}
+
+
+
+/* vim: set ai sw=2 : */