1%% options 2 3copyright owner = Dirk Krause 4copyright year = 2013-xxxx 5SPDX-License-Identifier: BSD-3-Clause 6 7 8%% header 9 10#ifdef __cplusplus 11extern "C" { 12#endif 13 14/** Write one HTML file. 15 @param job Job structure. 16 @param nodeptr Node for file to write. 17 @param p Previous node. 18 @param n Next node. 19*/ 20void 21hbhtml_write_file(hb_job_t *job,hb_node_t *nodeptr,hb_node_t *p,hb_node_t *n); 22 23/** Write one 32-bit character to HTML output. 24 @param job Job structure. 25 @param c32 Character to write. 26*/ 27void 28hbhtml_c32(hb_job_t *job, dk3_c32_t c32); 29 30/** Write some text as HTML. 31 @param job Job structure. 32 @param text Text to write. 33 @return 1 on success, 0 on error. 34*/ 35int 36hbhtml_output_for_text(hb_job_t *job, dkChar const *text); 37 38/** Write some URL text as HTML. 39 @param job Job structure. 40 @param text Text to write. 41 @return 1 on success, 0 on error. 42*/ 43int 44hbhtml_url_output_for_text(hb_job_t *job, dkChar const *text); 45 46/** Handle one input line, either from template or from text file. 47 @param obj Line processor structure. 48 @param il Input line to process. 49 @return 1 on success, 0 on error (continue), -1 on error (exit). 50*/ 51int 52hbhtml_line_handler(void *obj, dkChar *il); 53 54/** Construct output file name. 55 @param dptr Destination buffer pointer. 56 @param sz Destination buffer size. 57 @param job Job structure. 58 @param nptr Node to process. 59 @return 1 on success, 0 on error. 60*/ 61int 62hbhtml_create_output_filename( 63 dkChar *dptr, 64 size_t sz, 65 hb_job_t *job, 66 hb_node_t *nptr 67); 68 69/** Check whether a link is an external link (http:// or ftp:// 70 at start). 71 @param link Link to check. 72 @return 1 for external links, 0 for internal links. 73*/ 74int 75hbhtml_check_link_for_external(dkChar const *link); 76 77/** Find HTML doctype for a node. 78 @param job Htmlbook job. 79 @param nodeptr Node to start search. 80 @return Doctype for node or job. 81*/ 82int 83hbhtml_get_doctype( 84 hb_job_t *job, 85 hb_node_t *nodeptr 86); 87 88#ifdef __cplusplus 89} 90#endif 91 92 93%% state machine 94 95[options] 96 97name = hbhtml_stm1 98write header = no 99 100[states] 101STM1_ST_START # Start state 102STM1_ST_ERROR # Error occured 103STM1_ST_BS # Backslash found 104STM1_ST_PERCENT # One percent sign found 105STM1_ST_SPECIAL # Recording a special 106STM1_ST_SPEC_BS # Backslash found in special 107STM1_ST_SPEC_PC # Percent found in special 108 109[inputs] 110STM1_I_ANY # Any character 111STM1_I_BS # Backslash 112STM1_I_PERCENT # Percent sign 113 114[outputs] 115STM1_O_ERROR # Error, do nothing 116STM1_O_NOTHING # Do nothing 117STM1_O_SHIPOUT # Add character to shipout buffer 118STM1_O_BS_SHIPOUT # Shipout character after backslash 119STM1_O_PERCENT_SHIPOUT # Shipout percent sign and current character 120STM1_O_PERCENT # Shipout just percent sign 121STM1_O_SWITCH # Flush shipout and switch to saving special 122STM1_O_SPECIAL # Add current character to special 123STM1_O_SPEC_BS # Add char after backslash to special 124STM1_O_SPEC_PC_ADD # Add percent and current char to special 125STM1_O_SPEC_PC # Add percent sign to special 126STM1_O_EXECUTE # Execute special 127 128[rules] 129* * STM1_ST_ERROR STM1_O_ERROR 130 131STM1_ST_START * STM1_ST_START STM1_O_SHIPOUT 132STM1_ST_START STM1_I_BS STM1_ST_BS STM1_O_NOTHING 133STM1_ST_START STM1_I_PERCENT STM1_ST_PERCENT STM1_O_NOTHING 134 135STM1_ST_BS * STM1_ST_START STM1_O_BS_SHIPOUT 136 137STM1_ST_PERCENT * STM1_ST_START STM1_O_PERCENT_SHIPOUT 138STM1_ST_PERCENT STM1_I_BS STM1_ST_BS STM1_O_PERCENT 139STM1_ST_PERCENT STM1_I_PERCENT STM1_ST_SPECIAL STM1_O_SWITCH 140 141STM1_ST_SPECIAL * STM1_ST_SPECIAL STM1_O_SPECIAL 142STM1_ST_SPECIAL STM1_I_BS STM1_ST_SPEC_BS STM1_O_NOTHING 143STM1_ST_SPECIAL STM1_I_PERCENT STM1_ST_SPEC_PC STM1_O_NOTHING 144 145STM1_ST_SPEC_BS * STM1_ST_SPECIAL STM1_O_SPEC_BS 146 147STM1_ST_SPEC_PC * STM1_ST_SPECIAL STM1_O_SPEC_PC_ADD 148STM1_ST_SPEC_PC STM1_I_BS STM1_ST_SPEC_BS STM1_O_SPEC_PC 149STM1_ST_SPEC_PC STM1_I_PERCENT STM1_ST_START STM1_O_EXECUTE 150 151%% state machine 152[options] 153 name = hbhtml_stm3 154 write header = no 155[states] 156 STM3_ST_START # No character processed yet 157 STM3_ST_NAME # ASCII characters (for protocol name) found 158 STM3_ST_COLON # Colon found 159 STM3_ST_COLSL # Colon and slash 160 STM3_ST_SUCCESS # Colon and two slashes found 161 STM3_ST_ERROR # Not a protocol at start of text 162[inputs] 163 STM3_I_ANY # Anything not listed below 164 STM3_I_ASCII # a-zA-Z01-9_ 165 STM3_I_COLON # Colon 166 STM3_I_SLASH # Slash 167[outputs] 168 STM3_O_OK # OK so far 169 STM3_O_ERROR # ERROR found 170[rules] 171 * * STM3_ST_ERROR STM3_O_ERROR 172 STM3_ST_START STM3_I_ASCII STM3_ST_NAME STM3_O_OK 173 STM3_ST_NAME STM3_I_ASCII STM3_ST_NAME STM3_O_OK 174 STM3_ST_NAME STM3_I_COLON STM3_ST_COLON STM3_O_OK 175 STM3_ST_COLON STM3_I_SLASH STM3_ST_COLSL STM3_O_OK 176 STM3_ST_COLSL STM3_I_SLASH STM3_ST_SUCCESS STM3_O_OK 177 STM3_ST_SUCCESS * STM3_ST_SUCCESS STM3_O_OK 178 179 180%% module 181 182 183#include <libdk3c/dk3all.h> 184#include <libdk3c/dk3strkv.h> 185#include <htmlbook/htmlbook.h> 186#include <libdk3c/dk3enc.h> 187 188 189 190$!trace-include 191 192 193 194/** Object for line reader (special comments). 195*/ 196typedef struct { 197 hb_job_t *job; /**< Job structure. */ 198 hb_node_t *nodeptr; /**< Current node to process. */ 199 unsigned long lineno; /**< Current line number to process. */ 200} hb_spc_reader_t; 201 202 203 204/** Translation table for ASCII characters. 205*/ 206static char const * const hbhtml_translation_table[] = { 207/* 0 00 */ NULL, 208/* 1 01 */ NULL, 209/* 2 02 */ NULL, 210/* 3 03 */ NULL, 211/* 4 04 */ NULL, 212/* 5 05 */ NULL, 213/* 6 06 */ NULL, 214/* 7 07 */ NULL, 215/* 8 08 */ NULL, 216/* 9 09 */ "\t", 217/* 10 0a */ NULL, 218/* 11 0b */ NULL, 219/* 12 0c */ NULL, 220/* 13 0d */ NULL, 221/* 14 0e */ NULL, 222/* 15 0f */ NULL, 223/* 16 10 */ NULL, 224/* 17 11 */ NULL, 225/* 18 12 */ NULL, 226/* 19 13 */ NULL, 227/* 20 14 */ NULL, 228/* 21 15 */ NULL, 229/* 22 16 */ NULL, 230/* 23 17 */ NULL, 231/* 24 18 */ NULL, 232/* 25 19 */ NULL, 233/* 26 1a */ NULL, 234/* 27 1b */ NULL, 235/* 28 1c */ NULL, 236/* 29 1d */ NULL, 237/* 30 1e */ NULL, 238/* 31 1f */ NULL, 239/* 32 20 */ " ", 240/* 33 21 */ "!", 241/* 34 22 */ """, 242/* 35 23 */ "#", 243/* 36 24 */ "$", 244/* 37 25 */ "%", 245/* 38 26 */ "&", 246/* 39 27 */ "'", 247/* 40 28 */ "(", 248/* 41 29 */ ")", 249/* 42 2a */ "*", 250/* 43 2b */ "+", 251/* 44 2c */ ",", 252/* 45 2d */ "-", 253/* 46 2e */ ".", 254/* 47 2f */ "/", 255/* 48 30 */ "0", 256/* 49 31 */ "1", 257/* 50 32 */ "2", 258/* 51 33 */ "3", 259/* 52 34 */ "4", 260/* 53 35 */ "5", 261/* 54 36 */ "6", 262/* 55 37 */ "7", 263/* 56 38 */ "8", 264/* 57 39 */ "9", 265/* 58 3a */ ":", 266/* 59 3b */ ";", 267/* 60 3c */ "<", 268/* 61 3d */ "=", 269/* 62 3e */ ">", 270/* 63 3f */ "?", 271/* 64 40 */ "@", 272/* 65 41 */ "A", 273/* 66 42 */ "B", 274/* 67 43 */ "C", 275/* 68 44 */ "D", 276/* 69 45 */ "E", 277/* 70 46 */ "F", 278/* 71 47 */ "G", 279/* 72 48 */ "H", 280/* 73 49 */ "I", 281/* 74 4a */ "J", 282/* 75 4b */ "K", 283/* 76 4c */ "L", 284/* 77 4d */ "M", 285/* 78 4e */ "N", 286/* 79 4f */ "O", 287/* 80 50 */ "P", 288/* 81 51 */ "Q", 289/* 82 52 */ "R", 290/* 83 53 */ "S", 291/* 84 54 */ "T", 292/* 85 55 */ "U", 293/* 86 56 */ "V", 294/* 87 57 */ "W", 295/* 88 58 */ "X", 296/* 89 59 */ "Y", 297/* 90 5a */ "Z", 298/* 91 5b */ "[", 299/* 92 5c */ "\\", 300/* 93 5d */ "]", 301/* 94 5e */ "^", 302/* 95 5f */ "_", 303/* 96 60 */ "`", 304/* 97 61 */ "a", 305/* 98 62 */ "b", 306/* 99 63 */ "c", 307/* 100 64 */ "d", 308/* 101 65 */ "e", 309/* 102 66 */ "f", 310/* 103 67 */ "g", 311/* 104 68 */ "h", 312/* 105 69 */ "i", 313/* 106 6a */ "j", 314/* 107 6b */ "k", 315/* 108 6c */ "l", 316/* 109 6d */ "m", 317/* 110 6e */ "n", 318/* 111 6f */ "o", 319/* 112 70 */ "p", 320/* 113 71 */ "q", 321/* 114 72 */ "r", 322/* 115 73 */ "s", 323/* 116 74 */ "t", 324/* 117 75 */ "u", 325/* 118 76 */ "v", 326/* 119 77 */ "w", 327/* 120 78 */ "x", 328/* 121 79 */ "y", 329/* 122 7a */ "z", 330/* 123 7b */ "{", 331/* 124 7c */ "|", 332/* 125 7d */ "}", 333/* 126 7e */ "~", 334/* 127 7f */ NULL, 335/* 128 80 */ NULL, 336/* 129 81 */ NULL, 337/* 130 82 */ NULL, 338/* 131 83 */ NULL, 339/* 132 84 */ NULL, 340/* 133 85 */ NULL, 341/* 134 86 */ NULL, 342/* 135 87 */ NULL, 343/* 136 88 */ NULL, 344/* 137 89 */ NULL, 345/* 138 8a */ NULL, 346/* 139 8b */ NULL, 347/* 140 8c */ NULL, 348/* 141 8d */ NULL, 349/* 142 8e */ NULL, 350/* 143 8f */ NULL, 351/* 144 90 */ NULL, 352/* 145 91 */ NULL, 353/* 146 92 */ NULL, 354/* 147 93 */ NULL, 355/* 148 94 */ NULL, 356/* 149 95 */ NULL, 357/* 150 96 */ NULL, 358/* 151 97 */ NULL, 359/* 152 98 */ NULL, 360/* 153 99 */ NULL, 361/* 154 9a */ NULL, 362/* 155 9b */ NULL, 363/* 156 9c */ NULL, 364/* 157 9d */ NULL, 365/* 158 9e */ NULL, 366/* 159 9f */ NULL, 367/* 160 a0 */ " ", 368/* 161 a1 */ "¡", 369/* 162 a2 */ "¢", 370/* 163 a3 */ "£", 371/* 164 a4 */ "¤", 372/* 165 a5 */ "¥", 373/* 166 a6 */ "¦", 374/* 167 a7 */ "§", 375/* 168 a8 */ "¨", 376/* 169 a9 */ "©", 377/* 170 aa */ "ª", 378/* 171 ab */ "«", 379/* 172 ac */ "¬", 380/* 173 ad */ "­", 381/* 174 ae */ "®", 382/* 175 af */ "¯", 383/* 176 b0 */ "°", 384/* 177 b1 */ "±", 385/* 178 b2 */ "²", 386/* 179 b3 */ "³", 387/* 180 b4 */ "´", 388/* 181 b5 */ "µ", 389/* 182 b6 */ "¶", 390/* 183 b7 */ "·", 391/* 184 b8 */ "¸", 392/* 185 b9 */ "¹", 393/* 186 ba */ "º", 394/* 187 bb */ "»", 395/* 188 bc */ "¼", 396/* 189 bd */ "½", 397/* 190 be */ "¾", 398/* 191 bf */ "¿", 399/* 192 c0 */ "À", 400/* 193 c1 */ "Á", 401/* 194 c2 */ "Â", 402/* 195 c3 */ "Ã", 403/* 196 c4 */ "Ä", 404/* 197 c5 */ "Å", 405/* 198 c6 */ "Æ", 406/* 199 c7 */ "Ç", 407/* 200 c8 */ "È", 408/* 201 c9 */ "É", 409/* 202 ca */ "Ê", 410/* 203 cb */ "Ë", 411/* 204 cc */ "/Igrave;", 412/* 205 cd */ "Í", 413/* 206 ce */ "Î", 414/* 207 cf */ "Ï", 415/* 208 d0 */ "Ð", 416/* 209 d1 */ "Ñ", 417/* 210 d2 */ "Ò", 418/* 211 d3 */ "Ó", 419/* 212 d4 */ "Ô", 420/* 213 d5 */ "Õ", 421/* 214 d6 */ "Ö", 422/* 215 d7 */ "×", 423/* 216 d8 */ "Ø", 424/* 217 d9 */ "Ù", 425/* 218 da */ "Ú", 426/* 219 db */ "Û", 427/* 220 dc */ "Ü", 428/* 221 dd */ "Ý", 429/* 222 de */ "Þ", 430/* 223 df */ "ß", 431/* 224 e0 */ "à", 432/* 225 e1 */ "á", 433/* 226 e2 */ "â", 434/* 227 e3 */ "ã", 435/* 228 e4 */ "ä", 436/* 229 e5 */ "å", 437/* 230 e6 */ "æ", 438/* 231 e7 */ "ç", 439/* 232 e8 */ "è", 440/* 233 e9 */ "é", 441/* 234 ea */ "ê", 442/* 235 eb */ "ë", 443/* 236 ec */ "ì", 444/* 237 ed */ "í", 445/* 238 ee */ "î", 446/* 239 ef */ "ï", 447/* 240 f0 */ "ð", 448/* 241 f1 */ "ñ", 449/* 242 f2 */ "ò", 450/* 243 f3 */ "ó", 451/* 244 f4 */ "ô", 452/* 245 f5 */ "õ", 453/* 246 f6 */ "ö", 454/* 247 f7 */ "÷", 455/* 248 f8 */ "ø", 456/* 249 f9 */ "ù", 457/* 250 fa */ "ú", 458/* 251 fb */ "û", 459/* 252 fc */ "ü", 460/* 253 fd */ "ý", 461/* 254 fe */ "þ", 462/* 255 ff */ "ÿ" 463}; 464 465 466 467/** Constant 8-bit character keywords. 468*/ 469static char const * const hbhtml_c8_kw[] = { 470$!string-table 471# 472# 0 Newline 473# 474\n 475# 476# 1 Space 477# 478 479# 480# 2 Start of an image 481# 482<img 483# 484# 3 General tag end 485# 486> 487# 488# 4 Image source 489# 490src=" 491# 492# 5 End of attribute 493# 494" 495# 496# 6 alt attribute 497# 498 alt=" 499# 500# 7 title attribute 501# 502 title=" 503# 504# 8 border attribute 505# 506 border=" 507# 508# 9 width attribute 509# 510 width=" 511# 512# 10 height attribute 513# 514 height=" 515# 516# 11 12 HTML tag 517# 518<html>\n 519</html>\n 520# 521# 13 14 BODY tag 522# 523<body>\n 524</body>\n 525# 526# 15 16 HEAD tag 527# 528<head>\n 529</head>\n 530# 531# 17 18 Generated by 532# 533<!--\nGenerated by htmlbook (see http://sourceforge.net/p/dktools/wiki/htmlbook%20manual/)\n-->\n 534<meta name="generator" content="htmlbook (http://sourceforge.net/p/dktools/wiki/htmlbook/)">\n 535# 536# 19 20 TITLE tag 537# 538<title> 539</title>\n 540# 541# 21 22 Style sheet 542# 543<link rel="stylesheet" type="text/css" href=" 544">\n 545# 546# 23 24 Charset specifications 547# 548<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">\n 549<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\n 550# 551# 25 26 Author 552# 553<meta name="author" content=" 554">\n 555# 556# 27 28 Shortcut icon 557# 558<link rel="shortcut icon" href=" 559">\n 560# 561# 29 30 Navi menu div 562# 563<div class="hb_nm_div">\n 564</div><!-- class=hb_nm_div -->\n 565# 566# 31 32 Navi menu ul 567# 568<ul class="hb_nm_ul">\n 569</ul><!-- class=hb_nm_ul -->\n 570# 571# 33 Navi menu separator 572# 573<li class="hb_nm_sep"> </li>\n 574# 575# 34 35 Navi menu current node entry 576# 577<li class="hb_nm_c" 578</li>\n 579# 580# 36 37 Navi menu current entry 581# 582<li class="hb_nm_li"> 583</li>\n 584# 585# 38 Class name for navigation link 586# 587hb_nm_a 588# 589# 39 40 41 42 43 44 45 Link 590# 591<a href=" 592> 593</a> 594" 595 class=" 596 title=" 597 type=" 598# 599# 46 47 Navigation div 600# 601<div class="hb_navigation"> 602</div>\n 603# 604# 48 Space between navigation images 605# 606 607# 608# 49 50 51 52 Navigation link 609# 610<a class="hb_navi_a" href=" 611" title=" 612"> 613</a> 614# 615# 53 54 55 56 Image in navigation link 616# 617<img src=" 618" alt=" 619" title=" 620" class="hb_navi_img" border="0" 621# 622# 57 Default border 623# 6240 625# 626# 58 Name attribute 627# 628 name=" 629# 630# 59 longdesc attribute 631# 632 longdesc=" 633# 634# 60 Class attribute 635# 636 class=" 637# 638# 61 ID attribute 639# 640 id=" 641# 642# 62 Usemap attribute 643# 644 usemap=" 645# 646# 63 Align attribute 647# 648 align=" 649# 650# 64 Hspace attribute 651# 652 hspace=" 653# 654# 65 Vspace attribute 655# 656 vspace=" 657# 658# 66 Ismap attribute 659# 660 ismap 661# 662# 67 Width and height attributes 663# 664 width="%lu" height="%lu" 665# 666# 68 Link to enlarge image 667# 668<a class="hb_img_a_larger" href=" 669# 670# 69 Link target is a blank window 671# 672" target="_blank" 673# 674# 70 71 72 73 PDF object 675# 676<object type="application/pdf" data=" 677" width=" 678" height=" 679</object> 680# 681# 74 Named anchor 682# 683<a name=" 684# 685# 75 76 77 78 target type class id 686# 687" target=" 688" type=" 689" class=" 690" id=" 691# 692# 79 80 81 82 style hreflang title onblur 693# 694" style=" 695" hreflang=" 696" title=" 697" onblur=" 698# 699# 83 84 85 86 onfocus rel rev shape 700# 701" onfocus=" 702" rel=" 703" rev=" 704" shape=" 705# 706# 87 88 89 90 tabindex accesskey charset coords 707# 708" tabindex=" 709" accesskey=" 710" charset=" 711" coords=" 712# 713# 91 714# 715<span class="hb_link_number"> 〈%lu〉</span> 716# 717# 92 93 94 95 96 97 98 99 Menu entry table. 718# 719<table class="hb_me_ta" summary=" 720</table>\n 721<tr class="hb_me_tr">\n 722</tr>\n 723<td class="hb_me_td_text" colspan="%u"> 724</td>\n 725<td></td>\n 726<td class="hb_me_td_arrow"> → </td>\n 727# 728# 100 101 Link classes 729# 730hb_a_i 731hb_a_e 732# 733# 102 103 104 105 734# 735<div class="hb_file_div">\n 736<a class="hb_file_a" target="_blank" href=" 737text/plain 738<br>\n 739# 740# 106 107 741# 742<pre>\n 743</pre>\n 744# 745# 108 746# 747" target="_blank 748# 749# 109 110 111 112 113 750# 751<div class="hb_img_div_outer">\n 752<div class="hb_img_div_inner_img">\n 753<div class="hb_img_div_inner_img_centered">\n 754<p class="hb_img_p_download">\n 755<br class="clearboth">\n</p>\n 756# 757# 114 115 758# 759<object type="image/svg+xml" data=" 760<param name="src" value=" 761# 762# 116 117 763# 764<br>\n<span class="hb_img_caption"> 765</span> 766# 767# 118 119 768# 769 type="image/svg+xml" 770 type="application/pdf" 771# 772# 120 773# 774<p><br class="clearboth"></p>\n 775# 776# 121 122 777# 778<script src=" 779" type="text/javascript"></script>\n 780# 781# 123 124 125 126 782# 783<link rel=" 784" title=" 785" href=" 786">\n 787# 788# 127 ... 135 789# 790author 791contents 792index 793top 794up 795first 796prev 797next 798last 799# 800# 136 137 801# 802\#hb_toc 803\#hb_index 804# 805# 138 139 140 141 142 143 806# 807<table class="hb_img_ta" summary=" 808<tr class="hb_img_tr">\n 809<td class="hb_img_td_img">\n 810<td class="hb_img_td_empty"> </td>\n 811<td class="hb_img_td_a">\n 812">\n 813# 814# 144 815# 816hb_nm_a_parent 817# 818# 145 819# 820<div class="hb_img_div_no_vspace">\n 821# 822# 146 147 148 149 150 823# 824<code title=" 825"> 826</code> 827 828 829# 830# 151 152 153 831# 832<span class="hint" title=" 833"> 834</span> 835# 836# 154 837# 838<meta name="description" content=" 839# 840# 155 841# 842<meta name="keywords" content=" 843# 844# 156 157 845# 846&#x 847; 848# ↗ 849# 850# 158 851# 852<table class="hb_me_ta">\n 853# 854# 159 855# 856<table class="hb_img_ta">\n 857# 858# 160 859# 860<body bgcolor="#FFFFFF">\n 861# 862# 161, 162 863# 864<html lang=" 865">\n 866# 867# 163, 164 868# 869<meta charset="utf-8">\n 870<meta name="viewport" content="width=device-width, initial-scale=1.0">\n 871# 872# 165 873# 874<link rel="stylesheet" href=" 875# 876# 166, 167, 168 877# 878"></script>\n 879" async></script>\n 880" type="text/javascript" async></script>\n 881# 882# 169, 170 883# 884<script type="text/javascript" src=" 885<script src=" 886$!end 887}; 888 889 890 891static const char * const hbhtml_doctypes[] = { 892$!string-table 893<!DOCTYPE html>\n 894<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n 895<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">\n 896<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">\n 897<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n 898<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n 899<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">\n 900<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n 901$!end 902}; 903 904 905 906/** Special commands. 907*/ 908dkChar const * const hbhtml_special_commands[] = { 909$!string-table macro=dkT 910# 911# 0: Contents 912# 913contents 914# 915# 1: Title 916# 917title 918# 919# 2: Image 920# 921img 922# 923# 3: Menu 924# 925menu 926# 927# 4: Navigation 928# 929navigation 930# 931# 5: Links 932# 933links 934# 935# 6: Author 936# 937author 938# 939# 7: Location 940# 941location 942# 943# 8: Date 944# 945date 946# 947# 9: Variable 948# 949var 950# 951# 10: Code 952# 953code 954# 955# 11: a (link) 956# 957a 958# 959# 12: menuentry 960# 961menuentry 962# 963# 13: index (create keyword index entry) 964# 965index 966# 967# 14: source file 968# 969sourcefile 970# 971# 15: HTML file name 972# 973htmlname 974# 975# 16: Hint 976# 977hint 978$!end 979}; 980 981 982 983 984/** Attributes allowed in image special command. 985*/ 986dkChar const * const hbhtml_img_keys[] = { 987$!string-table macro=dkT 988ali$gn 989alt 990b$order 991he$ight 992hs$pace 993is$map 994lo$ngdesc 995n$ame 996sr$c 997u$semap 998v$space 999w$idth 1000la$rger 1001p$df 1002cac$he 1003ti$tle 1004cl$ass 1005id 1006div 1007cap$tion 1008ce$ntered 1009svg 1010svgwh 1011do$wnloads 1012o$bject 1013ta$ble 1014no-v$space 1015f$ile 1016$!end 1017}; 1018 1019 1020 1021/** Keys for hint. 1022*/ 1023dkChar const * const hbhtml_hint_keys[] = { 1024$!string-table macro=dkT 1025te$xt 1026ti$tle 1027$!end 1028}; 1029 1030 1031 1032/** Attributes for menu. 1033*/ 1034dkChar const * const hbhtml_menu_keys[] = { 1035$!string-table macro=dkT 1036st$yle 1037su$b 1038$!end 1039}; 1040 1041 1042 1043/** Attributes for menuentry. 1044*/ 1045dkChar const * const hbhtml_menuentry_keys[] = { 1046$!string-table macro=dkT 1047i$tem 1048$!end 1049}; 1050 1051 1052 1053/** Attributes for index entry. 1054*/ 1055dkChar const * const hbhtml_index_keys[] = { 1056$!string-table macro=dkT 1057t$ext 1058n$ame 1059ref$erence 1060$!end 1061}; 1062 1063 1064 1065/** Attributes for sourcefile special command. 1066*/ 1067dkChar const * const hbhtml_sourcef_keys[] = { 1068$!string-table macro=dkT 1069f$ile 1070ty$pe 1071ti$tle 1072l$ineno 1073$!end 1074}; 1075 1076 1077/** Attributes for navigation. 1078*/ 1079dkChar const * const hbhtml_navi_keys[] = { 1080$!string-table macro=dkT 1081t$oc 1082p$revious 1083n$ext 1084i$ndex 1085h$ome 1086$!end 1087}; 1088 1089 1090 1091/** Attributes for code special command. 1092*/ 1093dkChar const * const hbhtml_code_keys[] = { 1094$!string-table macro=dkT 1095e$nable 1096on 1097d$isable 1098of$f 1099t$oggle 1100l$ineno 1101$!end 1102}; 1103 1104 1105 1106/** Attribute for a. 1107*/ 1108dkChar const * const hbhtml_a_keys[] = { 1109$!string-table macro=dkT 1110te$xt 1111ti$tle 1112ac$cesskey 1113ch$arset 1114co$ords 1115href 1116hrefl$ang 1117na$me 1118onb$lur 1119onf$ocus 1120rel 1121rev 1122sh$ape 1123tab$index 1124tar$get 1125ty$pe 1126cl$ass 1127id 1128st$yle 1129ext$ernal 1130$!end 1131}; 1132 1133 1134 1135/** The menu styles. 1136*/ 1137dkChar const * const hbhtml_menu_styles[] = { 1138$!string-table macro=dkT 1139r$everse 1140f$ull 1141c$urrent 1142t$op 1143$!end 1144}; 1145 1146 1147 1148/** Attributes allowed in date special. 1149*/ 1150dkChar const * const hbhtml_date_keys[] = { 1151$!string-table macro=dkT 1152st$yle 1153$!end 1154}; 1155 1156 1157 1158/** Subcommands of img with not vertical space. 1159*/ 1160dkChar const * const hbhtml_no_vspace_suffixes[] = { 1161$!string-table macro=dkT 1162tex 1163$!end 1164}; 1165 1166 1167 1168/** File name suffixes. 1169*/ 1170dkChar const * const hbhtml_image_filename_suffixes[] = { 1171$!string-table macro=dkT 1172.png 1173.pdf 1174.svg 1175$!end 1176}; 1177 1178 1179 1180/** Check whether a character is useable in an URL. 1181 RFC 1630 and 3986 allow only 8-bit characters (octets) 1182 in URLs. 1183 @param c32 Character to check. 1184 @return 1 for usable character, 0 otherwise. 1185*/ 1186static 1187int 1188hbhtml_url_useable(dk3_c32_t c32) 1189{ 1190 int back = 1; 1191 $? "+ hbhtml_url_useable %lx %lu", dk3enc_uc_to_ul(c32), dk3enc_uc_to_ul(c32) 1192 if((dk3_c32_t)255 < c32) { 1193 back = 0; /* NOT REPORTED */ 1194 } $? "- hbhtml_url_useable %d", back 1195 return back; 1196} 1197 1198 1199 1200#if 0 1201/** Check whether a character must be written hex-encoded to an URL. 1202 See RFC 3986 for reserved and unreserved characters. 1203 @param c32 Character to check. 1204 @return 1 for hex-encoding, 0 for direct use. 1205*/ 1206static 1207int 1208hbhtml_url_must_encode_normally(dk3_c32_t c32) 1209{ 1210 int back = 1; 1211 char c; 1212 if(128UL > dk3enc_uc_to_ul(c32)) { 1213 c = (char)c32; 1214 c &= 0x7F; 1215 if(('a' <= c) && ('z' >= c)) { 1216 back = 0; 1217 } else { 1218 if(('A' <= c) && ('Z' >= c)) { 1219 back = 0; 1220 } else { 1221 if(('0' <= c) && ('9' >= c)) { 1222 back = 0; 1223 } else { 1224 switch(c) { 1225 case '-': case '_': case '.': case '~': { 1226 back = 0; 1227 } break; 1228 } 1229 } 1230 } 1231 } 1232 } 1233 return back; 1234} 1235#endif 1236 1237 1238 1239/** Check whether a character must be written hex-encoded to an URL. 1240 See RFC 3986 for reserved and unreserved characters. 1241 @param c32 Character to check. 1242 @return 1 for hex-encoding, 0 for direct use. 1243*/ 1244static 1245int 1246hbhtml_url_must_encode(dk3_c32_t c32) 1247{ 1248 int back = 0; 1249 $? "+ hbhtml_url_must_encode %lx %lu", dk3enc_uc_to_ul(c32), dk3enc_uc_to_ul(c32) 1250 if((dk3_c32_t)126 < c32) { 1251 back = 1; 1252 } else { 1253 if((dk3_c32_t)33 > c32) { 1254 back = 1; 1255 } else { 1256#if 0 1257 /* 1258 2017-10-10 Removed. Must use & instead of hex notation. 1259 */ 1260 /* 1261 2017-10-03 Recode ampersand. 1262 */ 1263 if (0x00000026UL == c32) { 1264 back = 1; 1265 } 1266#endif 1267 } 1268 } $? "- hbhtml_url_must_encode %d", back 1269 return back; 1270} 1271 1272 1273 1274/** Write one character in URL encoding, complain on problems. 1275 Unusable characters (not in octect range 0...0xFF) 1276 are UTF-8 encoded first and hex-converted for the URL. 1277 Some ASCII characters have special meaning in URL encoding 1278 (i.e. ampersand, question mark...). We assume the user 1279 intended to use these characters and specified the URL 1280 so we can use it "as is". 1281 1282 @param job Job structure. 1283 @param c32 Character to print. 1284*/ 1285static 1286void 1287hbhtml_url_c32(hb_job_t *job, dk3_c32_t c32) 1288{ 1289 char buf[16]; /* Buffer for hexadecimal notation */ 1290 unsigned char ub[16]; /* Buffer for UTF-8 notation */ 1291 size_t sz; /* Number of bytes used in ub */ 1292 size_t i; /* Traverse ub */ 1293 $? "+ hbhtml_url_c32 0x%lx = %lu", dk3enc_uc_to_ul(c32), dk3enc_uc_to_ul(c32) 1294 if(hbhtml_url_useable(c32)) { 1295 if(hbhtml_url_must_encode(c32)) { 1296 buf[0] = '%'; 1297 sprintf(&(buf[1]), "%02X", (unsigned)c32); 1298 fputs(buf, job->of); 1299 } else { 1300 if ((dk3_c32_t)'&' == c32) { 1301 fputc((((char)c32) & ((char)0x7F)), job->of); 1302 } 1303 else { 1304 fputc((((char)c32) & ((char)0x7F)), job->of); 1305 } 1306 } 1307 } else { 1308 job->non_url = 1; 1309 sz = dk3enc_uc2utf8(c32, ub, sizeof(ub)); 1310 for(i = 0; i < sz; i++) { 1311 buf[0] = '%'; 1312 sprintf(&(buf[1]), "%02X", ((unsigned)(ub[i]) & 0x00FFU)); 1313 fputs(buf, job->of); 1314 } 1315 } $? "- hbhtml_url_c32" 1316} 1317 1318 1319 1320/** Write shipout buffer in URL encoding. 1321 @param job Job structure. 1322*/ 1323static 1324void 1325hbhtml_url_flush_shipout(hb_job_t *job) 1326{ 1327#if DK3_CHAR_SIZE > 1 1328#if DK3_CHAR_SIZE > 2 1329 size_t i; 1330#else 1331 dk3_c16_t const *sp; /* Source character pointer */ 1332 dk3_c32_t c32; /* 32-bit character */ 1333 size_t sl; /* Remaining source string length */ 1334 size_t used; /* Number of source chars used */ 1335#endif 1336#else 1337 unsigned char const *sp; /* Source character pointer */ 1338 dk3_c32_t c32; /* 32-bit character */ 1339 size_t sl; /* Remaining source string length */ 1340 size_t used; /* Number of source chars used */ 1341 size_t i; /* Process all source chars */ 1342 unsigned char c; /* Current source char to process */ 1343#endif 1344 $? "+ hbhtml_url_flush_shipout" 1345 if(job->shipused) { 1346 job->non_url = 0; 1347 if(job->shipused < job->bs) { 1348 (job->shipbuffer)[job->shipused] = dkT('\0'); 1349#if DK3_CHAR_SIZE > 1 1350#if DK3_CHAR_SIZE > 2 1351 for(i = 0; i < (job->shipused); i++) { 1352 hbhtml_url_c32(job, (job->shipused)[i]); 1353 } 1354#else 1355 sp = (dk3_c16_t const *)(job->shipbuffer); 1356 sl = job->shipused; 1357 while(sl > 0) { 1358 used = 0; 1359 if(dk3enc_utf162uc(&c32, sp, sl, &used)) { 1360 hbhtml_url_c32(job, c32); 1361 if(used > 0) { 1362 if(sl >= used) { 1363 sl = sl - used; 1364 sp = &(sp[used]); 1365 } else { 1366 sl = 0; 1367 /* ERROR: Decoding */ 1368 dk3app_log_i1(job->app, DK3_LL_ERROR, 119); 1369 } 1370 } else { 1371 sl = 0; 1372 /* ERROR: Decoding */ 1373 dk3app_log_i1(job->app, DK3_LL_ERROR, 119); 1374 } 1375 } else { 1376 sl = 0; 1377 /* ERROR: Decoding */ 1378 dk3app_log_i1(job->app, DK3_LL_ERROR, 119); 1379 } 1380 } 1381#endif 1382#else 1383 $? "+ shipout ASCII" 1384 if(dk3app_get_encoding(job->app) == DK3_ENCODING_UTF8) { 1385 $? ". UTF-8" 1386 sp = (unsigned char const *)(job->shipbuffer); 1387 sl = job->shipused; 1388 while(sl > 0) { 1389 used = 0; 1390 if(dk3enc_utf82uc(&c32, sp, sl, &used)) { 1391 hbhtml_url_c32(job, c32); 1392 if(used > 0) { 1393 if(sl >= used) { 1394 sl = sl - used; 1395 sp = &(sp[used]); 1396 } else { 1397 sl = 0; 1398 /* ERROR: Decoding problem */ 1399 dk3app_log_i1(job->app, DK3_LL_ERROR, 118); 1400 } 1401 } else { 1402 sl = 0; 1403 /* ERROR: Decoding problem */ 1404 dk3app_log_i1(job->app, DK3_LL_ERROR, 118); 1405 } 1406 } else { 1407 sl = 0; 1408 /* ERROR: Decoding problem */ 1409 dk3app_log_i1(job->app, DK3_LL_ERROR, 118); 1410 } 1411 } 1412 } else { 1413 sp = (unsigned char const *)(job->shipbuffer); 1414 for(i = 0; i < (job->shipused); i++) { 1415 c = sp[i]; 1416 c32 = (dk3_c32_t)c; 1417 c32 &= 0x000000FFUL; 1418 hbhtml_url_c32(job, c32); 1419 } 1420 } 1421 $? "- shipout ASCII" 1422#endif 1423 if(job->non_url) { 1424 /* WARNING: Non-URL characters in string! */ 1425 dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 21, 22, job->shipbuffer); 1426 } 1427 } 1428 job->non_url = 0; 1429 } 1430 job->shipused = 0; 1431 $? "- hbhtml_url_flush_shipout" 1432} 1433 1434 1435 1436void 1437hbhtml_c32(hb_job_t *job, dk3_c32_t c32) 1438{ 1439 unsigned char ub[16]; /* Buffer for UTF-8 conversion */ 1440 size_t sz; /* Number of chars used in ub */ 1441 size_t i; /* Process all chars in ub */ 1442 char c; /* Current char from ub */ 1443 $? "+ hbhtml_c32 0x%lx %lu", dk3enc_uc_to_ul(c32), dk3enc_uc_to_ul(c32) 1444 if(128UL > dk3enc_uc_to_ul((unsigned long)c32)) { 1445 c = (((char)c32) & ((char)0x7F)); 1446 switch(c) { 1447 case '\n': { 1448 fputc('\n', job->of); 1449 } break; 1450 case '&': { 1451 if((job->options) & HB_JOB_OPT_CODE) { 1452 fputs(hbhtml_translation_table[38], job->of); 1453 } else { 1454 if(((job->currentnode)->options) & HB_NODE_OPT_REPLACE_AMPERSAND) { 1455 fputs(hbhtml_translation_table[38], job->of); 1456 } else { 1457 fputc('&', job->of); 1458 } 1459 } 1460 } break; 1461 case '<': { 1462 if((job->options) & HB_JOB_OPT_CODE) { 1463 fputs(hbhtml_translation_table[60], job->of); 1464 } else { 1465 fputc('<', job->of); 1466 } 1467 } break; 1468 case '>': { 1469 if((job->options) & HB_JOB_OPT_CODE) { 1470 fputs(hbhtml_translation_table[62], job->of); 1471 } else { 1472 fputc('>', job->of); 1473 } 1474 } break; 1475 case '"': { 1476 if((job->options) & HB_JOB_OPT_CODE) { 1477 fputs(hbhtml_translation_table[34], job->of); 1478 } else { 1479 fputc('"', job->of); 1480 } 1481 } break; 1482 case '%': { 1483 fputc('%', job->of); /* PROBABLY NEED A CODE */ 1484 } break; 1485 default: { 1486 sz = (size_t)c32; 1487 sz &= (size_t)0x007FU; 1488 if(hbhtml_translation_table[sz]) { 1489 fputs(hbhtml_translation_table[sz], job->of); 1490 } else { 1491 fprintf(job->of, "&#x%02lx;", dk3enc_uc_to_ul((unsigned long)c32)); 1492 } 1493 } break; 1494 } 1495 } else { 1496 if(((dk3_c32_t)256) > c32) { 1497 sz = (size_t)c32; 1498 sz &= (size_t)0x00FFU; 1499 if(hbhtml_translation_table[sz]) { 1500 fputs(hbhtml_translation_table[sz], job->of); 1501 } else { 1502 fprintf(job->of, "&#x%02lx;", dk3enc_uc_to_ul((unsigned long)c32)); 1503 } 1504 } else { 1505 if(HB_CS_UTF_8 == job->cs) { 1506 sz = dk3enc_uc2utf8(c32, ub, sizeof(ub)); 1507 for(i = 0; i < sz; i++) { fputc(ub[i], job->of); } 1508 } else { 1509 if(((dk3_c32_t)0x010000UL) > c32) { 1510 fprintf(job->of, "&#x%04lx;", dk3enc_uc_to_ul((unsigned long)c32)); 1511 } else { 1512 if(((dk3_c32_t)0x01000000UL) > c32) { 1513 fprintf(job->of, "&#x%06lx;", dk3enc_uc_to_ul((unsigned long)c32)); 1514 } else { 1515 fprintf(job->of, "&#x%08lx;", dk3enc_uc_to_ul((unsigned long)c32)); 1516 } 1517 } 1518 } 1519 } 1520 } $? "- hbhtml_c32" 1521} 1522 1523 1524 1525/** Flush the shipout buffer. 1526 @param job Job structure. 1527*/ 1528static 1529void 1530hbhtml_flush_shipout(hb_job_t *job) 1531{ 1532#if DK3_CHAR_SIZE > 1 1533#if DK3_CHAR_SIZE > 2 1534 size_t i; /* Process all characters */ 1535#else 1536 dk3_c16_t const *sp; /* Current source start */ 1537 dk3_c32_t c32; /* Current 32-bit char to process */ 1538 size_t sl; /* Remaining source length */ 1539 size_t used; /* Source chars used */ 1540#endif 1541#else 1542 unsigned char const *sp; /* Current source start */ 1543 dk3_c32_t c32; /* Current 32-bit char to process */ 1544 size_t sl; /* Remaining source length */ 1545 size_t used; /* Source chars used */ 1546 size_t i; /* Process all chars from buffer */ 1547 unsigned char c; /* Current char to process */ 1548#endif 1549 $? "+ hbhtml_flush_shipout" 1550 if(job->shipused) { 1551 if(job->shipused < job->bs) { 1552 (job->shipbuffer)[job->shipused] = dkT('\0'); 1553#if DK3_CHAR_SIZE > 1 1554#if DK3_CHAR_SIZE > 2 1555 for(i = 0; i < (job->shipused); i++) { 1556 hbhtml_c32(job, (job->shipused)[i]); 1557 } 1558#else 1559 sp = (dk3_c16_t const *)(job->shipbuffer); 1560 sl = job->shipused; 1561 while(sl > 0) { 1562 used = 0; 1563 if(dk3enc_utf162uc(&c32, sp, sl, &used)) { 1564 hbhtml_c32(job, c32); 1565 if(used > 0) { 1566 if(sl >= used) { 1567 sl = sl - used; 1568 sp = &(sp[used]); 1569 } else { 1570 sl = 0; 1571 /* ERROR: Decoding */ 1572 dk3app_log_i1(job->app, DK3_LL_ERROR, 119); 1573 } 1574 } else { 1575 sl = 0; 1576 /* ERROR: Decoding */ 1577 dk3app_log_i1(job->app, DK3_LL_ERROR, 119); 1578 } 1579 } else { 1580 sl = 0; 1581 /* ERROR: Decoding */ 1582 dk3app_log_i1(job->app, DK3_LL_ERROR, 119); 1583 } 1584 } 1585#endif 1586#else 1587 $? "+ shipout ASCII" 1588 if(dk3app_get_encoding(job->app) == DK3_ENCODING_UTF8) { 1589 $? ". UTF-8" 1590 sp = (unsigned char const *)(job->shipbuffer); 1591 sl = job->shipused; 1592 while(sl > 0) { 1593 used = 0; 1594 if(dk3enc_utf82uc(&c32, sp, sl, &used)) { 1595 hbhtml_c32(job, c32); 1596 if(used > 0) { 1597 if(sl >= used) { 1598 sl = sl - used; 1599 sp = &(sp[used]); 1600 } else { 1601 sl = 0; 1602 /* ERROR: Decoding problem */ 1603 dk3app_log_i1(job->app, DK3_LL_ERROR, 118); 1604 } 1605 } else { 1606 sl = 0; 1607 /* ERROR: Decoding problem */ 1608 dk3app_log_i1(job->app, DK3_LL_ERROR, 118); 1609 } 1610 } else { 1611 sl = 0; 1612 /* ERROR: Decoding problem */ 1613 dk3app_log_i1(job->app, DK3_LL_ERROR, 118); 1614 } 1615 } 1616 } else { 1617 sp = (unsigned char const *)(job->shipbuffer); 1618 for(i = 0; i < (job->shipused); i++) { 1619 c = sp[i]; 1620 c32 = (dk3_c32_t)c; 1621 c32 &= 0x000000FFUL; 1622 hbhtml_c32(job, c32); 1623 } 1624 } 1625 $? "- shipout ASCII" 1626#endif 1627 } 1628 } 1629 job->shipused = 0; 1630 $? "- hbhtml_flush_shipout" 1631} 1632 1633 1634 1635/** Add one character to shipout buffer. 1636 @param job Job structure. 1637 @param c Character to add. 1638 @return 1 on success, 0 on error. 1639*/ 1640static 1641int 1642hbhtml_shipout(hb_job_t *job, dkChar c) 1643{ 1644 int back = 1; 1645 $? "+ hbhtml_shipout" 1646 if((job->shipused) < (job->bs - 1)) { 1647 (job->shipbuffer)[job->shipused] = c; 1648 job->shipused += 1; 1649 if(job->shipused >= job->bs) { 1650 back = 0; 1651 } 1652 } else { 1653 back = 0; 1654 } $? "- hbhtml_shipout %d", back 1655 return back; 1656} 1657 1658 1659 1660/** Add one character to special command buffer. 1661 @param job Job structure. 1662 @param c Character to add. 1663 @return 1 on success, 0 on error. 1664*/ 1665static 1666int 1667hbhtml_add_to_special(hb_job_t *job, dkChar c) 1668{ 1669 int back = 1; 1670 $? "+ hbhtml_add_to_special" 1671 if((job->spused) < (job->bs - 1)) { 1672 (job->special)[job->spused] = c; 1673 job->spused += 1; 1674 if(job->spused >= job->bs) { 1675 back = 0; 1676 } 1677 } else { 1678 back = 0; 1679 } $? "- hbhtml_add_to_special %d", back 1680 return back; 1681} 1682 1683 1684 1685/** Classify a character for processing by state machine 1. 1686 @param c Character to classify. 1687 @return Classification result. 1688*/ 1689static 1690int 1691hbhtml_classify_for_stm1(dkChar c) 1692{ 1693 int back = STM1_I_ANY; 1694 switch(c) { 1695 case dkT('%'): { 1696 back = STM1_I_PERCENT; 1697 } break; 1698 case dkT('\\'): { 1699 back = STM1_I_BS; 1700 } break; 1701 } 1702 return back; 1703} 1704 1705 1706 1707/** Write text to HTML output file. 1708 @param job Job structure. 1709 @param text Text to write. 1710 @return 1 on success, 0 on error. 1711*/ 1712int 1713hbhtml_output_for_text(hb_job_t *job, dkChar const *text) 1714{ 1715 size_t sz; 1716#if VERSION_BEFORE_20131219 1717 int oldcode; 1718#endif 1719 int back = 0; 1720 $? "+ hbhtml_output_for_text \"%!ds\"", TR_STR(text) 1721 if((job) && (text)) { 1722 sz = dk3str_len(text); 1723 if(sz < job->bs) { $? ". size ok" 1724#if VERSION_BEFORE_20131219 1725 oldcode = (((job->options) & HB_JOB_OPT_CODE) ? 1 : 0); 1726 job->options &= (~(HB_JOB_OPT_CODE)); 1727#endif 1728 dk3str_cpy(job->shipbuffer, text); 1729 job->shipused = sz; $? ". text copied to shipout buffer" 1730 hbhtml_flush_shipout(job); $? ". flush completed" 1731 back = 1; 1732 job->spused = 0; 1733 job->shipused = 0; 1734#if VERSION_BEFORE_20131219 1735 if(oldcode) { 1736 job->options |= HB_JOB_OPT_CODE; 1737 } 1738#endif 1739 } 1740 } $? "- hbhtml_output_for_text %d", back 1741 return back; 1742} 1743 1744 1745 1746/** Write text to URL output file. 1747 @param job Job structure. 1748 @param text Text to write. 1749 @return 1 on success, 0 on error. 1750*/ 1751int 1752hbhtml_url_output_for_text(hb_job_t *job, dkChar const *text) 1753{ 1754 size_t sz; /* Text length */ 1755 int back = 0; 1756 $? "+ hbhtml_url_output_for_text \"%!ds\"", TR_STR(text) 1757 if((job) && (text)) { 1758 sz = dk3str_len(text); 1759 if(sz < job->bs) { 1760 dk3str_cpy(job->shipbuffer, text); 1761 job->shipused = sz; 1762 hbhtml_url_flush_shipout(job); 1763 back = 1; 1764 job->spused = 0; 1765 job->shipused = 0; 1766 } 1767 } $? "- hbhtml_url_output_for_text %d", back 1768 return back; 1769} 1770 1771 1772 1773/** Process the title special command. 1774 @param job Job structure. 1775 @return 1 on success, 0 on error. 1776*/ 1777static 1778int 1779hbhtml_process_sp_title(hb_job_t *job) 1780{ 1781 int back = 0; 1782 $? "+ hbhtml_process_sp_title" 1783 if(job->rootnode) { $? ". have node" 1784 if((job->rootnode)->title) { $? ". have title" 1785 if(hbhtml_output_for_text(job, (job->rootnode)->title)) { 1786 back = 1; 1787 } 1788 } 1789 } $? "- hbhtml_process_sp_title %d", back 1790 return back; 1791} 1792 1793 1794 1795/** Build new file name if necessary. 1796 @param oldname Existing file name. 1797 @param fnb File name buffer. 1798 @param fnbsz Size of file name buffer. 1799 @param sc Sub command. 1800 @param newsuffix New file name suffix. 1801 @param job Job structure. 1802 @param ecp Error code variable pointer. 1803*/ 1804static 1805dkChar * 1806hbhtml_sc_fn( 1807 dkChar *oldname, 1808 dkChar *fnb, 1809 size_t fnbsz, 1810 dkChar *sc, 1811 dkChar const *newsuffix, 1812 hb_job_t *job, 1813 int *ecp 1814) 1815{ 1816 dk3_stat_t stb; 1817 dkChar *back; 1818 dkChar *sp; 1819 $? "+ hbhtml_sc_fn \"%!ds\"", TR_STR(oldname) 1820 $? ". sc=\"%!ds\"", TR_STR(sc) 1821 $? ". newsuffix=\"%!ds\"", TR_STR(newsuffix) 1822 back = oldname; 1823 if(!(back)) { 1824 /* Remove suffix if it matches subcommand. 1825 */ 1826 sp = dk3str_get_suffix(fnb); 1827 if(sp) { 1828 if(0 == dk3str_casecmp(&(sp[1]), sc)) { 1829 *sp = dkT('\0'); 1830 } 1831 } 1832 /* Add new suffix. 1833 */ 1834 if(fnbsz > (dk3str_len(fnb) + dk3str_len(newsuffix))) { 1835 dk3str_cat(fnb, newsuffix); 1836 /* If file exists, use file name from fnb. 1837 */ 1838 if(dk3sf_stat_app(&stb, fnb, NULL)) { 1839 switch(stb.ft) { 1840 case DK3_FT_REGULAR: { 1841 back = fnb; 1842 } break; 1843 default: { 1844 /* ERROR: Not a regular file */ 1845 dk3app_log_i3(job->app, DK3_LL_ERROR, 255, 256, fnb); 1846 } break; 1847 } 1848 } else { 1849 dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 84, 85, fnb); 1850 } 1851 } else { 1852 /* ERROR: File name too long */ 1853 dk3app_log_i3(job->app, DK3_LL_ERROR, 65, 66, fnb); 1854 if(ecp) { *ecp = 1; } 1855 } 1856 } $? "- hbhtml_sc_fn \"%!ds\"", TR_STR(back) 1857 return back; 1858} 1859 1860 1861 1862/** Process image special command. 1863 @param job Job structure. 1864 @param pa Pointer to arguments. 1865 @param sc Subcommand, may be NULL. 1866 @return 1 on success, 0 on error. 1867*/ 1868static 1869int 1870hbhtml_process_sp_image(hb_job_t *job, dkChar *pa, dkChar *sc) 1871{ 1872 dkChar svgnbuf[DK3_MAX_PATH]; /* SVG file name */ 1873 dkChar pdfnbuf[DK3_MAX_PATH]; /* PDF file name */ 1874 dkChar pngnbuf[DK3_MAX_PATH]; /* PNG file name */ 1875 dk3_key_value_t kv[30]; /* Parameters */ 1876 dkChar wbuf[64]; /* Width buffer */ 1877 dkChar hbuf[64]; /* Height buffer */ 1878 dkChar *align = NULL; /* Align specified */ 1879 dkChar *alt = NULL; /* Alternative text */ 1880 dkChar *border = NULL; /* Border specified */ 1881 dkChar *height = NULL; /* Height specified */ 1882 dkChar *hspace = NULL; /* Horiz space specified */ 1883 dkChar *longdesc = NULL; /* Longdesc specified */ 1884 dkChar *name = NULL; /* Name. */ 1885 dkChar *src = NULL; /* Image file name */ 1886 dkChar *usemap = NULL; /* Usemap text */ 1887 dkChar *vspace = NULL; /* Vertical space specified */ 1888 dkChar *width = NULL; /* Width specified */ 1889 dkChar *larger = NULL; /* File name large resolution */ 1890 dkChar *pdf = NULL; /* PDF file name */ 1891 dkChar *clptr = NULL; /* Image CSS class */ 1892 dkChar *idptr = NULL; /* Image CSS id */ 1893 dkChar *title = NULL; /* Image title */ 1894 dkChar *capt = NULL; /* Image caption */ 1895 dkChar *svg = NULL; /* SVG file name */ 1896 dkChar *fnptr = NULL; /* The file argument */ 1897 unsigned long xw = 0UL; /* Width found */ 1898 unsigned long xh = 0UL; /* Height found */ 1899 size_t sz; /* Size of key value array */ 1900 size_t i; /* Traverse key value array */ 1901 int cache = 0; /* Flag: Cache width+height */ 1902 int ismap = 0; /* Flag: Write isamp attrib */ 1903 int back = 0; /* Result */ 1904 int tispec = 0; /* Flag: Title specified */ 1905 int caspec = 0; /* Flag: Capction specified */ 1906 int svgwh = 0; /* Flag: For SVG width+height */ 1907 int dodiv = 0; /* Img in div(1) or table(2) */ 1908 int center = 0; /* Flag: Center image */ 1909 int downlo = 0; /* Flag: Create download div */ 1910 int haveli = 0; /* Already have written link */ 1911 int crobj = 1; /* Flag: Create object */ 1912 int novsp = 0; /* Flag: No vertical space. */ 1913 int fnerr = 0; /* Flag: Error related file */ 1914 $? "+ hbhtml_process_sp_image pa=\"%!ds\" sc=\"%!ds\"", TR_STR(pa), TR_STR(sc) 1915 sz = DK3_SIZEOF(kv,dk3_key_value_t); 1916 svgnbuf[0] = pdfnbuf[0] = pngnbuf[0] = dkT('\0'); 1917 svgwh = job->svgwhdef; 1918 if(dk3str_to_key_value(kv, &sz, pa, job->app)) { 1919 $? ". sz = %u", (unsigned)sz 1920 if(sc) { $? ". sub command specified" 1921 tispec = 1; 1922 downlo = 1; 1923 dodiv = 2; 1924 if(-1 < dk3str_array_index(hbhtml_no_vspace_suffixes, sc, 0)) { 1925 novsp = 1; 1926 } 1927 } 1928 for(i = 0; i < sz; i++) { 1929 if(kv[i].key) { $? ". key = \"%!ds\"", kv[i].key 1930 switch(dk3str_array_abbr(hbhtml_img_keys, kv[i].key, dkT('$'), 0)) { 1931 case 0: { $? ". align" 1932 align = kv[i].val; 1933 } break; 1934 case 1: { $? ". alt" 1935 alt = kv[i].val; 1936 } break; 1937 case 2: { $? ". border" 1938 border = kv[i].val; 1939 } break; 1940 case 3: { $? ". height" 1941 height = kv[i].val; 1942 } break; 1943 case 4: { $? ". hspace" 1944 hspace = kv[i].val; 1945 } break; 1946 case 5: { /* ismap */ $? ". ismap" 1947 if(kv[i].val) { 1948 if(dk3str_is_bool(kv[i].val)) { 1949 if(dk3str_is_on(kv[i].val)) { 1950 ismap = 1; 1951 } else { 1952 ismap = 0; 1953 } 1954 } 1955 } else { 1956 ismap = 1; 1957 } 1958 } break; 1959 case 6: { $? ". longdesc" 1960 longdesc = kv[i].val; 1961 } break; 1962 case 7: { $? ". name" 1963 name = kv[i].val; 1964 } break; 1965 case 8: { $? ". src" 1966 src = kv[i].val; 1967 } break; 1968 case 9: { $? ". usemap" 1969 usemap = kv[i].val; 1970 } break; 1971 case 10: { $? ". vspace" 1972 vspace = kv[i].val; 1973 } break; 1974 case 11: { $? ". width" 1975 width = kv[i].val; 1976 } break; 1977 case 12: { $? ". set larger to \"%!ds\"", TR_STR(kv[i].val) 1978 larger = kv[i].val; 1979 } break; 1980 case 13: { $? ". pdf" 1981 pdf = kv[i].val; 1982 } break; 1983 case 14: { /* caching */ $? ". cache" 1984 if(kv[i].val) { 1985 if(dk3str_is_bool(kv[i].val)) { 1986 if(dk3str_is_on(kv[i].val)) { 1987 cache = 1; 1988 } else { 1989 cache = 0; 1990 } 1991 } 1992 } else { 1993 cache = 1; 1994 } 1995 } break; 1996 case 15: { $? ". title = \"%!ds\"", TR_STR(kv[i].val) 1997 title = kv[i].val; 1998 tispec = 1; 1999 } break; 2000 case 16: { $? ". class = \"%!ds\"", TR_STR(kv[i].val) 2001 clptr = kv[i].val; 2002 } break; 2003 case 17: { $? ". id = \"%!ds\"", TR_STR(kv[i].val) 2004 idptr = kv[i].val; 2005 } break; 2006 case 18: { /* div */ 2007 if(kv[i].val) { 2008 if(dk3str_is_bool(kv[i].val)) { 2009 dodiv = ((dk3str_is_on(kv[i].val)) ? 1 : 0); 2010 } else { 2011 /* ERROR: Not boolean */ 2012 dk3app_log_i3(job->app, DK3_LL_WARNING, 146, 144, kv[i].val); 2013 } 2014 } else { 2015 dodiv = 1; 2016 } 2017 } break; 2018 case 19: { /* caption */ 2019 caspec = 1; 2020 capt = kv[i].val; 2021 } break; 2022 case 20: { /* centered */ 2023 if(kv[i].val) { 2024 if(dk3str_is_bool(kv[i].val)) { 2025 center = ((dk3str_is_on(kv[i].val)) ? 1 : 0); 2026 } else { 2027 /* ERROR: Not boolean */ 2028 dk3app_log_i3(job->app, DK3_LL_WARNING, 146, 144, kv[i].val); 2029 } 2030 } else { 2031 center = 1; 2032 } 2033 } break; 2034 case 21: { /* svg */ 2035 svg = kv[i].val; 2036 } break; 2037 case 22: { /* svgwh */ 2038 if(kv[i].val) { 2039 if(dk3str_is_bool(kv[i].val)) { 2040 svgwh = ((dk3str_is_on(kv[i].val)) ? 1 : 0); 2041 } else { 2042 /* ERROR: Not boolean */ 2043 dk3app_log_i3(job->app, DK3_LL_WARNING, 146, 144, kv[i].val); 2044 } 2045 } else { 2046 svgwh = 1; 2047 } 2048 } break; 2049 case 23: { /* downloads */ 2050 if(kv[i].val) { 2051 if(dk3str_is_bool(kv[i].val)) { 2052 downlo = ((dk3str_is_on(kv[i].val)) ? 1 : 0); 2053 } else { 2054 /* ERROR: Not boolean */ 2055 dk3app_log_i3(job->app, DK3_LL_WARNING, 146, 144, kv[i].val); 2056 } 2057 } else { 2058 downlo = 1; 2059 } 2060 } break; 2061 case 24: { 2062 if(kv[i].val) { 2063 if(dk3str_is_bool(kv[i].val)) { 2064 crobj = ((dk3str_is_on(kv[i].val)) ? 1 : 0); 2065 } else { 2066 /* ERROR: Not boolean */ 2067 dk3app_log_i3(job->app, DK3_LL_WARNING, 146, 144, kv[i].val); 2068 } 2069 } else { 2070 crobj = 1; 2071 } 2072 } break; 2073 case 25: { 2074 if(kv[i].val) { 2075 if(dk3str_is_bool(kv[i].val)) { 2076 if(dk3str_is_on(kv[i].val)) { 2077 if(1 == dodiv) { 2078 /* Warning: Overwriting div by table */ 2079 dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 66); 2080 } 2081 dodiv = 2; 2082 } else { 2083 if(1 != dodiv) { 2084 dodiv = 0; 2085 } 2086 } 2087 } else { 2088 dk3app_log_i3(job->app, DK3_LL_WARNING, 146, 144, kv[i].val); 2089 } 2090 } else { 2091 if(1 == dodiv) { 2092 /* Warning: Overwriting div by table */ 2093 dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 66); 2094 } 2095 dodiv = 2; 2096 } 2097 } break; 2098 case 26: { 2099 if(kv[i].val) { 2100 if(dk3str_is_bool(kv[i].val)) { 2101 novsp = ((dk3str_is_on(kv[i].val)) ? 1 : 0); 2102 } else { 2103 /* ERROR: Not a boolean */ 2104 dk3app_log_i3(job->app, DK3_LL_WARNING, 146, 144, kv[i].val); 2105 } 2106 } else { 2107 novsp = 1; 2108 } 2109 } break; 2110 case 27: { $? ". file argument" 2111 if(kv[i].val) { 2112 if(fnptr) { $? ". overwriting" 2113 /* WARNING: Overwriting file setting! */ 2114 dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 86); 2115 } 2116 fnptr = kv[i].val; 2117 } else { $? "! missing file name" 2118 /* ERROR: No file name specified */ 2119 } 2120 } break; 2121 } 2122 } 2123 } 2124 if(fnptr) { $? ". file argument specified" 2125 if(dk3str_len(fnptr) < DK3_SIZEOF(svgnbuf,dkChar)) { 2126 dk3str_cpy(svgnbuf, fnptr); 2127 dk3str_cpy(pdfnbuf, fnptr); 2128 dk3str_cpy(pngnbuf, fnptr); 2129 src = hbhtml_sc_fn( 2130 src, pngnbuf, DK3_SIZEOF(pngnbuf,dkChar), sc, 2131 hbhtml_image_filename_suffixes[0], job, &fnerr 2132 ); 2133 svg = hbhtml_sc_fn( 2134 svg, svgnbuf, DK3_SIZEOF(svgnbuf,dkChar), sc, 2135 hbhtml_image_filename_suffixes[2], job, &fnerr 2136 ); 2137 pdf = hbhtml_sc_fn( 2138 pdf, pdfnbuf, DK3_SIZEOF(pdfnbuf,dkChar), sc, 2139 hbhtml_image_filename_suffixes[1], job, &fnerr 2140 ); 2141 } else { 2142 /* ERROR: Name too long */ 2143 dk3app_log_i3(job->app, DK3_LL_ERROR, 65, 66, fnptr); 2144 fnerr = 1; 2145 } 2146 } 2147 if(src) { 2148 if(!hbtool_check_filename(job, src)) { src = NULL; } 2149 } 2150 if(src) { 2151 if(0 == fnerr) { back = 1; } 2152 if(larger) { $? ". larger=\"%!ds\"", larger 2153 if(!hbtool_check_filename(job, larger)) { larger = NULL; } 2154 } 2155 if(pdf) { $? ". pdf=\"%!ds\"", pdf 2156 if(!hbtool_check_filename(job, pdf)) { pdf = NULL; } 2157 } 2158 if(svg) { $? ". svg=\"%!ds\"", svg 2159 if(!hbtool_check_filename(job, svg)) { svg = NULL; } 2160 } 2161 if(tispec) { 2162 if(!(title)) { title = alt; } 2163 if(!(title)) { title = src; } 2164 } 2165 if(caspec) { 2166 if(!(capt)) { capt = title; } 2167 if(!(capt)) { capt = alt; } 2168 } 2169 if(!((width) && (height))) { 2170 if(hbimgdim_find(job, src, &xw, &xh, cache)) { 2171 if((xw) && (xh)) { 2172#if VERSION_BEFORE_20140716 2173 dk3sf_sprintf3(wbuf, dkT("%lu"), xw); 2174 dk3sf_sprintf3(hbuf, dkT("%lu"), xh); 2175 if(!(width)) { width = wbuf; } 2176 if(!(height)) { height = hbuf; } 2177#else 2178 if(!(width)) { 2179 if (dk3ma_um_to_string(wbuf,DK3_SIZEOF(wbuf,dkChar),(dk3_um_t)xw)) 2180 { 2181 width = wbuf; 2182 } 2183 } 2184 if(!(height)) { 2185 if (dk3ma_um_to_string(hbuf,DK3_SIZEOF(hbuf,dkChar),(dk3_um_t)xh)) 2186 { 2187 height = hbuf; 2188 } 2189 } 2190#endif 2191 } 2192 } 2193 } 2194 if(capt) { if(!(dodiv)) { dodiv = 2; } } 2195 if(downlo) { if(!(dodiv)) { dodiv = 2; } } 2196 2197 /* Output creation starts here. 2198 */ 2199 if(dodiv) { 2200 if(2 == dodiv) { 2201 /* div Open outer div */ 2202 fputs(hbhtml_c8_kw[((novsp) ? (145) : (109))], job->of); 2203 /* table */ 2204 if (0 != job->tabsum) { 2205 fputs(hbhtml_c8_kw[138], job->of); 2206 hbhtml_output_for_text(job, (job->msg)[65]); 2207 fputs(hbhtml_c8_kw[143], job->of); 2208 } else { 2209 fputs(hbhtml_c8_kw[159], job->of); 2210 } 2211 /* tr */ 2212 fputs(hbhtml_c8_kw[139], job->of); 2213 /* td */ 2214 fputs(hbhtml_c8_kw[140], job->of); 2215 } else { 2216 /* div Open outer div */ 2217 fputs(hbhtml_c8_kw[109], job->of); 2218 /* div Open image div */ 2219 fputs(hbhtml_c8_kw[(center) ? 111 : 110], job->of); 2220 } 2221 } 2222 2223 /* SVG object start. 2224 */ 2225 if((svg) && (crobj)) { 2226 /* Opening object tag */ 2227 fputs(hbhtml_c8_kw[114], job->of); 2228 if(!hbhtml_url_output_for_text(job, svg)) { back = 0; } 2229 if((svgwh) && (width) && (height)) { 2230 fputs(hbhtml_c8_kw[71], job->of); 2231 if(!hbhtml_url_output_for_text(job, width)) { back = 0; } 2232 fputs(hbhtml_c8_kw[72], job->of); 2233 if(!hbhtml_url_output_for_text(job, height)) { back = 0; } 2234 } 2235 fputs(hbhtml_c8_kw[51], job->of); 2236 fputs(hbhtml_c8_kw[0], job->of); 2237 /* Object param */ 2238 fputs(hbhtml_c8_kw[115], job->of); 2239 if(!hbhtml_url_output_for_text(job, svg)) { back = 0; } 2240 fputs(hbhtml_c8_kw[51], job->of); 2241 fputs(hbhtml_c8_kw[0], job->of); 2242 } 2243 2244 /* Image 2245 */ 2246 fputs(hbhtml_c8_kw[2], job->of); 2247 fputs(hbhtml_c8_kw[4], job->of); 2248 if(!hbhtml_url_output_for_text(job, src)) { 2249 back = 0; 2250 } 2251 fputs(hbhtml_c8_kw[5], job->of); 2252 if(name) { 2253 fputs(hbhtml_c8_kw[58], job->of); 2254 if(!hbhtml_output_for_text(job, name)) { 2255 back = 0; 2256 } 2257 fputs(hbhtml_c8_kw[5], job->of); 2258 } 2259 fputs(hbhtml_c8_kw[6], job->of); 2260 if(alt) { 2261 if(!hbhtml_output_for_text(job, alt)) { 2262 back = 0; 2263 } 2264 } 2265 fputs(hbhtml_c8_kw[5], job->of); 2266 if(title) { 2267 fputs(hbhtml_c8_kw[7], job->of); 2268 if(!hbhtml_output_for_text(job, title)) { 2269 back = 0; 2270 } 2271 fputs(hbhtml_c8_kw[5], job->of); 2272 } 2273 if(longdesc) { 2274 fputs(hbhtml_c8_kw[59], job->of); 2275 if(!hbhtml_url_output_for_text(job, longdesc)) { 2276 back = 0; 2277 } 2278 fputs(hbhtml_c8_kw[5], job->of); 2279 } 2280 if((width) && (height)) { 2281 fputs(hbhtml_c8_kw[9], job->of); 2282 if(!hbhtml_url_output_for_text(job, width)) { 2283 back = 0; 2284 } 2285 fputs(hbhtml_c8_kw[5], job->of); 2286 fputs(hbhtml_c8_kw[10], job->of); 2287 if(!hbhtml_url_output_for_text(job, height)) { 2288 back = 0; 2289 } 2290 fputs(hbhtml_c8_kw[5], job->of); 2291 } 2292 fputs(hbhtml_c8_kw[8], job->of); 2293 if(border) { 2294 if(!hbhtml_url_output_for_text(job, border)) { 2295 back = 0; 2296 } 2297 } else { 2298 fputs(hbhtml_c8_kw[57], job->of); 2299 } 2300 fputs(hbhtml_c8_kw[5], job->of); 2301 if(clptr) { 2302 fputs(hbhtml_c8_kw[60], job->of); 2303 if(!hbhtml_url_output_for_text(job, clptr)) { 2304 back = 0; 2305 } 2306 fputs(hbhtml_c8_kw[5], job->of); 2307 } 2308 if(idptr) { 2309 fputs(hbhtml_c8_kw[61], job->of); 2310 if(!hbhtml_url_output_for_text(job, idptr)) { 2311 back = 0; 2312 } 2313 fputs(hbhtml_c8_kw[5], job->of); 2314 } 2315 if(usemap) { 2316 fputs(hbhtml_c8_kw[62], job->of); 2317 if(!hbhtml_url_output_for_text(job, usemap)) { 2318 back = 0; 2319 } 2320 fputs(hbhtml_c8_kw[5], job->of); 2321 } 2322 if(align) { 2323 fputs(hbhtml_c8_kw[63], job->of); 2324 if(!hbhtml_url_output_for_text(job, align)) { 2325 back = 0; 2326 } 2327 fputs(hbhtml_c8_kw[5], job->of); 2328 } 2329 if(hspace) { 2330 fputs(hbhtml_c8_kw[64], job->of); 2331 if(!hbhtml_url_output_for_text(job, hspace)) { 2332 back = 0; 2333 } 2334 fputs(hbhtml_c8_kw[5], job->of); 2335 } 2336 if(vspace) { 2337 fputs(hbhtml_c8_kw[65], job->of); 2338 if(!hbhtml_url_output_for_text(job, vspace)) { 2339 back = 0; 2340 } 2341 fputs(hbhtml_c8_kw[5], job->of); 2342 } 2343 if(ismap) { 2344 fputs(hbhtml_c8_kw[66], job->of); 2345 } 2346 fputs(hbhtml_c8_kw[3], job->of); 2347 fputs(hbhtml_c8_kw[0], job->of); 2348 2349 /* SVG object end. 2350 */ 2351 if((svg) && (crobj)) { 2352 /* Closing object tag */ 2353 fputs(hbhtml_c8_kw[73], job->of); 2354 fputs(hbhtml_c8_kw[0], job->of); 2355 } 2356 2357 /* Table or div end 2358 */ 2359 if(dodiv) { 2360 if(capt) { 2361 /* Print caption 2362 */ 2363 fputs(hbhtml_c8_kw[116], job->of); 2364 if(!hbhtml_output_for_text(job, capt)) { back = 0; } 2365 fputs(hbhtml_c8_kw[117], job->of); 2366 /* fputs(hbhtml_c8_kw[0], job->of); */ 2367 } 2368 if(2 == dodiv) { 2369 /* !td Close image td */ 2370 fputs(hbhtml_c8_kw[97], job->of); 2371 } else { 2372 /* !div Close inner div */ 2373 fputs(hbhtml_c8_kw[47], job->of); 2374 } 2375 if(downlo) { 2376 if(2 == dodiv) { 2377 /* td space !td Space div */ 2378 fputs(hbhtml_c8_kw[141], job->of); 2379 /* td Open download td */ 2380 fputs(hbhtml_c8_kw[142], job->of); 2381 } else { 2382 /* p Open download p */ 2383 fputs(hbhtml_c8_kw[112], job->of); 2384 } 2385 /* Write download links */ 2386 { 2387 haveli = 0; 2388 if(svg) { $? ". svg = \"%!ds\"", svg 2389 haveli = 1; 2390 fputs(hbhtml_c8_kw[68], job->of); 2391 if(!hbhtml_url_output_for_text(job, svg)) { back = 0; } 2392 fputs(hbhtml_c8_kw[69], job->of); 2393 fputs(hbhtml_c8_kw[118], job->of); 2394 fputs(hbhtml_c8_kw[40], job->of); 2395 if(!hbhtml_output_for_text(job, (job->kwnl)[33])) { back = 0; } 2396 fputs(hbhtml_c8_kw[41], job->of); 2397 } 2398 if(pdf) { $? ". pdf = \"%!ds\"", pdf 2399 if(haveli) { 2400 fputs(hbhtml_c8_kw[105], job->of); 2401 } 2402 haveli = 1; 2403 fputs(hbhtml_c8_kw[68], job->of); 2404 if(!hbhtml_url_output_for_text(job, pdf)) { back = 0; } 2405 fputs(hbhtml_c8_kw[69], job->of); 2406 fputs(hbhtml_c8_kw[119], job->of); 2407 fputs(hbhtml_c8_kw[40], job->of); 2408 if(!hbhtml_output_for_text(job, (job->kwnl)[34])) { back = 0; } 2409 fputs(hbhtml_c8_kw[41], job->of); 2410 } 2411 if(larger) { $? ". larger = \"%!ds\"", larger 2412 if(haveli) { 2413 fputs(hbhtml_c8_kw[105], job->of); 2414 } 2415 haveli = 1; 2416 fputs(hbhtml_c8_kw[68], job->of); 2417 if(!hbhtml_url_output_for_text(job, larger)) { back = 0; } 2418 fputs(hbhtml_c8_kw[69], job->of); 2419 fputs(hbhtml_c8_kw[40], job->of); 2420 if(!hbhtml_output_for_text(job, (job->msg)[58])) { back = 0; } 2421 fputs(hbhtml_c8_kw[41], job->of); 2422 } 2423 if(haveli) { 2424 fputs(hbhtml_c8_kw[105], job->of); 2425 } 2426 fputs(hbhtml_c8_kw[68], job->of); 2427 if(!hbhtml_url_output_for_text(job, src)) { back = 0; } 2428 fputs(hbhtml_c8_kw[69], job->of); 2429 fputs(hbhtml_c8_kw[40], job->of); 2430 if(!hbhtml_output_for_text(job, (job->msg)[59])) { back = 0; } 2431 fputs(hbhtml_c8_kw[41], job->of); 2432 } 2433 if(2 == dodiv) { 2434 /* !td Close download td */ 2435 fputs(hbhtml_c8_kw[97], job->of); 2436 } else { 2437 /* !p Close download p */ 2438 fputs(hbhtml_c8_kw[113], job->of); 2439 } 2440 } else { 2441 if(2 == dodiv) { 2442 } else { 2443 fputs(hbhtml_c8_kw[120], job->of); 2444 } 2445 } 2446 if(2 == dodiv) { 2447 /* !tr */ 2448 fputs(hbhtml_c8_kw[95], job->of); 2449 /* !table */ 2450 fputs(hbhtml_c8_kw[93], job->of); 2451 /* !div Close outer div */ 2452 fputs(hbhtml_c8_kw[47], job->of); 2453 } else { 2454 /* !div Close outer div */ 2455 fputs(hbhtml_c8_kw[47], job->of); 2456 } 2457#if 0 2458 if(2 == dodiv) { 2459 } else { 2460 /* Close image div 2461 */ 2462 fputs(hbhtml_c8_kw[47], job->of); 2463 if(downlo) { 2464 /* Open outer download div */ 2465 fputs(hbhtml_c8_kw[112], job->of); 2466 /* Download links */ 2467 { 2468 haveli = 0; 2469 if(svg) { $? ". svg = \"%!ds\"", svg 2470 haveli = 1; 2471 fputs(hbhtml_c8_kw[68], job->of); 2472 if(!hbhtml_url_output_for_text(job, svg)) { back = 0; } 2473 fputs(hbhtml_c8_kw[69], job->of); 2474 fputs(hbhtml_c8_kw[118], job->of); 2475 fputs(hbhtml_c8_kw[40], job->of); 2476 if(!hbhtml_output_for_text(job, (job->kwnl)[33])) { back = 0; } 2477 fputs(hbhtml_c8_kw[41], job->of); 2478 } 2479 if(pdf) { $? ". pdf = \"%!ds\"", pdf 2480 if(haveli) { 2481 fputs(hbhtml_c8_kw[105], job->of); 2482 } 2483 haveli = 1; 2484 fputs(hbhtml_c8_kw[68], job->of); 2485 if(!hbhtml_url_output_for_text(job, pdf)) { back = 0; } 2486 fputs(hbhtml_c8_kw[69], job->of); 2487 fputs(hbhtml_c8_kw[119], job->of); 2488 fputs(hbhtml_c8_kw[40], job->of); 2489 if(!hbhtml_output_for_text(job, (job->kwnl)[34])) { back = 0; } 2490 fputs(hbhtml_c8_kw[41], job->of); 2491 } 2492 if(larger) { $? ". larger = \"%!ds\"", larger 2493 if(haveli) { 2494 fputs(hbhtml_c8_kw[105], job->of); 2495 } 2496 haveli = 1; 2497 fputs(hbhtml_c8_kw[68], job->of); 2498 if(!hbhtml_url_output_for_text(job, larger)) { back = 0; } 2499 fputs(hbhtml_c8_kw[69], job->of); 2500 fputs(hbhtml_c8_kw[40], job->of); 2501 if(!hbhtml_output_for_text(job, (job->msg)[58])) { back = 0; } 2502 fputs(hbhtml_c8_kw[41], job->of); 2503 } 2504 if(haveli) { 2505 fputs(hbhtml_c8_kw[105], job->of); 2506 } 2507 fputs(hbhtml_c8_kw[68], job->of); 2508 if(!hbhtml_url_output_for_text(job, src)) { back = 0; } 2509 fputs(hbhtml_c8_kw[69], job->of); 2510 fputs(hbhtml_c8_kw[40], job->of); 2511 if(!hbhtml_output_for_text(job, (job->msg)[59])) { back = 0; } 2512 fputs(hbhtml_c8_kw[41], job->of); 2513 } 2514 /* Close output download div */ 2515 fputs(hbhtml_c8_kw[113], job->of); 2516 } else { 2517 fputs(hbhtml_c8_kw[120], job->of); 2518 } 2519 /* Close outer div 2520 */ 2521 fputs(hbhtml_c8_kw[47], job->of); 2522 } 2523#endif 2524 } 2525 2526 /* Output creation is finished here. 2527 Now we add the files to copy to the list. 2528 */ 2529 if(src) { if(!hbtool_add_url(job, src)) { back = 0; } } 2530 if(larger) { if(!hbtool_add_url(job, larger)) { back = 0; } } 2531 if(pdf) { if(!hbtool_add_url(job, pdf)) { back = 0; } } 2532 if(svg) { if(!hbtool_add_url(job, svg)) { back = 0; } } 2533 } 2534 } else { 2535 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 40); 2536 } $? "- hbhtml_process_sp_image %d", back 2537 return back; 2538} 2539 2540 2541 2542/** Write current node item to navigation menu. 2543 @param job Job structure. 2544 @param nptr Current node. 2545 @return 1 on success, 0 on error. 2546*/ 2547static 2548int 2549hbhtml_link_to_current_node(hb_job_t *job, hb_node_t *nptr) 2550{ 2551 dkChar *p; /* Text to show */ 2552 int back = 1; 2553 $? "+ hbhtml_link_to_current_node" 2554 p = nptr->shorttitle; 2555 if(!(p)) { p = nptr->title; } 2556 if(p) { 2557 fputs(hbhtml_c8_kw[34], job->of); 2558 if(nptr->title) { 2559 fputs(hbhtml_c8_kw[7], job->of); 2560 if(hbtool_write_header_number(job, nptr)) { 2561 fputs(hbhtml_c8_kw[1], job->of); 2562 } 2563 if(!hbhtml_output_for_text(job, nptr->title)) { back = 0; } 2564 fputs(hbhtml_c8_kw[5], job->of); 2565 } 2566 fputs(hbhtml_c8_kw[3], job->of); 2567 if (!hbhtml_output_for_text(job, p)) { back = 0; } 2568 fputs(hbhtml_c8_kw[35], job->of); 2569 } else { 2570 back = 0; $? "! ERROR" 2571 } $? "- hbhtml_link_to_current_node %d", back 2572 return back; 2573} 2574 2575 2576 2577/** Write opening link tag to HTML output. 2578 @param job Job structure. 2579 @param cl Class name. 2580 @param ti Title. 2581 @param dp Destination. 2582 @param tp Type (optional). 2583 @param nptr Current node. 2584 @return 1 on success, 0 on error. 2585*/ 2586static 2587int 2588hbhtml_write_link_start( 2589 hb_job_t *job, 2590 char const *cl, 2591 dkChar const *ti, 2592 dkChar const *dp, 2593 dkChar const *tp, 2594 hb_node_t *nptr 2595) 2596{ 2597 int back = 0; 2598 $? "+ hbhtml_write_link_start" 2599 if(dp) { 2600 back = 1; 2601 fputs(hbhtml_c8_kw[39], job->of); 2602 if(!(hbhtml_url_output_for_text(job, dp))) { 2603 back = 0; $? "! ERROR" 2604 } 2605 fputs(hbhtml_c8_kw[42], job->of); 2606 if(cl) { 2607 fputs(hbhtml_c8_kw[43], job->of); 2608 if(EOF == fputs(cl, job->of)) { back = 0; } 2609 fputs(hbhtml_c8_kw[42], job->of); 2610 } 2611 if(ti) { 2612 fputs(hbhtml_c8_kw[44], job->of); 2613 if(hbtool_write_header_number(job, nptr)) { 2614 fputs(hbhtml_c8_kw[1], job->of); 2615 } 2616 if(!(hbhtml_output_for_text(job, ti))) { 2617 back = 0; $? "! ERROR" 2618 } 2619 fputs(hbhtml_c8_kw[42], job->of); 2620 } 2621 if(tp) { 2622 fputs(hbhtml_c8_kw[45], job->of); 2623 if(!(hbhtml_output_for_text(job, tp))) { 2624 back = 0; $? "! ERROR" 2625 } 2626 fputs(hbhtml_c8_kw[42], job->of); 2627 } 2628 fputs(hbhtml_c8_kw[40], job->of); 2629 } $? "- hbhtml_write_link_start %d", back 2630 return back; 2631} 2632 2633 2634 2635/** Write closing link tag. 2636 @param job Job structure. 2637*/ 2638static 2639void 2640hbhtml_write_link_end(hb_job_t *job) 2641{ 2642 fputs(hbhtml_c8_kw[41], job->of); 2643 $? "= hbhtml_write_link_end" 2644} 2645 2646 2647 2648 2649/** Write a link to HTML output. 2650 @param job Job structure. 2651 @param cl Class name. 2652 @param ti Title. 2653 @param dp Destination. 2654 @param tp Type (optional). 2655 @param tx Link text. 2656 @param nptr Current node. 2657 @return 1 on success, 0 on error. 2658*/ 2659static 2660int 2661hbhtml_write_link( 2662 hb_job_t *job, 2663 char const *cl, 2664 dkChar const *ti, 2665 dkChar const *dp, 2666 dkChar const *tp, 2667 dkChar const *tx, 2668 hb_node_t *nptr 2669) 2670{ 2671 int back = 0; 2672 $? "+ hbhtml_write_link" 2673 if((tx) && (dp)) { 2674 back = 1; 2675 if(!(hbhtml_write_link_start(job, cl, ti, dp, tp, nptr))) { 2676 back = 0; $? "! ERROR" 2677 } 2678 if(!(hbhtml_output_for_text(job, tx))) { 2679 back = 0; $? "! ERROR" 2680 } 2681 hbhtml_write_link_end(job); 2682 } $? "- hbhtml_write_link %d", back 2683 return back; 2684} 2685 2686 2687 2688int 2689hbhtml_create_output_filename( 2690 dkChar *dptr, 2691 size_t sz, 2692 hb_job_t *job, 2693 hb_node_t *nptr 2694) 2695{ 2696 dkChar const *sptr; /* Suffix for output file */ 2697 dkChar *p1; /* Suffix position */ 2698 size_t nsz; /* Summary length name + new suffix */ 2699 int back = 0; 2700 $? "+ hbhtml_create_output_filename dptr=PTR=%d sz=%u nptr=PTR:%d", TR_IPTR(dptr), (unsigned)sz, TR_IPTR(nptr) 2701 if (nptr) { 2702 dptr[0] = dkT('\0'); 2703 if(0UL == nptr->objno) { $? ". node 0" 2704 if(dk3str_len((job->kwnl)[8]) < sz) { 2705 dk3str_cpy(dptr, (job->kwnl)[8]); 2706 back = 1; 2707 } else { 2708 /* ERROR: Name too long! */ 2709 dk3app_log_i3(job->app, DK3_LL_ERROR, 65, 66, (job->kwnl)[8]); 2710 } 2711 } else { $? ". other node" 2712 if(nptr->filename) { $? ". have source file name" 2713 if(dk3str_len(nptr->filename) < sz) { $? ". length ok" 2714 dk3str_cpy(dptr, nptr->filename); 2715 p1 = dk3str_get_suffix(dptr); 2716 if(p1) { 2717 p1++; 2718 *p1 = dkT('\0'); 2719 if(nptr->suffix) { 2720 sptr = nptr->suffix; 2721 } else { 2722 sptr = (job->kwnl)[10]; 2723 } 2724 nsz = dk3str_len(dptr) + dk3str_len(sptr); 2725 if(nsz < sz) { 2726 dk3str_cat(dptr, sptr); 2727 back = 1; 2728 } else { $? "! file name too long" 2729 /* ERROR: File name too long! */ 2730 dk3app_log_i3(job->app, DK3_LL_ERROR, 65, 66, nptr->filename); 2731 } 2732 } else { 2733 if(nptr->suffix) { 2734 sptr = nptr->suffix; 2735 } else { 2736 sptr = (job->kwnl)[10]; 2737 } 2738 nsz = dk3str_len(dptr)+dk3str_len(sptr)+dk3str_len((job->kwnl)[9]); 2739 if(nsz < sz) { 2740 dk3str_cat(dptr, (job->kwnl)[9]); 2741 dk3str_cat(dptr, sptr); 2742 back = 1; 2743 } else { $? "! file name too long" 2744 /* File name too long! */ 2745 dk3app_log_i3(job->app, DK3_LL_ERROR, 65, 66, nptr->filename); 2746 } 2747 } 2748 } else { $? "! input file name to long" 2749 /* ERROR: Input file name too long! */ 2750 dk3app_log_i3(job->app, DK3_LL_ERROR, 65, 66, nptr->filename); 2751 } 2752 } else { $? "! no source file name" 2753 /* ERROR: No source file name! */ 2754 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 24); 2755 } 2756 } 2757 } else { $? "! missing nptr" 2758 } 2759 $? "- hbhtml_create_output_filename %d \"%!ds\"", back, dptr 2760 return back; 2761} 2762 2763 2764 2765/** Write link to one node to navigation menu. 2766 @param job Job structure. 2767 @param nptr Node to link to. 2768 @param bold Flag: Make link bold. 2769 @return 1 on success, 0 on error. 2770*/ 2771static 2772int 2773hbhtml_link_to_node(hb_job_t *job, hb_node_t *nptr, int bold) 2774{ 2775 dkChar bu[DK3_MAX_PATH]; /* Buffer for destination name */ 2776 hb_node_t *jnode; /* Link jump destination */ 2777 dkChar *p1; /* Link title (full) */ 2778 dkChar *p2; /* Link title (short or full) */ 2779 int back = 0; 2780 $? "+ hbhtml_link_to_node" 2781 jnode = nptr; 2782 if(!(nptr->filename)) { 2783 jnode = nptr->jumpnode; 2784 } 2785 p1 = nptr->title; 2786 p2 = ((nptr->shorttitle) ? (nptr->shorttitle) : (nptr->title)); 2787 if((p1) && (p2)) { 2788 if(jnode) { 2789 if(hbhtml_create_output_filename(bu, DK3_SIZEOF(bu,dkChar), job, jnode)) { 2790 fputs(hbhtml_c8_kw[36], job->of); 2791 back = hbhtml_write_link( 2792 job, hbhtml_c8_kw[(bold) ? 144 : 38], p1, bu, NULL, p2, nptr 2793 ); 2794 fputs(hbhtml_c8_kw[37], job->of); 2795 } 2796 } else { 2797 /* ERROR: No text node! */ 2798 dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 52, 53, nptr->title); 2799 } 2800 } $? "- hbhtml_link_to_node %d", back 2801 return back; 2802} 2803 2804 2805 2806/** Instead of writing a navigation menu list separator item, 2807 finish current list and start a new one. 2808 @param job Job structure. 2809*/ 2810static 2811void 2812hbhtml_navi_menu_next_list(hb_job_t *job) 2813{ 2814 fputs(hbhtml_c8_kw[32], job->of); 2815 fputs(hbhtml_c8_kw[31], job->of); 2816} 2817 2818 2819 2820/** Write the menu entries for a node. 2821 @param job Job structure. 2822 @param nptr Node to write menu entries for. 2823 @param sepreq Flag: Menu separator required. 2824 @return 1 on success, 0 on error. 2825*/ 2826static 2827int 2828hbhtml_menu_entries_for_node(hb_job_t *job, hb_node_t *nptr, int sepreq) 2829{ 2830 hb_node_t *subnode; /* Current node */ 2831 hb_node_t *jnptr; /* Jump node for subnode */ 2832 int active; /* Flag: Active node */ 2833 int sepdone = 0; /* Flag: Separator done */ 2834 int bold = 0; /* Flag: Make bold */ 2835 int back = 1; 2836 $? "+ hbhtml_menu_entries_for_node" 2837 if(nptr) { $? ". current node \"%!ds\"", TR_STR(nptr->title) 2838 dk3sto_it_reset(nptr->i_subnodes); 2839 while(NULL != (subnode = (hb_node_t *)dk3sto_it_next(nptr->i_subnodes))) { 2840 jnptr = subnode; 2841 if(!(jnptr->filename)) { jnptr = jnptr->jumpnode; } 2842 if(sepreq) { 2843 if(!(sepdone)) { 2844 sepdone = 1; 2845#if VERSION_BEFORE_2020_07_16 2846 fputs(hbhtml_c8_kw[33], job->of); 2847#else 2848 hbhtml_navi_menu_next_list(job); 2849#endif 2850 } 2851 } $? ". current subnode \"%!ds\"", TR_STR(subnode->title) 2852 active = 1; 2853 bold = 0; 2854#if VERSION_BEFORE_20140109 2855 if(nptr->curchild) { 2856 if(((nptr->curchild)->objno) == (subnode->objno)) { 2857 active = 0; 2858 } 2859 } 2860#else 2861 if(job->currentnode) { 2862 if(jnptr) { 2863 if(jnptr->objno == (job->currentnode)->objno) { 2864 active = 0; 2865 } 2866 } 2867 } 2868 if(nptr->curchild) { 2869 if(((nptr->curchild)->objno) == (subnode->objno)) { 2870 bold = 1; 2871 } 2872 } 2873#endif 2874 if(active) { 2875 hbhtml_link_to_node(job, subnode, bold); 2876 } else { 2877 hbhtml_link_to_current_node(job, subnode); 2878 } 2879 } 2880 } $? "- hbhtml_menu_entries_for_node %d", back 2881 return back; 2882} 2883 2884 2885 2886/** Check whether a node has sub menu items. 2887 @param ptr Node to check. 2888 @return 1 if sub items are present, 0 otherwise. 2889*/ 2890static 2891int 2892hbhtml_have_sub_menu_items(hb_node_t *ptr) 2893{ 2894 int back = 0; 2895 $? "+ hbhtml_have_sub_menu_items" 2896 dk3sto_it_reset(ptr->i_subnodes); 2897 while(NULL != dk3sto_it_next(ptr->i_subnodes)) { 2898 back = 1; 2899 } $? "- hbhtml_have_sub_menu_items %d", back 2900 return back; 2901} 2902 2903 2904 2905/** Process menu special command. 2906 @param job Job structure. 2907 @param pa Special command arguments. 2908 @return 1 on success, 0 on error (continue), -1 on error (exit). 2909*/ 2910static 2911int 2912hbhtml_process_sp_menu(hb_job_t *job, dkChar *pa) 2913{ 2914 dk3_key_value_t kv[10]; /* Key value pairs */ 2915 hb_node_t *mnptr; /* Menu node pointer */ 2916 size_t sz; /* Size of kv */ 2917 size_t i; /* Traverse kv */ 2918 int res; /* Result from writing link */ 2919 int sep = 0; /* Flag: Need separator */ 2920 int tv = 0; /* Test value */ 2921 int mnst = 0; /* Menu style (full) */ 2922 int sub = 1; /* Include sub menu of current node */ 2923 int back = 1; 2924 $? "+ hbhtml_process_sp_menu \"%!ds\"", pa 2925 sz = DK3_SIZEOF(kv,dk3_key_value_t); 2926 if(dk3str_to_key_value(kv, &sz, pa, job->app)) { 2927 for(i = 0; i < sz; i++) { 2928 if(kv[i].key) { 2929 switch(dk3str_array_abbr(hbhtml_menu_keys, kv[i].key, dkT('$'), 0)) { 2930 case 0: { 2931 if(kv[i].val) { 2932 tv = dk3str_array_abbr(hbhtml_menu_styles,kv[i].val,dkT('$'),0); 2933 if(0 <= tv) { 2934 mnst = tv; 2935 } else { 2936 /* ERROR: Illegal menu style */ 2937 dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,25,26,kv[i].val); 2938 } 2939 } 2940 } break; 2941 case 1: { 2942 if(kv[i].val) { 2943 sub = ((dk3str_is_on(kv[i].val)) ? 1 : 0); 2944 } else { 2945 sub = 1; 2946 } 2947 } break; 2948 default: { 2949 /* ERROR: Illegal key. */ 2950 dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,27,26,kv[i].key); 2951 } break; 2952 } 2953 } 2954 } 2955 } else { 2956 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 40); 2957 } $? ". mnst=%d sub=%d", mnst, sub 2958 if(((job->currentnode)->options) & HB_NODE_OPT_IMPRESSUM) { 2959 /* When we are writing the menu for the impressum page, 2960 we print the top menu only. 2961 */ 2962 mnst = 3; 2963 sub = 0; 2964 } $? ". mnst=%d sub=%d", mnst, sub 2965 if(((job->currentnode)->options) & HB_NODE_OPT_PRIVACY) { 2966 /* When we are writing the menu for the privacy statement page, 2967 we print the top menu only. 2968 */ 2969 mnst = 3; 2970 sub = 0; 2971 } $? ". mnst=%d sub=%d", mnst, sub 2972 fputs(hbhtml_c8_kw[29], job->of); 2973 fputs(hbhtml_c8_kw[31], job->of); 2974 /* Impressum node first, separator. 2975 */ 2976 if(job->impressumnode) { $? ". have impressum node" 2977 if(((job->currentnode)->options) & HB_NODE_OPT_IMPRESSUM) { 2978 if(!hbhtml_link_to_current_node(job, job->impressumnode)) { 2979 back = 0; $? "! ERROR" 2980 } 2981 } else { 2982 if(!hbhtml_link_to_node(job, job->impressumnode, 0)) { 2983 back = 0; $? "! ERROR" 2984 } 2985 } 2986 /* Separator */ 2987 if (NULL == job->privacynode) { 2988 if (NULL == job->privacylink) { 2989#if VERSION_BEFORE_2020_07_16 2990 fputs(hbhtml_c8_kw[33], job->of); 2991#else 2992 hbhtml_navi_menu_next_list(job); 2993#endif 2994 } 2995 } 2996 } else { 2997 if(job->impressumlink) { $? ". have impressum link" 2998 fputs(hbhtml_c8_kw[36], job->of); 2999 res = hbhtml_write_link( 3000 job, hbhtml_c8_kw[38], (job->msg)[0], job->impressumlink, 3001 NULL, (job->msg)[0], NULL 3002 ); 3003 fputs(hbhtml_c8_kw[37], job->of); 3004 if(!(res)) { 3005 back = 0; $? "! ERROR" 3006 } 3007 /* Separator */ 3008 if (NULL == job->privacynode) { 3009 if (NULL == job->privacylink) { 3010#if VERSION_BEFORE_2020_07_16 3011 fputs(hbhtml_c8_kw[33], job->of); 3012#else 3013 hbhtml_navi_menu_next_list(job); 3014#endif 3015 } 3016 } 3017 } else { $? ". no impressum link" 3018 } 3019 } 3020 /* Privacy node first, separator. 3021 */ 3022 if(job->privacynode) { $? ". have privacy node" 3023 if(((job->currentnode)->options) & HB_NODE_OPT_PRIVACY) { 3024 if(!hbhtml_link_to_current_node(job, job->privacynode)) { 3025 back = 0; $? "! ERROR" 3026 } 3027 } else { 3028 if(!hbhtml_link_to_node(job, job->privacynode, 0)) { 3029 back = 0; $? "! ERROR" 3030 } 3031 } 3032 /* Separator */ 3033#if VERSION_BEFORE_2020_07_16 3034 fputs(hbhtml_c8_kw[33], job->of); 3035#else 3036 hbhtml_navi_menu_next_list(job); 3037#endif 3038 } else { 3039 if(job->privacylink) { $? ". have privacy link" 3040 fputs(hbhtml_c8_kw[36], job->of); 3041 res = hbhtml_write_link( 3042 job, hbhtml_c8_kw[38], (job->msg)[105], job->privacylink, 3043 NULL, (job->msg)[104], NULL 3044 ); 3045 fputs(hbhtml_c8_kw[37], job->of); 3046 if(!(res)) { 3047 back = 0; $? "! ERROR" 3048 } 3049 /* Separator */ 3050#if VERSION_BEFORE_2020_07_16 3051 fputs(hbhtml_c8_kw[33], job->of); 3052#else 3053 hbhtml_navi_menu_next_list(job); 3054#endif 3055 } else { $? ". no privacy link" 3056 } 3057 } 3058 /* Now real menu(s) 3059 0=reverse, 1=full, 2=current, 3=top 3060 */ 3061 mnptr = job->currentnode; 3062 if(mnptr) { $? ". current node: \"%!ds\"", TR_STR(mnptr->title) 3063 switch(mnst) { 3064 case -1: case 0: case 2: { $? ". reverse or current" 3065 if(sub) { 3066 if(hbhtml_have_sub_menu_items(mnptr)) { $? " current entry" 3067 /* Menu for mnptr without leading space */ 3068 $? ". menu from current entry" 3069 hbhtml_menu_entries_for_node(job, mnptr, 0); 3070 sep = 1; 3071 } 3072 } 3073 mnptr = mnptr->parent; 3074 if(mnptr) { 3075 /* Menu for mnptr with leading space */ 3076 $? ". menu from parent entry" 3077 hbhtml_menu_entries_for_node(job, mnptr, sep); 3078 if(2 != mnst) { $? ". grandparents" 3079 do { 3080 mnptr = mnptr->parent; 3081 if(mnptr) { 3082 /* Menu for mnptr with leading space */ 3083 $? ". menu from further parent entry" 3084 hbhtml_menu_entries_for_node(job, mnptr, 1); 3085 } 3086 } while(mnptr); 3087 } 3088 } 3089 } break; 3090 case 1: case 3: { $? ". full or top" 3091 if(((job->currentnode)->options) & HB_NODE_OPT_IMPRESSUM) { 3092 mnptr = job->rootnode; 3093 sub = 0; 3094 } else { 3095 while(mnptr->parent) { mnptr = mnptr->parent; } 3096 } 3097 /* Menu for mnptr without leading space */ 3098 $? ". menu entries from root node" 3099 hbhtml_menu_entries_for_node(job, mnptr, 0); 3100 if(1 == mnst) { $? ". full, continue with children" 3101 do { 3102 mnptr = mnptr->curchild; 3103 if(mnptr) { 3104 if(mnptr->curchild) { 3105 /* Menu for mnptr with leading space */ 3106 $? ". menu entries form parents/grandparents of current node" 3107 hbhtml_menu_entries_for_node(job, mnptr, 1); 3108 } else { 3109 if(sub) { 3110 /* Menu entry from current node */ 3111 $? ". menu from current node" 3112 hbhtml_menu_entries_for_node(job, mnptr, 1); 3113 } 3114 } 3115 } 3116 } while(mnptr); 3117 } 3118 } break; 3119 } 3120 } 3121 fputs(hbhtml_c8_kw[32], job->of); 3122 fputs(hbhtml_c8_kw[30], job->of); $? "- hbhtml_process_sp_menu %d", back 3123 return back; 3124} 3125 3126 3127 3128/** Write image with link for one navigation icon. 3129 @param job Job structure. 3130 @param iconfile Icon file name. 3131 @param dest Destination URL. 3132 @param titlea1 Title part 1 when icon link is active. 3133 @param titlea2 Title part 2 when icon link is active. 3134 @param titlena Title when icon is not active. 3135 @param act Flag: Link is active. 3136 @return 1 on success, 0 on error. 3137*/ 3138static 3139int 3140hbhtml_one_navi_icon( 3141 hb_job_t *job, 3142 dkChar const *iconfile, 3143 dkChar const *dest, 3144 dkChar const *titlea1, 3145 dkChar const *titlea2, 3146 dkChar const *titlena, 3147 int act 3148) 3149{ 3150 int back = 1; 3151 unsigned long w = 0UL; /* Icon width */ 3152 unsigned long h = 0UL; /* Icon height */ 3153 $? "+ hbhtml_one_navi_icon" 3154 $? ". iconfile = \"%!ds\"", TR_STR(iconfile) 3155 $? ". dest = \"%!ds\"", TR_STR(dest) 3156 $? ". titlea1 = \"%!ds\"", TR_STR(titlea1) 3157 $? ". titlea2 = \"%!ds\"", TR_STR(titlea2) 3158 $? ". titlena = \"%!ds\"", TR_STR(titlena) 3159 $? ". act = %d", act 3160 if(act) { $? ". act" 3161 fputs(hbhtml_c8_kw[49], job->of); 3162 if(!(hbhtml_url_output_for_text(job, dest))) { 3163 back = 0; 3164 } $? ". 1" 3165 fputs(hbhtml_c8_kw[50], job->of); 3166 if(!(hbhtml_output_for_text(job, titlea1))) { 3167 back = 0; 3168 } $? ". 2" 3169 if(titlea2) { 3170 if(!(hbhtml_output_for_text(job, titlea2))) { 3171 back = 0; 3172 } 3173 } $? ". 3" 3174 fputs(hbhtml_c8_kw[51], job->of); 3175 fputs(hbhtml_c8_kw[53], job->of); 3176 if(!(hbhtml_url_output_for_text(job, iconfile))) { 3177 back = 0; 3178 } $? ". 4" 3179 fputs(hbhtml_c8_kw[54], job->of); 3180 if(!(hbhtml_output_for_text(job, titlea1))) { 3181 back = 0; 3182 } $? ". 6" 3183 if(titlea2) { 3184 if(!(hbhtml_output_for_text(job, titlea2))) { 3185 back = 0; 3186 } 3187 } 3188 fputs(hbhtml_c8_kw[55], job->of); 3189 if(!(hbhtml_output_for_text(job, titlea1))) { 3190 back = 0; 3191 } $? ". 6" 3192 if(titlea2) { 3193 if(!(hbhtml_output_for_text(job, titlea2))) { 3194 back = 0; 3195 } 3196 } 3197 fputs(hbhtml_c8_kw[56], job->of); 3198 if(hbimgdim_find(job, iconfile, &w, &h, 1)) { 3199 if((w) && (h)) { 3200 fprintf(job->of, hbhtml_c8_kw[67], w, h); 3201 } 3202 } 3203 fputs(hbhtml_c8_kw[3], job->of); 3204 fputs(hbhtml_c8_kw[52], job->of); $? ". 7" 3205 } else { $? ". not act" 3206 fputs(hbhtml_c8_kw[53], job->of); 3207 if(!(hbhtml_url_output_for_text(job, iconfile))) { 3208 back = 0; 3209 } $? ". 8" 3210 fputs(hbhtml_c8_kw[54], job->of); 3211 if(!(hbhtml_output_for_text(job, titlea1))) { 3212 back = 0; 3213 } $? ". 6" 3214 if(titlea2) { 3215 if(!(hbhtml_output_for_text(job, titlea2))) { 3216 back = 0; 3217 } 3218 } 3219 fputs(hbhtml_c8_kw[55], job->of); 3220 if(!(hbhtml_output_for_text(job, titlena))) { 3221 back = 0; 3222 } $? ". 10" 3223 fputs(hbhtml_c8_kw[56], job->of); 3224 if(hbimgdim_find(job, iconfile, &w, &h, 1)) { 3225 if((w) && (h)) { 3226 fprintf(job->of, hbhtml_c8_kw[67], w, h); 3227 } 3228 } 3229 fputs(hbhtml_c8_kw[3], job->of); 3230 } $? "- hbhtml_one_navi_icon %d", back 3231 return back; 3232} 3233 3234 3235 3236/** Process special command to build navigation div. 3237 @param job Job structure. 3238 @param pa Programm arguments (ignored). 3239 @param p Previous node. 3240 @param n Next node. 3241 @return 1 on success, 0 on error. 3242*/ 3243static 3244int 3245hbhtml_process_sp_navigation( 3246 hb_job_t *job, 3247 dkChar *pa, 3248 hb_node_t *p, 3249 hb_node_t *n 3250) 3251{ 3252 dk3_key_value_t kv[10]; /* Command parameters */ 3253 dkChar bu[DK3_MAX_PATH]; /* Construct file name */ 3254 hb_node_t *nptr; /* Current node */ 3255 dkChar const *itop = NULL; /* TOC icon name */ 3256 dkChar const *iprev = NULL; /* Previous icon name */ 3257 dkChar const *inext = NULL; /* Next icon name */ 3258 dkChar const *ihome = NULL; /* Home icon name */ 3259 dkChar const *ikind = NULL; /* Index icon name */ 3260 dkChar const *ta1; /* Icon image title, node */ 3261 dkChar const *ta2; /* Icon image title */ 3262 dkChar const *tna; /* Icon image title start */ 3263 size_t sz; /* Number of command params */ 3264 size_t szurl; /* URL length */ 3265 size_t i; /* Traverse command params */ 3266 int res; /* Result create one icon */ 3267 int kind = 0; /* Flag: Keyword index */ 3268 int ptoc = 0; /* Flag: TOC */ 3269 int back = 1; 3270 $? "+ hbhtml_process_sp_navigation" 3271 sz = DK3_SIZEOF(kv,dk3_key_value_t); 3272 if(dk3str_to_key_value(kv, &sz, pa, job->app)) { 3273 for(i = 0; i < sz; i++) { 3274 if(kv[i].key) { 3275 switch(dk3str_array_abbr(hbhtml_navi_keys, kv[i].key, dkT('$'), 0)) { 3276 case 0: { 3277 itop = kv[i].val; 3278 } break; 3279 case 1: { 3280 iprev = kv[i].val; 3281 } break; 3282 case 2: { 3283 inext = kv[i].val; 3284 } break; 3285 case 3: { 3286 ikind = kv[i].val; 3287 } break; 3288 case 4: { 3289 ihome = kv[i].val; 3290 } break; 3291 } 3292 } 3293 } 3294 } else { 3295 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 40); 3296 } 3297 nptr = job->currentnode; 3298 kind = (((job->options) & HB_JOB_OPT_CREATE_INDEX) ? 1 : 0); 3299 ptoc = (((job->options) & HB_JOB_OPT_CREATE_TOC) ? 1 : 0); 3300 while( 3301 (nptr) 3302 && ( 3303 !( 3304 ((itop) || (!(ptoc))) 3305 && (ihome) 3306 && (iprev) && (inext) 3307 && ((ikind) || (!(kind))) 3308 ) 3309 ) 3310 ) 3311 { 3312 if(!(itop)) itop = nptr->icontoc; 3313 if(!(iprev)) iprev = nptr->iconprev; 3314 if(!(inext)) inext = nptr->iconnext; 3315 if(!(ikind)) ikind = nptr->iconindex; 3316 if(!(ihome)) ihome = nptr->iconhome; 3317 nptr = nptr->parent; 3318 } 3319 $? ". before corrections" 3320 if(!(itop)) itop = (job->kwnl)[14]; 3321 if(!(iprev)) iprev = (job->kwnl)[15]; 3322 if(!(inext)) inext = (job->kwnl)[16]; 3323 if(!(ikind)) ikind = (job->kwnl)[17]; 3324 if(!(ihome)) ihome = (job->kwnl)[37]; 3325 $? ". after corrections" 3326 if( 3327 ((itop) || (!(ptoc))) 3328 && (iprev) && (inext) && (ihome) 3329 && ((ikind) || (!(kind))) 3330 ) 3331 { 3332 back = 1; 3333 if(itop) { if(!hbtool_add_file(job, itop)) { back = 0; } } 3334 if(iprev) { if(!hbtool_add_file(job, iprev)) { back = 0; } } 3335 if(inext) { if(!hbtool_add_file(job, inext)) { back = 0; } } 3336 if(ikind) { if(!hbtool_add_file(job, ikind)) { back = 0; } } 3337 if(ihome) { if(!hbtool_add_file(job, ihome)) { back = 0; } } 3338 fputs(hbhtml_c8_kw[46], job->of); 3339 3340 /* HOME */ $? ". home" 3341 ta1 = (job->msg)[1]; 3342 ta2 = (job->rootnode)->title; 3343 tna = (job->msg)[2]; 3344 res = hbhtml_create_output_filename( 3345 bu, DK3_SIZEOF(bu,dkChar), job, job->rootnode 3346 ); 3347 if(res) { $? ". fn ok \"%!ds\"", bu 3348 $? ". icon = \"%!ds\"", itop 3349 res = hbhtml_one_navi_icon( 3350 job, ihome, bu, ta1, ta2, tna, 3351 ( 3352 (0 != job->currentnode->havenavimenu) 3353 ? (1) 3354 : (((0UL == (job->currentnode)->objno) ? 0 : 1)) 3355 ) 3356 ); 3357 if(!(res)) { back = 0; } 3358 $? ". navi icon completed" 3359 } else { $? "! fn" 3360 back = 0; 3361 } 3362 /* Previous */ $? ". prev" 3363 ta1 = (job->msg)[3]; 3364 ta2 = NULL; 3365 if(p) ta2 = p->title; 3366 tna = (job->msg)[4]; 3367 if(p) { 3368 res = hbhtml_create_output_filename( 3369 bu, DK3_SIZEOF(bu,dkChar), job, p 3370 ); 3371 if(res) { 3372 fputs(hbhtml_c8_kw[48], job->of); 3373 res = hbhtml_one_navi_icon(job, iprev, bu, ta1, ta2, tna, 1); 3374 if(!(res)) { back = 0; } 3375 } else { 3376 back = 0; 3377 } 3378 } else { 3379 fputs(hbhtml_c8_kw[48], job->of); 3380 res = hbhtml_one_navi_icon(job, iprev, NULL, ta1, ta2, tna, 0); 3381 if(!(res)) { back = 0; } 3382 } 3383 /* Next */ $? ". next" 3384 ta1 = (job->msg)[5]; 3385 ta2 = NULL; 3386 if(n) ta2 = n->title; 3387 tna = (job->msg)[6]; 3388 if(n) { 3389 res = hbhtml_create_output_filename( 3390 bu, DK3_SIZEOF(bu,dkChar), job, n 3391 ); 3392 if(res) { 3393 fputs(hbhtml_c8_kw[48], job->of); 3394 res = hbhtml_one_navi_icon(job, inext, bu, ta1, ta2, tna, 1); 3395 if(!(res)) { back = 0; } 3396 } else { 3397 back = 0; 3398 } 3399 } else { 3400 fputs(hbhtml_c8_kw[48], job->of); 3401 res = hbhtml_one_navi_icon(job, inext, NULL, ta1, ta2, tna, 0); 3402 if(!(res)) { back = 0; } 3403 } 3404 /* TOC */ $? ". toc" 3405 if(ptoc) { 3406 ta1 = (job->msg)[93]; 3407 ta2 = (job->rootnode)->title; 3408 tna = (job->msg)[94]; 3409 res = hbhtml_create_output_filename( 3410 bu, DK3_SIZEOF(bu,dkChar), job, job->rootnode 3411 ); 3412 if(res) { $? ". fn ok \"%!ds\"", bu 3413 szurl = dk3str_len(bu); 3414 szurl += dk3str_len((job->kwnl)[31]); 3415 if(szurl < DK3_SIZEOF(bu,dkChar)) { 3416 dk3str_cat(bu, (job->kwnl)[31]); 3417 } else { 3418 back = 0; 3419 } 3420 $? ". icon = \"%!ds\"", itop 3421 fputs(hbhtml_c8_kw[48], job->of); 3422 res = hbhtml_one_navi_icon(job, itop, bu, ta1, ta2, tna, 1); 3423 if(!(res)) { back = 0; } 3424 $? ". navi icon completed" 3425 } else { $? "! fn" 3426 back = 0; 3427 } 3428 } 3429 /* Key index */ 3430 if(kind) { $? ". kind" 3431 ta1 = (job->msg)[7]; 3432 ta2 = NULL; 3433 tna = NULL; 3434 res = hbhtml_create_output_filename( 3435 bu, DK3_SIZEOF(bu,dkChar), job, job->rootnode 3436 ); 3437 if(res) { 3438 if(dk3str_len(bu)+dk3str_len((job->kwnl)[13]) < DK3_SIZEOF(bu,dkChar)) { 3439 dk3str_cat(bu, (job->kwnl)[13]); 3440 fputs(hbhtml_c8_kw[48], job->of); 3441 res = hbhtml_one_navi_icon(job, ikind, bu, ta1, ta2, tna, 1); 3442 if(!(res)) { back = 0; } 3443 } else { 3444 back = 0; 3445 } 3446 } else { 3447 back = 0; 3448 } 3449 } 3450 fputs(hbhtml_c8_kw[47], job->of); 3451 job->currentnode->havenavimenu = 1; 3452 $? ". finished" 3453 } else { $? "! icons missing" 3454 $? ". itop = \"%!ds\"", TR_STR(itop) 3455 $? ". iprev = \"%!ds\"", TR_STR(iprev) 3456 $? ". inext = \"%!ds\"", TR_STR(inext) 3457 $? ". ikind = \"%!ds\"", TR_STR(ikind) 3458 $? ". ihome = \"%!ds\"", TR_STR(ihome) 3459 } 3460 $? "- hbhtml_process_sp_navigation %d", back 3461 return back; 3462} 3463 3464 3465 3466/** Process author special command. 3467 @param job Job structure. 3468 @return 1 on success, 0 on error (continue), -1 on error (exit). 3469*/ 3470static 3471int 3472hbhtml_process_sp_author(hb_job_t *job) 3473{ 3474 dkChar const *ptr; /* Author name */ 3475 int back = 0; 3476 $? "+ hbhtml_process_sp_author" 3477 ptr = hbconf_author(job->currentnode); 3478 if(ptr) { 3479 if(hbhtml_output_for_text(job, ptr)) { 3480 back = 1; 3481 } 3482 } $? "- hbhtml_process_sp_author %d", back 3483 return back; 3484} 3485 3486 3487 3488/** Process location special command. 3489 @param job Job structure. 3490 @return 1 on success, 0 on error (continue), -1 on error (exit). 3491*/ 3492static 3493int 3494hbhtml_process_sp_location(hb_job_t *job) 3495{ 3496 dkChar const *ptr; /* Location name */ 3497 int back = 0; 3498 $? "+ hbhtml_process_sp_location" 3499 ptr = hbconf_location(job->currentnode); 3500 if(ptr) { 3501 if(hbhtml_output_for_text(job, ptr)) { 3502 back = 1; 3503 } 3504 } $? "- hbhtml_process_sp_location %d", back 3505 return back; 3506} 3507 3508 3509 3510/** Process date special command. 3511 @param job Job structure. 3512 @param pa Program arguments. 3513 @return 1 on success, 0 on error (continue), -1 on error (exit). 3514*/ 3515static 3516int 3517hbhtml_process_sp_date(hb_job_t *job, dkChar *pa) 3518{ 3519 dk3_key_value_t kv[5]; /* Command parameters */ 3520 size_t sz; /* Number of command paramters */ 3521 size_t i; /* Traverse command paramters */ 3522 int german = 0; /* Flag: German style date */ 3523 int back = 1; 3524 $? "+ hbhtml_process_sp_date \"%!ds\"", TR_STR(pa) 3525 sz = DK3_SIZEOF(kv,dk3_key_value_t); 3526 if(dk3str_to_key_value(kv,&sz,pa,job->app)) { $? ". to key value" 3527 for(i = 0; i < sz; i++) { $? ". i=%u", (unsigned)i 3528 if(kv[i].key) { $? ". key=\"%!ds\" val=\"%!ds\"", TR_STR(kv[i].key), TR_STR(kv[i].val) 3529 switch(dk3str_array_abbr(hbhtml_date_keys, kv[i].key, dkT('$'), 0)) { 3530 case 0: { 3531 if(kv[i].val) { 3532 if(0 == dk3str_casecmp((job->kwnl)[11], kv[i].val)) { 3533 german = 1; $? ". german" 3534 } else { 3535 german = 0; $? ". not german" 3536 } 3537 } 3538 } break; 3539 default: { 3540 /* ERROR: Illegal attribute! */ 3541 dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,27,26,kv[i].key); 3542 back = 0; $? "! ERROR" 3543 } break; 3544 } 3545 } 3546 } 3547 } else { $? "! dk3str_to_key_value" 3548 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 40); 3549 } 3550 if(german) { 3551 fprintf( 3552 job->of, "%02d.%02d.%04d", 3553 (job->starttime).D, (job->starttime).M, (job->starttime).Y 3554 ); 3555 } else { 3556 fprintf( 3557 job->of, "%04d-%02d-%02d", 3558 (job->starttime).Y, (job->starttime).M, (job->starttime).D 3559 ); 3560 } $? "- hbhtml_process_sp_date %d", back 3561 return back; 3562} 3563 3564 3565 3566/** Process special command to show variable. 3567 @param job Job structure. 3568 @param pa Pointer to arguments. 3569 @return 1 on success, 0 on error. 3570*/ 3571static 3572int 3573hbhtml_process_sp_variable(hb_job_t *job, dkChar *pa) 3574{ 3575 dk3_key_value_t kv[5]; /* Argument pairs */ 3576 dkChar const *varname; /* Variable name. */ 3577 dkChar const *varval; /* Variable value */ 3578 size_t sz; /* Size of kv */ 3579 size_t i; /* Traverse kv */ 3580 int urlm = 0; /* Flag: URL mode */ 3581 int back = 1; 3582 $? "+ hbhtml_process_sp_variable" 3583 sz = DK3_SIZEOF(kv,dk3_key_value_t); 3584 if(dk3str_to_key_value(kv,&sz,pa,job->app)) { 3585 if(sz > 0) { 3586 varname = kv[0].key; 3587 for(i = 1; i < sz; i++) { 3588 if(kv[i].key) { 3589 if(dk3str_casecmp((job->kwnl)[12], kv[i].key) == 0) { 3590 if(kv[i].val) { 3591 urlm = ((dk3str_is_on(kv[i].val)) ? 1 : 0); 3592 } else { 3593 urlm = 1; 3594 } 3595 } else { 3596 back = 0; $? "! ERROR" 3597 /* ERROR: Illegal argument */ 3598 dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,27,26,kv[i].key); 3599 } 3600 } 3601 } 3602 varval = hbnode_variable(job->currentnode, varname); 3603 if(varval) { 3604 if(urlm) { 3605 if(!hbhtml_url_output_for_text(job, varval)) { 3606 back = 0; $? "! ERROR" 3607 } 3608 } else { 3609 if(!hbhtml_output_for_text(job, varval)) { 3610 back = 0; $? "! ERROR" 3611 } 3612 } 3613 } 3614 } 3615 } else { 3616 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 40); 3617 } $? "- hbhtml_process_sp_variable %d", back 3618 return back; 3619} 3620 3621 3622 3623/** Process contents of one file. 3624 @param job Job structure. 3625 @param p Previous node. 3626 @param n Next node. 3627 @return 1 on success, 0 on error (can continue), -1 on error (exit). 3628*/ 3629static 3630int 3631hbhtml_process_sp_contents(hb_job_t *job, hb_node_t *p, hb_node_t *n) 3632{ 3633 int back = 1; 3634 job->spused = 0; 3635 job->shipused = 0; 3636 $? "+ hbhtml_process_sp_contents %lu", (job->currentnode)->objno 3637 if(job->currentnode) { $? ". have current node" 3638 if((job->currentnode)->filename) { $? ". have input file name" 3639 back = hbcont_process(job, p, n); 3640 } else { $? "! no input file name" 3641 if(0UL == (job->currentnode)->objno) { $? ". root node" 3642 back = hbcont_process(job, p, n); 3643 } else { $? "! not root node" 3644 } 3645 } 3646 } $? "- hbhtml_process_sp_contents %d", back 3647 return back; 3648} 3649 3650 3651 3652/** Open code tag for line number. 3653 @param job Job structure. 3654 @return 1 on success, 0 on error. 3655*/ 3656static 3657int 3658hbhtml_coli_open(hb_job_t *job) 3659{ 3660 int back = 1; 3661 if (EOF == fputs(hbhtml_c8_kw[146], job->of)) { back = 0; } 3662 if (1000 > job->coli) { 3663 if (0 > fprintf(job->of, "%03d", job->coli)) { back = 0; } 3664 job->coli += 1; 3665 if (1000 == job->coli) { 3666 back = 0; 3667 /* WARNING: Too many code lines */ 3668 dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 88); 3669 } 3670 } else { 3671 back = 0; 3672 fputs(hbhtml_c8_kw[149], job->of); 3673 } 3674 if (EOF == fputs(hbhtml_c8_kw[147], job->of)) { back = 0; } 3675 return back; 3676} 3677 3678 3679 3680/** Close code tag for line number. 3681 @param job Job structure. 3682 @return 1 on success, 0 on error. 3683*/ 3684static 3685int 3686hbhtml_coli_close(hb_job_t *job) 3687{ 3688 int back = 1; 3689 if (EOF == fputs(hbhtml_c8_kw[148], job->of)) { back = 0; } 3690 return back; 3691} 3692 3693 3694 3695/** Output dummy code line to avoid trimming emptry code tag. 3696 @param job Job structure. 3697 @return 1 on success, 0 on error 3698*/ 3699static 3700int 3701hbhtml_coli_dummy(hb_job_t *job) 3702{ 3703 int back = 1; 3704 if (!hbhtml_coli_open(job)) { back = 0; } 3705 if (EOF == fputs(hbhtml_c8_kw[150], job->of)) { back = 0; } 3706 if (!hbhtml_coli_close(job)) { back = 0; } 3707 return back; 3708} 3709 3710 3711 3712/** Start of a code line found. 3713 Invoked from the input line handler. 3714 @param job Job structure. 3715 @return 1 on success, 0 on error. 3716*/ 3717static 3718int 3719hbhtml_code_line_start(hb_job_t *job) 3720{ 3721 int back = 1; 3722 if (((job->options) & HB_JOB_OPT_CODE) && (0 < job->coli)) { 3723 switch (job->cols) { 3724 case HB_COLIST_NONE: { 3725 if (!hbhtml_coli_open(job)) { back = 0; } 3726 job->cols = HB_COLIST_OPENED; 3727 } break; 3728 case HB_COLIST_NOT_OPENED: { 3729 if (!hbhtml_coli_open(job)) { back = 0; } 3730 job->cols = HB_COLIST_OPENED; 3731 } break; 3732#if 0 3733 case HB_COLIST_OPENED: { 3734 } break; 3735#endif 3736 } 3737 } 3738 return back; 3739} 3740 3741 3742 3743/** Finalize a code line. 3744 Invoked from the input line handler. 3745 @param job Job structure. 3746 @return 1 on success, 0 on error. 3747*/ 3748static 3749int 3750hbhtml_code_line_end(hb_job_t *job) 3751{ 3752 int back = 1; 3753 if (((job->options) & HB_JOB_OPT_CODE) && (0 < job->coli)) { 3754 switch (job->cols) { 3755 case HB_COLIST_NONE: { 3756 job->cols = HB_COLIST_NOT_OPENED; 3757 } break; 3758 case HB_COLIST_NOT_OPENED: { 3759 if (!hbhtml_coli_dummy(job)) { back = 0; } 3760 } break; 3761 case HB_COLIST_OPENED: { 3762 if (!hbhtml_coli_close(job)) { back = 0; } 3763 job->cols = HB_COLIST_NOT_OPENED; 3764 } break; 3765 } 3766 } 3767 return back; 3768} 3769 3770 3771 3772/** Start code line numbering. 3773 Invoked from the input line handler. 3774 Invoked from the code special command. 3775 @param job Job structure. 3776 @return 1 on success, 0 on error. 3777*/ 3778static 3779int 3780hbhtml_start_code_line_numbers(hb_job_t *job) 3781{ 3782 int back = 1; 3783 job->coli = 1; 3784 job->cols = HB_COLIST_NONE; 3785 return back; 3786} 3787 3788 3789 3790/** End code line numbering if it was started. 3791 Invoked from the code special command. 3792 @param job Job structure. 3793 @return 1 on success, 0 on error. 3794*/ 3795static 3796int 3797hbhtml_end_code_line_numbers(hb_job_t *job) 3798{ 3799 int back = 1; 3800 if (((job->options) & HB_JOB_OPT_CODE) && (0 < job->coli)) { 3801 switch (job->cols) { 3802 case HB_COLIST_OPENED: { 3803 if (EOF == fputs(hbhtml_c8_kw[148], job->of)) { back = 0; } 3804 } break; 3805 } 3806 } 3807 job->coli = 0; 3808 job->cols = HB_COLIST_NONE; 3809 return back; 3810} 3811 3812 3813 3814/** Process the code special command. 3815 @param job Job structure. 3816 @param pa Arguments 3817*/ 3818static 3819void 3820hbhtml_process_sp_code(hb_job_t *job, dkChar *pa) 3821{ 3822 dk3_key_value_t kv[10]; /* Command paramters */ 3823 size_t sz; /* Number of command parameters */ 3824 size_t i; /* Process all command parameters */ 3825 int act = 0; /* Action to take */ 3826 int lineno = 0; /* Flag: Write line numbers */ 3827 3828 $? "+ hbhtml_process_sp_code" 3829 3830 /* Get configuration defaults 3831 */ 3832 if ((job->options) & HB_JOB_OPT_CODE_LINE_NUMBERS) { 3833 lineno = 1; 3834 } 3835 3836 /* Use command options 3837 */ 3838 sz = DK3_SIZEOF(kv,dk3_key_value_t); 3839 if(dk3str_to_key_value(kv,&sz,pa,job->app)) { 3840 if(sz > 0) { 3841 for(i = 0; i < sz; i++) { 3842 if(kv[i].key) { 3843 switch(dk3str_array_abbr(hbhtml_code_keys, kv[i].key, dkT('$'), 0)) { 3844 case 0: case 1: { 3845 if(kv[i].val) { 3846 if(dk3str_is_bool(kv[i].val)) { 3847 if(dk3str_is_on(kv[i].val)) { 3848 act = 1; 3849 } else { 3850 act = 2; 3851 } 3852 } else { 3853 act = 1; 3854 } 3855 } else { 3856 act = 1; 3857 } 3858 } break; 3859 case 2: case 3: { 3860 if(kv[i].val) { 3861 if(dk3str_is_bool(kv[i].val)) { 3862 if(dk3str_is_on(kv[i].val)) { 3863 act = 2; 3864 } else { 3865 act = 1; 3866 } 3867 } else { 3868 act = 2; 3869 } 3870 } else { 3871 act = 2; 3872 } 3873 } break; 3874 case 4: { 3875 act = 0; 3876 } break; 3877 case 5: { 3878 if (kv[i].val) { 3879 if (dk3str_is_bool(kv[i].val)) { 3880 lineno = ((dk3str_is_on(kv[i].val)) ? 1 : 0); 3881 } else { 3882 /* Warning: Not a boolean */ 3883 dk3app_log_i3(job->app, DK3_LL_WARNING, 146, 144, kv[i].val); 3884 } 3885 } else { 3886 lineno = 1; 3887 } 3888 } break; 3889 } 3890 } 3891 } 3892 } 3893 } else { 3894 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 40); 3895 } 3896 3897 /* Finish open code line numbering. 3898 */ 3899 (void)hbhtml_end_code_line_numbers(job); 3900 3901 /* Turn code mode on or off. 3902 */ 3903 switch(act) { 3904 case 0: { 3905 if((job->options) & HB_JOB_OPT_CODE) { 3906 job->options &= (~(HB_JOB_OPT_CODE)); 3907 } else { 3908 job->options |= HB_JOB_OPT_CODE; 3909 if (lineno) { 3910 (void)hbhtml_start_code_line_numbers(job); 3911 } 3912 } 3913 } break; 3914 case 1: { 3915 job->options |= HB_JOB_OPT_CODE; 3916 if (lineno) { 3917 (void)hbhtml_start_code_line_numbers(job); 3918 } 3919 } break; 3920 case 2: { 3921 job->options &= (~(HB_JOB_OPT_CODE)); 3922 } break; 3923 } $? "- hbhtml_process_sp_code" 3924} 3925 3926 3927 3928#if 0 3929static 3930int 3931hbhtml_check_link_for_external(dkChar *link, hb_job_t *job) 3932{ 3933 size_t sz; 3934 int back = 0; 3935 if(link) { 3936 sz = dk3str_len(link); 3937 if(sz >= dk3str_len((job->kwnl)[20])) { 3938 if(0 == dk3str_ncmp(link, (job->kwnl)[20], dk3str_len((job->kwnl)[20]))) { 3939 back = 1; 3940 } 3941 } 3942 if(sz >= dk3str_len((job->kwnl)[21])) { 3943 if(0 == dk3str_ncmp(link, (job->kwnl)[21], dk3str_len((job->kwnl)[21]))) { 3944 back = 1; 3945 } 3946 } 3947 } 3948 return back; 3949} 3950#endif 3951 3952 3953 3954int 3955hbhtml_check_link_for_external(dkChar const *link) 3956{ 3957 dkChar const *ptr; /* Traverse string */ 3958 dkChar c; /* Current character */ 3959 int stm3; /* State machine for traversal */ 3960 int i; /* Input classification */ 3961 int back = 0; 3962 $? "+ hbhtml_check_link_for_external \"%!ds\"", TR_STR(link) 3963 hbhtml_stm3_reset(&stm3); 3964 ptr = link; 3965 while(*ptr) { 3966 c = *(ptr++); 3967 i = STM3_I_ANY; 3968 switch(c) { 3969 case dkT(':'): { 3970 i = STM3_I_COLON; 3971 } break; 3972 case dkT('/'): { 3973 i = STM3_I_SLASH; 3974 } break; 3975 case dkT('_'): { 3976 i = STM3_I_ASCII; 3977 } break; 3978 default: { 3979 if((dkT('a') <= c) && (dkT('z') >= c)) { 3980 i = STM3_I_ASCII; 3981 } else { 3982 if((dkT('A') <= c) && (dkT('Z') >= c)) { 3983 i = STM3_I_ASCII; 3984 } else { 3985 if((dkT('0') <= c) && (dkT('9') >= c)) { 3986 i = STM3_I_ASCII; 3987 } 3988 } 3989 } 3990 } break; 3991 } 3992 hbhtml_stm3_step(&stm3, i); 3993 } 3994 if(STM3_ST_SUCCESS == stm3) { 3995 back = 1; 3996 } $? "- hbhtml_check_link_for_external %d", back 3997 return back; 3998} 3999 4000 4001 4002/** Process special command to build a link. 4003 @param job Job structure. 4004 @param pa Program arguments. 4005 @return 1 on success, 0 on error (continue), -1 on error (exit). 4006*/ 4007static 4008int 4009hbhtml_process_sp_a(hb_job_t *job, dkChar *pa) 4010{ 4011 dk3_key_value_t kv[25]; /* Command parameters */ 4012 hb_link_t *linkptr; /* Link data for URL */ 4013 hb_node_t *nptr; /* Current node */ 4014 dkChar *text = NULL; /* Link text */ 4015 dkChar *title = NULL; /* Link title */ 4016 dkChar *accessk = NULL; /* Accesskey argument */ 4017 dkChar *charset = NULL; /* Charset argument */ 4018 dkChar *coords = NULL; /* Coords argument */ 4019 dkChar *href = NULL; /* href argument */ 4020 dkChar *hrefl = NULL; /* hreflang argument */ 4021 dkChar *name = NULL; /* name argument */ 4022 dkChar *onblur = NULL; /* onblur argument */ 4023 dkChar *onfocus = NULL; /* onfocus argument */ 4024 dkChar *rel = NULL; /* rel argument */ 4025 dkChar *rev = NULL; /* rev argument */ 4026 dkChar *shape = NULL; /* shape argument */ 4027 dkChar *tabind = NULL; /* tabindex argument */ 4028 dkChar *target = NULL; /* target argument */ 4029 dkChar *type = NULL; /* type argument */ 4030 dkChar *clptr = NULL; /* class argument */ 4031 dkChar *idptr = NULL; /* id argument */ 4032 dkChar *style = NULL; /* style argument */ 4033 size_t sz; /* Number of parameters */ 4034 size_t i; /* Traverse parameters */ 4035 unsigned oldopt = 0; /* Save options */ 4036 int external = 0; /* Flag: External link */ 4037 int extspec = 0; /* Flag: External specified */ 4038 int titlespec = 0; /* Flag: Title specified */ 4039 int tifl = 0; /* Flag: Title from link */ 4040 int back = 0; 4041 $? "+ hbhtml_process_sp_a" 4042 nptr = job->currentnode; 4043 sz = DK3_SIZEOF(kv,dk3_key_value_t); 4044 if(dk3str_to_key_value(kv,&sz,pa,job->app)) { 4045 if(sz > 0) { 4046 for(i = 0; i < sz; i++) { 4047 if(kv[i].key) { 4048 switch(dk3str_array_abbr(hbhtml_a_keys, kv[i].key, dkT('$'), 0)) { 4049 case 0: { $? ". text" 4050 text = kv[i].val; 4051 } break; 4052 case 1: { $? ". title" 4053 title = kv[i].val; titlespec = 1; 4054 } break; 4055 case 2: { $? ". accesskey" 4056 accessk = kv[i].val; 4057 } break; 4058 case 3: { $? ". charset" 4059 charset = kv[i].val; 4060 } break; 4061 case 4: { $? ". coords" 4062 coords = kv[i].val; 4063 } break; 4064 case 5: { $? ". href" 4065 href= kv[i].val; 4066 } break; 4067 case 6: { $? ". hreflang" 4068 hrefl = kv[i].val; 4069 } break; 4070 case 7: { $? ". name" 4071 name = kv[i].val; 4072 } break; 4073 case 8: { $? ". onblur" 4074 onblur = kv[i].val; 4075 } break; 4076 case 9: { $? ". onfocus" 4077 onfocus = kv[i].val; 4078 } break; 4079 case 10: { $? ". rel" 4080 rel = kv[i].val; 4081 } break; 4082 case 11: { $? ". rev" 4083 rev = kv[i].val; 4084 } break; 4085 case 12: { $? ". shape" 4086 shape = kv[i].val; 4087 } break; 4088 case 13: { $? ". tabindex" 4089 tabind = kv[i].val; 4090 } break; 4091 case 14: { $? ". target" 4092 target = kv[i].val; 4093 } break; 4094 case 15: { $? ". type" 4095 type = kv[i].val; 4096 } break; 4097 case 16: { $? ". class" 4098 clptr = kv[i].val; 4099 } break; 4100 case 17: { $? ". id" 4101 idptr = kv[i].val; 4102 } break; 4103 case 18: { $? ". style" 4104 style = kv[i].val; 4105 } break; 4106 case 19: { 4107 if(kv[i].val) { 4108 if(dk3str_is_bool(kv[i].val)) { 4109 if(dk3str_is_on(kv[i].val)) { 4110 external = 1; extspec = 1; 4111 } else { 4112 external = 0; extspec = 1; 4113 } 4114 } 4115 } else { 4116 external = 1; extspec = 1; 4117 } 4118 } break; 4119 default: { 4120 dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,27,26,kv[i].key); 4121 } break; 4122 } 4123 } 4124 } 4125 } 4126 } else { 4127 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 40); 4128 } 4129 if(href) { 4130 if(!(extspec)) { 4131 external = hbhtml_check_link_for_external(href); 4132 } 4133 if(titlespec) { 4134 if(!(title)) { title = text; } 4135 if(!(title)) { title = href; tifl = 1; } 4136 } 4137 back = 1; 4138 } else { 4139 if(name) { 4140 back = 1; 4141 } 4142 } 4143 /* Checks ok, all required information available. 4144 */ 4145 if(back) { 4146 /* Write <a...> */ 4147 if(href) { 4148 /* <a href=" */ 4149 fputs(hbhtml_c8_kw[39], job->of); 4150 if(!hbhtml_url_output_for_text(job, href)) { back = 0; } 4151 } else { 4152 /* <a name=" */ 4153 fputs(hbhtml_c8_kw[74], job->of); 4154 if(!hbhtml_url_output_for_text(job, name)) { back = 0; } 4155 } 4156 if(target) { 4157 /* " target=" */ 4158 fputs(hbhtml_c8_kw[75], job->of); 4159 if(!hbhtml_url_output_for_text(job, target)) { back = 0; } 4160 } else { 4161 if(external) { 4162 /* " target="_blank */ 4163 fputs(hbhtml_c8_kw[108], job->of); 4164 } 4165 } 4166 if(type) { 4167 /* " type=" */ 4168 fputs(hbhtml_c8_kw[76], job->of); 4169 if(!hbhtml_url_output_for_text(job, type)) { back = 0; } 4170 } 4171 /* " class=" */ 4172 fputs(hbhtml_c8_kw[77], job->of); 4173 if(clptr) { 4174 if(!hbhtml_url_output_for_text(job, clptr)) { back = 0; } 4175 } else { 4176 if(external) { 4177 /* hb_a_e */ 4178 fputs(hbhtml_c8_kw[101], job->of); 4179 } else { 4180 /* hb_a_i */ 4181 fputs(hbhtml_c8_kw[100], job->of); 4182 } 4183 } 4184 if(idptr) { 4185 /* " id=" */ 4186 fputs(hbhtml_c8_kw[78], job->of); 4187 if(!hbhtml_url_output_for_text(job, idptr)) { back = 0; } 4188 } 4189 if(style) { 4190 /* " style=" */ 4191 fputs(hbhtml_c8_kw[79], job->of); 4192 if(!hbhtml_url_output_for_text(job, style)) { back = 0; } 4193 } 4194 if(hrefl) { 4195 /* " hreflang=" */ 4196 fputs(hbhtml_c8_kw[80], job->of); 4197 if(!hbhtml_url_output_for_text(job, hrefl)) { back = 0; } 4198 } 4199 if(title) { 4200 /* " title=" */ 4201 fputs(hbhtml_c8_kw[81], job->of); 4202 if ((0 != external) && (0 != job->markel) && (0 < strlen(job->elmbuf))) { 4203 /* &#x */ 4204 fputs(hbhtml_c8_kw[156], job->of); 4205 fputs(job->elmbuf, job->of); 4206 /* ; */ 4207 fputs(hbhtml_c8_kw[157], job->of); 4208 } 4209 /* ##### a title, Ausgabe des href als Title */ 4210 oldopt = (job->currentnode)->options; 4211 if (0 != tifl) { 4212 (job->currentnode)->options &= (~(HB_NODE_OPT_REPLACE_AMPERSAND)); 4213 } 4214 if(!hbhtml_output_for_text(job, title)) { back = 0; } 4215 (job->currentnode)->options = oldopt; 4216 } else { 4217 if ((0 != external) && (0 != job->markel) && (0 < strlen(job->elmbuf))) { 4218 /* " title=" */ 4219 fputs(hbhtml_c8_kw[81], job->of); 4220 /* &#x */ 4221 fputs(hbhtml_c8_kw[156], job->of); 4222 fputs(job->elmbuf, job->of); 4223 /* ; */ 4224 fputs(hbhtml_c8_kw[157], job->of); 4225 } 4226 } 4227 if(onblur) { 4228 /* " onblur=" */ 4229 fputs(hbhtml_c8_kw[82], job->of); 4230 if(!hbhtml_url_output_for_text(job, onblur)) { back = 0; } 4231 } 4232 if(onfocus) { 4233 /* " onfocus=" */ 4234 fputs(hbhtml_c8_kw[83], job->of); 4235 if(!hbhtml_url_output_for_text(job, onfocus)) { back = 0; } 4236 } 4237 if(rel) { 4238 /* " rel=" */ 4239 fputs(hbhtml_c8_kw[84], job->of); 4240 if(!hbhtml_url_output_for_text(job, rel)) { back = 0; } 4241 } 4242 if(rev) { 4243 /* " rev=" */ 4244 fputs(hbhtml_c8_kw[85], job->of); 4245 if(!hbhtml_url_output_for_text(job, rev)) { back = 0; } 4246 } 4247 if(shape) { 4248 /* " shape=" */ 4249 fputs(hbhtml_c8_kw[86], job->of); 4250 if(!hbhtml_url_output_for_text(job, shape)) { back = 0; } 4251 } 4252 if(tabind) { 4253 /* " tabindex=" */ 4254 fputs(hbhtml_c8_kw[87], job->of); 4255 if(!hbhtml_url_output_for_text(job, tabind)) { back = 0; } 4256 } 4257 if(accessk) { 4258 /* " accesskey=" */ 4259 fputs(hbhtml_c8_kw[88], job->of); 4260 if(!hbhtml_url_output_for_text(job, accessk)) { back = 0; } 4261 } 4262 if(charset) { 4263 /* " charset=" */ 4264 fputs(hbhtml_c8_kw[89], job->of); 4265 if(!hbhtml_url_output_for_text(job, charset)) { back = 0; } 4266 } 4267 if(coords) { 4268 /* " coords=" */ 4269 fputs(hbhtml_c8_kw[90], job->of); 4270 if(!hbhtml_url_output_for_text(job, coords)) { back = 0; } 4271 } 4272 /* " */ 4273 fputs(hbhtml_c8_kw[5], job->of); 4274 /* > */ 4275 fputs(hbhtml_c8_kw[3], job->of); 4276 if(href) { 4277 if(text) { 4278 if(!hbhtml_output_for_text(job, text)) { back = 0; } 4279 } else { 4280 /* ##### Link-Text, Ausgabe des href-Attributes als Text */ 4281 /* Save options 4282 */ 4283 oldopt = (job->currentnode)->options; 4284 /* 4285 Replace ampersands 4286 */ 4287 (job->currentnode)->options &= (~(HB_NODE_OPT_REPLACE_AMPERSAND)); 4288 /* 4289 Write href text as hyperlink text 4290 */ 4291 if(!hbhtml_output_for_text(job, href)) { back = 0; } 4292 /* 4293 Restore options 4294 */ 4295 (job->currentnode)->options = oldopt; 4296 } 4297 } 4298 /* </a> */ 4299 fputs(hbhtml_c8_kw[41], job->of); 4300 if((href) && (external) && (text)) { 4301 /* Save link and write link number */ 4302 linkptr = (hb_link_t *)dk3sto_it_find_like(nptr->i_lbyurl, href, 1); 4303 if(linkptr) { 4304 fprintf(job->of, hbhtml_c8_kw[91], (1UL + linkptr->lno)); 4305 } else { 4306 linkptr = hbnode_link_new(href, nptr->nextlink, job->app); 4307 if(linkptr) { 4308 if(dk3sto_add(nptr->s_lbyurl, linkptr)) { 4309 nptr->nextlink += 1UL; 4310 if(dk3sto_add(nptr->s_lbylno, linkptr)) { 4311 fprintf(job->of, hbhtml_c8_kw[91], (1UL + linkptr->lno)); 4312 } else { 4313 back = 0; 4314 } 4315 } else { 4316 back = 0; 4317 hbnode_link_delete(linkptr); 4318 linkptr = NULL; 4319 } 4320 } else { 4321 back = 0; 4322 } 4323 } 4324 } 4325 if((!(href)) && (name)) { 4326 if(text) { 4327 if(!hbhtml_output_for_text(job, text)) { back = 0; } 4328 } 4329 } 4330 if(href) { 4331 if(!hbtool_add_url(job, href)) { back = 0; } 4332 } 4333 } $? "- hbhtml_process_sp_a %d", back 4334 return back; 4335} 4336 4337 4338 4339/** Process menuentry special command. 4340 @param job Job structure. 4341 @param pa Arguments. 4342 @return 1 on success, 0 on error (continue), -1 on error (exit). 4343*/ 4344static 4345int 4346hbhtml_process_sp_menuentry(hb_job_t *job, dkChar *pa) 4347{ 4348 dk3_key_value_t kv[20]; /* Command parameters */ 4349 dkChar *items[DK3_SIZEOF(kv,dk3_key_value_t)]; 4350 size_t sz; /* Number of command parameters */ 4351 size_t i; /* Traverse command parameters */ 4352 size_t n_items = 0; /* number of items */ 4353 size_t cr; /* Current item index */ 4354 int back = 0; 4355 $? "+ hbhtml_process_sp_menuentry" 4356 sz = DK3_SIZEOF(kv,dk3_key_value_t); 4357 if(dk3str_to_key_value(kv,&sz,pa,job->app)) { 4358 if(sz > 0) { 4359 for(i = 0; i < sz; i++) { 4360 if(kv[i].key) { 4361 switch(dk3str_array_abbr(hbhtml_menuentry_keys,kv[i].key,dkT('$'),0)) 4362 { 4363 case 0: { 4364 if(kv[i].val) { 4365 if(n_items < DK3_SIZEOF(kv,dk3_key_value_t)) { 4366 items[n_items++] = kv[i].val; 4367 } else { 4368 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 41); 4369 } 4370 } 4371 } break; 4372 default: { 4373 dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,27,26,kv[i].key); 4374 back = 0; 4375 } break; 4376 } 4377 } 4378 } 4379 } 4380 } else { 4381 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 40); 4382 } 4383 if(n_items) { 4384 back = 1; 4385 if (0 != job->tabsum) { 4386 fputs(hbhtml_c8_kw[92], job->of); 4387 if(!hbhtml_output_for_text(job, (job->msg)[60])) { back = 0; } 4388 fputs(hbhtml_c8_kw[22], job->of); 4389 } else { 4390 fputs(hbhtml_c8_kw[158], job->of); 4391 } 4392 for(cr = 0; cr < n_items; cr++) { 4393 fputs(hbhtml_c8_kw[94], job->of); 4394 if(cr) { 4395 for(i = 0; i < (cr - 1); i++) { 4396 fputs(hbhtml_c8_kw[98], job->of); 4397 } 4398 fputs(hbhtml_c8_kw[99], job->of); 4399 fprintf(job->of, hbhtml_c8_kw[96], (unsigned)(n_items - cr)); 4400 if(!hbhtml_output_for_text(job, items[cr])) { back = 0; } 4401 fputs(hbhtml_c8_kw[97], job->of); 4402 } else { 4403 fprintf(job->of, hbhtml_c8_kw[96], (unsigned)n_items); 4404 if(!hbhtml_output_for_text(job, items[cr])) { back = 0; } 4405 fputs(hbhtml_c8_kw[97], job->of); 4406 } 4407 fputs(hbhtml_c8_kw[95], job->of); 4408 } 4409 fputs(hbhtml_c8_kw[93], job->of); 4410 } else { 4411 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 42); 4412 } $? "- hbhtml_process_sp_menuentry %d", back 4413 return back; 4414} 4415 4416 4417 4418/** Process index special command. 4419 @param job Job structure. 4420 @param pa Program arguments. 4421 @return 1 on success, 0 on error (continue), -1 on error (exit). 4422*/ 4423static 4424int 4425hbhtml_process_sp_index(hb_job_t *job, dkChar *pa) 4426{ 4427 dk3_key_value_t kv[10]; /* Command parameters */ 4428 hb_node_t *nptr; /* Current node */ 4429 hb_index_entry_t *indptr; /* New index entry item */ 4430 dkChar *text = NULL; /* Text for index entry */ 4431 dkChar *name = NULL; /* Name for index entry */ 4432 size_t sz; /* Number of command paramters */ 4433 size_t i; /* Traverse command parameters */ 4434 int refer = 0; /* Flag: Refer to existing entry */ 4435 int back = 0; 4436 $? "+ hbhtml_process_sp_index" 4437 nptr = job->currentnode; 4438 sz = DK3_SIZEOF(kv,dk3_key_value_t); 4439 if(dk3str_to_key_value(kv,&sz,pa,job->app)) { 4440 if(sz > 0) { 4441 for(i = 0; i < sz; i++) { 4442 if(kv[i].key) { 4443 switch(dk3str_array_abbr(hbhtml_index_keys, kv[i].key, dkT('$'), 0)) { 4444 case 0: { 4445 text = kv[i].val; 4446 } break; 4447 case 1: { 4448 name = kv[i].val; 4449 } break; 4450 case 2: { 4451 if(kv[i].val) { 4452 if(dk3str_is_bool(kv[i].val)) { 4453 if(dk3str_is_on(kv[i].val)) { 4454 refer = 1; 4455 } else { 4456 refer = 0; 4457 } 4458 } else { 4459 /* ERROR: Not a boolean */ 4460 dk3app_log_i3(job->app, DK3_LL_WARNING, 146, 144, kv[i].val); 4461 } 4462 } else { 4463 refer = 1; 4464 } 4465 } break; 4466 } 4467 } 4468 } 4469 if(text) { 4470 if((job->options) & HB_JOB_OPT_CREATE_INDEX) { 4471 indptr = hbindex_new( 4472 text, nptr->outFileName, name, nptr->nextindex, job->app, nptr 4473 ); 4474 if(indptr) { 4475 if(dk3sto_add(job->s_index, indptr)) { 4476 back = 1; 4477 nptr->nextindex += 1UL; 4478 if(!((name) && (refer))) { 4479 fputs(hbhtml_c8_kw[74], job->of); 4480 if(!hb_index_write_anchor(job, indptr)) { back = 0; } 4481 fputs(hbhtml_c8_kw[51], job->of); 4482 fputs(hbhtml_c8_kw[52], job->of); 4483 } 4484 } else { 4485 hbindex_delete(indptr); 4486 } 4487 } 4488 } else { 4489 back = 1; 4490 } 4491 } else { 4492 /* ERROR: Missing text attribute! */ 4493 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 48); 4494 } 4495 } 4496 } else { 4497 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 40); 4498 } $? "- hbhtml_process_sp_index %d", back 4499 return back; 4500} 4501 4502 4503 4504/** Handle one source code line. 4505 @param obj Job structure. 4506 @param il Input line. 4507 @return 1 on success, 0 on error (continue), -1 on error (exit). 4508*/ 4509static 4510int 4511hbhtml_sourcefile_line_handler(void *obj, dkChar *il) 4512{ 4513 hb_job_t *job; 4514 int back = 1; 4515 4516 job = (hb_job_t *)obj; 4517 dk3str_delnl(il); 4518 $? "+ hbhtml_sourcefile_line_handler \"%!ds\"", il 4519 if (job->coli) { 4520 if (0 < dk3str_len(il)) { 4521 if (!hbhtml_coli_open(job)) { back = 0; } 4522 if(!hbhtml_output_for_text(job, il)) { back = 0; } 4523 if (!hbhtml_coli_close(job)) { back = 0; } 4524 } else { 4525 if (!hbhtml_coli_dummy(job)) { back = 0; } 4526 } 4527 } else { 4528 if(!hbhtml_output_for_text(job, il)) { back = 0; } 4529 } 4530 fputc('\n', job->of); 4531 $? "- hbhtml_sourcefile_line_handler %d", back 4532 return back; 4533} 4534 4535 4536 4537/** Process sourcefile special command. 4538 @param job Job structure. 4539 @param pa Program arguemnts. 4540 @return 1 on success, 0 on error (continue), -1 on error (exit). 4541*/ 4542static 4543int 4544html_process_sp_sourcefile(hb_job_t *job, dkChar *pa) 4545{ 4546 dkChar bu[4096]; /* Buffer for source file lines */ 4547 dk3_key_value_t kv[10]; /* Command parameters */ 4548 dkChar *file = NULL; /* Input file */ 4549 dkChar *type = NULL; /* Type argument */ 4550 dkChar *title = NULL; /* Title argument */ 4551 size_t sz; /* Number of command parameters */ 4552 size_t i; /* Traverse command parameters */ 4553 int lineno = 0; /* Flag: Write line numbers */ 4554 int back = 0; 4555 int res; /* Result from processing file */ 4556 int oldcode; /* Old code flag value */ 4557 $? "+ html_process_sp_sourcefile" 4558 if ((job->options) & HB_JOB_OPT_CODE_LINE_NUMBERS) { 4559 lineno = 1; 4560 } 4561 sz = DK3_SIZEOF(kv,dk3_key_value_t); 4562 if(dk3str_to_key_value(kv, &sz, pa, job->app)) { 4563 if(sz > 0) { 4564 for(i = 0; i < sz; i++) { 4565 if(kv[i].key) { 4566 switch(dk3str_array_abbr(hbhtml_sourcef_keys,kv[i].key,dkT('$'),0)) { 4567 case 0: { 4568 file = kv[i].val; 4569 } break; 4570 case 1: { 4571 type = kv[i].val; 4572 } break; 4573 case 2: { 4574 title = kv[i].val; 4575 } break; 4576 case 3: { 4577 if (kv[i].val) { 4578 if (dk3str_is_bool(kv[i].val)) { 4579 lineno = ((dk3str_is_on(kv[i].val)) ? 1 : 0); 4580 } else { 4581 /* WARNING: Not a boolean */ 4582 dk3app_log_i3(job->app, DK3_LL_WARNING, 146, 144, kv[i].val); 4583 } 4584 } else { 4585 lineno = 1; 4586 } 4587 } break; 4588 } 4589 } 4590 } 4591 } 4592 if(file) { 4593 back = 1; 4594 if(hbtool_add_file(job, file)) { 4595 fputs(hbhtml_c8_kw[102], job->of); 4596 fputs(hbhtml_c8_kw[103], job->of); 4597 if(!hbhtml_url_output_for_text(job, file)) { back = 0; } 4598 fputs(hbhtml_c8_kw[81], job->of); 4599 if(title) { 4600 if(!hbhtml_output_for_text(job, title)) { back = 0; } 4601 } else { 4602 if(!hbhtml_output_for_text(job, file)) { back = 0; } 4603 } 4604 fputs(hbhtml_c8_kw[76], job->of); 4605 if(type) { 4606 if(!hbhtml_output_for_text(job, type)) { back = 0; } 4607 } else { 4608 fputs(hbhtml_c8_kw[104], job->of); 4609 } 4610 fputs(hbhtml_c8_kw[51], job->of); 4611 if(!hbhtml_output_for_text(job, file)) { back = 0; } 4612 fputs(hbhtml_c8_kw[52], job->of); 4613 fputs(hbhtml_c8_kw[105], job->of); 4614 fputs(hbhtml_c8_kw[106], job->of); 4615 oldcode = (((job->options) & HB_JOB_OPT_CODE) ? 1 : 0); 4616 job->options |= HB_JOB_OPT_CODE; 4617 job->coli = ((lineno) ? 1 : 0); 4618 res = dk3stream_process_filename_lines_app( 4619 (void *)job, hbhtml_sourcefile_line_handler, file, 4620 bu, DK3_SIZEOF(bu,dkChar), 4621 dk3app_get_encoding(job->app), 4622 dk3app_get_input_file_encoding(job->app), 4623 job->app 4624 ); 4625 job->coli = 0; 4626 if(!(res)) { back = 0; } 4627 if(oldcode) { 4628 job->options |= HB_JOB_OPT_CODE; 4629 } else { 4630 job->options &= (~(HB_JOB_OPT_CODE)); 4631 } 4632 fputs(hbhtml_c8_kw[107], job->of); 4633 fputs(hbhtml_c8_kw[47], job->of); 4634 } else { 4635 back = 0; 4636 } 4637 } else { 4638 /* ERROR: No file name specified! */ 4639 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 49); 4640 } 4641 } else { 4642 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 40); 4643 } $? "- html_process_sp_sourcefile %d", back 4644 return back; 4645} 4646 4647 4648 4649/** Process sourcefile special command. 4650 @param job Job structure. 4651 @return 1 on success, 0 on error (continue), -1 on error (exit). 4652*/ 4653static 4654int 4655html_process_sp_htmlname(hb_job_t *job) 4656{ 4657 dkChar buf[DK3_MAX_PATH]; 4658 size_t szbuf = DK3_SIZEOF(buf,dkChar); 4659 int back = 0; 4660 $? "+ html_process_sp_htmlname" 4661 if (NULL != job->currentnode) { 4662 if (0 != hbhtml_create_output_filename(buf, szbuf, job, job->currentnode)) { 4663 back = hbhtml_url_output_for_text(job, buf); 4664 if (0 == back) { $? "! failed to write text" 4665 job->exv = 1; 4666 } 4667 } else { $? "! filename conversion" 4668 job->exv = 1; 4669 } 4670 } else { $? "! no current node" 4671 } 4672 $? "- html_process_sp_htmlname %d", back 4673 return back; 4674} 4675 4676 4677 4678/** Process sourcefile special command. 4679 @param job Job structure. 4680 @param pa Program arguemnts. 4681 @return 1 on success, 0 on error (continue), -1 on error (exit). 4682*/ 4683static 4684int 4685html_process_sp_hint(hb_job_t *job, dkChar *pa) 4686{ 4687 dk3_key_value_t kv[30]; 4688 dkChar *hint_text = NULL; 4689 dkChar *hint_title = NULL; 4690 size_t sz; 4691 size_t i; 4692 int back = 0; 4693 4694 sz = DK3_SIZEOF(kv,dk3_key_value_t); 4695 if (0 != dk3str_to_key_value(kv, &sz, pa, job->app)) { 4696 for (i = 0; i < sz; i++) { 4697 if (NULL != kv[i].key) { 4698 switch (dk3str_array_abbr(hbhtml_hint_keys, kv[i].key, dkT('$'), 0)) { 4699 case 0: { 4700 hint_text = kv[i].val; 4701 } break; 4702 case 1: { 4703 hint_title = kv[i].val; 4704 } break; 4705 default: { 4706 /* Warning: Unusable key */ 4707 dk3app_log_3(job->app, DK3_LL_WARNING, job->msg, 89, 90, kv[i].key); 4708 } break; 4709 } 4710 } 4711 } 4712 if (NULL != hint_text) { 4713 back = 1; 4714 if (NULL != hint_title) { 4715 if (EOF == fputs(hbhtml_c8_kw[151], job->of)) { 4716 back = 0; 4717 } 4718 if (0 ==hbhtml_output_for_text(job, hint_title)) { 4719 back = 0; 4720 } 4721 if (EOF == fputs(hbhtml_c8_kw[152], job->of)) { 4722 back = 0; 4723 } 4724 if (0 == hbhtml_output_for_text(job, hint_text)) { 4725 back = 0; 4726 } 4727 if (EOF == fputs(hbhtml_c8_kw[153], job->of)) { 4728 back = 0; 4729 } 4730 } 4731 else { 4732 dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 92); 4733 if (0 == hbhtml_output_for_text(job, hint_text)) { 4734 back = 0; 4735 } 4736 } 4737 } 4738 else { 4739 /* ERROR: No text */ 4740 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 91); 4741 } 4742 } 4743 else { 4744 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 40); 4745 } 4746 if (0 == back) { 4747 job->exv = 1; 4748 } 4749 return back; 4750} 4751 4752 4753 4754/** Process a special command. 4755 @param job Job structure. 4756 @param in_template Flag: Processing a template. 4757 @param p Previous node. 4758 @param n Next node. 4759 @return 1 on success, 0 on error (continue), -1 on error (exit). 4760*/ 4761static 4762int 4763hbhtml_process_special( 4764 hb_job_t *job, 4765 int in_template, 4766 hb_node_t *p, 4767 hb_node_t *n 4768) 4769{ 4770 dkChar *pc; /* Special command name */ 4771 dkChar *pa; /* Start of command arguments */ 4772 dkChar *sc; /* Start of sub command. */ 4773 int ct; /* Command identifier */ 4774 int back = 0; 4775 $? "+ hbhtml_process_special" 4776 pc = dk3str_start(job->special, NULL); 4777 sc = NULL; 4778 if(pc) { 4779 pa = dk3str_next(pc, NULL); 4780 if(pa) { 4781 dk3str_chomp(pa, NULL); 4782 } 4783 sc = dk3str_chr(pc, dkT('.')); 4784 if(sc) { *(sc++) = dkT('\0'); } 4785 ct = dk3str_array_index(hbhtml_special_commands, pc, 0); 4786 $? ". ct = %d", ct 4787 switch(ct) { 4788 case 0: { $? ". contents" 4789 if(in_template) { 4790 back = hbhtml_process_sp_contents(job, p, n); 4791 } else { 4792 /* ERROR: Contents special not allowed in contents! */ 4793 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 28); 4794 } 4795 } break; 4796 case 1: { $? ". title" 4797 back = hbhtml_process_sp_title(job); 4798 if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } 4799 } break; 4800 case 2: { $? ". image" 4801 back = hbhtml_process_sp_image(job, pa, sc); 4802 if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } 4803 } break; 4804 case 3: { $? ". menu" 4805 back = hbhtml_process_sp_menu(job, pa); 4806 if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } 4807 } break; 4808 case 4: { $? ". navigation" 4809 back = hbhtml_process_sp_navigation(job, pa, p, n); 4810 if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } 4811 } break; 4812 case 5: { /* links */ 4813 /* #### Probably not */ 4814 back = 1; 4815 } break; 4816 case 6: { $? ". author" 4817 back = hbhtml_process_sp_author(job); 4818 if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } 4819 } break; 4820 case 7: { $? ". location" 4821 back = hbhtml_process_sp_location(job); 4822 if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } 4823 } break; 4824 case 8: { $? ". date" 4825 back = hbhtml_process_sp_date(job, pa); 4826 if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } 4827 } break; 4828 case 9: { $? ". variable" 4829 back = hbhtml_process_sp_variable(job, pa); 4830 if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } 4831 } break; 4832 case 10: { 4833 hbhtml_process_sp_code(job, pa); 4834 back = 1; 4835 } break; 4836 case 11: { 4837 back = hbhtml_process_sp_a(job, pa); 4838 if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } 4839 } break; 4840 case 12: { 4841 back = hbhtml_process_sp_menuentry(job, pa); 4842 if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } 4843 } break; 4844 case 13: { 4845 if(0 == in_template) { 4846 back = hbhtml_process_sp_index(job, pa); 4847 if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } 4848 } else { 4849 /* ERROR: Can not be used in template */ 4850 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 50); 4851 } 4852 } break; 4853 case 14: { 4854 back = html_process_sp_sourcefile(job, pa); 4855 if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } 4856 } break; 4857 case 15: { 4858 back = html_process_sp_htmlname(job); 4859 } break; 4860 case 16: { 4861 back = html_process_sp_hint(job, pa); 4862 } break; 4863 default: { $? "! unknown command" 4864 back = 0; 4865 /* ERROR: Unknown special command. */ 4866 dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,29,26,pc); 4867 } break; 4868 } 4869 } else { 4870 back = 1; /* Empty special */ 4871 } 4872 $? "- hbhtml_process_special %d", back 4873 return back; 4874} 4875 4876 4877 4878int 4879hbhtml_line_handler(void *obj, dkChar *il) 4880{ 4881 dkChar xmsg[8]; /* Array for diagnostics */ 4882 hb_file_processor_t *proc; /* Line processor */ 4883 hb_job_t *job; /* Job */ 4884 dkChar *p1; /* Start of input line */ 4885 size_t pos; /* Non-whitespace position */ 4886 int i; /* Input classification */ 4887 int o; /* Reaction from state machine */ 4888 int ltl = 0; /* Flag: Error from shipout */ 4889 int back = 1; 4890 dkChar c; /* Character to ship out */ 4891 $? "+ hbhtml_line_handler \"%!ds\"", il 4892 pos = 0; 4893 proc = (hb_file_processor_t *)obj; 4894 job = proc->job; 4895 dk3str_delnl(il); 4896 hbhtml_stm1_reset(&(proc->stm)); 4897 job->shipused = 0; 4898 job->spused = 0; 4899 p1 = il; 4900 while(*p1) { 4901 c = *p1; 4902 i = hbhtml_classify_for_stm1(c); 4903 o = hbhtml_stm1_step(&(proc->stm), i); 4904 switch(o) { 4905 case STM1_O_ERROR: { 4906 /* ERROR: Parse error */ 4907 dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,30,26,p1); 4908 back = -1; $? "! FATAL ERROR" 4909 } break; 4910 case STM1_O_NOTHING: { 4911 } break; 4912 case STM1_O_SHIPOUT: { 4913 if (!hbhtml_code_line_start(job)) { back = 0; } 4914 if(!(hbhtml_shipout(job, c))) { 4915 back = 0; $? "! ERROR" 4916 if(0 == ltl) { 4917 ltl = 1; 4918 /* ERROR: Line too long! */ 4919 } 4920 } 4921 } break; 4922 case STM1_O_BS_SHIPOUT: { 4923 switch(c) { 4924 case dkT('n'): { 4925 if (!hbhtml_code_line_start(job)) { back = 0; } 4926 if(!(hbhtml_shipout(job, dkT('\n')))) { 4927 back = 0; $? "! ERROR" 4928 if(0 == ltl) { 4929 ltl = 1; 4930 /* ERROR: Line too long! */ 4931 } 4932 } 4933 } break; 4934 case dkT('r'): { 4935 if (!hbhtml_code_line_start(job)) { back = 0; } 4936 if(!(hbhtml_shipout(job, dkT('\r')))) { 4937 back = 0; $? "! ERROR" 4938 if(0 == ltl) { 4939 ltl = 1; 4940 /* ERROR: Line too long! */ 4941 } 4942 } 4943 } break; 4944 case dkT('t'): { 4945 if (!hbhtml_code_line_start(job)) { back = 0; } 4946 if(!(hbhtml_shipout(job, dkT('\t')))) { 4947 back = 0; $? "! ERROR" 4948 if(0 == ltl) { 4949 ltl = 1; 4950 /* ERROR: Line too long! */ 4951 } 4952 } 4953 } break; 4954 case dkT('%'): case dkT('\\'): { 4955 if (!hbhtml_code_line_start(job)) { back = 0; } 4956 if(!(hbhtml_shipout(job, c))) { 4957 back = 0; $? "! ERROR" 4958 if(0 == ltl) { 4959 ltl = 1; 4960 /* ERROR: Line too long! */ 4961 } 4962 } 4963 } break; 4964 case dkT('.'): { 4965 /* We can escape a leading dot. 4966 */ 4967 if(1 < pos) { 4968 xmsg[0] = dkT('\\'); 4969 xmsg[1] = c; 4970 xmsg[2] = dkT('\0'); 4971 dk3app_log_3(job->app, DK3_LL_WARNING, job->msg, 63, 64, xmsg); 4972 } 4973 if (!hbhtml_code_line_start(job)) { back = 0; } 4974 if(!(hbhtml_shipout(job, c))) { 4975 back = 0; $? "! ERROR" 4976 if(0 == ltl) { 4977 ltl = 1; 4978 /* ERROR: Line too long! */ 4979 } 4980 } 4981 } break; 4982 case dkT('#'): { 4983 /* We can escape a leading raute. 4984 */ 4985 if(1 < pos) { 4986 xmsg[0] = dkT('\\'); 4987 xmsg[1] = c; 4988 xmsg[2] = dkT('\0'); 4989 dk3app_log_3(job->app, DK3_LL_WARNING, job->msg, 63, 64, xmsg); 4990 } 4991 if (!hbhtml_code_line_start(job)) { back = 0; } 4992 if(!(hbhtml_shipout(job, c))) { 4993 back = 0; $? "! ERROR" 4994 if(0 == ltl) { 4995 ltl = 1; 4996 /* ERROR: Line too long! */ 4997 } 4998 } 4999 } break; 5000 default: { 5001 xmsg[0] = dkT('\\'); 5002 xmsg[1] = c; 5003 xmsg[2] = dkT('\0'); 5004 dk3app_log_3(job->app, DK3_LL_WARNING, job->msg, 63, 64, xmsg); 5005 if (!hbhtml_code_line_start(job)) { back = 0; } 5006 if(!(hbhtml_shipout(job, c))) { 5007 back = 0; $? "! ERROR" 5008 if(0 == ltl) { 5009 ltl = 1; 5010 /* ERROR: Line too long! */ 5011 } 5012 } 5013 } break; 5014 } 5015 } break; 5016 case STM1_O_PERCENT_SHIPOUT: { 5017 if (!hbhtml_code_line_start(job)) { back = 0; } 5018 if(!(hbhtml_shipout(job, dkT('%')))) { 5019 back = 0; $? "! ERROR" 5020 if(0 == ltl) { 5021 ltl = 1; 5022 } 5023 } 5024 if(!(hbhtml_shipout(job, c))) { 5025 back = 0; $? "! ERROR" 5026 if(0 == ltl) { 5027 ltl = 1; 5028 } 5029 } 5030 } break; 5031 case STM1_O_PERCENT: { 5032 if (!hbhtml_code_line_start(job)) { back = 0; } 5033 if(!(hbhtml_shipout(job, dkT('%')))) { 5034 back = 0; $? "! ERROR" 5035 if(0 == ltl) { 5036 ltl = 1; 5037 } 5038 } 5039 } break; 5040 case STM1_O_SWITCH: { 5041 hbhtml_flush_shipout(job); 5042 job->spused = 0; 5043 } break; 5044 case STM1_O_SPECIAL: { 5045 if(!hbhtml_add_to_special(job, c)) { 5046 back = 0; $? "! ERROR" 5047 if(0 == ltl) { 5048 ltl = 1; 5049 } 5050 } 5051 } break; 5052 case STM1_O_SPEC_BS: { 5053 switch(c) { 5054 case dkT('n'): { 5055 if(!hbhtml_add_to_special(job, dkT('\n'))) { 5056 back = 0; $? "! ERROR" 5057 if(0 == ltl) { 5058 ltl = 1; 5059 } 5060 } 5061 } break; 5062 case dkT('r'): { 5063 if(!hbhtml_add_to_special(job, dkT('\r'))) { 5064 back = 0; $? "! ERROR" 5065 if(0 == ltl) { 5066 ltl = 1; 5067 } 5068 } 5069 } break; 5070 case dkT('t'): { 5071 if(!hbhtml_add_to_special(job, dkT('\t'))) { 5072 back = 0; $? "! ERROR" 5073 if(0 == ltl) { 5074 ltl = 1; 5075 } 5076 } 5077 } break; 5078 default: { 5079 if(!hbhtml_add_to_special(job, c)) { 5080 back = 0; $? "! ERROR" 5081 if(0 == ltl) { 5082 ltl = 1; 5083 } 5084 } 5085 } break; 5086 } 5087 } break; 5088 case STM1_O_SPEC_PC_ADD: { 5089 if(!hbhtml_add_to_special(job, dkT('%'))) { 5090 back = 0; $? "! ERROR" 5091 if(0 == ltl) { 5092 ltl = 1; 5093 } 5094 } 5095 if(!hbhtml_add_to_special(job, c)) { 5096 back = 0; $? "! ERROR" 5097 if(0 == ltl) { 5098 ltl = 1; 5099 } 5100 } 5101 } break; 5102 case STM1_O_SPEC_PC: { 5103 if(!hbhtml_add_to_special(job, dkT('%'))) { 5104 back = 0; $? "! ERROR" 5105 if(0 == ltl) { 5106 ltl = 1; 5107 } 5108 } 5109 } break; 5110 case STM1_O_EXECUTE: { 5111 if((job->spused) < (job->bs)) { 5112 (job->special)[job->spused] = dkT('\0'); 5113 back = hbhtml_process_special(job,proc->in_template,proc->p,proc->n); 5114 } else { 5115 back = 0; $? "! ERROR" 5116 if(0 == ltl) { 5117 ltl = 1; 5118 } 5119 } 5120 job->spused = 0; 5121 job->shipused = 0; 5122 } break; 5123 } 5124 p1++; 5125 if((dkT(' ') != c) && (dkT('\t') != c)) { 5126 pos++; 5127 } 5128 } 5129 switch(proc->stm) { 5130 case STM1_ST_BS: { 5131 if (!hbhtml_code_line_start(job)) { back = 0; } 5132 if(!(hbhtml_shipout(job, dkT('\\')))) { 5133 back = 0; 5134 if(0 == ltl) { ltl = 1; } 5135 } 5136 } break; 5137 case STM1_ST_PERCENT: { 5138 if (!hbhtml_code_line_start(job)) { back = 0; } 5139 if(!(hbhtml_shipout(job, dkT('%')))) { 5140 back = 0; 5141 if(0 == ltl) { ltl = 1; } 5142 } 5143 } break; 5144 case STM1_ST_SPECIAL: case STM1_ST_SPEC_BS: case STM1_ST_SPEC_PC: { 5145 /* ERROR: Unfinished special command! */ 5146 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 62); 5147 back = 0; 5148 } break; 5149 } 5150 if(ltl) { 5151 dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 31, 26, il); 5152 } 5153 hbhtml_flush_shipout(job); 5154 if (!hbhtml_code_line_end(job)) { back = 0; } 5155 if (EOF == fputc('\n', job->of)) { 5156 back = 0; $? "! ERROR Newline" 5157 } 5158 $? "- hbhtml_line_handler %d", back 5159 return back; 5160} 5161 5162 5163 5164/** Write JS files to HTML header. 5165 @param job Job structure. 5166 @param nptr Node to write JS file list for. 5167 @param htdt Document type. 5168 @param ptocjs Flag: Write JS file for page toc. 5169 @return 1 on success, 0 on error. 5170*/ 5171static 5172int 5173hbhtml_write_js_files(hb_job_t *job, hb_node_t *nptr, int htdt, int ptocjs) 5174{ 5175 hb_link_t *linkptr; /* File name data for JavaScript file */ 5176 int back = 1; 5177 $? "+ hbhtml_write_js_files" 5178 /* Write parent JS files. 5179 */ 5180 if(nptr->parent) { 5181 if(!((nptr->options) & HB_NODE_OPT_STOP_JS_INHERITANCE)) { 5182 hbhtml_write_js_files(job, nptr->parent, htdt, 0); 5183 } 5184 } 5185 5186 /* Write node JS files. 5187 */ 5188 if((nptr->s_jsfiles) && (nptr->i_jsfiles)) { 5189 dk3sto_it_reset(nptr->i_jsfiles); 5190 while(NULL != (linkptr = (hb_link_t *)dk3sto_it_next(nptr->i_jsfiles))) { 5191 if(linkptr->url) { 5192 fputs(hbhtml_c8_kw[121], job->of); 5193 if(!hbhtml_url_output_for_text(job, linkptr->url)) { back = 0; } 5194 fputs( 5195 hbhtml_c8_kw[ 5196 (HTML_DOCTYPE_5 == htdt) 5197 ? ( 5198 (0 != (LINK_FLAG_SCRIPT_ASYNC & (linkptr->flags))) 5199 ? (167) : (166) 5200 ) 5201 : ( 5202 (0 != (LINK_FLAG_SCRIPT_ASYNC & (linkptr->flags))) 5203 ? (168) : (122) 5204 ) 5205 ], 5206 job->of 5207 ); 5208 } 5209 } 5210 } 5211 5212 /* Write script code to fold and unfold page table of contents 5213 */ 5214 if (0 != (HB_NODE_OPT_PAGE_TOC & (nptr->options))) { 5215 if (0 != (HB_JOB_OPT_FOLD_PTOC & (job->options))) { 5216 if ((0 != ptocjs) && (NULL != job->ptocjsfile)) { 5217 job->ptocjsused = 1; 5218 /* 5219 script-tag 5220 */ 5221 fputs( 5222 hbhtml_c8_kw[(HTML_DOCTYPE_5 == htdt) ? (170) : (169)], 5223 job->of 5224 ); 5225 /* Script text 5226 */ 5227 if(!hbhtml_url_output_for_text(job, job->ptocjsfile)) { back = 0; } 5228 /* 5229 End script-tag 5230 */ 5231 fputs(hbhtml_c8_kw[166], job->of); 5232 } 5233 } 5234 } 5235 $? "- hbhtml_write_js_files" 5236 return back; 5237} 5238 5239 5240 5241/** Write one head navigation entry. 5242 @param job Job structure. 5243 @param nptr Node (may be NULL for impressum or privacy). 5244 @param url URL to use if nptr is NULL. 5245 @param titleind Title index if nptr is NULL. 5246 @param linkkwind Link keyword index. 5247 @param appendind Index for keyword index. 5248*/ 5249static 5250void 5251hbhtml_one_head_navigation( 5252 hb_job_t *job, 5253 hb_node_t *nptr, 5254 dkChar const *url, 5255 size_t titleind, 5256 size_t linkkwind, 5257 size_t appendind 5258) 5259{ 5260 dkChar bu[DK3_MAX_PATH]; /* Buffer for output file name */ 5261 hb_node_t *jnptr; /* Jump node */ 5262 5263 if(nptr) { 5264 jnptr = nptr; 5265 if(!(jnptr->filename)) { jnptr = jnptr->jumpnode; } 5266 if(hbhtml_create_output_filename(bu, DK3_SIZEOF(bu,dkChar), job, jnptr)) { 5267 fputs(hbhtml_c8_kw[123], job->of); 5268 fputs(hbhtml_c8_kw[linkkwind], job->of); 5269 fputs(hbhtml_c8_kw[124], job->of); 5270 if(!hbhtml_output_for_text(job, jnptr->title)) { job->exv = 1; } 5271 fputs(hbhtml_c8_kw[125], job->of); 5272 if(!hbhtml_url_output_for_text(job, bu)) { job->exv = 1; } 5273 if(appendind) { 5274 fputs(hbhtml_c8_kw[appendind], job->of); 5275 } 5276 fputs(hbhtml_c8_kw[126], job->of); 5277 } else { 5278 job->exv = 1; 5279 } 5280 } else { 5281 fputs(hbhtml_c8_kw[123], job->of); 5282 fputs(hbhtml_c8_kw[linkkwind], job->of); 5283 fputs(hbhtml_c8_kw[124], job->of); 5284 if(!hbhtml_output_for_text(job, (job->msg)[titleind])) { job->exv = 1; } 5285 fputs(hbhtml_c8_kw[125], job->of); 5286 if(!hbhtml_url_output_for_text(job, url)) { job->exv = 1; } 5287 if(appendind) { 5288 fputs(hbhtml_c8_kw[appendind], job->of); 5289 } 5290 fputs(hbhtml_c8_kw[126], job->of); 5291 } 5292} 5293 5294 5295 5296/** Write navigation entries to HTML header. 5297 @param job Job structure. 5298 @param node Current node to write. 5299 @param prev Previous node. 5300 @param next Next node. 5301*/ 5302static 5303void 5304hbhtml_write_head_navigation( 5305 hb_job_t *job, 5306 hb_node_t *node, 5307 hb_node_t *prev, 5308 hb_node_t *next 5309) 5310{ 5311 hb_node_t *nptr; /* Current node to process */ 5312 5313 /* Navigation (links) 5314 author (impressum), contents, index, top, up, first, prev, next, last 5315 link rel="..." title="..." href="..." 5316 */ 5317 if(job->impressumnode) { 5318 nptr = job->impressumnode; 5319 hbhtml_one_head_navigation(job, nptr, NULL, 0, 127, 0); 5320 } else { 5321 if(job->impressumlink) { 5322 hbhtml_one_head_navigation(job, NULL, job->impressumlink, 61, 127, 0); 5323 } 5324 } 5325 if(job->privacynode) { 5326 nptr = job->privacynode; 5327 hbhtml_one_head_navigation(job, nptr, NULL, 0, 127, 0); 5328 } else { 5329 if(job->privacylink) { 5330 hbhtml_one_head_navigation(job, NULL, job->privacylink, 104, 127, 0); 5331 } 5332 } 5333 if(job->rootnode) { 5334 hbhtml_one_head_navigation( 5335 job, job->rootnode, NULL, 0, 128, 5336 ( 5337 ( 5338 (0 != ((job->options) & HB_JOB_OPT_CREATE_TOC)) 5339 && (0 == ((job->options) & HB_JOB_OPT_CHM)) 5340 ) 5341 ? 136 : 0 5342 ) 5343 ); 5344 hbhtml_one_head_navigation( 5345 job, job->rootnode, NULL, 0, 129, 5346 ( 5347 ( 5348 (0 != ((job->options) & HB_JOB_OPT_CREATE_INDEX)) 5349 && (0 == ((job->options) & HB_JOB_OPT_CHM)) 5350 ) 5351 ? 137 : 0 5352 ) 5353 ); 5354 hbhtml_one_head_navigation(job, job->rootnode, NULL, 0, 130, 0); 5355 } 5356 nptr = node; 5357 nptr = nptr->parent; 5358 if(nptr) { 5359 while((!(nptr->filename)) && (nptr->parent)) { nptr = nptr->parent; } 5360 if(nptr) { 5361 hbhtml_one_head_navigation(job, nptr, NULL, 0, 131, 0); 5362 } 5363 } 5364 if(job->firstnode) { 5365 hbhtml_one_head_navigation(job, job->firstnode, NULL, 0, 132, 0); 5366 } 5367 if(prev) { 5368 hbhtml_one_head_navigation(job, prev, NULL, 0, 133, 0); 5369 } 5370 if(next) { 5371 hbhtml_one_head_navigation(job, next, NULL, 0, 134, 0); 5372 } 5373 if(job->lastnode) { 5374 hbhtml_one_head_navigation(job, job->lastnode, NULL, 0, 135, 0); 5375 } 5376} 5377 5378 5379 5380/** Write HTML header 5381 @param job Job structure. 5382 @param nodeptr Current node to write. 5383 @param prev Previous node. 5384 @param next Next node. 5385 @param htdt HTML doc type to use. 5386*/ 5387static 5388void 5389hbhtml_write_header( 5390 hb_job_t *job, hb_node_t *nodeptr, hb_node_t *prev, hb_node_t *next, int htdt 5391) 5392{ 5393 dkChar const *ptr; /* Multiple text elements */ 5394 $? "+ hbhtml_write_header" 5395 fputs(hbhtml_c8_kw[15], job->of); 5396 /* 5397 Meta charset, viewport 5398 */ 5399 if (HTML_DOCTYPE_5 == htdt) { 5400 if (HB_CS_UTF_8 == job->cs) { 5401 fputs(hbhtml_c8_kw[163], job->of); 5402 } 5403 fputs(hbhtml_c8_kw[164], job->of); 5404 } 5405 /* Title 5406 */ 5407 fputs(hbhtml_c8_kw[19], job->of); 5408#if 1 5409 if (((job->options) & HB_JOB_OPT_NUM_IN_PAGE_HEADER)) { 5410 if (!((job->options) & HB_JOB_OPT_CHM)) { 5411 if (NULL != job->currentnode) { 5412 if((job->currentnode)->depth < job->headlevels) { 5413 if(hbtool_write_header_number(job, job->currentnode)) { 5414 hbhtml_output_for_text(job, (job->kwnl[35])); 5415 } 5416 } 5417 } 5418 } 5419 } 5420#endif 5421 hbhtml_output_for_text(job, hbconf_title(nodeptr)); 5422 fputs(hbhtml_c8_kw[20], job->of); 5423 /* Generator (comment) 5424 */ 5425 if((nodeptr->options) & HB_NODE_OPT_USE_TIDY) { 5426 fputs(hbhtml_c8_kw[17], job->of); 5427 } 5428 /* Generator (meta) 5429 */ 5430 fputs(hbhtml_c8_kw[18], job->of); 5431 /* Style (link) 5432 */ 5433 ptr = hbconf_stylefile(nodeptr); 5434 if(ptr) { 5435 if(!hbtool_add_file(job, ptr)) { job->exv = 1; } 5436 fputs(hbhtml_c8_kw[(HTML_DOCTYPE_5 == htdt) ? (165) : (21)], job->of); 5437 hbhtml_url_output_for_text(job, ptr); 5438 fputs(hbhtml_c8_kw[22], job->of); 5439 } 5440 /* Shortcut icon (link) 5441 */ 5442 ptr = hbconf_favicon(nodeptr); 5443 if(ptr) { 5444 fputs(hbhtml_c8_kw[27], job->of); 5445 hbhtml_url_output_for_text(job, ptr); 5446 fputs(hbhtml_c8_kw[28], job->of); 5447 } 5448 /* Navigation (links) 5449 */ 5450 hbhtml_write_head_navigation(job, nodeptr, prev, next); 5451 /* Character set (meta) 5452 */ 5453 if (HTML_DOCTYPE_5 != htdt) { 5454 if(HB_CS_UTF_8 == job->cs) { 5455 fputs(hbhtml_c8_kw[24], job->of); 5456 } else { 5457 fputs(hbhtml_c8_kw[23], job->of); 5458 } 5459 } 5460 /* Author (meta) 5461 */ 5462 ptr = hbconf_author(nodeptr); 5463 if(ptr) { 5464 fputs(hbhtml_c8_kw[25], job->of); 5465 hbhtml_output_for_text(job, ptr); 5466 fputs(hbhtml_c8_kw[26], job->of); 5467 } 5468 /* Meta description tag 5469 */ 5470 if (NULL != nodeptr->metadesc) { 5471 fputs(hbhtml_c8_kw[154], job->of); 5472 hbhtml_output_for_text(job, nodeptr->metadesc); 5473 fputs(hbhtml_c8_kw[26], job->of); 5474 } 5475 /* Meta keywords tag. 5476 */ 5477 if (NULL != nodeptr->metakeyw) { 5478 fputs(hbhtml_c8_kw[155], job->of); 5479 hbhtml_output_for_text(job, nodeptr->metakeyw); 5480 fputs(hbhtml_c8_kw[26], job->of); 5481 } 5482 /* JavaScript files. 5483 */ 5484 (void)hbhtml_write_js_files(job, nodeptr, htdt, 1); 5485 /* 5486 End header tag 5487 */ 5488 fputs(hbhtml_c8_kw[16], job->of); $? "- hbhtml_write_header" 5489} 5490 5491 5492 5493/** Line handler processing function. 5494 @param obj Handler object. 5495 @param il Input line to process. 5496 @return 1 on success, 0 on error (continue), -1 on error (exit). 5497*/ 5498static 5499int 5500hbhtml_spcl_handler(void *obj, dkChar *il) 5501{ 5502 hb_spc_reader_t *pspcr; 5503 hb_job_t *job = NULL; 5504 hb_node_t *nptr = NULL; 5505 hb_link_t *linkptr= NULL; 5506 dkChar *vptr = NULL; 5507 dkChar *cptr = NULL; 5508 size_t sl = 0; 5509 int back = 1; 5510 int idx = 0; 5511 $? "+ hbhtml_spcl_handler \"%!ds\"", il 5512 pspcr = (hb_spc_reader_t *)obj; 5513 if (NULL != pspcr) { 5514 job = pspcr->job; 5515 nptr = pspcr->nodeptr; 5516 pspcr->lineno += 1UL; 5517 dk3app_set_source_line(job->app, pspcr->lineno); 5518 idx = hbcont_metadata_index(il); 5519 if (0 <= idx) { 5520 $? ". meta data found" 5521 dk3str_delnl(il); 5522 sl = hbcont_metadata_length((size_t)idx); 5523 if (0 < sl) { 5524 sl++; 5525 vptr = dk3str_start(&(il[sl]), NULL); 5526 $? ". value \"%!ds\"", vptr 5527 } 5528 switch (idx) { 5529 case 0: { $? ". description" 5530 if (NULL != vptr) { 5531 $? ". value ok" 5532 cptr = dk3str_dup_app(vptr, job->app); 5533 if (NULL != cptr) { 5534 $? ". allocation ok" 5535 if (NULL != nptr->metadesc) { 5536 /* Warning: Overwriting description text */ 5537 dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 97); 5538 dk3mem_free(nptr->metadesc); 5539 } 5540 nptr->metadesc = cptr; 5541 } 5542 } else { 5543 /* ERROR: Missing description text */ 5544 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 96); 5545 back = -1; 5546 } 5547 } break; 5548 case 1: { $? ". keywords" 5549 if (NULL != vptr) { 5550 $? ". value ok" 5551 cptr = dk3str_dup_app(vptr, job->app); 5552 if (NULL != cptr) { 5553 $? ". allocation ok" 5554 if (NULL != nptr->metakeyw) { 5555 /* Warning: Overwriting keywords */ 5556 dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 98); 5557 dk3mem_free(nptr->metakeyw); 5558 } 5559 nptr->metakeyw = cptr; 5560 } 5561 } else { 5562 /* ERROR: Missing keywords text */ 5563 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 96); 5564 back = -1; 5565 } 5566 } break; 5567 case 2: { $? ". author" 5568 if (NULL != vptr) { 5569 cptr = dk3str_dup_app(vptr, job->app); 5570 if (NULL != cptr) { 5571 if (NULL != nptr->author) { 5572 if (0UL != nptr->objno) { 5573 dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 69); 5574 } 5575 dk3mem_free(nptr->author); 5576 } 5577 nptr->author = cptr; 5578 } else { 5579 back = -1; 5580 } 5581 } else { 5582 /* ERROR: Missing author name */ 5583 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 96); 5584 back = -1; 5585 } 5586 } break; 5587 case 3: { $? ". title" 5588 if (NULL != vptr) { 5589 cptr = dk3str_dup_app(vptr, job->app); 5590 if (NULL != cptr) { 5591 if (NULL != nptr->fulltitle) { 5592 /* Warning: Overwriting title */ 5593 dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 70); 5594 dk3mem_free(nptr->fulltitle); 5595 } 5596 nptr->fulltitle = cptr; 5597 } else { 5598 back = -1; 5599 } 5600 } else { 5601 /* ERROR: Missing title text */ 5602 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 96); 5603 back = -1; 5604 } 5605 } break; 5606 case 4: { $? ". short title" 5607 if (NULL != vptr) { 5608 cptr = dk3str_dup_app(vptr, job->app); 5609 if (NULL != cptr) { 5610 if (NULL != nptr->shorttitle) { 5611 /* Warning: Overwriting short title */ 5612 dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 75); 5613 dk3mem_free(nptr->shorttitle); 5614 } 5615 nptr->shorttitle = cptr; 5616 } else { 5617 back = -1; 5618 } 5619 } else { 5620 /* ERROR: Missing short title text */ 5621 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 96); 5622 back = -1; 5623 } 5624 } break; 5625 case 5: { $? ". location" 5626 if (NULL != vptr) { 5627 cptr = dk3str_dup_app(vptr, job->app); 5628 if (NULL != cptr) { 5629 if (NULL != nptr->location) { 5630 /* Warning: Overwriting location */ 5631 dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 99); 5632 dk3mem_free(nptr->location); 5633 } 5634 nptr->location = cptr; 5635 } else { 5636 back = -1; 5637 } 5638 } else { 5639 /* ERROR: Missing location text */ 5640 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 96); 5641 back = -1; 5642 } 5643 } break; 5644 case 6: { $? ". page-toc" 5645 if (NULL != vptr) { 5646 if (0 != dk3str_is_bool(vptr)) { 5647 if (0 != dk3str_is_on(vptr)) { 5648 (job->currentnode)->options |= HB_NODE_OPT_PAGE_TOC; 5649 } else { 5650 (job->currentnode)->options &= (~(HB_NODE_OPT_PAGE_TOC)); 5651 } 5652 } else { 5653 dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 144, vptr); 5654 back = -1; 5655 } 5656 } else { 5657 (job->currentnode)->options |= HB_NODE_OPT_PAGE_TOC; 5658 } 5659 } break; 5660 case 7: { $? ". replace-ampersand" 5661 if (NULL != vptr) { 5662 if (0 != dk3str_is_bool(vptr)) { 5663 if (0 != dk3str_is_on(vptr)) { 5664 (job->currentnode)->options |= HB_NODE_OPT_REPLACE_AMPERSAND; 5665 } else { 5666 (job->currentnode)->options &= 5667 (~(HB_NODE_OPT_REPLACE_AMPERSAND)); 5668 } 5669 } else { 5670 dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 144, vptr); 5671 back = -1; 5672 } 5673 } else { 5674 (job->currentnode)->options |= HB_NODE_OPT_REPLACE_AMPERSAND; 5675 } 5676 } break; 5677 case 8: { $? ". write-position" 5678 if (NULL != vptr) { 5679 if (0 != dk3str_is_bool(vptr)) { 5680 if (0 != dk3str_is_on(vptr)) { 5681 (job->currentnode)->options |= HB_NODE_OPT_HEADER_CHAIN; 5682 } else { 5683 (job->currentnode)->options &= (~(HB_NODE_OPT_HEADER_CHAIN)); 5684 } 5685 } else { 5686 dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 144, vptr); 5687 back = -1; 5688 } 5689 } else { 5690 (job->currentnode)->options |= HB_NODE_OPT_HEADER_CHAIN; 5691 } 5692 } break; 5693 case 9: { $? ". suffix" 5694 if (NULL != vptr) { 5695 cptr = dk3str_dup_app(vptr, job->app); 5696 if (NULL != cptr) { 5697 if (NULL != nptr->suffix) { 5698 /* Warning: Overwriting suffix */ 5699 dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 77); 5700 dk3mem_free(nptr->suffix); 5701 } 5702 nptr->suffix = cptr; 5703 } else { 5704 back = -1; 5705 } 5706 } else { 5707 /* ERROR: Missing suffix */ 5708 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 96); 5709 back = -1; 5710 } 5711 } break; 5712 case 10: { $? ". shortcut-icon" 5713 if (NULL != vptr) { 5714 cptr = dk3str_dup_app(vptr, job->app); 5715 if (NULL != cptr) { 5716 dk3str_correct_filename(cptr); 5717 hbtool_correct_backslash_to_slash(cptr); 5718 if (NULL != nptr->favicon) { 5719 /* Warning: Overwriting favicon */ 5720 dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 82); 5721 dk3mem_free(nptr->favicon); 5722 } 5723 nptr->favicon = cptr; 5724 if (!(hbtool_add_file(job, cptr))) { 5725 back = -1; 5726 } 5727 if(!hbtool_check_filename_encoding(job, cptr)) { back = -1; } 5728 } else { 5729 back = -1; 5730 } 5731 } else { 5732 /* ERROR: Missing icon name */ 5733 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 96); 5734 back = -1; 5735 } 5736 } break; 5737 case 11: { $? ". js-file" 5738 if (NULL != vptr) { 5739 if (NULL == nptr->s_jsfiles) { 5740 nptr->s_jsfiles = dk3sto_open_app(job->app); 5741 if (NULL != nptr->s_jsfiles) { 5742 dk3sto_set_comp(nptr->s_jsfiles, hbnode_link_compare, 2); 5743 } 5744 } 5745 if (NULL == nptr->i_jsfiles) { 5746 if (NULL != nptr->s_jsfiles) { 5747 nptr->i_jsfiles = dk3sto_it_open(nptr->s_jsfiles); 5748 } 5749 } 5750 if ((NULL != nptr->s_jsfiles) && (NULL != nptr->i_jsfiles)) { 5751 linkptr = hbnode_link_new(vptr, nptr->nextjs, job->app); 5752 if (NULL != linkptr) { 5753 if(dk3sto_add(nptr->s_jsfiles, linkptr)) { 5754 nptr->nextjs += 1UL; 5755 if(!hbtool_add_url(job, vptr)) { back = -1; } 5756 } else { 5757 hbnode_link_delete(linkptr); 5758 back = -1; 5759 } 5760 } else { 5761 back = -1; 5762 } 5763 } else { 5764 back = -1; 5765 } 5766 } else { 5767 /* ERROR: Missing file name */ 5768 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 96); 5769 back = -1; 5770 } 5771 } break; 5772 case 12: { $? ". inherit-js" 5773 if (NULL != vptr) { 5774 if (0 != dk3str_is_bool(vptr)) { 5775 if (0 != dk3str_is_on(vptr)) { 5776 (job->currentnode)->options &= 5777 (~(HB_NODE_OPT_STOP_JS_INHERITANCE)); 5778 } else { 5779 (job->currentnode)->options |= HB_NODE_OPT_STOP_JS_INHERITANCE; 5780 } 5781 } else { 5782 dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 144, vptr); 5783 back = -1; 5784 } 5785 } else { 5786 (job->currentnode)->options &= (~(HB_NODE_OPT_STOP_JS_INHERITANCE)); 5787 } 5788 } break; 5789 case 13: { $? ". context-number" 5790 long cn; 5791 if (NULL != vptr) { 5792 if (0 != dk3ma_l_from_string(&cn, vptr, NULL)) { 5793 nptr->contnum = cn; 5794 } else { 5795 dk3app_log_i1(job->app, DK3_LL_ERROR, 141); 5796 back = -1; 5797 } 5798 } else { 5799 /* ERROR: Missing number */ 5800 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 96); 5801 back = -1; 5802 } 5803 } break; 5804 } 5805 } 5806 } 5807 $? "- hbhtml_spcl_handler %d", back 5808 return back; 5809} 5810 5811 5812 5813/** Read special comments from input file for node. 5814 @param job Job structure. 5815 @param nodeptr Node to read file for. 5816*/ 5817static 5818void 5819hbhtml_read_special_comments(hb_job_t *job, hb_node_t *nodeptr) 5820{ 5821 hb_spc_reader_t spcr; 5822 const dkChar *oldsourcefile; 5823 unsigned long oldsourceline; 5824 int inenc; 5825 $? "+ hbhtml_read_special_comments" 5826 if (NULL != nodeptr->filename) { $? ". have file name" 5827 spcr.job = job; 5828 spcr.nodeptr = nodeptr; 5829 spcr.lineno = 0UL; 5830 inenc = dk3app_get_input_file_encoding(job->app); 5831 if(0 <= job->iecmd) { inenc = job->iecmd; } 5832 if(0 <= nodeptr->inenc) { inenc = nodeptr->inenc; } 5833 oldsourcefile = dk3app_get_source_file(job->app); 5834 oldsourceline = dk3app_get_source_line(job->app); 5835 dk3app_set_source_file(job->app, nodeptr->filename); 5836 dk3app_set_source_line(job->app, 0UL); 5837 (void)dk3stream_process_filename_lines_app( 5838 (void *)(&spcr), hbhtml_spcl_handler, nodeptr->filename, 5839 job->ilfile, job->bs, 5840 dk3app_get_encoding(job->app), 5841 inenc, 5842 job->app 5843 ); 5844 dk3app_set_source_file(job->app, oldsourcefile); 5845 dk3app_set_source_line(job->app, oldsourceline); 5846 } 5847 $? "- hbhtml_read_special_comments" 5848} 5849 5850 5851 5852int 5853hbhtml_get_doctype( 5854 hb_job_t *job, 5855 hb_node_t *nodeptr 5856) 5857{ 5858 int back = HTML_DOCTYPE_UNSPECIFIED; 5859 while ((HTML_DOCTYPE_UNSPECIFIED == back) && (NULL != nodeptr)) { 5860 back = nodeptr->htdt; 5861 nodeptr = nodeptr->parent; 5862 } 5863 if ((HTML_DOCTYPE_UNSPECIFIED == back) && (NULL != job)) { 5864 back = job->htdt; 5865 } 5866 if (HTML_DOCTYPE_UNSPECIFIED == back) { 5867 back = HTML_DOCTYPE_5; 5868 } 5869 return back; 5870} 5871 5872 5873 5874/** Write one output file. 5875 @param job Job structure. 5876 @param nodeptr Current node to write. 5877 @param fn Output file name. 5878 @param p Previous node. 5879 @param n Next node. 5880*/ 5881static 5882void 5883hbhtml_write_named_file( 5884 hb_job_t *job, 5885 hb_node_t *nodeptr, 5886 dkChar const *fn, 5887 hb_node_t *p, 5888 hb_node_t *n 5889) 5890{ 5891 hb_file_processor_t proc; /* Template file processor */ 5892 dkChar const *templateName; /* Template file name */ 5893 dkChar const *oldsourcefile; /* Old source file name */ 5894 dkChar const *htlang; /* HTML language */ 5895 unsigned long oldsourceline; /* Old source file line */ 5896 int inenc; /* Input encoding */ 5897 int res; /* Result from file processing */ 5898 int htdt; /* HTML doctype */ 5899 $? "+ hbhtml_write_named_file" 5900 $? ". input file \"%!ds\"", TR_STR(nodeptr->filename) 5901 $? ". output file \"%!ds\"", fn 5902 oldsourcefile = dk3app_get_source_file(job->app); 5903 oldsourceline = dk3app_get_source_line(job->app); 5904 dk3app_set_source_line(job->app, nodeptr->lineno); 5905 nodeptr->outFileName = fn; 5906 job->currentnode = nodeptr; 5907 job->of = NULL; 5908 templateName = hbconf_node_template(nodeptr); 5909 if(templateName) { 5910 dk3app_set_source_file(job->app, templateName); 5911 job->options &= (~(HB_JOB_OPT_CODE)); 5912 job->of = dk3sf_fopen_app(fn, dkT("w"), job->app); 5913 if(job->of) { 5914 hbhtml_read_special_comments(job, nodeptr); 5915 htdt = hbhtml_get_doctype(job, nodeptr); 5916 if (HTML_DOCTYPE_NONE < htdt) { 5917 fputs(hbhtml_doctypes[htdt-1], job->of); 5918 } 5919 if (HTML_DOCTYPE_5 == htdt) { 5920 htlang = job->htmllang; 5921 if (NULL == htlang) { 5922 htlang = dk3app_get_language(job->app); 5923 } 5924 if (NULL != htlang) { 5925 fputs(hbhtml_c8_kw[161], job->of); 5926 /* 5927 We assume the language is specified correctly 5928 using characters from the ASCII set only. 5929 */ 5930 while (dkT('\0') != *htlang) { fputc((char)(*(htlang++)), job->of); } 5931 fputs(hbhtml_c8_kw[162], job->of); 5932 } 5933 else { 5934 fputs(hbhtml_c8_kw[11], job->of); 5935 } 5936 } 5937 else { 5938 fputs(hbhtml_c8_kw[11], job->of); 5939 } 5940 hbhtml_write_header(job, nodeptr, p, n, htdt); 5941 if (0 != (HB_JOB_OPT_CHM & (job->options))) { 5942 fputs(hbhtml_c8_kw[160], job->of); 5943 } else { 5944 fputs(hbhtml_c8_kw[13], job->of); 5945 } 5946 proc.job = job; 5947 proc.in_template = 1; 5948 proc.stm = 0; 5949 proc.p = p; 5950 proc.n = n; 5951 inenc = dk3app_get_input_file_encoding(job->app); 5952 if(0 <= job->iecmd) { inenc = job->iecmd; } 5953 res = dk3stream_process_filename_lines_app( 5954 (void *)(&proc), hbhtml_line_handler, templateName, 5955 job->iltemplate, job->bs, 5956 dk3app_get_encoding(job->app), 5957 inenc, 5958 job->app 5959 ); 5960 fputs(hbhtml_c8_kw[14], job->of); 5961 fputs(hbhtml_c8_kw[12], job->of); 5962 if(1 != res) { 5963 job->exv = 1; $? "! ERROR" 5964 } 5965 if(!(dk3sf_fclose_fn_app(job->of, fn, job->app))) { 5966 job->exv = 1; $? "! ERROR" 5967 } 5968 } else { 5969 job->exv = 1; $? "! ERROR" 5970 } 5971 } else { 5972 /* ERROR: No template! */ 5973 dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 19); 5974 job->exv = 1; $? "! ERROR" 5975 } 5976 nodeptr->outFileName = NULL; 5977 dk3app_set_source_file(job->app, oldsourcefile); 5978 dk3app_set_source_line(job->app, oldsourceline); 5979 $? "- hbhtml_write_named_file" 5980} 5981 5982 5983 5984/** Mark path to current node in parent nodes 5985 (set the curchild element). 5986 @param nodeptr Current node. 5987*/ 5988static 5989void 5990hbhtml_mark_path(hb_node_t *nodeptr) 5991{ 5992 hb_node_t *cp; /* Current node */ 5993 $? "+ hbhtml_mark_path" 5994 cp = nodeptr; 5995 cp->curchild = NULL; 5996 while(cp) { 5997 if(cp->parent) { (cp->parent)->curchild = cp; } 5998 cp = cp->parent; 5999 } $? "- hbhtml_mark_path" 6000} 6001 6002 6003 6004void 6005hbhtml_write_file(hb_job_t *job, hb_node_t *nodeptr, hb_node_t *p, hb_node_t *n) 6006{ 6007 dkChar bu[DK3_MAX_PATH]; /* File name buffer. */ 6008 $? "+ hbhtml_write_file %lu \"%!ds\"", nodeptr->objno, TR_STR(nodeptr->title) 6009 6010 /* Set things up for new file. 6011 */ 6012 job->coli = 0; 6013 job->cols = HB_COLIST_NONE; 6014 job->options &= (~(HB_JOB_OPT_CODE)); 6015 6016 /* Process the file. 6017 */ 6018 hbhtml_mark_path(nodeptr); 6019 if(hbhtml_create_output_filename(bu, DK3_SIZEOF(bu,dkChar), job, nodeptr)) { 6020 $? ". have output file name" 6021 hbhtml_write_named_file(job, nodeptr, bu, p, n); 6022 } else { 6023 job->exv = 1; $? "! ERROR" 6024 } 6025 6026 $? "- hbhtml_write_file" 6027} 6028 6029 6030