/* Copyright (C) 2016-2020, Dirk Krause SPDX-License-Identifier: BSD-3-Clause */ /* WARNING: This file was generated by the dkct program (see http://dktools.sourceforge.net/ for details). Changes you make here will be lost if dkct is run again! You should modify the original source and run dkct on it. Original source: dk4paper.ctr */ /** @file dk4paper.c The dk4paper module. */ #line 373 "dk4paper.ctr" #include "dk4conf.h" #include "dk4mem.h" #include "dk4strd.h" #include "dk4paper.h" #include "dk4maiddbl.h" #include "dk4fs.h" #include "dk4mpl.h" #include "dk4tspdk.h" #include "dk4strm.h" #include "dk4strmr.h" #include "dk4enc.h" #include "dk4loc.h" #include "dk4user.h" #include "dk4inst.h" #include "dk4unused.h" #if DK4_HAVE_ASSERT_H #ifndef ASSERT_H_INCLUDED #include #define ASSERT_H_INCLUDED 1 #endif #endif #line 399 "dk4paper.ctr" /** Object passed as pointer to the line handler. */ typedef struct { dk4_paper_size_collection_t *coll; /**< Collection to modify. */ } reader_obj_t; /** Configuration files to search for. */ static const dkChar * const conf_file_names[] = { dkT("dk4paper.conf"), dkT("dk3paper.conf") }; /** Default paper size names always defined. */ static const dkChar *default_paper_sizes[] = { /* 0 */ dkT("A4"), /* 1 */ dkT("a4"), /* 2 */ dkT("Letter"), /* 3 */ dkT("letter"), NULL #line 428 "dk4paper.ctr" }; void dk4papersize_delete(dk4_paper_size_t *pps) { #line 436 "dk4paper.ctr" #if DK4_USE_ASSERT assert(NULL != pps); #endif if (NULL != pps) { #line 440 "dk4paper.ctr" if (NULL != pps->name) { #line 441 "dk4paper.ctr" #line 442 "dk4paper.ctr" dk4mem_free(pps->name); pps->name = NULL; } dk4mem_free(pps); } #if TRACE_DEBUG else { #line 449 "dk4paper.ctr" } #endif #line 452 "dk4paper.ctr" } dk4_paper_size_t * dk4papersize_new(const dkChar *name, dk4_er_t *erp) { dk4_paper_size_t *back = NULL; #line 461 "dk4paper.ctr" #if DK4_USE_ASSERT assert(NULL != name); #endif if (NULL != name) { back = dk4mem_new(dk4_paper_size_t,1,erp); if (NULL != back) { back->w = 0.0; back->h = 0.0; back->i = 0.0; back->o = 0.0; back->t = 0.0; back->b = 0.0; back->name = dk4str_dup(name, erp); if (NULL == back->name) { dk4mem_free(back); back = NULL; } } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } #line 484 "dk4paper.ctr" return back; } void dk4papersize_coll_close(dk4_paper_size_collection_t *ptr) { dk4_paper_size_t *pps; #line 495 "dk4paper.ctr" #if DK4_USE_ASSERT assert(NULL != ptr); #endif if (NULL != ptr) { #line 499 "dk4paper.ctr" if (NULL != ptr->s_ps) { #line 500 "dk4paper.ctr" if (NULL != ptr->i_ps) { #line 501 "dk4paper.ctr" dk4sto_it_reset(ptr->i_ps); do { pps = (dk4_paper_size_t *)dk4sto_it_next(ptr->i_ps); if (NULL != pps) { #line 505 "dk4paper.ctr" dk4papersize_delete(pps); } } while (NULL != pps); dk4sto_it_close(ptr->i_ps); ptr->i_ps = NULL; } #if TRACE_DEBUG else { #line 513 "dk4paper.ctr" } #endif dk4sto_close(ptr->s_ps); ptr->s_ps = NULL; } #if TRACE_DEBUG else { #line 520 "dk4paper.ctr" } #endif #line 523 "dk4paper.ctr" dk4mem_free(ptr); } #if TRACE_DEBUG else { #line 527 "dk4paper.ctr" } #endif #line 530 "dk4paper.ctr" } int dk4papersize_cmp(const void *l, const void *r, int cr) { const dk4_paper_size_t *pl = NULL; const dk4_paper_size_t *pr = NULL; const dkChar *nm = NULL; int back = 0; if (NULL != l) { if (NULL != r) { pl = (const dk4_paper_size_t *)l; switch (cr) { case 1 : { nm = (const dkChar *)r; back = dk4str_cmp(pl->name, nm); } break; default : { pr = (const dk4_paper_size_t *)r; back = dk4str_cmp(pl->name, pr->name); } break; } } else { back = 1; } } else { if (NULL != r) { back = -1; } } return back; } static int dk4papersize_i_add_one_default_size( dk4_paper_size_collection_t *pscptr, const dkChar *name, double w, double h, double i, double o, double t, double b, dk4_er_t *erp ) { dk4_paper_size_t *ptr; int back = 0; #line 588 "dk4paper.ctr" #if DK4_USE_ASSERT assert(NULL != pscptr); assert(NULL != name); #endif ptr = dk4papersize_new(name, erp); if (NULL != ptr) { #line 594 "dk4paper.ctr" ptr->w = w; ptr->h = h; ptr->i = i; ptr->o = o; ptr->t = t; ptr->b = b; #line 596 "dk4paper.ctr" #line 597 "dk4paper.ctr" #line 598 "dk4paper.ctr" #line 599 "dk4paper.ctr" #line 600 "dk4paper.ctr" #line 601 "dk4paper.ctr" if (0 != dk4sto_add(pscptr->s_ps, ptr, erp)) { back = 1; #line 603 "dk4paper.ctr" } else { #line 605 "dk4paper.ctr" dk4papersize_delete(ptr); ptr = NULL; } } #if TRACE_DEBUG else { #line 611 "dk4paper.ctr" } #endif #line 614 "dk4paper.ctr" return back; } static int dk4papersize_i_add_default_sizes( dk4_paper_size_collection_t *pscptr, dk4_er_t *erp ) { int back = 0; #line 628 "dk4paper.ctr" #if DK4_USE_ASSERT assert(NULL != pscptr); #endif back = dk4papersize_i_add_one_default_size( pscptr, default_paper_sizes[0], 595.0, 842.0, 0.0, 0.0, 0.0, 0.0, erp ); if (0 == back) { goto finished; } back = dk4papersize_i_add_one_default_size( pscptr, default_paper_sizes[1], 595.0, 842.0, 56.0, 28.0, 14.0, 14.0, erp ); if (0 == back) { goto finished; } back = dk4papersize_i_add_one_default_size( pscptr, default_paper_sizes[2], 612.0, 792.0, 0.0, 0.0, 0.0, 0.0, erp ); if (0 == back) { goto finished; } back = dk4papersize_i_add_one_default_size( pscptr, default_paper_sizes[3], 612.0, 792.0, 56.0, 28.0, 14.0, 14.0, erp ); if (0 == back) { goto finished; } back = 1; finished: #line 655 "dk4paper.ctr" return back; } dk4_paper_size_collection_t * dk4papersize_coll_open(dk4_er_t *erp) { dk4_paper_size_collection_t *back = NULL; int ok = 0; #line 667 "dk4paper.ctr" back = dk4mem_new(dk4_paper_size_collection_t,1,erp); if (NULL != back) { back->i_ps = NULL; back->s_ps = dk4sto_open(erp); if (NULL != back->s_ps) { (void)dk4sto_set_comp(back->s_ps, dk4papersize_cmp, 0); back->i_ps = dk4sto_it_open(back->s_ps, erp); if (NULL != back->i_ps) { ok = dk4papersize_i_add_default_sizes(back, erp); } } if (0 == ok) { dk4papersize_coll_close(back); back = NULL; } } #line 683 "dk4paper.ctr" return back; } const dk4_paper_size_t * dk4papersize_coll_find_with_index( dk4_paper_size_collection_t *ptr, const dkChar *name, size_t *ppsi, dk4_er_t *erp ) { dk4_paper_size_t *back = NULL; dk4_paper_size_t const *psptr; size_t i; int found; #line 702 "dk4paper.ctr" #if DK4_USE_ASSERT assert(NULL != ptr); assert(NULL != name); #endif if ((NULL != ptr) && (NULL != name)) { back = (dk4_paper_size_t *)dk4sto_it_find_like(ptr->i_ps, name, 1); if (NULL != back) { if (NULL != ppsi) { found = 0; i = 0; dk4papersize_coll_reset(ptr); do { psptr = dk4papersize_coll_next(ptr); if (NULL != psptr) { if (NULL != psptr->name) { if (0 == dk4str_cmp(name, psptr->name)) { found = 1; *ppsi = i; } } } i++; } while ((NULL != psptr) && (0 == found)); } } else { dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND); } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } #line 734 "dk4paper.ctr" return ((const dk4_paper_size_t *)back); } const dk4_paper_size_t * dk4papersize_coll_find( dk4_paper_size_collection_t *ptr, const dkChar *name, dk4_er_t *erp ) { #if DK4_USE_ASSERT assert(NULL != ptr); assert(NULL != name); #endif return (dk4papersize_coll_find_with_index(ptr, name, NULL, erp)); } double dk4papersize_get_width(const dk4_paper_size_t *psptr) { double back = -1.0; #if DK4_USE_ASSERT assert(NULL != psptr); #endif if (NULL != psptr) { back = psptr->w; } return back; } double dk4papersize_get_height(const dk4_paper_size_t *psptr) { double back = -1.0; #if DK4_USE_ASSERT assert(NULL != psptr); #endif if (NULL != psptr) { back = psptr->h; } return back; } double dk4papersize_get_left_border(const dk4_paper_size_t *psptr) { double back = -1.0; #if DK4_USE_ASSERT assert(NULL != psptr); #endif if (NULL != psptr) { back = psptr->i; } return back; } double dk4papersize_get_right_border(const dk4_paper_size_t *psptr) { double back = -1.0; #if DK4_USE_ASSERT assert(NULL != psptr); #endif if (NULL != psptr) { back = psptr->o; } return back; } double dk4papersize_get_top_border(const dk4_paper_size_t *psptr) { double back = -1.0; #if DK4_USE_ASSERT assert(NULL != psptr); #endif if (NULL != psptr) { back = psptr->t; } return back; } double dk4papersize_get_bottom_border(const dk4_paper_size_t *psptr) { double back = -1.0; #if DK4_USE_ASSERT assert(NULL != psptr); #endif if (NULL != psptr) { back = psptr->b; } return back; } const dkChar * dk4papersize_get_name(const dk4_paper_size_t *psptr) { const dkChar *back = NULL; #if DK4_USE_ASSERT assert(NULL != psptr); #endif if (NULL != psptr) { back = psptr->name; } return back; } size_t dk4papersize_coll_size(dk4_paper_size_collection_t *ptr) { size_t back = 0; #if DK4_USE_ASSERT assert(NULL != ptr); #endif if (NULL != ptr) { dk4sto_it_reset(ptr->i_ps); while (NULL != dk4sto_it_next(ptr->i_ps)) { back++; } } return back; } void dk4papersize_coll_reset(dk4_paper_size_collection_t *ptr) { #if DK4_USE_ASSERT assert(NULL != ptr); #endif if (NULL != ptr) { dk4sto_it_reset(ptr->i_ps); } } const dk4_paper_size_t * dk4papersize_coll_next(dk4_paper_size_collection_t *ptr) { dk4_paper_size_t *back = NULL; #if DK4_USE_ASSERT assert(NULL != ptr); #endif if (NULL != ptr) { back = (dk4_paper_size_t *)dk4sto_it_next(ptr->i_ps); } return ((const dk4_paper_size_t *)back); } const dk4_paper_size_t * dk4papersize_coll_get(dk4_paper_size_collection_t *ptr, size_t n) { dk4_paper_size_t *back = NULL; size_t i = 0; #if DK4_USE_ASSERT assert(NULL != ptr); #endif if (NULL != ptr) { dk4sto_it_reset(ptr->i_ps); do { back = (dk4_paper_size_t *)dk4sto_it_next(ptr->i_ps); } while ((NULL != back) && (++i <= n)); } return ((const dk4_paper_size_t *)back); } /** Process one input line. @param obj Reader object. @param line Current line to process. @param lineno Line number. @param erp Error report, may be NULL. @return DK4_TSP_RES_OK if processing succeeded, DK4_TSP_RES_ERROR on errors (can continue), DK4_TSP_RES_FATAL on fatal errors (can not continue). */ static int dk4papersize_line_handler( void *obj, dkChar *line, dk4_um_t DK4_ARG_UNUSED(lineno), dk4_er_t *erp ) { double val[6]; /* w, h, i, o, t, b */ dkChar *tok[16]; /* tokens from the value side */ dk4_paper_size_collection_t *coll; /* collection to complete */ dk4_paper_size_t *ps; /* paper size to modify */ reader_obj_t *rdo; /* reader object */ const dkChar *ep; /* end pointer after double value */ dkChar *pls; /* Line start */ dkChar *pval; /* Start of value side */ size_t ntok; /* number of tokens found */ size_t i; /* traverse tokens */ int back = DK4_TSP_RES_OK; #line 958 "dk4paper.ctr" DK4_UNUSED_ARG(lineno) /* Retrieve pointers */ rdo = (reader_obj_t *)obj; coll = rdo->coll; /* Find start of line, ignore empty lines */ pls = dk4str_start(line, NULL); if (NULL == pls) { #line 968 "dk4paper.ctr" goto finished; } /* Ignore comment lines */ if (dkT('#') == *pls) { #line 974 "dk4paper.ctr" goto finished; } /* Find value side */ pval = dk4str_chr(pls, dkT('=')); if (NULL == pval) { /* ERROR: Syntax */ dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); back = DK4_TSP_RES_ERROR; goto finished; } /* Check whether value side contains text */ *(pval++) = dkT('\0'); pval = dk4str_start(pval, NULL); if (NULL == pval) { /* ERROR: Syntax */ dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); back = DK4_TSP_RES_ERROR; goto finished; } /* Check name length */ dk4str_rtwh(pls, NULL); if (0 == dk4str_len(pls)) { /* ERROR: Syntax */ dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); back = DK4_TSP_RES_ERROR; goto finished; } /* Tokenize string */ ntok = dk4str_tokenize(tok, 16, pval, NULL, NULL); if ((2 > ntok) || (6 < ntok)) { /* ERROR: Syntax */ dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); back = DK4_TSP_RES_ERROR; goto finished; } /* Initialize values */ for (i = 0; i < 6; i++) { val[i] = 0.0; } /* Process tokens to values */ for (i = 0; i < ntok; i++) { ep = NULL; if (0 == dk4ma_input_dk_double(&(val[i]), tok[i], &ep, 1, NULL)) { /* ERROR: Syntax */ dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); back = DK4_TSP_RES_ERROR; goto finished; } } /* Modify existing paper size or create a new one */ ps = (dk4_paper_size_t *)dk4sto_it_find_like(coll->i_ps, pls, 1); if (NULL == ps) { ps = dk4papersize_new(pls, NULL); if (NULL != ps) { if (0 == dk4sto_add(coll->s_ps, ps, NULL)) { /* ERROR: Memory */ dk4error_set_simple_error_code( erp, DK4_E_MEMORY_ALLOCATION_FAILED ); dk4papersize_delete(ps); ps = NULL; back = DK4_TSP_RES_FATAL; } } else { /* ERROR: Memory */ dk4error_set_simple_error_code(erp, DK4_E_MEMORY_ALLOCATION_FAILED); back = DK4_TSP_RES_FATAL; } } if (NULL == ps) { goto finished; } ps->w = val[0]; ps->h = val[1]; ps->i = val[2]; ps->o = val[3]; ps->t = val[4]; ps->b = val[5]; finished: #line 1056 "dk4paper.ctr" return back; } /** Apply a file to a paper size collection. @param coll Collection to modify. @param fn Configuration file name. @param enc Encoding used in memory. @param erp Error report, may be NULL. @return 1 on success, 0 on errors. */ static int dk4paper_apply_file( dk4_paper_size_collection_t *coll, const dkChar *fn, int enc, dk4_er_t *erp ) { char ib[4096]; dkChar il[1024]; dk4_tspdk_t tsp; reader_obj_t rdo; dk4_stream_t *istrm = NULL; size_t rb = 0; int cc = 1; int res = 0; int back = 1; #line 1088 "dk4paper.ctr" #if DK4_USE_ASSERT assert(NULL != coll); assert(NULL != fn); #endif /* Open input stream */ istrm = dk4stream_open_file_reader(fn, erp); if (NULL == istrm) { goto finished; } /* Set up reader structure */ rdo.coll = coll; /* Set up text processing */ res = dk4tspdk_setup_line( &tsp, &rdo, dk4papersize_line_handler, il, DK4_SIZEOF(il,dkChar), enc, ( (DK4_ENCODING_UTF8 == enc) ? (DK4_FILE_ENCODING_UTF8) : ( #if DK4_ON_WINDOWS DK4_FILE_ENCODING_WIN1252 #else DK4_FILE_ENCODING_PLAIN #endif ) ), erp ); if (0 == res) { goto finished; } /* Process input file */ res = DK4_TSP_RES_OK; do { #line 1125 "dk4paper.ctr" cc = 0; rb = sizeof(ib); if (0 != dk4stream_read(ib, &rb, istrm, erp)) { #line 1128 "dk4paper.ctr" if (0 < rb) { #line 1129 "dk4paper.ctr" res = dk4tspdk_add_bytes(&tsp, (const unsigned char *)ib, rb); if (DK4_TSP_RES_FATAL == res) { #line 1131 "dk4paper.ctr" back = 0; } else { #line 1134 "dk4paper.ctr" cc = 1; } } #if TRACE_DEBUG else { #line 1139 "dk4paper.ctr" } #endif } #if TRACE_DEBUG else { #line 1144 "dk4paper.ctr" } #endif #line 1147 "dk4paper.ctr" } while (1 == cc); /* Finalize text stream processor */ if (DK4_TSP_RES_FATAL != res) { if (DK4_TSP_RES_FATAL == dk4tspdk_finish(&tsp)) { #line 1153 "dk4paper.ctr" back = 0; } } finished: if (NULL != istrm) { dk4stream_close(istrm, NULL); } #line 1160 "dk4paper.ctr" return back; } dk4_paper_size_collection_t * dk4papersize_coll_for_application( const dkChar *progname, const dkChar *grpname, dk4_er_t *erp ) { dkChar fnb[DK4_MAX_PATH]; /* Construct filename */ dkChar home[DK4_MAX_PATH]; /* User home dir */ dkChar langbuf[16]; /* Language */ dkChar regbuf[16]; /* Region */ dk4_paper_size_collection_t *back = NULL; /* Result */ size_t i; /* File search index */ int enc; /* Encoding */ int res; /* Operation result */ int ok; /* Flag: No error */ #line 1182 "dk4paper.ctr" /* Create default collection */ #if DK4_USE_ASSERT assert(NULL != progname); assert(NULL != grpname); #endif back = dk4papersize_coll_open(erp); if (NULL == back) { #line 1190 "dk4paper.ctr" goto finished; } #line 1192 "dk4paper.ctr" /* Check program and program group name */ if ((NULL == progname) || (NULL == grpname)) { #line 1195 "dk4paper.ctr" dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); goto finished; } #line 1198 "dk4paper.ctr" /* Find users home directory. */ if (0 == dk4user_get_homedir(home, DK4_SIZEOF(home,dkChar), 0, NULL)) { goto finished; } #line 1203 "dk4paper.ctr" /* Find encoding */ res = dk4loc_get_settings( langbuf, DK4_SIZEOF(langbuf,dkChar), regbuf, DK4_SIZEOF(regbuf,dkChar), &enc, NULL ); #line 1209 "dk4paper.ctr" if (0 == res) { #if DK4_ON_WINDOWS enc = DK4_ENCODING_WIN1252; #else enc = DK4_ENCODING_PLAIN; #endif } #line 1216 "dk4paper.ctr" /* Apply configuration files from build-in directory names */ ok = 1; for (i = 0; i <= DK4_FS_CONF_MAX; i++) { #if DK4_HAVE_COMPATDKTOOLS3 res = dk4fs_config_compat_one( fnb, DK4_SIZEOF(fnb,dkChar), conf_file_names[1], dk4inst_get_directory(2), dk4inst_get_directory(1), home, progname, grpname, (int)i, 1, 1, NULL ); if (0 != res) { #line 1227 "dk4paper.ctr" if (0 == dk4paper_apply_file(back, fnb, enc, erp)) { ok = 0; #line 1229 "dk4paper.ctr" } } #endif res = dk4fs_config_one( fnb, DK4_SIZEOF(fnb,dkChar), conf_file_names[0], dk4inst_get_directory(2), dk4inst_get_directory(1), home, progname, grpname, (int)i, 1, NULL ); if (0 != res) { #line 1238 "dk4paper.ctr" if (0 == dk4paper_apply_file(back, fnb, enc, erp)) { ok = 0; #line 1240 "dk4paper.ctr" } } } if (0 == ok) { #line 1244 "dk4paper.ctr" dk4papersize_coll_close(back); back = NULL; } finished: #line 1250 "dk4paper.ctr" return back; } double dk4paper_difference(dk4_paper_size_t const *l, dk4_paper_size_t const *r) { double back = 0.0; double value = 0.0; #if DK4_USE_ASSERT assert(NULL != l); assert(NULL != r); #endif if ((NULL != l) && (NULL != r)) { back = fabs(l->w - r->w); value = fabs(l->h - r->h); if (value > back) { back = value; } value = fabs(l->i - r->i); if (value > back) { back = value; } value = fabs(l->o - r->o); if (value > back) { back = value; } value = fabs(l->t - r->t); if (value > back) { back = value; } value = fabs(l->b - r->b); if (value > back) { back = value; } } return back; } int dk4paper_find_nearest( size_t *pres, dk4_paper_size_t *a, size_t sza, dk4_paper_size_t *vptr, dk4_er_t *erp ) { double mindiff = 0.0; /* Minimum difference so far */ double thisdiff = 0.0; /* Difference for current size */ size_t i; /* Current array index to test */ size_t minind = 0; /* Index of minimum array element */ int back = 0; #line 1292 "dk4paper.ctr" #if DK4_USE_ASSERT assert(NULL != pres); assert(NULL != a); assert(0 < sza); assert(NULL != vptr); #endif if ((NULL != pres) && (NULL != a) && (0 < sza) && (NULL != vptr)) { for (i = 0; i < sza; i++) { thisdiff = dk4paper_difference(a, vptr); if (0 == i) { minind = 0; mindiff = thisdiff; } else { if (thisdiff < mindiff) { mindiff = thisdiff; minind = i; } } a++; } *pres = minind; back = 1; } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } #line 1320 "dk4paper.ctr" return back; } /* vim: set ai sw=4 ts=4 : */