diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/dktools/dk3uc2l.ctr |
Initial commit
Diffstat (limited to 'support/dktools/dk3uc2l.ctr')
-rw-r--r-- | support/dktools/dk3uc2l.ctr | 2062 |
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 : */ |