1%% options 2 3copyright owner = Dirk Krause 4copyright year = 2013-xxxx 5SPDX-License-Identifier: BSD-3-Clause 6 7 8 9%% header 10 11#ifdef __cplusplus 12extern "C" { 13#endif 14 15/** Compare two nodes. 16 @param l Pointer to left node. 17 @param r Pointer to right node. 18 @param cr Comparison criteria (ignored). 19 @return Comparison result. 20*/ 21int 22hb_node_compare(void const *l, void const *r, int cr); 23 24/** Create node, allocate memory. 25 @param job Job structure. 26 @param parent Parent node. 27 @param lineno Line number where object was created. 28 @param objno Object number (in order of creation). 29 @param indent Line indent. 30 @return Pointer to new node on success, NULL on error. 31*/ 32hb_node_t * 33hb_node_new( 34 hb_job_t *job, 35 hb_node_t *parent, 36 unsigned long lineno, 37 unsigned long objno, 38 int indent 39); 40 41/** Destroy node, release memory. 42 @param ptr Node to destroy. 43*/ 44void 45hb_node_delete(hb_node_t *ptr); 46 47/** Search for variable in node and parents. 48 @param node Start node for search. 49 @param name Variable name. 50 @return Pointer to value on success, NULL on error. 51*/ 52dkChar const * 53hbnode_variable(hb_node_t *node, dkChar const *name); 54 55/** Create link structure. 56 @param url URL to store. 57 @param lno Link number. 58 @param app Application structure for diagnostics, may be NULL. 59 @return Pointer to new link structure on success, NULL on error. 60*/ 61hb_link_t * 62hbnode_link_new(dkChar const *url, unsigned long lno, dk3_app_t *app); 63 64/** Delete link structure. 65 @param ptr Link structure to delete. 66*/ 67void 68hbnode_link_delete(hb_link_t *ptr); 69 70/** Compare two link structures. 71 @param l Left structure. 72 @param r Right structure or URL. 73 @param cr Comparison criteria 74 (0=obj/obj by URL, 1=obj/URL, 2=obj/obj by lno). 75 @return Comparison result. 76*/ 77int 78hbnode_link_compare(const void *l, const void *r, int cr); 79 80#ifdef __cplusplus 81} 82#endif 83 84%% module 85 86#include <htmlbook/htmlbook.h> 87#include <libdk3c/dk3all.h> 88#include <libdk3c/dk3unused.h> 89 90 91 92$!trace-include 93 94 95 96void 97hbnode_link_delete(hb_link_t *ptr) 98{ 99 $? "+ hbnode_link_delete" 100 if(ptr) { 101 ptr->lno = 0UL; 102 dk3_release(ptr->url); 103 dk3_delete(ptr); 104 } $? "- hbnode_link_delete" 105} 106 107 108 109hb_link_t * 110hbnode_link_new(dkChar const *url, unsigned long lno, dk3_app_t *app) 111{ 112 hb_link_t *back = NULL; 113 $? "+ hbnode_link_new" 114 if(url) { 115 back = dk3_new_app(hb_link_t,1,app); 116 if(back) { 117 back->lno = lno; 118 back->url = dk3str_dup_app(url,app); 119 back->flags = 0; 120 if(!(back->url)) { 121 hbnode_link_delete(back); 122 back = NULL; 123 } 124 } 125 } $? "- hbnode_link_new PTR=%d", TR_IPTR(back) 126 return back; 127} 128 129 130 131int 132hbnode_link_compare(const void *l, const void *r, int cr) 133{ 134 hb_link_t *pl; 135 hb_link_t *pr; 136 int back = 0; 137 $? "+ hbnode_link_compare PTR=%d PTR=%d", TR_IPTR(l), TR_IPTR(r) 138 if(l) { 139 if(r) { 140 pl = (hb_link_t *)l; 141 switch(cr) { 142 case 0: { 143 pr = (hb_link_t *)r; 144 back = dk3str_cmp(pl->url, pr->url); 145 } break; 146 case 1: { 147 back = dk3str_cmp(pl->url, (dkChar const *)r); 148 } break; 149 default: { 150 pr = (hb_link_t *)r; 151 if(pl->lno > pr->lno) { 152 back = 1; 153 } else { 154 if(pl->lno < pr->lno) { 155 back = -1; 156 } 157 } 158 } break; 159 } 160 if(-1 > back) { back = -1; } 161 if( 1 < back) { back = 1; } 162 } else back = 1; 163 } else { 164 if(r) back = -1; 165 } $? "- hbnode_link_compare %d", back 166 return back; 167} 168 169 170 171int 172hb_node_compare(void const *l, void const *r, int DK3_ARG_UNUSED(cr) ) 173{ 174 hb_node_t const *pl; 175 hb_node_t const *pr; 176 int back = 0; 177 $? "+ hb_node_compare PTR=%d PTR=%d", TR_IPTR(l), TR_IPTR(r) 178 DK3_UNUSED_ARG(cr) 179 if(l) { 180 if(r) { 181 pl = (hb_node_t const *)l; 182 pr = (hb_node_t const *)r; 183 if(pl->objno > pr->objno) { 184 back = 1; 185 } else { 186 if(pr->objno > pl->objno) { 187 back = -1; 188 } 189 } 190 } else { 191 back = 1; 192 } 193 } else { 194 if(r) { 195 back = -1; 196 } 197 } $? "- hb_node_compare %d", back 198 return back; 199} 200 201 202 203void 204hb_node_delete(hb_node_t *ptr) 205{ 206 hb_link_t *linkptr; 207 hb_line_t *hp; 208 dk3_key_value_t *kp; 209 if(ptr) { 210 $? "+ hb_node_delete \"%!ds\"", TR_STR(ptr->title) 211 if(ptr->s_lbylno) { 212 if(ptr->i_lbylno) { 213 dk3sto_it_close(ptr->i_lbylno); 214 } 215 dk3sto_close(ptr->s_lbylno); 216 } 217 ptr->s_lbylno = NULL; ptr->i_lbylno = NULL; 218 if(ptr->s_lbyurl) { 219 if(ptr->i_lbyurl) { 220 dk3sto_it_reset(ptr->i_lbyurl); 221 while(NULL != (linkptr = (hb_link_t *)dk3sto_it_next(ptr->i_lbyurl))) { 222 hbnode_link_delete(linkptr); 223 } 224 dk3sto_it_close(ptr->i_lbyurl); 225 } 226 dk3sto_close(ptr->s_lbyurl); 227 } 228 ptr->s_lbyurl = NULL; ptr->i_lbyurl = NULL; 229 if(ptr->s_lines) { 230 if(ptr->i_lines) { 231 dk3sto_it_reset(ptr->i_lines); 232 while(NULL != (hp = (hb_line_t *)dk3sto_it_next(ptr->i_lines))) { 233 hbcont_line_delete(hp); 234 } 235 dk3sto_it_close(ptr->i_lines); 236 } 237 dk3sto_close(ptr->s_lines); 238 } ptr->s_lines = NULL; ptr->i_lines = NULL; 239 if(ptr->s_variables) { 240 if(ptr->i_variables) { 241 dk3sto_it_reset(ptr->i_variables); 242 do { 243 kp = (dk3_key_value_t *)dk3sto_it_next(ptr->i_variables); 244 if(kp) { dk3kv_delete(kp); } 245 } while(kp); 246 dk3sto_it_close(ptr->i_variables); 247 } 248 dk3sto_close(ptr->s_variables); 249 } 250 ptr->s_variables = NULL; ptr->i_variables = NULL; 251 if(ptr->s_jsfiles) { 252 if(ptr->i_jsfiles) { 253 dk3sto_it_reset(ptr->i_jsfiles); 254 while(NULL != (linkptr = (hb_link_t *)dk3sto_it_next(ptr->i_jsfiles))) { 255 $? ". js file %lu \"%!ds\"", linkptr->lno, linkptr->url 256 hbnode_link_delete(linkptr); 257 } 258 dk3sto_it_close(ptr->i_jsfiles); 259 } 260 dk3sto_close(ptr->s_jsfiles); 261 } ptr->s_jsfiles = NULL; ptr->i_jsfiles = NULL; 262 /* We can simply close the storage here, all nodes are listed 263 in the s_nodes storage of the job structure. 264 */ 265 if(ptr->s_subnodes) { 266 if(ptr->i_subnodes) { 267 dk3sto_it_close(ptr->i_subnodes); 268 } 269 dk3sto_close(ptr->s_subnodes); 270 } 271 ptr->s_subnodes = NULL; 272 ptr->i_subnodes = NULL; 273 ptr->parent = NULL; 274 ptr->curchild = NULL; 275 ptr->jumpnode = NULL; 276#if TRACE_DEBUG 277 $? ". objno = %lu", ptr->objno 278 $? ". lineno = %lu", ptr->lineno 279 $? ". options = %u", ptr->options 280 $? ". indent = %d", ptr->indent 281 if(ptr->parent) { $? ". have parent" 282 } 283 if(ptr->title) { $? ". title = \"%!ds\"", ptr->title 284 } 285 if(ptr->shorttitle) { $? ". shorttitle = \"%!ds\"", ptr->shorttitle 286 } 287 if(ptr->fulltitle) { $? ". fulltitle= = \"%!ds\"", ptr->fulltitle 288 } 289 if(ptr->filename) { $? ". filename = \"%!ds\"", ptr->filename 290 } 291 if(ptr->suffix) { $? ". suffix = \"%!ds\"", ptr->suffix 292 } 293 if(ptr->templatefi) { $? ". templatefi = \"%!ds\"", ptr->templatefi 294 } 295 if(ptr->stylefile) { $? ". stylefile = \"%!ds\"", ptr->stylefile 296 } 297 if(ptr->author) { $? ". author = \"%!ds\"", ptr->author 298 } 299 if(ptr->location) { $? ". location = \"%!ds\"", ptr->location 300 } 301 if(ptr->icontoc) { $? ". icontoc = \"%!ds\"", ptr->icontoc 302 } 303 if(ptr->iconprev) { $? ". iconprev = \"%!ds\"", ptr->iconprev 304 } 305 if(ptr->iconnext) { $? ". iconnext = \"%!ds\"", ptr->iconnext 306 } 307 if(ptr->iconhome) { $? ". iconhome = \"%!ds\"", ptr->iconhome 308 } 309 if(ptr->iconindex) { $? ". iconindex = \"%!ds\"", ptr->iconindex 310 } 311 if(ptr->favicon) { $? ". favicon = \"%!ds\"", ptr->favicon 312 } 313 if(ptr->metadesc) { $? ". metadesc = \"%!ds\"", ptr->metadesc 314 } 315 if(ptr->metakeyw) { $? ". metakeyw = \"%!ds\"", ptr->metakeyw 316 } 317#endif 318 dk3_release(ptr->title); 319 dk3_release(ptr->shorttitle); 320 dk3_release(ptr->fulltitle); 321 dk3_release(ptr->filename); 322 dk3_release(ptr->suffix); 323 dk3_release(ptr->templatefi); 324 dk3_release(ptr->stylefile); 325 dk3_release(ptr->author); 326 dk3_release(ptr->location); 327 dk3_release(ptr->icontoc); 328 dk3_release(ptr->iconprev); 329 dk3_release(ptr->iconnext); 330 dk3_release(ptr->iconindex); 331 dk3_release(ptr->iconhome); 332 dk3_release(ptr->favicon); 333 dk3_release(ptr->metadesc); 334 dk3_release(ptr->metakeyw); 335 ptr->lineno = 0UL; 336 ptr->objno = 0UL; 337 ptr->indent = 0; 338 ptr->inenc = 0; 339 ptr->options = 0U; 340 ptr->havenavimenu = 0; 341 dk3_delete(ptr); 342 $? "- hb_node_delete" 343 } 344} 345 346 347 348/** Find depth of a node. 349 @param ptr Node to inspect. 350 @return Node depth. 351*/ 352static 353int 354hbnode_find_depth(hb_node_t *ptr) 355{ 356 int back = 0; 357 $? "+ hbnode_find_depth" 358 ptr = ptr->parent; 359 while(ptr) { 360 back++; 361 ptr = ptr->parent; 362 } $? "- hbnode_find_depth %d", back 363 return back; 364} 365 366 367 368hb_node_t * 369hb_node_new( 370 hb_job_t *job, 371 hb_node_t *parent, 372 unsigned long lineno, 373 unsigned long objno, 374 int indent 375) 376{ 377 hb_node_t *back = NULL; 378 int ok = 0; 379 $? "+ hb_node_new" 380 back = dk3_new_app(hb_node_t,1,job->app); 381 if(back) { 382 back->parent = parent; 383 back->curchild = NULL; 384 back->jumpnode = NULL; 385 back->s_subnodes = NULL; 386 back->i_subnodes = NULL; 387 back->s_variables = NULL; 388 back->i_variables = NULL; 389 back->s_lines = NULL; 390 back->i_lines = NULL; 391 back->s_lbyurl = NULL; 392 back->i_lbyurl = NULL; 393 back->s_lbylno = NULL; 394 back->i_lbylno = NULL; 395 back->s_jsfiles = NULL; 396 back->i_jsfiles = NULL; 397 back->title = NULL; 398 back->shorttitle = NULL; 399 back->fulltitle = NULL; 400 back->filename = NULL; 401 back->suffix = NULL; 402 back->templatefi = NULL; 403 back->stylefile = NULL; 404 back->author = NULL; 405 back->location = NULL; 406 back->icontoc = NULL; 407 back->iconprev = NULL; 408 back->iconnext = NULL; 409 back->iconindex = NULL; 410 back->iconhome = NULL; 411 back->favicon = NULL; 412 back->metadesc = NULL; 413 back->metakeyw = NULL; 414 back->lineno = lineno; 415 back->objno = objno; 416 back->pobjno = 0UL; 417 back->nextlink = 0UL; 418 back->nextindex = 0UL; 419 back->outFileName = NULL; 420 back->headno = 0UL; 421 back->nextsubheadno = 0UL; 422 back->nextjs = 0UL; 423 back->contnum = 0L; 424 back->havenavimenu = 0; 425 back->htdt = HTML_DOCTYPE_UNSPECIFIED; 426 /* back->inenc = -1; */ 427 if(parent) { 428 back->inenc = parent->inenc; 429 } else { 430 back->inenc = job->iecmd; 431 } 432 /* As each node is configured after the parent is finished we can 433 implement option inheritance by simply copying the parents options. 434 */ 435 back->options = 0U; if(parent) { back->options = parent->options; } 436 back->indent = indent; 437 back->depth = 0; 438 back->tocstate = HB_TOC_STATE_INIT; 439 back->s_subnodes = dk3sto_open_app(job->app); 440 if(back->s_subnodes) { 441 dk3sto_set_comp(back->s_subnodes, hb_node_compare, 0); 442 back->i_subnodes = dk3sto_it_open(back->s_subnodes); 443 if(back->i_subnodes) { 444 back->s_variables = dk3sto_open_app(job->app); 445 if(back->s_variables) { 446 dk3sto_set_comp(back->s_variables, dk3kv_compare, 0); 447 back->i_variables = dk3sto_it_open(back->s_variables); 448 if(back->i_variables) { 449 back->s_lbyurl = dk3sto_open_app(job->app); 450 if(back->s_lbyurl) { 451 dk3sto_set_comp(back->s_lbyurl, hbnode_link_compare, 0); 452 back->i_lbyurl = dk3sto_it_open(back->s_lbyurl); 453 if(back->i_lbyurl) { 454 back->s_lbylno = dk3sto_open_app(job->app); 455 if(back->s_lbylno) { 456 dk3sto_set_comp(back->s_lbylno, hbnode_link_compare, 2); 457 back->i_lbylno = dk3sto_it_open(back->s_lbylno); 458 if(back->i_lbylno) { 459 ok = 1; 460 } 461 } 462 } 463 } 464 } 465 } 466 } 467 } 468 if(!(ok)) { 469 hb_node_delete(back); 470 back = NULL; 471 } 472 if(back) { 473 back->depth = hbnode_find_depth(back); 474 } 475 } $? "- hb_node_new PTR=%d", TR_IPTR(back) 476 return back; 477} 478 479 480 481dkChar const * 482hbnode_variable(hb_node_t *node, dkChar const *name) 483{ 484 dk3_key_value_t *kvp; 485 dkChar const *back = NULL; 486 int cc = 1; 487 $? "+ hbnode_variable \"%!ds\"", TR_STR(name) 488 if((node) && (name)) { 489 while(cc) { 490 if(node) { 491 kvp = (dk3_key_value_t *)dk3sto_it_find_like(node->i_variables,name,1); 492 if(kvp) { 493 cc = 0; 494 back = kvp->val; 495 } else { 496 node = node->parent; 497 } 498 } else { 499 cc = 0; 500 } 501 } 502 } $? "- hbnode_variable \"%!ds\"", TR_STR(back) 503 return back; 504} 505 506 507 508