%% options copyright owner = Dirk Krause copyright year = 2013-2014 license = bsd %% header #ifdef __cplusplus extern "C" { #endif /** Compare two nodes. @param l Pointer to left node. @param r Pointer to right node. @param cr Comparison criteria (ignored). @return Comparison result. */ int hb_node_compare(void const *l, void const *r, int cr); /** Create node, allocate memory. @param job Job structure. @param parent Parent node. @param lineno Line number where object was created. @param objno Object number (in order of creation). @param indent Line indent. @return Pointer to new node on success, NULL on error. */ hb_node_t * hb_node_new( hb_job_t *job, hb_node_t *parent, unsigned long lineno, unsigned long objno, int indent ); /** Destroy node, release memory. @param ptr Node to destroy. */ void hb_node_delete(hb_node_t *ptr); /** Search for variable in node and parents. @param node Start node for search. @param name Variable name. @return Pointer to value on success, NULL on error. */ dkChar const * hbnode_variable(hb_node_t *node, dkChar const *name); /** Create link structure. @param url URL to store. @param lno Link number. @param app Application structure for diagnostics, may be NULL. @return Pointer to new link structure on success, NULL on error. */ hb_link_t * hbnode_link_new(dkChar const *url, unsigned long lno, dk3_app_t *app); /** Delete link structure. @param ptr Link structure to delete. */ void hbnode_link_delete(hb_link_t *ptr); /** Compare two link structures. @param l Left structure. @param r Right structure or URL. @param cr Comparison criteria (0=obj/obj by URL, 1=obj/URL, 2=obj/obj by lno). @return Comparison result. */ int hbnode_link_compare(const void *l, const void *r, int cr); #ifdef __cplusplus } #endif %% module #include "htmlbook.h" #include "dk3all.h" $!trace-include void hbnode_link_delete(hb_link_t *ptr) { $? "+ hbnode_link_delete" if(ptr) { ptr->lno = 0UL; dk3_release(ptr->url); dk3_delete(ptr); } $? "- hbnode_link_delete" } hb_link_t * hbnode_link_new(dkChar const *url, unsigned long lno, dk3_app_t *app) { hb_link_t *back = NULL; $? "+ hbnode_link_new" if(url) { back = dk3_new_app(hb_link_t,1,app); if(back) { back->lno = lno; back->url = dk3str_dup_app(url,app); if(!(back->url)) { hbnode_link_delete(back); back = NULL; } } } $? "- hbnode_link_new %s", TR_PTR(back) return back; } int hbnode_link_compare(const void *l, const void *r, int cr) { hb_link_t *pl; hb_link_t *pr; int back = 0; $? "+ hbnode_link_compare %s %s", TR_PTR(l), TR_PTR(r) if(l) { if(r) { pl = (hb_link_t *)l; switch(cr) { case 0: { pr = (hb_link_t *)r; back = dk3str_cmp(pl->url, pr->url); } break; case 1: { back = dk3str_cmp(pl->url, (dkChar const *)r); } break; default: { pr = (hb_link_t *)r; if(pl->lno > pr->lno) { back = 1; } else { if(pl->lno < pr->lno) { back = -1; } } } break; } if(-1 > back) { back = -1; } if( 1 < back) { back = 1; } } else back = 1; } else { if(r) back = -1; } $? "- hbnode_link_compare %d", back return back; } int hb_node_compare(void const *l, void const *r, int cr) { hb_node_t const *pl; hb_node_t const *pr; int back = 0; $? "+ hb_node_compare %s %s", TR_PTR(l), TR_PTR(r) if(l) { if(r) { pl = (hb_node_t const *)l; pr = (hb_node_t const *)r; if(pl->objno > pr->objno) { back = 1; } else { if(pr->objno > pl->objno) { back = -1; } } } else { back = 1; } } else { if(r) { back = -1; } } $? "- hb_node_compare %d", back return back; } void hb_node_delete(hb_node_t *ptr) { hb_link_t *linkptr; hb_line_t *hp; dk3_key_value_t *kp; if(ptr) { $? "+ hb_node_delete \"%s\"", TR_STR(ptr->title) if(ptr->s_lbylno) { if(ptr->i_lbylno) { dk3sto_it_close(ptr->i_lbylno); } dk3sto_close(ptr->s_lbylno); } ptr->s_lbylno = NULL; ptr->i_lbylno = NULL; if(ptr->s_lbyurl) { if(ptr->i_lbyurl) { dk3sto_it_reset(ptr->i_lbyurl); while(NULL != (linkptr = (hb_link_t *)dk3sto_it_next(ptr->i_lbyurl))) { hbnode_link_delete(linkptr); } dk3sto_it_close(ptr->i_lbyurl); } dk3sto_close(ptr->s_lbyurl); } ptr->s_lbyurl = NULL; ptr->i_lbyurl = NULL; if(ptr->s_lines) { if(ptr->i_lines) { dk3sto_it_reset(ptr->i_lines); while(NULL != (hp = (hb_line_t *)dk3sto_it_next(ptr->i_lines))) { hbcont_line_delete(hp); } dk3sto_it_close(ptr->i_lines); } dk3sto_close(ptr->s_lines); } ptr->s_lines = NULL; ptr->i_lines = NULL; if(ptr->s_variables) { if(ptr->i_variables) { dk3sto_it_reset(ptr->i_variables); do { kp = (dk3_key_value_t *)dk3sto_it_next(ptr->i_variables); if(kp) { dk3kv_delete(kp); } } while(kp); dk3sto_it_close(ptr->i_variables); } dk3sto_close(ptr->s_variables); } ptr->s_variables = NULL; ptr->i_variables = NULL; if(ptr->s_jsfiles) { if(ptr->i_jsfiles) { dk3sto_it_reset(ptr->i_jsfiles); while(NULL != (linkptr = (hb_link_t *)dk3sto_it_next(ptr->i_jsfiles))) { $? ". js file %lu \"%s\"", linkptr->lno, linkptr->url hbnode_link_delete(linkptr); } dk3sto_it_close(ptr->i_jsfiles); } dk3sto_close(ptr->s_jsfiles); } ptr->s_jsfiles = NULL; ptr->i_jsfiles = NULL; /* We can simply close the storage here, all nodes are listed in the s_nodes storage of the job structure. */ if(ptr->s_subnodes) { if(ptr->i_subnodes) { dk3sto_it_close(ptr->i_subnodes); } dk3sto_close(ptr->s_subnodes); } ptr->s_subnodes = NULL; ptr->i_subnodes = NULL; ptr->parent = NULL; ptr->curchild = NULL; ptr->jumpnode = NULL; #if TRACE_DEBUG $? ". objno = %lu", ptr->objno $? ". lineno = %lu", ptr->lineno $? ". options = %u", ptr->options $? ". indent = %d", ptr->indent if(ptr->parent) { $? ". have parent" } if(ptr->title) { $? ". title = \"%s\"", ptr->title } if(ptr->shorttitle) { $? ". shorttitle = \"%s\"", ptr->shorttitle } if(ptr->filename) { $? ". filename = \"%s\"", ptr->filename } if(ptr->suffix) { $? ". suffix = \"%s\"", ptr->suffix } if(ptr->template) { $? ". template = \"%s\"", ptr->template } if(ptr->stylefile) { $? ". stylefile = \"%s\"", ptr->stylefile } if(ptr->author) { $? ". author = \"%s\"", ptr->author } if(ptr->location) { $? ". location = \"%s\"", ptr->location } if(ptr->icontoc) { $? ". icontoc = \"%s\"", ptr->icontoc } if(ptr->iconprev) { $? ". iconprev = \"%s\"", ptr->iconprev } if(ptr->iconnext) { $? ". iconnext = \"%s\"", ptr->iconnext } if(ptr->iconindex) { $? ". iconindex = \"%s\"", ptr->iconindex } if(ptr->favicon) { $? ". favicon = \"%s\"", ptr->favicon } #endif dk3_release(ptr->title); dk3_release(ptr->shorttitle); dk3_release(ptr->filename); dk3_release(ptr->suffix); dk3_release(ptr->template); dk3_release(ptr->stylefile); dk3_release(ptr->author); dk3_release(ptr->location); dk3_release(ptr->icontoc); dk3_release(ptr->iconprev); dk3_release(ptr->iconnext); dk3_release(ptr->iconindex); dk3_release(ptr->favicon); ptr->lineno = 0UL; ptr->objno = 0UL; ptr->indent = 0; ptr->inenc = 0; ptr->options = 0U; dk3_delete(ptr); $? "- hb_node_delete" } } /** Find depth of a node. @param ptr Node to inspect. @return Node depth. */ static int hbnode_find_depth(hb_node_t *ptr) { int back = 0; $? "+ hbnode_find_depth" ptr = ptr->parent; while(ptr) { back++; ptr = ptr->parent; } $? "- hbnode_find_depth %d", back return back; } hb_node_t * hb_node_new( hb_job_t *job, hb_node_t *parent, unsigned long lineno, unsigned long objno, int indent ) { hb_node_t *back = NULL; int ok = 0; $? "+ hb_node_new" back = dk3_new_app(hb_node_t,1,job->app); if(back) { back->parent = parent; back->curchild = NULL; back->jumpnode = NULL; back->s_subnodes = NULL; back->i_subnodes = NULL; back->s_variables = NULL; back->i_variables = NULL; back->s_lines = NULL; back->i_lines = NULL; back->s_lbyurl = NULL; back->i_lbyurl = NULL; back->s_lbylno = NULL; back->i_lbylno = NULL; back->s_jsfiles = NULL; back->i_jsfiles = NULL; back->title = NULL; back->shorttitle = NULL; back->filename = NULL; back->suffix = NULL; back->template = NULL; back->stylefile = NULL; back->author = NULL; back->location = NULL; back->icontoc = NULL; back->iconprev = NULL; back->iconnext = NULL; back->iconindex = NULL; back->favicon = NULL; back->lineno = lineno; back->objno = objno; back->pobjno = 0UL; back->nextlink = 0UL; back->nextindex = 0UL; back->outFileName = NULL; back->headno = 0UL; back->nextsubheadno = 0UL; back->nextjs = 0UL; back->contnum = 0L; /* back->inenc = -1; */ if(parent) { back->inenc = parent->inenc; } else { back->inenc = job->iecmd; } /* As each node is configured after the parent is finished we can implement option inheritance by simply copying the parents options. */ back->options = 0U; if(parent) { back->options = parent->options; } back->indent = indent; back->depth = 0; back->tocstate = HB_TOC_STATE_INIT; back->s_subnodes = dk3sto_open_app(job->app); if(back->s_subnodes) { dk3sto_set_comp(back->s_subnodes, hb_node_compare, 0); back->i_subnodes = dk3sto_it_open(back->s_subnodes); if(back->i_subnodes) { back->s_variables = dk3sto_open_app(job->app); if(back->s_variables) { dk3sto_set_comp(back->s_variables, dk3kv_compare, 0); back->i_variables = dk3sto_it_open(back->s_variables); if(back->i_variables) { back->s_lbyurl = dk3sto_open_app(job->app); if(back->s_lbyurl) { dk3sto_set_comp(back->s_lbyurl, hbnode_link_compare, 0); back->i_lbyurl = dk3sto_it_open(back->s_lbyurl); if(back->i_lbyurl) { back->s_lbylno = dk3sto_open_app(job->app); if(back->s_lbylno) { dk3sto_set_comp(back->s_lbylno, hbnode_link_compare, 2); back->i_lbylno = dk3sto_it_open(back->s_lbylno); if(back->i_lbylno) { ok = 1; } } } } } } } } if(!(ok)) { hb_node_delete(back); back = NULL; } if(back) { back->depth = hbnode_find_depth(back); } } $? "- hb_node_new %s", TR_PTR(back) return back; } dkChar const * hbnode_variable(hb_node_t *node, dkChar const *name) { dk3_key_value_t *kvp; dkChar const *back = NULL; int cc = 1; $? "+ hbnode_variable \"%s\"", TR_STR(name) if((node) && (name)) { while(cc) { if(node) { kvp = dk3sto_it_find_like(node->i_variables, name, 1); if(kvp) { cc = 0; back = kvp->val; } else { node = node->parent; } } else { cc = 0; } } } $? "- hbnode_variable \"%s\"", TR_STR(back) return back; }