%% options copyright owner = Dirk Krause copyright year = 2013-xxxx license = bsd %% header #ifdef __cplusplus extern "C" { #endif /** Write one HTML file. @param job Job structure. @param nodeptr Node for file to write. @param p Previous node. @param n Next node. */ void hbhtml_write_file(hb_job_t *job,hb_node_t *nodeptr,hb_node_t *p,hb_node_t *n); /** Write one 32-bit character to HTML output. @param job Job structure. @param c32 Character to write. */ void hbhtml_c32(hb_job_t *job, dk3_c32_t c32); /** Write some text as HTML. @param job Job structure. @param text Text to write. @return 1 on success, 0 on error. */ int hbhtml_output_for_text(hb_job_t *job, dkChar const *text); /** Write some URL text as HTML. @param job Job structure. @param text Text to write. @return 1 on success, 0 on error. */ int hbhtml_url_output_for_text(hb_job_t *job, dkChar const *text); /** Handle one input line, either from template or from text file. @param obj Line processor structure. @param il Input line to process. @return 1 on success, 0 on error (continue), -1 on error (exit). */ int hbhtml_line_handler(void *obj, dkChar *il); /** Construct output file name. @param dptr Destination buffer pointer. @param sz Destination buffer size. @param job Job structure. @param nptr Node to process. @return 1 on success, 0 on error. */ int hbhtml_create_output_filename( dkChar *dptr, size_t sz, hb_job_t *job, hb_node_t *nptr ); /** Check whether a link is an external link (http:// or ftp:// at start). @param link Link to check. @return 1 for external links, 0 for internal links. */ int hbhtml_check_link_for_external(dkChar const *link); #ifdef __cplusplus } #endif %% state machine [options] name = hbhtml_stm1 write header = no [states] STM1_ST_START # Start state STM1_ST_ERROR # Error occured STM1_ST_BS # Backslash found STM1_ST_PERCENT # One percent sign found STM1_ST_SPECIAL # Recording a special STM1_ST_SPEC_BS # Backslash found in special STM1_ST_SPEC_PC # Percent found in special [inputs] STM1_I_ANY # Any character STM1_I_BS # Backslash STM1_I_PERCENT # Percent sign [outputs] STM1_O_ERROR # Error, do nothing STM1_O_NOTHING # Do nothing STM1_O_SHIPOUT # Add character to shipout buffer STM1_O_BS_SHIPOUT # Shipout character after backslash STM1_O_PERCENT_SHIPOUT # Shipout percent sign and current character STM1_O_PERCENT # Shipout just percent sign STM1_O_SWITCH # Flush shipout and switch to saving special STM1_O_SPECIAL # Add current character to special STM1_O_SPEC_BS # Add char after backslash to special STM1_O_SPEC_PC_ADD # Add percent and current char to special STM1_O_SPEC_PC # Add percent sign to special STM1_O_EXECUTE # Execute special [rules] * * STM1_ST_ERROR STM1_O_ERROR STM1_ST_START * STM1_ST_START STM1_O_SHIPOUT STM1_ST_START STM1_I_BS STM1_ST_BS STM1_O_NOTHING STM1_ST_START STM1_I_PERCENT STM1_ST_PERCENT STM1_O_NOTHING STM1_ST_BS * STM1_ST_START STM1_O_BS_SHIPOUT STM1_ST_PERCENT * STM1_ST_START STM1_O_PERCENT_SHIPOUT STM1_ST_PERCENT STM1_I_BS STM1_ST_BS STM1_O_PERCENT STM1_ST_PERCENT STM1_I_PERCENT STM1_ST_SPECIAL STM1_O_SWITCH STM1_ST_SPECIAL * STM1_ST_SPECIAL STM1_O_SPECIAL STM1_ST_SPECIAL STM1_I_BS STM1_ST_SPEC_BS STM1_O_NOTHING STM1_ST_SPECIAL STM1_I_PERCENT STM1_ST_SPEC_PC STM1_O_NOTHING STM1_ST_SPEC_BS * STM1_ST_SPECIAL STM1_O_SPEC_BS STM1_ST_SPEC_PC * STM1_ST_SPECIAL STM1_O_SPEC_PC_ADD STM1_ST_SPEC_PC STM1_I_BS STM1_ST_SPEC_BS STM1_O_SPEC_PC STM1_ST_SPEC_PC STM1_I_PERCENT STM1_ST_START STM1_O_EXECUTE %% state machine [options] name = hbhtml_stm3 write header = no [states] STM3_ST_START # No character processed yet STM3_ST_NAME # ASCII characters (for protocol name) found STM3_ST_COLON # Colon found STM3_ST_COLSL # Colon and slash STM3_ST_SUCCESS # Colon and two slashes found STM3_ST_ERROR # Not a protocol at start of text [inputs] STM3_I_ANY # Anything not listed below STM3_I_ASCII # a-zA-Z01-9_ STM3_I_COLON # Colon STM3_I_SLASH # Slash [outputs] STM3_O_OK # OK so far STM3_O_ERROR # ERROR found [rules] * * STM3_ST_ERROR STM3_O_ERROR STM3_ST_START STM3_I_ASCII STM3_ST_NAME STM3_O_OK STM3_ST_NAME STM3_I_ASCII STM3_ST_NAME STM3_O_OK STM3_ST_NAME STM3_I_COLON STM3_ST_COLON STM3_O_OK STM3_ST_COLON STM3_I_SLASH STM3_ST_COLSL STM3_O_OK STM3_ST_COLSL STM3_I_SLASH STM3_ST_SUCCESS STM3_O_OK STM3_ST_SUCCESS * STM3_ST_SUCCESS STM3_O_OK %% module #include "dk3all.h" #include "dk3strkv.h" #include "htmlbook.h" $!trace-include /** Object for line reader (special comments). */ typedef struct { hb_job_t *job; /**< Job structure. */ hb_node_t *nodeptr; /**< Current node to process. */ unsigned long lineno; /**< Current line number to process. */ } hb_spc_reader_t; /** Translation table for ASCII characters. */ static char const * const hbhtml_translation_table[] = { /* 0 00 */ NULL, /* 1 01 */ NULL, /* 2 02 */ NULL, /* 3 03 */ NULL, /* 4 04 */ NULL, /* 5 05 */ NULL, /* 6 06 */ NULL, /* 7 07 */ NULL, /* 8 08 */ NULL, /* 9 09 */ "\t", /* 10 0a */ NULL, /* 11 0b */ NULL, /* 12 0c */ NULL, /* 13 0d */ NULL, /* 14 0e */ NULL, /* 15 0f */ NULL, /* 16 10 */ NULL, /* 17 11 */ NULL, /* 18 12 */ NULL, /* 19 13 */ NULL, /* 20 14 */ NULL, /* 21 15 */ NULL, /* 22 16 */ NULL, /* 23 17 */ NULL, /* 24 18 */ NULL, /* 25 19 */ NULL, /* 26 1a */ NULL, /* 27 1b */ NULL, /* 28 1c */ NULL, /* 29 1d */ NULL, /* 30 1e */ NULL, /* 31 1f */ NULL, /* 32 20 */ " ", /* 33 21 */ "!", /* 34 22 */ """, /* 35 23 */ "#", /* 36 24 */ "$", /* 37 25 */ "%", /* 38 26 */ "&", /* 39 27 */ "'", /* 40 28 */ "(", /* 41 29 */ ")", /* 42 2a */ "*", /* 43 2b */ "+", /* 44 2c */ ",", /* 45 2d */ "-", /* 46 2e */ ".", /* 47 2f */ "/", /* 48 30 */ "0", /* 49 31 */ "1", /* 50 32 */ "2", /* 51 33 */ "3", /* 52 34 */ "4", /* 53 35 */ "5", /* 54 36 */ "6", /* 55 37 */ "7", /* 56 38 */ "8", /* 57 39 */ "9", /* 58 3a */ ":", /* 59 3b */ ";", /* 60 3c */ "<", /* 61 3d */ "=", /* 62 3e */ ">", /* 63 3f */ "?", /* 64 40 */ "@", /* 65 41 */ "A", /* 66 42 */ "B", /* 67 43 */ "C", /* 68 44 */ "D", /* 69 45 */ "E", /* 70 46 */ "F", /* 71 47 */ "G", /* 72 48 */ "H", /* 73 49 */ "I", /* 74 4a */ "J", /* 75 4b */ "K", /* 76 4c */ "L", /* 77 4d */ "M", /* 78 4e */ "N", /* 79 4f */ "O", /* 80 50 */ "P", /* 81 51 */ "Q", /* 82 52 */ "R", /* 83 53 */ "S", /* 84 54 */ "T", /* 85 55 */ "U", /* 86 56 */ "V", /* 87 57 */ "W", /* 88 58 */ "X", /* 89 59 */ "Y", /* 90 5a */ "Z", /* 91 5b */ "[", /* 92 5c */ "\\", /* 93 5d */ "]", /* 94 5e */ "^", /* 95 5f */ "_", /* 96 60 */ "`", /* 97 61 */ "a", /* 98 62 */ "b", /* 99 63 */ "c", /* 100 64 */ "d", /* 101 65 */ "e", /* 102 66 */ "f", /* 103 67 */ "g", /* 104 68 */ "h", /* 105 69 */ "i", /* 106 6a */ "j", /* 107 6b */ "k", /* 108 6c */ "l", /* 109 6d */ "m", /* 110 6e */ "n", /* 111 6f */ "o", /* 112 70 */ "p", /* 113 71 */ "q", /* 114 72 */ "r", /* 115 73 */ "s", /* 116 74 */ "t", /* 117 75 */ "u", /* 118 76 */ "v", /* 119 77 */ "w", /* 120 78 */ "x", /* 121 79 */ "y", /* 122 7a */ "z", /* 123 7b */ "{", /* 124 7c */ "|", /* 125 7d */ "}", /* 126 7e */ "~", /* 127 7f */ NULL, /* 128 80 */ NULL, /* 129 81 */ NULL, /* 130 82 */ NULL, /* 131 83 */ NULL, /* 132 84 */ NULL, /* 133 85 */ NULL, /* 134 86 */ NULL, /* 135 87 */ NULL, /* 136 88 */ NULL, /* 137 89 */ NULL, /* 138 8a */ NULL, /* 139 8b */ NULL, /* 140 8c */ NULL, /* 141 8d */ NULL, /* 142 8e */ NULL, /* 143 8f */ NULL, /* 144 90 */ NULL, /* 145 91 */ NULL, /* 146 92 */ NULL, /* 147 93 */ NULL, /* 148 94 */ NULL, /* 149 95 */ NULL, /* 150 96 */ NULL, /* 151 97 */ NULL, /* 152 98 */ NULL, /* 153 99 */ NULL, /* 154 9a */ NULL, /* 155 9b */ NULL, /* 156 9c */ NULL, /* 157 9d */ NULL, /* 158 9e */ NULL, /* 159 9f */ NULL, /* 160 a0 */ " ", /* 161 a1 */ "¡", /* 162 a2 */ "¢", /* 163 a3 */ "£", /* 164 a4 */ "¤", /* 165 a5 */ "¥", /* 166 a6 */ "¦", /* 167 a7 */ "§", /* 168 a8 */ "¨", /* 169 a9 */ "©", /* 170 aa */ "ª", /* 171 ab */ "«", /* 172 ac */ "¬", /* 173 ad */ "­", /* 174 ae */ "®", /* 175 af */ "¯", /* 176 b0 */ "°", /* 177 b1 */ "±", /* 178 b2 */ "²", /* 179 b3 */ "³", /* 180 b4 */ "´", /* 181 b5 */ "µ", /* 182 b6 */ "¶", /* 183 b7 */ "·", /* 184 b8 */ "¸", /* 185 b9 */ "¹", /* 186 ba */ "º", /* 187 bb */ "»", /* 188 bc */ "¼", /* 189 bd */ "½", /* 190 be */ "¾", /* 191 bf */ "¿", /* 192 c0 */ "À", /* 193 c1 */ "Á", /* 194 c2 */ "Â", /* 195 c3 */ "Ã", /* 196 c4 */ "Ä", /* 197 c5 */ "Å", /* 198 c6 */ "Æ", /* 199 c7 */ "Ç", /* 200 c8 */ "È", /* 201 c9 */ "É", /* 202 ca */ "Ê", /* 203 cb */ "Ë", /* 204 cc */ "/Igrave;", /* 205 cd */ "Í", /* 206 ce */ "Î", /* 207 cf */ "Ï", /* 208 d0 */ "Ð", /* 209 d1 */ "Ñ", /* 210 d2 */ "Ò", /* 211 d3 */ "Ó", /* 212 d4 */ "Ô", /* 213 d5 */ "Õ", /* 214 d6 */ "Ö", /* 215 d7 */ "×", /* 216 d8 */ "Ø", /* 217 d9 */ "Ù", /* 218 da */ "Ú", /* 219 db */ "Û", /* 220 dc */ "Ü", /* 221 dd */ "Ý", /* 222 de */ "Þ", /* 223 df */ "ß", /* 224 e0 */ "à", /* 225 e1 */ "á", /* 226 e2 */ "â", /* 227 e3 */ "ã", /* 228 e4 */ "ä", /* 229 e5 */ "å", /* 230 e6 */ "æ", /* 231 e7 */ "ç", /* 232 e8 */ "è", /* 233 e9 */ "é", /* 234 ea */ "ê", /* 235 eb */ "ë", /* 236 ec */ "ì", /* 237 ed */ "í", /* 238 ee */ "î", /* 239 ef */ "ï", /* 240 f0 */ "ð", /* 241 f1 */ "ñ", /* 242 f2 */ "ò", /* 243 f3 */ "ó", /* 244 f4 */ "ô", /* 245 f5 */ "õ", /* 246 f6 */ "ö", /* 247 f7 */ "÷", /* 248 f8 */ "ø", /* 249 f9 */ "ù", /* 250 fa */ "ú", /* 251 fb */ "û", /* 252 fc */ "ü", /* 253 fd */ "ý", /* 254 fe */ "þ", /* 255 ff */ "ÿ" }; /** Constant 8-bit character keywords. */ static char const * const hbhtml_c8_kw[] = { $!string-table # # 0 Newline # \n # # 1 Space # # # 2 Start of an image # # # 4 Image source # src=" # # 5 End of attribute # " # # 6 alt attribute # alt=" # # 7 title attribute # title=" # # 8 border attribute # border=" # # 9 width attribute # width=" # # 10 height attribute # height=" # # 11 12 HTML tag # \n \n # # 13 14 BODY tag # \n \n # # 15 16 HEAD tag # \n \n # # 17 18 Generated by # \n \n # # 19 20 TITLE tag # \n # # 21 22 Style sheet # \n # # 23 24 Charset specifications # \n \n # # 25 26 Author # \n # # 27 28 Shortcut icon # \n # # 29 30 Navi menu div #
\n
\n # # 31 32 Navi menu ul # \n # # 33 Navi menu separator #
  •  
  • \n # # 34 35 Navi menu current node entry #
  • \n # # 36 37 Navi menu current entry #
  • \n # # 38 Class name for navigation link # hb_nm_a # # 39 40 41 42 43 44 45 Link # \n # # 48 Space between navigation images #   # # 49 50 51 52 Navigation link # # # 53 54 55 56 Image in navigation link # 
 〈%lu〉 # # 92 93 94 95 96 97 98 99 Menu entry table. # \n \n \n \n \n # # 100 101 Link classes # hb_a_i hb_a_e # # 102 103 104 105 #
    \n \n
    \n
    \n

    \n
    \n

    \n # # 114 115 # \n # # 118 119 # type="image/svg+xml" type="application/pdf" # # 120 #


    \n # # 121 122 # \n # # 123 124 125 126 # \n # # 127 ... 135 # author contents index top up first prev next last # # 136 137 # \#hb_toc \#hb_index # # 138 139 140 141 142 143 #
     → 
    \n \n
    \n  \n ">\n # # 144 # hb_nm_a_parent # # 145 #
    \n # # 146 147 148 149 150 # # # 151 152 153 # # # 154 # c32) { c = (char)c32; c &= 0x7F; if(('a' <= c) && ('z' >= c)) { back = 0; } else { if(('A' <= c) && ('Z' >= c)) { back = 0; } else { if(('0' <= c) && ('9' >= c)) { back = 0; } else { switch(c) { case '-': case '_': case '.': case '~': { back = 0; } break; } } } } } return back; } #endif /** Check whether a character must be written hex-encoded to an URL. See RFC 3986 for reserved and unreserved characters. @param c32 Character to check. @return 1 for hex-encoding, 0 for direct use. */ static int hbhtml_url_must_encode(dk3_c32_t c32) { int back = 0; $? "+ hbhtml_url_must_encode %lx %lu", (unsigned long)c32, (unsigned long)c32 if((dk3_c32_t)126 < c32) { back = 1; } else { if((dk3_c32_t)33 > c32) { back = 1; } } $? "- hbhtml_url_must_encode %d", back return back; } /** Write one character in URL encoding, complain on problems. Unusable characters (not in octect range 0...0xFF) are UTF-8 encoded first and hex-converted for the URL. Some ASCII characters have special meaning in URL encoding (i.e. ampersand, question mark...). We assume the user intended to use these characters and specified the URL so we can use it "as is". @param job Job structure. @param c32 Character to print. */ static void hbhtml_url_c32(hb_job_t *job, dk3_c32_t c32) { char buf[16]; /* Buffer for hexadecimal notation */ unsigned char ub[16]; /* Buffer for UTF-8 notation */ size_t sz; /* Number of bytes used in ub */ size_t i; /* Traverse ub */ $? "+ hbhtml_url_c32 0x%lx = %lu", (unsigned long)c32, (unsigned long)c32 if(hbhtml_url_useable(c32)) { if(hbhtml_url_must_encode(c32)) { buf[0] = '%'; sprintf(&(buf[1]), "%02X", (unsigned)c32); fputs(buf, job->of); } else { fputc((((char)c32) & ((char)0x7F)), job->of); } } else { job->non_url = 1; sz = dk3enc_uc2utf8(c32, ub, sizeof(ub)); for(i = 0; i < sz; i++) { buf[0] = '%'; sprintf(&(buf[1]), "%02X", ((unsigned)(ub[i]) & 0x00FFU)); fputs(buf, job->of); } } $? "- hbhtml_url_c32" } /** Write shipout buffer in URL encoding. @param job Job structure. */ static void hbhtml_url_flush_shipout(hb_job_t *job) { #if DK3_CHAR_SIZE > 1 #if DK3_CHAR_SIZE > 2 size_t i; #else dk3_c16_t const *sp; /* Source character pointer */ dk3_c32_t c32; /* 32-bit character */ size_t sl; /* Remaining source string length */ size_t used; /* Number of source chars used */ #endif #else unsigned char const *sp; /* Source character pointer */ dk3_c32_t c32; /* 32-bit character */ size_t sl; /* Remaining source string length */ size_t used; /* Number of source chars used */ size_t i; /* Process all source chars */ unsigned char c; /* Current source char to process */ #endif $? "+ hbhtml_flush_shipout" if(job->shipused) { job->non_url = 0; if(job->shipused < job->bs) { (job->shipbuffer)[job->shipused] = dkT('\0'); #if DK3_CHAR_SIZE > 1 #if DK3_CHAR_SIZE > 2 for(i = 0; i < (job->shipused); i++) { hbhtml_url_c32(job, (job->shipused)[i]); } #else sp = (dk3_c16_t const *)(job->shipbuffer); sl = job->shipused; while(sl > 0) { used = 0; if(dk3enc_utf162uc(&c32, sp, sl, &used)) { hbhtml_url_c32(job, c32); if(used > 0) { if(sl >= used) { sl = sl - used; sp = &(sp[used]); } else { sl = 0; /* ERROR: Decoding */ dk3app_log_i1(job->app, DK3_LL_ERROR, 119); } } else { sl = 0; /* ERROR: Decoding */ dk3app_log_i1(job->app, DK3_LL_ERROR, 119); } } else { sl = 0; /* ERROR: Decoding */ dk3app_log_i1(job->app, DK3_LL_ERROR, 119); } } #endif #else $? "+ shipout ASCII" if(dk3app_get_encoding(job->app) == DK3_ENCODING_UTF8) { $? ". UTF-8" sp = (unsigned char const *)(job->shipbuffer); sl = job->shipused; while(sl > 0) { used = 0; if(dk3enc_utf82uc(&c32, sp, sl, &used)) { hbhtml_url_c32(job, c32); if(used > 0) { if(sl >= used) { sl = sl - used; sp = &(sp[used]); } else { sl = 0; /* ERROR: Decoding problem */ dk3app_log_i1(job->app, DK3_LL_ERROR, 118); } } else { sl = 0; /* ERROR: Decoding problem */ dk3app_log_i1(job->app, DK3_LL_ERROR, 118); } } else { sl = 0; /* ERROR: Decoding problem */ dk3app_log_i1(job->app, DK3_LL_ERROR, 118); } } } else { sp = (unsigned char const *)(job->shipbuffer); for(i = 0; i < (job->shipused); i++) { c = sp[i]; c32 = (dk3_c32_t)c; c32 &= 0x000000FFUL; hbhtml_url_c32(job, c32); } } $? "- shipout ASCII" #endif if(job->non_url) { /* WARNING: Non-URL characters in string! */ dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 21, 22, job->shipbuffer); } } job->non_url = 0; } job->shipused = 0; $? "- hbhtml_flush_shipout" } void hbhtml_c32(hb_job_t *job, dk3_c32_t c32) { unsigned char ub[16]; /* Buffer for UTF-8 conversion */ size_t sz; /* Number of chars used in ub */ size_t i; /* Process all chars in ub */ char c; /* Current char from ub */ $? "+ hbhtml_c32 0x%lx %lu", (unsigned long)c32, (unsigned long)c32 if(((dk3_c32_t)128) > c32) { c = (((char)c32) & ((char)0x7F)); switch(c) { case '\n': { fputc('\n', job->of); } break; case '&': { if((job->options) & HB_JOB_OPT_CODE) { fputs(hbhtml_translation_table[38], job->of); } else { if(((job->currentnode)->options) & HB_NODE_OPT_REPLACE_AMPERSAND) { fputs(hbhtml_translation_table[38], job->of); } else { fputc('&', job->of); } } } break; case '<': { if((job->options) & HB_JOB_OPT_CODE) { fputs(hbhtml_translation_table[60], job->of); } else { fputc('<', job->of); } } break; case '>': { if((job->options) & HB_JOB_OPT_CODE) { fputs(hbhtml_translation_table[62], job->of); } else { fputc('>', job->of); } } break; case '"': { if((job->options) & HB_JOB_OPT_CODE) { fputs(hbhtml_translation_table[34], job->of); } else { fputc('"', job->of); } } break; case '%': { fputc('%', job->of); /* PROBABLY NEED A CODE */ } break; default: { sz = (size_t)c32; sz &= (size_t)0x007FU; if(hbhtml_translation_table[sz]) { fputs(hbhtml_translation_table[sz], job->of); } else { fprintf(job->of, "&#x%02lx;", (unsigned long)c32); } } break; } } else { if(((dk3_c32_t)256) > c32) { sz = (size_t)c32; sz &= (size_t)0x00FFU; if(hbhtml_translation_table[sz]) { fputs(hbhtml_translation_table[sz], job->of); } else { fprintf(job->of, "&#x%02lx;", (unsigned long)c32); } } else { if(HB_CS_UTF_8 == job->cs) { sz = dk3enc_uc2utf8(c32, ub, sizeof(ub)); for(i = 0; i < sz; i++) { fputc(ub[i], job->of); } } else { if(((dk3_c32_t)0x010000UL) > c32) { fprintf(job->of, "&#x%04lx;", (unsigned long)c32); } else { if(((dk3_c32_t)0x01000000UL) > c32) { fprintf(job->of, "&#x%06lx;", (unsigned long)c32); } else { fprintf(job->of, "&#x%08lx;", (unsigned long)c32); } } } } } $? "- hbhtml_c32" } /** Flush the shipout buffer. @param job Job structure. */ static void hbhtml_flush_shipout(hb_job_t *job) { #if DK3_CHAR_SIZE > 1 #if DK3_CHAR_SIZE > 2 size_t i; /* Process all characters */ #else dk3_c16_t const *sp; /* Current source start */ dk3_c32_t c32; /* Current 32-bit char to process */ size_t sl; /* Remaining source length */ size_t used; /* Source chars used */ #endif #else unsigned char const *sp; /* Current source start */ dk3_c32_t c32; /* Current 32-bit char to process */ size_t sl; /* Remaining source length */ size_t used; /* Source chars used */ size_t i; /* Process all chars from buffer */ unsigned char c; /* Current char to process */ #endif $? "+ hbhtml_flush_shipout" if(job->shipused) { if(job->shipused < job->bs) { (job->shipbuffer)[job->shipused] = dkT('\0'); #if DK3_CHAR_SIZE > 1 #if DK3_CHAR_SIZE > 2 for(i = 0; i < (job->shipused); i++) { hbhtml_c32(job, (job->shipused)[i]); } #else sp = (dk3_c16_t const *)(job->shipbuffer); sl = job->shipused; while(sl > 0) { used = 0; if(dk3enc_utf162uc(&c32, sp, sl, &used)) { hbhtml_c32(job, c32); if(used > 0) { if(sl >= used) { sl = sl - used; sp = &(sp[used]); } else { sl = 0; /* ERROR: Decoding */ dk3app_log_i1(job->app, DK3_LL_ERROR, 119); } } else { sl = 0; /* ERROR: Decoding */ dk3app_log_i1(job->app, DK3_LL_ERROR, 119); } } else { sl = 0; /* ERROR: Decoding */ dk3app_log_i1(job->app, DK3_LL_ERROR, 119); } } #endif #else $? "+ shipout ASCII" if(dk3app_get_encoding(job->app) == DK3_ENCODING_UTF8) { $? ". UTF-8" sp = (unsigned char const *)(job->shipbuffer); sl = job->shipused; while(sl > 0) { used = 0; if(dk3enc_utf82uc(&c32, sp, sl, &used)) { hbhtml_c32(job, c32); if(used > 0) { if(sl >= used) { sl = sl - used; sp = &(sp[used]); } else { sl = 0; /* ERROR: Decoding problem */ dk3app_log_i1(job->app, DK3_LL_ERROR, 118); } } else { sl = 0; /* ERROR: Decoding problem */ dk3app_log_i1(job->app, DK3_LL_ERROR, 118); } } else { sl = 0; /* ERROR: Decoding problem */ dk3app_log_i1(job->app, DK3_LL_ERROR, 118); } } } else { sp = (unsigned char const *)(job->shipbuffer); for(i = 0; i < (job->shipused); i++) { c = sp[i]; c32 = (dk3_c32_t)c; c32 &= 0x000000FFUL; hbhtml_c32(job, c32); } } $? "- shipout ASCII" #endif } } job->shipused = 0; $? "- hbhtml_flush_shipout" } /** Add one character to shipout buffer. @param job Job structure. @param c Character to add. @return 1 on success, 0 on error. */ static int hbhtml_shipout(hb_job_t *job, dkChar c) { int back = 1; $? "+ hbhtml_shipout" if((job->shipused) < (job->bs - 1)) { (job->shipbuffer)[job->shipused] = c; job->shipused += 1; if(job->shipused >= job->bs) { back = 0; } } else { back = 0; } $? "- hbhtml_shipout %d", back return back; } /** Add one character to special command buffer. @param job Job structure. @param c Character to add. @return 1 on success, 0 on error. */ static int hbhtml_add_to_special(hb_job_t *job, dkChar c) { int back = 1; $? "+ hbhtml_add_to_special" if((job->spused) < (job->bs - 1)) { (job->special)[job->spused] = c; job->spused += 1; if(job->spused >= job->bs) { back = 0; } } else { back = 0; } $? "- hbhtml_add_to_special %d", back return back; } /** Classify a character for processing by state machine 1. @param c Character to classify. @return Classification result. */ static int hbhtml_classify_for_stm1(dkChar c) { int back = STM1_I_ANY; switch(c) { case dkT('%'): { back = STM1_I_PERCENT; } break; case dkT('\\'): { back = STM1_I_BS; } break; } return back; } /** Write text to HTML output file. @param job Job structure. @param text Text to write. @return 1 on success, 0 on error. */ int hbhtml_output_for_text(hb_job_t *job, dkChar const *text) { size_t sz; #if VERSION_BEFORE_20131219 int oldcode; #endif int back = 0; $? "+ hbhtml_output_for_text \"%!ds\"", TR_STR(text) if((job) && (text)) { sz = dk3str_len(text); if(sz < job->bs) { $? ". size ok" #if VERSION_BEFORE_20131219 oldcode = (((job->options) & HB_JOB_OPT_CODE) ? 1 : 0); job->options &= (~(HB_JOB_OPT_CODE)); #endif dk3str_cpy(job->shipbuffer, text); job->shipused = sz; $? ". text copied to shipout buffer" hbhtml_flush_shipout(job); $? ". flush completed" back = 1; job->spused = 0; job->shipused = 0; #if VERSION_BEFORE_20131219 if(oldcode) { job->options |= HB_JOB_OPT_CODE; } #endif } } $? "- hbhtml_output_for_text %d", back return back; } /** Write text to URL output file. @param job Job structure. @param text Text to write. @return 1 on success, 0 on error. */ int hbhtml_url_output_for_text(hb_job_t *job, dkChar const *text) { size_t sz; /* Text length */ int back = 0; $? "+ hbhtml_url_output_for_text \"%!ds\"", TR_STR(text) if((job) && (text)) { sz = dk3str_len(text); if(sz < job->bs) { dk3str_cpy(job->shipbuffer, text); job->shipused = sz; hbhtml_url_flush_shipout(job); back = 1; job->spused = 0; job->shipused = 0; } } $? "- hbhtml_url_output_for_text %d", back return back; } /** Process the title special command. @param job Job structure. @return 1 on success, 0 on error. */ static int hbhtml_process_sp_title(hb_job_t *job) { int back = 0; $? "+ hbhtml_process_sp_title" if(job->rootnode) { $? ". have node" if((job->rootnode)->title) { $? ". have title" if(hbhtml_output_for_text(job, (job->rootnode)->title)) { back = 1; } } } $? "- hbhtml_process_sp_title %d", back return back; } /** Build new file name if necessary. @param oldname Existing file name. @param fnb File name buffer. @param fnbsz Size of file name buffer. @param sc Sub command. @param newsuffix New file name suffix. @param job Job structure. @param ecp Error code variable pointer. */ static dkChar * hbhtml_sc_fn( dkChar *oldname, dkChar *fnb, size_t fnbsz, dkChar *sc, dkChar const *newsuffix, hb_job_t *job, int *ecp ) { dk3_stat_t stb; dkChar *back; dkChar *sp; $? "+ hbhtml_sc_fn \"%!ds\"", TR_STR(oldname) $? ". sc=\"%!ds\"", TR_STR(sc) $? ". newsuffix=\"%!ds\"", TR_STR(newsuffix) back = oldname; if(!(back)) { /* Remove suffix if it matches subcommand. */ sp = dk3str_get_suffix(fnb); if(sp) { if(0 == dk3str_casecmp(&(sp[1]), sc)) { *sp = dkT('\0'); } } /* Add new suffix. */ if(fnbsz > (dk3str_len(fnb) + dk3str_len(newsuffix))) { dk3str_cat(fnb, newsuffix); /* If file exists, use file name from fnb. */ if(dk3sf_stat_app(&stb, fnb, NULL)) { switch(stb.ft) { case DK3_FT_REGULAR: { back = fnb; } break; default: { /* ERROR: Not a regular file */ dk3app_log_i3(job->app, DK3_LL_ERROR, 255, 256, fnb); } break; } } else { dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 84, 85, fnb); } } else { /* ERROR: File name too long */ dk3app_log_i3(job->app, DK3_LL_ERROR, 65, 66, fnb); if(ecp) { *ecp = 1; } } } $? "- hbhtml_sc_fn \"%!ds\"", TR_STR(back) return back; } /** Process image special command. @param job Job structure. @param pa Pointer to arguments. @param sc Subcommand, may be NULL. @param in_template Flag: Processing the template. @return 1 on success, 0 on error. */ static int hbhtml_process_sp_image(hb_job_t *job, dkChar *pa, dkChar *sc, int in_template) { dkChar svgnbuf[DK3_MAX_PATH]; /* SVG file name */ dkChar pdfnbuf[DK3_MAX_PATH]; /* PDF file name */ dkChar pngnbuf[DK3_MAX_PATH]; /* PNG file name */ dk3_key_value_t kv[30]; /* Parameters */ dkChar wbuf[64]; /* Width buffer */ dkChar hbuf[64]; /* Height buffer */ dkChar *align = NULL; /* Align specified */ dkChar *alt = NULL; /* Alternative text */ dkChar *border = NULL; /* Border specified */ dkChar *height = NULL; /* Height specified */ dkChar *hspace = NULL; /* Horiz space specified */ dkChar *longdesc = NULL; /* Longdesc specified */ dkChar *name = NULL; /* Name. */ dkChar *src = NULL; /* Image file name */ dkChar *usemap = NULL; /* Usemap text */ dkChar *vspace = NULL; /* Vertical space specified */ dkChar *width = NULL; /* Width specified */ dkChar *larger = NULL; /* File name large resolution */ dkChar *pdf = NULL; /* PDF file name */ dkChar *clptr = NULL; /* Image CSS class */ dkChar *idptr = NULL; /* Image CSS id */ dkChar *title = NULL; /* Image title */ dkChar *capt = NULL; /* Image caption */ dkChar *svg = NULL; /* SVG file name */ dkChar *fnptr = NULL; /* The file argument */ unsigned long xw = 0UL; /* Width found */ unsigned long xh = 0UL; /* Height found */ size_t sz; /* Size of key value array */ size_t i; /* Traverse key value array */ int cache = 0; /* Flag: Cache width+height */ int ismap = 0; /* Flag: Write isamp attrib */ int back = 0; /* Result */ int tispec = 0; /* Flag: Title specified */ int caspec = 0; /* Flag: Capction specified */ int svgwh = 0; /* Flag: For SVG width+height */ int dodiv = 0; /* Img in div(1) or table(2) */ int center = 0; /* Flag: Center image */ int downlo = 0; /* Flag: Create download div */ int haveli = 0; /* Already have written link */ int crobj = 1; /* Flag: Create object */ int novsp = 0; /* Flag: No vertical space. */ int fnerr = 0; /* Flag: Error related file */ $? "+ hbhtml_process_sp_image pa=\"%!ds\" sc=\"%!ds\"", TR_STR(pa), TR_STR(sc) sz = DK3_SIZEOF(kv,dk3_key_value_t); svgnbuf[0] = pdfnbuf[0] = pngnbuf[0] = dkT('\0'); if(dk3str_to_key_value(kv, &sz, pa, job->app)) { $? ". sz = %u", (unsigned)sz if(sc) { $? ". sub command specified" tispec = 1; downlo = 1; dodiv = 2; if(-1 < dk3str_array_index(hbhtml_no_vspace_suffixes, sc, 0)) { novsp = 1; } } for(i = 0; i < sz; i++) { if(kv[i].key) { $? ". key = \"%!ds\"", kv[i].key switch(dk3str_array_abbr(hbhtml_img_keys, kv[i].key, dkT('$'), 0)) { case 0: { $? ". align" align = kv[i].val; } break; case 1: { $? ". alt" alt = kv[i].val; } break; case 2: { $? ". border" border = kv[i].val; } break; case 3: { $? ". height" height = kv[i].val; } break; case 4: { $? ". hspace" hspace = kv[i].val; } break; case 5: { /* ismap */ $? ". ismap" if(kv[i].val) { if(dk3str_is_bool(kv[i].val)) { if(dk3str_is_on(kv[i].val)) { ismap = 1; } else { ismap = 0; } } } else { ismap = 1; } } break; case 6: { $? ". longdesc" longdesc = kv[i].val; } break; case 7: { $? ". name" name = kv[i].val; } break; case 8: { $? ". src" src = kv[i].val; } break; case 9: { $? ". usemap" usemap = kv[i].val; } break; case 10: { $? ". vspace" vspace = kv[i].val; } break; case 11: { $? ". width" width = kv[i].val; } break; case 12: { $? ". set larger to \"%!ds\"", TR_STR(kv[i].val) larger = kv[i].val; } break; case 13: { $? ". pdf" pdf = kv[i].val; } break; case 14: { /* caching */ $? ". cache" if(kv[i].val) { if(dk3str_is_bool(kv[i].val)) { if(dk3str_is_on(kv[i].val)) { cache = 1; } else { cache = 0; } } } else { cache = 1; } } break; case 15: { $? ". title = \"%!ds\"", TR_STR(kv[i].val) title = kv[i].val; tispec = 1; } break; case 16: { $? ". class = \"%!ds\"", TR_STR(kv[i].val) clptr = kv[i].val; } break; case 17: { $? ". id = \"%!ds\"", TR_STR(kv[i].val) idptr = kv[i].val; } break; case 18: { /* div */ if(kv[i].val) { if(dk3str_is_bool(kv[i].val)) { dodiv = ((dk3str_is_on(kv[i].val)) ? 1 : 0); } else { /* ERROR: Not boolean */ dk3app_log_i3(job->app, DK3_LL_WARNING, 146, 144, kv[i].val); } } else { dodiv = 1; } } break; case 19: { /* caption */ caspec = 1; capt = kv[i].val; } break; case 20: { /* centered */ if(kv[i].val) { if(dk3str_is_bool(kv[i].val)) { center = ((dk3str_is_on(kv[i].val)) ? 1 : 0); } else { /* ERROR: Not boolean */ dk3app_log_i3(job->app, DK3_LL_WARNING, 146, 144, kv[i].val); } } else { center = 1; } } break; case 21: { /* svg */ svg = kv[i].val; } break; case 22: { /* svgwh */ if(kv[i].val) { if(dk3str_is_bool(kv[i].val)) { svgwh = ((dk3str_is_on(kv[i].val)) ? 1 : 0); } else { /* ERROR: Not boolean */ dk3app_log_i3(job->app, DK3_LL_WARNING, 146, 144, kv[i].val); } } else { svgwh = 1; } } break; case 23: { /* downloads */ if(kv[i].val) { if(dk3str_is_bool(kv[i].val)) { downlo = ((dk3str_is_on(kv[i].val)) ? 1 : 0); } else { /* ERROR: Not boolean */ dk3app_log_i3(job->app, DK3_LL_WARNING, 146, 144, kv[i].val); } } else { downlo = 1; } } break; case 24: { if(kv[i].val) { if(dk3str_is_bool(kv[i].val)) { crobj = ((dk3str_is_on(kv[i].val)) ? 1 : 0); } else { /* ERROR: Not boolean */ dk3app_log_i3(job->app, DK3_LL_WARNING, 146, 144, kv[i].val); } } else { crobj = 1; } } break; case 25: { if(kv[i].val) { if(dk3str_is_bool(kv[i].val)) { if(dk3str_is_on(kv[i].val)) { if(1 == dodiv) { /* Warning: Overwriting div by table */ dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 66); } dodiv = 2; } else { if(1 != dodiv) { dodiv = 0; } } } else { dk3app_log_i3(job->app, DK3_LL_WARNING, 146, 144, kv[i].val); } } else { if(1 == dodiv) { /* Warning: Overwriting div by table */ dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 66); } dodiv = 2; } } break; case 26: { if(kv[i].val) { if(dk3str_is_bool(kv[i].val)) { novsp = ((dk3str_is_on(kv[i].val)) ? 1 : 0); } else { /* ERROR: Not a boolean */ dk3app_log_i3(job->app, DK3_LL_WARNING, 146, 144, kv[i].val); } } else { novsp = 1; } } break; case 27: { $? ". file argument" if(kv[i].val) { if(fnptr) { $? ". overwriting" /* WARNING: Overwriting file setting! */ dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 86); } fnptr = kv[i].val; } else { $? "! missing file name" /* ERROR: No file name specified */ } } break; } } } if(fnptr) { $? ". file argument specified" if(dk3str_len(fnptr) < DK3_SIZEOF(svgnbuf,dkChar)) { dk3str_cpy(svgnbuf, fnptr); dk3str_cpy(pdfnbuf, fnptr); dk3str_cpy(pngnbuf, fnptr); src = hbhtml_sc_fn( src, pngnbuf, DK3_SIZEOF(pngnbuf,dkChar), sc, hbhtml_image_filename_suffixes[0], job, &fnerr ); svg = hbhtml_sc_fn( svg, svgnbuf, DK3_SIZEOF(svgnbuf,dkChar), sc, hbhtml_image_filename_suffixes[2], job, &fnerr ); pdf = hbhtml_sc_fn( pdf, pdfnbuf, DK3_SIZEOF(pdfnbuf,dkChar), sc, hbhtml_image_filename_suffixes[1], job, &fnerr ); } else { /* ERROR: Name too long */ dk3app_log_i3(job->app, DK3_LL_ERROR, 65, 66, fnptr); fnerr = 1; } } if(src) { if(!hbtool_check_filename(job, src)) { src = NULL; } } if(src) { if(0 == fnerr) { back = 1; } if(larger) { $? ". larger=\"%!ds\"", larger if(!hbtool_check_filename(job, larger)) { larger = NULL; } } if(pdf) { $? ". pdf=\"%!ds\"", pdf if(!hbtool_check_filename(job, pdf)) { pdf = NULL; } } if(svg) { $? ". svg=\"%!ds\"", svg if(!hbtool_check_filename(job, svg)) { svg = NULL; } } if(tispec) { if(!(title)) { title = alt; } if(!(title)) { title = src; } } if(caspec) { if(!(capt)) { capt = title; } if(!(capt)) { capt = alt; } } if(!((width) && (height))) { if(hbimgdim_find(job, src, &xw, &xh, cache)) { if((xw) && (xh)) { #if VERSION_BEFORE_20140716 dk3sf_sprintf3(wbuf, dkT("%lu"), xw); dk3sf_sprintf3(hbuf, dkT("%lu"), xh); if(!(width)) { width = wbuf; } if(!(height)) { height = hbuf; } #else if(!(width)) { if (dk3ma_um_to_string(wbuf,DK3_SIZEOF(wbuf,dkChar),(dk3_um_t)xw)) { width = wbuf; } } if(!(height)) { if (dk3ma_um_to_string(hbuf,DK3_SIZEOF(hbuf,dkChar),(dk3_um_t)xh)) { height = hbuf; } } #endif } } } if(capt) { if(!(dodiv)) { dodiv = 2; } } if(downlo) { if(!(dodiv)) { dodiv = 2; } } /* Output creation starts here. */ if(dodiv) { if(2 == dodiv) { /* div Open outer div */ fputs(hbhtml_c8_kw[((novsp) ? (145) : (109))], job->of); /* table */ fputs(hbhtml_c8_kw[138], job->of); hbhtml_output_for_text(job, (job->msg)[65]); fputs(hbhtml_c8_kw[143], job->of); /* tr */ fputs(hbhtml_c8_kw[139], job->of); /* td */ fputs(hbhtml_c8_kw[140], job->of); } else { /* div Open outer div */ fputs(hbhtml_c8_kw[109], job->of); /* div Open image div */ fputs(hbhtml_c8_kw[(center) ? 111 : 110], job->of); } } /* SVG object start. */ if((svg) && (crobj)) { /* Opening object tag */ fputs(hbhtml_c8_kw[114], job->of); if(!hbhtml_url_output_for_text(job, svg)) { back = 0; } if((svgwh) && (width) && (height)) { fputs(hbhtml_c8_kw[71], job->of); if(!hbhtml_url_output_for_text(job, width)) { back = 0; } fputs(hbhtml_c8_kw[72], job->of); if(!hbhtml_url_output_for_text(job, height)) { back = 0; } } fputs(hbhtml_c8_kw[51], job->of); fputs(hbhtml_c8_kw[0], job->of); /* Object param */ fputs(hbhtml_c8_kw[115], job->of); if(!hbhtml_url_output_for_text(job, svg)) { back = 0; } fputs(hbhtml_c8_kw[51], job->of); fputs(hbhtml_c8_kw[0], job->of); } /* Image */ fputs(hbhtml_c8_kw[2], job->of); fputs(hbhtml_c8_kw[4], job->of); if(!hbhtml_url_output_for_text(job, src)) { back = 0; } fputs(hbhtml_c8_kw[5], job->of); if(name) { fputs(hbhtml_c8_kw[58], job->of); if(!hbhtml_output_for_text(job, name)) { back = 0; } fputs(hbhtml_c8_kw[5], job->of); } fputs(hbhtml_c8_kw[6], job->of); if(alt) { if(!hbhtml_output_for_text(job, alt)) { back = 0; } } fputs(hbhtml_c8_kw[5], job->of); if(title) { fputs(hbhtml_c8_kw[7], job->of); if(!hbhtml_output_for_text(job, title)) { back = 0; } fputs(hbhtml_c8_kw[5], job->of); } if(longdesc) { fputs(hbhtml_c8_kw[59], job->of); if(!hbhtml_url_output_for_text(job, longdesc)) { back = 0; } fputs(hbhtml_c8_kw[5], job->of); } if((width) && (height)) { fputs(hbhtml_c8_kw[9], job->of); if(!hbhtml_url_output_for_text(job, width)) { back = 0; } fputs(hbhtml_c8_kw[5], job->of); fputs(hbhtml_c8_kw[10], job->of); if(!hbhtml_url_output_for_text(job, height)) { back = 0; } fputs(hbhtml_c8_kw[5], job->of); } fputs(hbhtml_c8_kw[8], job->of); if(border) { if(!hbhtml_url_output_for_text(job, border)) { back = 0; } } else { fputs(hbhtml_c8_kw[57], job->of); } fputs(hbhtml_c8_kw[5], job->of); if(clptr) { fputs(hbhtml_c8_kw[60], job->of); if(!hbhtml_url_output_for_text(job, clptr)) { back = 0; } fputs(hbhtml_c8_kw[5], job->of); } if(idptr) { fputs(hbhtml_c8_kw[61], job->of); if(!hbhtml_url_output_for_text(job, idptr)) { back = 0; } fputs(hbhtml_c8_kw[5], job->of); } if(usemap) { fputs(hbhtml_c8_kw[62], job->of); if(!hbhtml_url_output_for_text(job, usemap)) { back = 0; } fputs(hbhtml_c8_kw[5], job->of); } if(align) { fputs(hbhtml_c8_kw[63], job->of); if(!hbhtml_url_output_for_text(job, align)) { back = 0; } fputs(hbhtml_c8_kw[5], job->of); } if(hspace) { fputs(hbhtml_c8_kw[64], job->of); if(!hbhtml_url_output_for_text(job, hspace)) { back = 0; } fputs(hbhtml_c8_kw[5], job->of); } if(vspace) { fputs(hbhtml_c8_kw[65], job->of); if(!hbhtml_url_output_for_text(job, vspace)) { back = 0; } fputs(hbhtml_c8_kw[5], job->of); } if(ismap) { fputs(hbhtml_c8_kw[66], job->of); } fputs(hbhtml_c8_kw[3], job->of); fputs(hbhtml_c8_kw[0], job->of); /* SVG object end. */ if((svg) && (crobj)) { /* Closing object tag */ fputs(hbhtml_c8_kw[73], job->of); fputs(hbhtml_c8_kw[0], job->of); } /* Table or div end */ if(dodiv) { if(capt) { /* Print caption */ fputs(hbhtml_c8_kw[116], job->of); if(!hbhtml_output_for_text(job, capt)) { back = 0; } fputs(hbhtml_c8_kw[117], job->of); /* fputs(hbhtml_c8_kw[0], job->of); */ } if(2 == dodiv) { /* !td Close image td */ fputs(hbhtml_c8_kw[97], job->of); } else { /* !div Close inner div */ fputs(hbhtml_c8_kw[47], job->of); } if(downlo) { if(2 == dodiv) { /* td space !td Space div */ fputs(hbhtml_c8_kw[141], job->of); /* td Open download td */ fputs(hbhtml_c8_kw[142], job->of); } else { /* p Open download p */ fputs(hbhtml_c8_kw[112], job->of); } /* Write download links */ { haveli = 0; if(svg) { $? ". svg = \"%!ds\"", svg haveli = 1; fputs(hbhtml_c8_kw[68], job->of); if(!hbhtml_url_output_for_text(job, svg)) { back = 0; } fputs(hbhtml_c8_kw[69], job->of); fputs(hbhtml_c8_kw[118], job->of); fputs(hbhtml_c8_kw[40], job->of); if(!hbhtml_output_for_text(job, (job->kwnl)[33])) { back = 0; } fputs(hbhtml_c8_kw[41], job->of); } if(pdf) { $? ". pdf = \"%!ds\"", pdf if(haveli) { fputs(hbhtml_c8_kw[105], job->of); } haveli = 1; fputs(hbhtml_c8_kw[68], job->of); if(!hbhtml_url_output_for_text(job, pdf)) { back = 0; } fputs(hbhtml_c8_kw[69], job->of); fputs(hbhtml_c8_kw[119], job->of); fputs(hbhtml_c8_kw[40], job->of); if(!hbhtml_output_for_text(job, (job->kwnl)[34])) { back = 0; } fputs(hbhtml_c8_kw[41], job->of); } if(larger) { $? ". larger = \"%!ds\"", larger if(haveli) { fputs(hbhtml_c8_kw[105], job->of); } haveli = 1; fputs(hbhtml_c8_kw[68], job->of); if(!hbhtml_url_output_for_text(job, larger)) { back = 0; } fputs(hbhtml_c8_kw[69], job->of); fputs(hbhtml_c8_kw[40], job->of); if(!hbhtml_output_for_text(job, (job->msg)[58])) { back = 0; } fputs(hbhtml_c8_kw[41], job->of); } if(haveli) { fputs(hbhtml_c8_kw[105], job->of); } fputs(hbhtml_c8_kw[68], job->of); if(!hbhtml_url_output_for_text(job, src)) { back = 0; } fputs(hbhtml_c8_kw[69], job->of); fputs(hbhtml_c8_kw[40], job->of); if(!hbhtml_output_for_text(job, (job->msg)[59])) { back = 0; } fputs(hbhtml_c8_kw[41], job->of); } if(2 == dodiv) { /* !td Close download td */ fputs(hbhtml_c8_kw[97], job->of); } else { /* !p Close download p */ fputs(hbhtml_c8_kw[113], job->of); } } else { if(2 == dodiv) { } else { fputs(hbhtml_c8_kw[120], job->of); } } if(2 == dodiv) { /* !tr */ fputs(hbhtml_c8_kw[95], job->of); /* !table */ fputs(hbhtml_c8_kw[93], job->of); /* !div Close outer div */ fputs(hbhtml_c8_kw[47], job->of); } else { /* !div Close outer div */ fputs(hbhtml_c8_kw[47], job->of); } #if 0 if(2 == dodiv) { } else { /* Close image div */ fputs(hbhtml_c8_kw[47], job->of); if(downlo) { /* Open outer download div */ fputs(hbhtml_c8_kw[112], job->of); /* Download links */ { haveli = 0; if(svg) { $? ". svg = \"%!ds\"", svg haveli = 1; fputs(hbhtml_c8_kw[68], job->of); if(!hbhtml_url_output_for_text(job, svg)) { back = 0; } fputs(hbhtml_c8_kw[69], job->of); fputs(hbhtml_c8_kw[118], job->of); fputs(hbhtml_c8_kw[40], job->of); if(!hbhtml_output_for_text(job, (job->kwnl)[33])) { back = 0; } fputs(hbhtml_c8_kw[41], job->of); } if(pdf) { $? ". pdf = \"%!ds\"", pdf if(haveli) { fputs(hbhtml_c8_kw[105], job->of); } haveli = 1; fputs(hbhtml_c8_kw[68], job->of); if(!hbhtml_url_output_for_text(job, pdf)) { back = 0; } fputs(hbhtml_c8_kw[69], job->of); fputs(hbhtml_c8_kw[119], job->of); fputs(hbhtml_c8_kw[40], job->of); if(!hbhtml_output_for_text(job, (job->kwnl)[34])) { back = 0; } fputs(hbhtml_c8_kw[41], job->of); } if(larger) { $? ". larger = \"%!ds\"", larger if(haveli) { fputs(hbhtml_c8_kw[105], job->of); } haveli = 1; fputs(hbhtml_c8_kw[68], job->of); if(!hbhtml_url_output_for_text(job, larger)) { back = 0; } fputs(hbhtml_c8_kw[69], job->of); fputs(hbhtml_c8_kw[40], job->of); if(!hbhtml_output_for_text(job, (job->msg)[58])) { back = 0; } fputs(hbhtml_c8_kw[41], job->of); } if(haveli) { fputs(hbhtml_c8_kw[105], job->of); } fputs(hbhtml_c8_kw[68], job->of); if(!hbhtml_url_output_for_text(job, src)) { back = 0; } fputs(hbhtml_c8_kw[69], job->of); fputs(hbhtml_c8_kw[40], job->of); if(!hbhtml_output_for_text(job, (job->msg)[59])) { back = 0; } fputs(hbhtml_c8_kw[41], job->of); } /* Close output download div */ fputs(hbhtml_c8_kw[113], job->of); } else { fputs(hbhtml_c8_kw[120], job->of); } /* Close outer div */ fputs(hbhtml_c8_kw[47], job->of); } #endif } /* Output creation is finished here. Now we add the files to copy to the list. */ if(src) { if(!hbtool_add_url(job, src)) { back = 0; } } if(larger) { if(!hbtool_add_url(job, larger)) { back = 0; } } if(pdf) { if(!hbtool_add_url(job, pdf)) { back = 0; } } if(svg) { if(!hbtool_add_url(job, svg)) { back = 0; } } } } else { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 40); } $? "- hbhtml_process_sp_image %d", back return back; } /** Write current node item to navigation menu. @param job Job structure. @param nptr Current node. @return 1 on success, 0 on error. */ static int hbhtml_link_to_current_node(hb_job_t *job, hb_node_t *nptr) { dkChar *p; /* Text to show */ int back = 1; $? "+ hbhtml_link_to_current_node" p = nptr->shorttitle; if(!(p)) { p = nptr->title; } if(p) { fputs(hbhtml_c8_kw[34], job->of); if(nptr->title) { fputs(hbhtml_c8_kw[7], job->of); if(hbtool_write_header_number(job, nptr)) { fputs(hbhtml_c8_kw[1], job->of); } if(!hbhtml_output_for_text(job, nptr->title)) { back = 0; } fputs(hbhtml_c8_kw[5], job->of); } fputs(hbhtml_c8_kw[3], job->of); if (!hbhtml_output_for_text(job, p)) { back = 0; } fputs(hbhtml_c8_kw[35], job->of); } else { back = 0; $? "! ERROR" } $? "- hbhtml_link_to_current_node %d", back return back; } /** Write opening link tag to HTML output. @param job Job structure. @param cl Class name. @param ti Title. @param dp Destination. @param tp Type (optional). @param nptr Current node. @return 1 on success, 0 on error. */ static int hbhtml_write_link_start( hb_job_t *job, char const *cl, dkChar const *ti, dkChar const *dp, dkChar const *tp, hb_node_t *nptr ) { int back = 0; $? "+ hbhtml_write_link_start" if(dp) { back = 1; fputs(hbhtml_c8_kw[39], job->of); if(!(hbhtml_url_output_for_text(job, dp))) { back = 0; $? "! ERROR" } fputs(hbhtml_c8_kw[42], job->of); if(cl) { fputs(hbhtml_c8_kw[43], job->of); if(EOF == fputs(cl, job->of)) { back = 0; } fputs(hbhtml_c8_kw[42], job->of); } if(ti) { fputs(hbhtml_c8_kw[44], job->of); if(hbtool_write_header_number(job, nptr)) { fputs(hbhtml_c8_kw[1], job->of); } if(!(hbhtml_output_for_text(job, ti))) { back = 0; $? "! ERROR" } fputs(hbhtml_c8_kw[42], job->of); } if(tp) { fputs(hbhtml_c8_kw[45], job->of); if(!(hbhtml_output_for_text(job, tp))) { back = 0; $? "! ERROR" } fputs(hbhtml_c8_kw[42], job->of); } fputs(hbhtml_c8_kw[40], job->of); } $? "- hbhtml_write_link_start %d", back return back; } /** Write closing link tag. @param job Job structure. */ static void hbhtml_write_link_end(hb_job_t *job) { fputs(hbhtml_c8_kw[41], job->of); $? "= hbhtml_write_link_end" } /** Write a link to HTML output. @param job Job structure. @param cl Class name. @param ti Title. @param dp Destination. @param tp Type (optional). @param tx Link text. @param nptr Current node. @return 1 on success, 0 on error. */ static int hbhtml_write_link( hb_job_t *job, char const *cl, dkChar const *ti, dkChar const *dp, dkChar const *tp, dkChar const *tx, hb_node_t *nptr ) { int back = 0; $? "+ hbhtml_write_link" if((tx) && (dp)) { back = 1; if(!(hbhtml_write_link_start(job, cl, ti, dp, tp, nptr))) { back = 0; $? "! ERROR" } if(!(hbhtml_output_for_text(job, tx))) { back = 0; $? "! ERROR" } hbhtml_write_link_end(job); } $? "- hbhtml_write_link %d", back return back; } int hbhtml_create_output_filename( dkChar *dptr, size_t sz, hb_job_t *job, hb_node_t *nptr ) { dkChar const *sptr; /* Suffix for output file */ dkChar *p1; /* Suffix position */ size_t nsz; /* Summary length name + new suffix */ int back = 0; $? "+ hbhtml_create_output_filename dptr=PTR=%d sz=%u nptr=PTR:%d", TR_IPTR(dptr), (unsigned)sz, TR_IPTR(nptr) if (nptr) { dptr[0] = dkT('\0'); if(0UL == nptr->objno) { $? ". node 0" if(dk3str_len((job->kwnl)[8]) < sz) { dk3str_cpy(dptr, (job->kwnl)[8]); back = 1; } else { /* ERROR: Name too long! */ dk3app_log_i3(job->app, DK3_LL_ERROR, 65, 66, (job->kwnl)[8]); } } else { $? ". other node" if(nptr->filename) { $? ". have source file name" if(dk3str_len(nptr->filename) < sz) { $? ". length ok" dk3str_cpy(dptr, nptr->filename); p1 = dk3str_get_suffix(dptr); if(p1) { p1++; *p1 = dkT('\0'); if(nptr->suffix) { sptr = nptr->suffix; } else { sptr = (job->kwnl)[10]; } nsz = dk3str_len(dptr) + dk3str_len(sptr); if(nsz < sz) { dk3str_cat(dptr, sptr); back = 1; } else { $? "! file name too long" /* ERROR: File name too long! */ dk3app_log_i3(job->app, DK3_LL_ERROR, 65, 66, nptr->filename); } } else { if(nptr->suffix) { sptr = nptr->suffix; } else { sptr = (job->kwnl)[10]; } nsz = dk3str_len(dptr)+dk3str_len(sptr)+dk3str_len((job->kwnl)[9]); if(nsz < sz) { dk3str_cat(dptr, (job->kwnl)[9]); dk3str_cat(dptr, sptr); back = 1; } else { $? "! file name too long" /* File name too long! */ dk3app_log_i3(job->app, DK3_LL_ERROR, 65, 66, nptr->filename); } } } else { $? "! input file name to long" /* ERROR: Input file name too long! */ dk3app_log_i3(job->app, DK3_LL_ERROR, 65, 66, nptr->filename); } } else { $? "! no source file name" /* ERROR: No source file name! */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 24); } } } else { $? "! missing nptr" } $? "- hbhtml_create_output_filename %d \"%!ds\"", back, dptr return back; } /** Write link to one node to navigation menu. @param job Job structure. @param nptr Node to link to. @param bold Flag: Make link bold. @return 1 on success, 0 on error. */ static int hbhtml_link_to_node(hb_job_t *job, hb_node_t *nptr, int bold) { dkChar bu[DK3_MAX_PATH]; /* Buffer for destination name */ hb_node_t *jnode; /* Link jump destination */ dkChar *p1; /* Link title (full) */ dkChar *p2; /* Link title (short or full) */ int back = 0; $? "+ hbhtml_link_to_node" jnode = nptr; if(!(nptr->filename)) { jnode = nptr->jumpnode; } p1 = nptr->title; p2 = ((nptr->shorttitle) ? (nptr->shorttitle) : (nptr->title)); if((p1) && (p2)) { if(jnode) { if(hbhtml_create_output_filename(bu, DK3_SIZEOF(bu,dkChar), job, jnode)) { fputs(hbhtml_c8_kw[36], job->of); back = hbhtml_write_link( job, hbhtml_c8_kw[(bold) ? 144 : 38], p1, bu, NULL, p2, nptr ); fputs(hbhtml_c8_kw[37], job->of); } } else { /* ERROR: No text node! */ dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 52, 53, nptr->title); } } $? "- hbhtml_link_to_node %d", back return back; } /** Write the menu entries for a node. @param job Job structure. @param nptr Node to write menu entries for. @param sepreq Flag: Menu separator required. @return 1 on success, 0 on error. */ static int hbhtml_menu_entries_for_node(hb_job_t *job, hb_node_t *nptr, int sepreq) { hb_node_t *subnode; /* Current node */ hb_node_t *jnptr; /* Jump node for subnode */ int active; /* Flag: Active node */ int sepdone = 0; /* Flag: Separator done */ int bold = 0; /* Flag: Make bold */ int back = 1; $? "+ hbhtml_menu_entries_for_node" if(nptr) { $? ". current node \"%!ds\"", TR_STR(nptr->title) dk3sto_it_reset(nptr->i_subnodes); while(NULL != (subnode = (hb_node_t *)dk3sto_it_next(nptr->i_subnodes))) { jnptr = subnode; if(!(jnptr->filename)) { jnptr = jnptr->jumpnode; } if(sepreq) { if(!(sepdone)) { sepdone = 1; fputs(hbhtml_c8_kw[33], job->of); } } $? ". current subnode \"%!ds\"", TR_STR(subnode->title) active = 1; bold = 0; #if VERSION_BEFORE_20140109 if(nptr->curchild) { if(((nptr->curchild)->objno) == (subnode->objno)) { active = 0; } } #else if(job->currentnode) { if(jnptr) { if(jnptr->objno == (job->currentnode)->objno) { active = 0; } } } if(nptr->curchild) { if(((nptr->curchild)->objno) == (subnode->objno)) { bold = 1; } } #endif if(active) { hbhtml_link_to_node(job, subnode, bold); } else { hbhtml_link_to_current_node(job, subnode); } } } $? "- hbhtml_menu_entries_for_node %d", back return back; } /** Check whether a node has sub menu items. @param ptr Node to check. @return 1 if sub items are present, 0 otherwise. */ static int hbhtml_have_sub_menu_items(hb_node_t *ptr) { int back = 0; $? "+ hbhtml_have_sub_menu_items" dk3sto_it_reset(ptr->i_subnodes); while(NULL != dk3sto_it_next(ptr->i_subnodes)) { back = 1; } $? "- hbhtml_have_sub_menu_items %d", back return back; } /** Process menu special command. @param job Job structure. @param pa Special command arguments. @return 1 on success, 0 on error (continue), -1 on error (exit). */ static int hbhtml_process_sp_menu(hb_job_t *job, dkChar *pa) { dk3_key_value_t kv[10]; /* Key value pairs */ hb_node_t *mnptr; /* Menu node pointer */ size_t sz; /* Size of kv */ size_t i; /* Traverse kv */ int res; /* Result from writing link */ int sep = 0; /* Flag: Need separator */ int tv = 0; /* Test value */ int mnst = 0; /* Menu style (full) */ int sub = 1; /* Include sub menu of current node */ int back = 1; $? "+ hbhtml_process_sp_menu \"%!ds\"", pa sz = DK3_SIZEOF(kv,dk3_key_value_t); if(dk3str_to_key_value(kv, &sz, pa, job->app)) { for(i = 0; i < sz; i++) { if(kv[i].key) { switch(dk3str_array_abbr(hbhtml_menu_keys, kv[i].key, dkT('$'), 0)) { case 0: { if(kv[i].val) { tv = dk3str_array_abbr(hbhtml_menu_styles,kv[i].val,dkT('$'),0); if(0 <= tv) { mnst = tv; } else { /* ERROR: Illegal menu style */ dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,25,26,kv[i].val); } } } break; case 1: { if(kv[i].val) { sub = ((dk3str_is_on(kv[i].val)) ? 1 : 0); } else { sub = 1; } } break; default: { /* ERROR: Illegal key. */ dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,27,26,kv[i].key); } break; } } } } else { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 40); } $? ". mnst=%d sub=%d", mnst, sub if(((job->currentnode)->options) & HB_NODE_OPT_IMPRESSUM) { /* When we are writing the menu for the impressum page, we print the top menu only. */ mnst = 3; sub = 0; } $? ". mnst=%d sub=%d", mnst, sub fputs(hbhtml_c8_kw[29], job->of); fputs(hbhtml_c8_kw[31], job->of); /* Impressum node first, separator. */ if(job->impressumnode) { $? ". have impressum node" if(((job->currentnode)->options) & HB_NODE_OPT_IMPRESSUM) { if(!hbhtml_link_to_current_node(job, job->impressumnode)) { back = 0; $? "! ERROR" } } else { if(!hbhtml_link_to_node(job, job->impressumnode, 0)) { back = 0; $? "! ERROR" } } /* Separator */ fputs(hbhtml_c8_kw[33], job->of); } else { if(job->impressumlink) { $? ". have impressum link" fputs(hbhtml_c8_kw[36], job->of); res = hbhtml_write_link( job, hbhtml_c8_kw[38], (job->msg)[0], job->impressumlink, NULL, (job->msg)[0], NULL ); fputs(hbhtml_c8_kw[37], job->of); if(!(res)) { back = 0; $? "! ERROR" } /* Separator */ fputs(hbhtml_c8_kw[33], job->of); } else { $? ". no impressum link" } } /* Now real menu(s) 0=reverse, 1=full, 2=current, 3=top */ mnptr = job->currentnode; if(mnptr) { $? ". current node: \"%!ds\"", TR_STR(mnptr->title) switch(mnst) { case -1: case 0: case 2: { $? ". reverse or current" if(sub) { if(hbhtml_have_sub_menu_items(mnptr)) { $? " current entry" /* Menu for mnptr without leading space */ $? ". menu from current entry" hbhtml_menu_entries_for_node(job, mnptr, 0); sep = 1; } } mnptr = mnptr->parent; if(mnptr) { /* Menu for mnptr with leading space */ $? ". menu from parent entry" hbhtml_menu_entries_for_node(job, mnptr, sep); if(2 != mnst) { $? ". grandparents" do { mnptr = mnptr->parent; if(mnptr) { /* Menu for mnptr with leading space */ $? ". menu from further parent entry" hbhtml_menu_entries_for_node(job, mnptr, 1); } } while(mnptr); } } } break; case 1: case 3: { $? ". full or top" if(((job->currentnode)->options) & HB_NODE_OPT_IMPRESSUM) { mnptr = job->rootnode; sub = 0; } else { while(mnptr->parent) { mnptr = mnptr->parent; } } /* Menu for mnptr without leading space */ $? ". menu entries from root node" hbhtml_menu_entries_for_node(job, mnptr, 0); if(1 == mnst) { $? ". full, continue with children" do { mnptr = mnptr->curchild; if(mnptr) { if(mnptr->curchild) { /* Menu for mnptr with leading space */ $? ". menu entries form parents/grandparents of current node" hbhtml_menu_entries_for_node(job, mnptr, 1); } else { if(sub) { /* Menu entry from current node */ $? ". menu from current node" hbhtml_menu_entries_for_node(job, mnptr, 1); } } } } while(mnptr); } } break; } } fputs(hbhtml_c8_kw[32], job->of); fputs(hbhtml_c8_kw[30], job->of); $? "- hbhtml_process_sp_menu %d", back return back; } /** Write image with link for one navigation icon. @param job Job structure. @param iconfile Icon file name. @param dest Destination URL. @param titlea1 Title part 1 when icon link is active. @param titlea2 Title part 2 when icon link is active. @param titlena Title when icon is not active. @param act Flag: Link is active. @return 1 on success, 0 on error. */ static int hbhtml_one_navi_icon( hb_job_t *job, dkChar const *iconfile, dkChar const *dest, dkChar const *titlea1, dkChar const *titlea2, dkChar const *titlena, int act ) { int back = 1; unsigned long w = 0UL; /* Icon width */ unsigned long h = 0UL; /* Icon height */ $? "+ hbhtml_one_navi_icon" $? ". iconfile = \"%!ds\"", TR_STR(iconfile) $? ". dest = \"%!ds\"", TR_STR(dest) $? ". titlea1 = \"%!ds\"", TR_STR(titlea1) $? ". titlea2 = \"%!ds\"", TR_STR(titlea2) $? ". titlena = \"%!ds\"", TR_STR(titlena) $? ". act = %d", act if(act) { $? ". act" fputs(hbhtml_c8_kw[49], job->of); if(!(hbhtml_url_output_for_text(job, dest))) { back = 0; } $? ". 1" fputs(hbhtml_c8_kw[50], job->of); if(!(hbhtml_output_for_text(job, titlea1))) { back = 0; } $? ". 2" if(titlea2) { if(!(hbhtml_output_for_text(job, titlea2))) { back = 0; } } $? ". 3" fputs(hbhtml_c8_kw[51], job->of); fputs(hbhtml_c8_kw[53], job->of); if(!(hbhtml_url_output_for_text(job, iconfile))) { back = 0; } $? ". 4" fputs(hbhtml_c8_kw[54], job->of); if(!(hbhtml_output_for_text(job, titlea1))) { back = 0; } $? ". 6" if(titlea2) { if(!(hbhtml_output_for_text(job, titlea2))) { back = 0; } } fputs(hbhtml_c8_kw[55], job->of); if(!(hbhtml_output_for_text(job, titlea1))) { back = 0; } $? ". 6" if(titlea2) { if(!(hbhtml_output_for_text(job, titlea2))) { back = 0; } } fputs(hbhtml_c8_kw[56], job->of); if(hbimgdim_find(job, iconfile, &w, &h, 1)) { if((w) && (h)) { fprintf(job->of, hbhtml_c8_kw[67], w, h); } } fputs(hbhtml_c8_kw[3], job->of); fputs(hbhtml_c8_kw[52], job->of); $? ". 7" } else { $? ". not act" fputs(hbhtml_c8_kw[53], job->of); if(!(hbhtml_url_output_for_text(job, iconfile))) { back = 0; } $? ". 8" fputs(hbhtml_c8_kw[54], job->of); if(!(hbhtml_output_for_text(job, titlea1))) { back = 0; } $? ". 6" if(titlea2) { if(!(hbhtml_output_for_text(job, titlea2))) { back = 0; } } fputs(hbhtml_c8_kw[55], job->of); if(!(hbhtml_output_for_text(job, titlena))) { back = 0; } $? ". 10" fputs(hbhtml_c8_kw[56], job->of); if(hbimgdim_find(job, iconfile, &w, &h, 1)) { if((w) && (h)) { fprintf(job->of, hbhtml_c8_kw[67], w, h); } } fputs(hbhtml_c8_kw[3], job->of); } $? "- hbhtml_one_navi_icon %d", back return back; } /** Process special command to build navigation div. @param job Job structure. @param pa Programm arguments (ignored). @param p Previous node. @param n Next node. @return 1 on success, 0 on error. */ static int hbhtml_process_sp_navigation( hb_job_t *job, dkChar *pa, hb_node_t *p, hb_node_t *n ) { dk3_key_value_t kv[10]; /* Command parameters */ dkChar bu[DK3_MAX_PATH]; /* Construct file name */ hb_node_t *nptr; /* Current node */ dkChar const *itop = NULL; /* TOC icon name */ dkChar const *iprev = NULL; /* Previous icon name */ dkChar const *inext = NULL; /* Next icon name */ dkChar const *ihome = NULL; /* Home icon name */ dkChar const *ikind = NULL; /* Index icon name */ dkChar const *ta1; /* Icon image title, node */ dkChar const *ta2; /* Icon image title */ dkChar const *tna; /* Icon image title start */ size_t sz; /* Number of command params */ size_t szurl; /* URL length */ size_t i; /* Traverse command params */ int res; /* Result create one icon */ int kind = 0; /* Flag: Keyword index */ int ptoc = 0; /* Flag: TOC */ int back = 1; $? "+ hbhtml_process_sp_navigation" sz = DK3_SIZEOF(kv,dk3_key_value_t); if(dk3str_to_key_value(kv, &sz, pa, job->app)) { for(i = 0; i < sz; i++) { if(kv[i].key) { switch(dk3str_array_abbr(hbhtml_navi_keys, kv[i].key, dkT('$'), 0)) { case 0: { itop = kv[i].val; } break; case 1: { iprev = kv[i].val; } break; case 2: { inext = kv[i].val; } break; case 3: { ikind = kv[i].val; } break; case 4: { ihome = kv[i].val; } break; } } } } else { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 40); } nptr = job->currentnode; kind = (((job->options) & HB_JOB_OPT_CREATE_INDEX) ? 1 : 0); ptoc = (((job->options) & HB_JOB_OPT_CREATE_TOC) ? 1 : 0); while( (nptr) && ( !( ((itop) || (!(ptoc))) && (ihome) && (iprev) && (inext) && ((ikind) || (!(kind))) ) ) ) { if(!(itop)) itop = nptr->icontoc; if(!(iprev)) iprev = nptr->iconprev; if(!(inext)) inext = nptr->iconnext; if(!(ikind)) ikind = nptr->iconindex; if(!(ihome)) ihome = nptr->iconhome; nptr = nptr->parent; } $? ". before corrections" if(!(itop)) itop = (job->kwnl)[14]; if(!(iprev)) iprev = (job->kwnl)[15]; if(!(inext)) inext = (job->kwnl)[16]; if(!(ikind)) ikind = (job->kwnl)[17]; if(!(ihome)) ihome = (job->kwnl)[37]; $? ". after corrections" if( ((itop) || (!(ptoc))) && (iprev) && (inext) && (ihome) && ((ikind) || (!(kind))) ) { back = 1; if(itop) { if(!hbtool_add_file(job, itop)) { back = 0; } } if(iprev) { if(!hbtool_add_file(job, iprev)) { back = 0; } } if(inext) { if(!hbtool_add_file(job, inext)) { back = 0; } } if(ikind) { if(!hbtool_add_file(job, ikind)) { back = 0; } } if(ihome) { if(!hbtool_add_file(job, ihome)) { back = 0; } } fputs(hbhtml_c8_kw[46], job->of); /* HOME */ $? ". home" ta1 = (job->msg)[1]; ta2 = (job->rootnode)->title; tna = (job->msg)[2]; res = hbhtml_create_output_filename( bu, DK3_SIZEOF(bu,dkChar), job, job->rootnode ); if(res) { $? ". fn ok \"%!ds\"", bu $? ". icon = \"%!ds\"", itop res = hbhtml_one_navi_icon( job, ihome, bu, ta1, ta2, tna, ( (0 != job->currentnode->havenavimenu) ? (1) : (((0UL == (job->currentnode)->objno) ? 0 : 1)) ) ); if(!(res)) { back = 0; } $? ". navi icon completed" } else { $? "! fn" back = 0; } /* Previous */ $? ". prev" ta1 = (job->msg)[3]; ta2 = NULL; if(p) ta2 = p->title; tna = (job->msg)[4]; if(p) { res = hbhtml_create_output_filename( bu, DK3_SIZEOF(bu,dkChar), job, p ); if(res) { fputs(hbhtml_c8_kw[48], job->of); res = hbhtml_one_navi_icon(job, iprev, bu, ta1, ta2, tna, 1); if(!(res)) { back = 0; } } else { back = 0; } } else { fputs(hbhtml_c8_kw[48], job->of); res = hbhtml_one_navi_icon(job, iprev, NULL, ta1, ta2, tna, 0); if(!(res)) { back = 0; } } /* Next */ $? ". next" ta1 = (job->msg)[5]; ta2 = NULL; if(n) ta2 = n->title; tna = (job->msg)[6]; if(n) { res = hbhtml_create_output_filename( bu, DK3_SIZEOF(bu,dkChar), job, n ); if(res) { fputs(hbhtml_c8_kw[48], job->of); res = hbhtml_one_navi_icon(job, inext, bu, ta1, ta2, tna, 1); if(!(res)) { back = 0; } } else { back = 0; } } else { fputs(hbhtml_c8_kw[48], job->of); res = hbhtml_one_navi_icon(job, inext, NULL, ta1, ta2, tna, 0); if(!(res)) { back = 0; } } /* TOC */ $? ". toc" if(ptoc) { ta1 = (job->msg)[93]; ta2 = (job->rootnode)->title; tna = (job->msg)[94]; res = hbhtml_create_output_filename( bu, DK3_SIZEOF(bu,dkChar), job, job->rootnode ); if(res) { $? ". fn ok \"%!ds\"", bu szurl = dk3str_len(bu); szurl += dk3str_len((job->kwnl)[31]); if(szurl < DK3_SIZEOF(bu,dkChar)) { dk3str_cat(bu, (job->kwnl)[31]); } else { back = 0; } $? ". icon = \"%!ds\"", itop fputs(hbhtml_c8_kw[48], job->of); res = hbhtml_one_navi_icon(job, itop, bu, ta1, ta2, tna, 1); if(!(res)) { back = 0; } $? ". navi icon completed" } else { $? "! fn" back = 0; } } /* Key index */ if(kind) { $? ". kind" ta1 = (job->msg)[7]; ta2 = NULL; tna = NULL; res = hbhtml_create_output_filename( bu, DK3_SIZEOF(bu,dkChar), job, job->rootnode ); if(res) { if(dk3str_len(bu)+dk3str_len((job->kwnl)[13]) < DK3_SIZEOF(bu,dkChar)) { dk3str_cat(bu, (job->kwnl)[13]); fputs(hbhtml_c8_kw[48], job->of); res = hbhtml_one_navi_icon(job, ikind, bu, ta1, ta2, tna, 1); if(!(res)) { back = 0; } } else { back = 0; } } else { back = 0; } } fputs(hbhtml_c8_kw[47], job->of); job->currentnode->havenavimenu = 1; $? ". finished" } else { $? "! icons missing" $? ". itop = \"%!ds\"", TR_STR(itop) $? ". iprev = \"%!ds\"", TR_STR(iprev) $? ". inext = \"%!ds\"", TR_STR(inext) $? ". ikind = \"%!ds\"", TR_STR(ikind) $? ". ihome = \"%!ds\"", TR_STR(ihome) } $? "- hbhtml_process_sp_navigation %d", back return back; } /** Process author special command. @param job Job structure. @param pa Program arguments. @return 1 on success, 0 on error (continue), -1 on error (exit). */ static int hbhtml_process_sp_author(hb_job_t *job, dkChar *pa) { dkChar const *ptr; /* Author name */ int back = 0; $? "+ hbhtml_process_sp_author" ptr = hbconf_author(job->currentnode); if(ptr) { if(hbhtml_output_for_text(job, ptr)) { back = 1; } } $? "- hbhtml_process_sp_author %d", back return back; } /** Process location special command. @param job Job structure. @param pa Program arguments. @return 1 on success, 0 on error (continue), -1 on error (exit). */ static int hbhtml_process_sp_location(hb_job_t *job, dkChar *pa) { dkChar const *ptr; /* Location name */ int back = 0; $? "+ hbhtml_process_sp_location" ptr = hbconf_location(job->currentnode); if(ptr) { if(hbhtml_output_for_text(job, ptr)) { back = 1; } } $? "- hbhtml_process_sp_location %d", back return back; } /** Process date special command. @param job Job structure. @param pa Program arguments. @return 1 on success, 0 on error (continue), -1 on error (exit). */ static int hbhtml_process_sp_date(hb_job_t *job, dkChar *pa) { dk3_key_value_t kv[5]; /* Command parameters */ size_t sz; /* Number of command paramters */ size_t i; /* Traverse command paramters */ int german = 0; /* Flag: German style date */ int back = 1; $? "+ hbhtml_process_sp_date \"%!ds\"", TR_STR(pa) sz = DK3_SIZEOF(kv,dk3_key_value_t); if(dk3str_to_key_value(kv,&sz,pa,job->app)) { $? ". to key value" for(i = 0; i < sz; i++) { $? ". i=%u", (unsigned)i if(kv[i].key) { $? ". key=\"%!ds\" val=\"%!ds\"", TR_STR(kv[i].key), TR_STR(kv[i].val) switch(dk3str_array_abbr(hbhtml_date_keys, kv[i].key, dkT('$'), 0)) { case 0: { if(kv[i].val) { if(0 == dk3str_casecmp((job->kwnl)[11], kv[i].val)) { german = 1; $? ". german" } else { german = 0; $? ". not german" } } } break; default: { /* ERROR: Illegal attribute! */ dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,27,26,kv[i].key); back = 0; $? "! ERROR" } break; } } } } else { $? "! dk3str_to_key_value" dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 40); } if(german) { fprintf( job->of, "%02d.%02d.%04d", (job->starttime).D, (job->starttime).M, (job->starttime).Y ); } else { fprintf( job->of, "%04d-%02d-%02d", (job->starttime).Y, (job->starttime).M, (job->starttime).D ); } $? "- hbhtml_process_sp_date %d", back return back; } /** Process special command to show variable. @param job Job structure. @param pa Pointer to arguments. @return 1 on success, 0 on error. */ static int hbhtml_process_sp_variable(hb_job_t *job, dkChar *pa) { dk3_key_value_t kv[5]; /* Argument pairs */ dkChar const *varname; /* Variable name. */ dkChar const *varval; /* Variable value */ size_t sz; /* Size of kv */ size_t i; /* Traverse kv */ int urlm = 0; /* Flag: URL mode */ int back = 1; $? "+ hbhtml_process_sp_variable" sz = DK3_SIZEOF(kv,dk3_key_value_t); if(dk3str_to_key_value(kv,&sz,pa,job->app)) { if(sz > 0) { varname = kv[0].key; for(i = 1; i < sz; i++) { if(kv[i].key) { if(dk3str_casecmp((job->kwnl)[12], kv[i].key) == 0) { if(kv[i].val) { urlm = ((dk3str_is_on(kv[i].val)) ? 1 : 0); } else { urlm = 1; } } else { back = 0; $? "! ERROR" /* ERROR: Illegal argument */ dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,27,26,kv[i].key); } } } varval = hbnode_variable(job->currentnode, varname); if(varval) { if(urlm) { if(!hbhtml_url_output_for_text(job, varval)) { back = 0; $? "! ERROR" } } else { if(!hbhtml_output_for_text(job, varval)) { back = 0; $? "! ERROR" } } } } } else { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 40); } $? "- hbhtml_process_sp_variable %d", back return back; } /** Process contents of one file. @param job Job structure. @param p Previous node. @param n Next node. @return 1 on success, 0 on error (can continue), -1 on error (exit). */ static int hbhtml_process_sp_contents(hb_job_t *job, hb_node_t *p, hb_node_t *n) { int back = 1; job->spused = 0; job->shipused = 0; $? "+ hbhtml_process_sp_contents %lu", (job->currentnode)->objno if(job->currentnode) { $? ". have current node" if((job->currentnode)->filename) { $? ". have input file name" back = hbcont_process(job, p, n); } else { $? "! no input file name" if(0UL == (job->currentnode)->objno) { $? ". root node" back = hbcont_process(job, p, n); } else { $? "! not root node" } } } $? "- hbhtml_process_sp_contents %d", back return back; } /** Open code tag for line number. @param job Job structure. @return 1 on success, 0 on error. */ static int hbhtml_coli_open(hb_job_t *job) { int back = 1; if (EOF == fputs(hbhtml_c8_kw[146], job->of)) { back = 0; } if (1000 > job->coli) { if (0 > fprintf(job->of, "%03d", job->coli)) { back = 0; } job->coli += 1; if (1000 == job->coli) { back = 0; /* WARNING: Too many code lines */ dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 88); } } else { back = 0; fputs(hbhtml_c8_kw[149], job->of); } if (EOF == fputs(hbhtml_c8_kw[147], job->of)) { back = 0; } return back; } /** Close code tag for line number. @param job Job structure. @return 1 on success, 0 on error. */ static int hbhtml_coli_close(hb_job_t *job) { int back = 1; if (EOF == fputs(hbhtml_c8_kw[148], job->of)) { back = 0; } return back; } /** Output dummy code line to avoid trimming emptry code tag. @param job Job structure. @return 1 on success, 0 on error */ static int hbhtml_coli_dummy(hb_job_t *job) { int back = 1; if (!hbhtml_coli_open(job)) { back = 0; } if (EOF == fputs(hbhtml_c8_kw[150], job->of)) { back = 0; } if (!hbhtml_coli_close(job)) { back = 0; } return back; } /** Start of a code line found. Invoked from the input line handler. @param job Job structure. @return 1 on success, 0 on error. */ static int hbhtml_code_line_start(hb_job_t *job) { int back = 1; if (((job->options) & HB_JOB_OPT_CODE) && (0 < job->coli)) { switch (job->cols) { case HB_COLIST_NONE: { if (!hbhtml_coli_open(job)) { back = 0; } job->cols = HB_COLIST_OPENED; } break; case HB_COLIST_NOT_OPENED: { if (!hbhtml_coli_open(job)) { back = 0; } job->cols = HB_COLIST_OPENED; } break; #if 0 case HB_COLIST_OPENED: { } break; #endif } } return back; } /** Finalize a code line. Invoked from the input line handler. @param job Job structure. @return 1 on success, 0 on error. */ static int hbhtml_code_line_end(hb_job_t *job) { int back = 1; if (((job->options) & HB_JOB_OPT_CODE) && (0 < job->coli)) { switch (job->cols) { case HB_COLIST_NONE: { job->cols = HB_COLIST_NOT_OPENED; } break; case HB_COLIST_NOT_OPENED: { if (!hbhtml_coli_dummy(job)) { back = 0; } } break; case HB_COLIST_OPENED: { if (!hbhtml_coli_close(job)) { back = 0; } job->cols = HB_COLIST_NOT_OPENED; } break; } } return back; } /** Start code line numbering. Invoked from the input line handler. Invoked from the code special command. @param job Job structure. @return 1 on success, 0 on error. */ static int hbhtml_start_code_line_numbers(hb_job_t *job) { int back = 1; job->coli = 1; job->cols = HB_COLIST_NONE; return back; } /** End code line numbering if it was started. Invoked from the code special command. @param job Job structure. @return 1 on success, 0 on error. */ static int hbhtml_end_code_line_numbers(hb_job_t *job) { int back = 1; if (((job->options) & HB_JOB_OPT_CODE) && (0 < job->coli)) { switch (job->cols) { case HB_COLIST_OPENED: { if (EOF == fputs(hbhtml_c8_kw[148], job->of)) { back = 0; } } break; } } job->coli = 0; job->cols = HB_COLIST_NONE; return back; } /** Process the code special command. @param job Job structure. @param pa Arguments */ static void hbhtml_process_sp_code(hb_job_t *job, dkChar *pa) { dk3_key_value_t kv[10]; /* Command paramters */ size_t sz; /* Number of command parameters */ size_t i; /* Process all command parameters */ int act = 0; /* Action to take */ int lineno = 0; /* Flag: Write line numbers */ $? "+ hbhtml_process_sp_code" /* Get configuration defaults */ if ((job->options) & HB_JOB_OPT_CODE_LINE_NUMBERS) { lineno = 1; } /* Use command options */ sz = DK3_SIZEOF(kv,dk3_key_value_t); if(dk3str_to_key_value(kv,&sz,pa,job->app)) { if(sz > 0) { for(i = 0; i < sz; i++) { if(kv[i].key) { switch(dk3str_array_abbr(hbhtml_code_keys, kv[i].key, dkT('$'), 0)) { case 0: case 1: { if(kv[i].val) { if(dk3str_is_bool(kv[i].val)) { if(dk3str_is_on(kv[i].val)) { act = 1; } else { act = 2; } } else { act = 1; } } else { act = 1; } } break; case 2: case 3: { if(kv[i].val) { if(dk3str_is_bool(kv[i].val)) { if(dk3str_is_on(kv[i].val)) { act = 2; } else { act = 1; } } else { act = 2; } } else { act = 2; } } break; case 4: { act = 0; } break; case 5: { if (kv[i].val) { if (dk3str_is_bool(kv[i].val)) { lineno = ((dk3str_is_on(kv[i].val)) ? 1 : 0); } else { /* Warning: Not a boolean */ dk3app_log_i3(job->app, DK3_LL_WARNING, 146, 144, kv[i].val); } } else { lineno = 1; } } break; } } } } } else { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 40); } /* Finish open code line numbering. */ (void)hbhtml_end_code_line_numbers(job); /* Turn code mode on or off. */ switch(act) { case 0: { if((job->options) & HB_JOB_OPT_CODE) { job->options &= (~(HB_JOB_OPT_CODE)); } else { job->options |= HB_JOB_OPT_CODE; if (lineno) { (void)hbhtml_start_code_line_numbers(job); } } } break; case 1: { job->options |= HB_JOB_OPT_CODE; if (lineno) { (void)hbhtml_start_code_line_numbers(job); } } break; case 2: { job->options &= (~(HB_JOB_OPT_CODE)); } break; } $? "- hbhtml_process_sp_code" } #if 0 static int hbhtml_check_link_for_external(dkChar *link, hb_job_t *job) { size_t sz; int back = 0; if(link) { sz = dk3str_len(link); if(sz >= dk3str_len((job->kwnl)[20])) { if(0 == dk3str_ncmp(link, (job->kwnl)[20], dk3str_len((job->kwnl)[20]))) { back = 1; } } if(sz >= dk3str_len((job->kwnl)[21])) { if(0 == dk3str_ncmp(link, (job->kwnl)[21], dk3str_len((job->kwnl)[21]))) { back = 1; } } } return back; } #endif int hbhtml_check_link_for_external(dkChar const *link) { dkChar const *ptr; /* Traverse string */ dkChar c; /* Current character */ int stm3; /* State machine for traversal */ int i; /* Input classification */ int back = 0; $? "+ hbhtml_check_link_for_external \"%!ds\"", TR_STR(link) hbhtml_stm3_reset(&stm3); ptr = link; while(*ptr) { c = *(ptr++); i = STM3_I_ANY; switch(c) { case dkT(':'): { i = STM3_I_COLON; } break; case dkT('/'): { i = STM3_I_SLASH; } break; case dkT('_'): { i = STM3_I_ASCII; } break; default: { if((dkT('a') <= c) && (dkT('z') >= c)) { i = STM3_I_ASCII; } else { if((dkT('A') <= c) && (dkT('Z') >= c)) { i = STM3_I_ASCII; } else { if((dkT('0') <= c) && (dkT('9') >= c)) { i = STM3_I_ASCII; } } } } break; } hbhtml_stm3_step(&stm3, i); } if(STM3_ST_SUCCESS == stm3) { back = 1; } $? "- hbhtml_check_link_for_external %d", back return back; } /** Process special command to build a link. @param job Job structure. @param pa Program arguments. @return 1 on success, 0 on error (continue), -1 on error (exit). */ static int hbhtml_process_sp_a(hb_job_t *job, dkChar *pa) { dk3_key_value_t kv[25]; /* Command parameters */ hb_link_t *linkptr; /* Link data for URL */ hb_node_t *nptr; /* Current node */ dkChar *text = NULL; /* Link text */ dkChar *title = NULL; /* Link title */ dkChar *accessk = NULL; /* Accesskey argument */ dkChar *charset = NULL; /* Charset argument */ dkChar *coords = NULL; /* Coords argument */ dkChar *href = NULL; /* href argument */ dkChar *hrefl = NULL; /* hreflang argument */ dkChar *name = NULL; /* name argument */ dkChar *onblur = NULL; /* onblur argument */ dkChar *onfocus = NULL; /* onfocus argument */ dkChar *rel = NULL; /* rel argument */ dkChar *rev = NULL; /* rev argument */ dkChar *shape = NULL; /* shape argument */ dkChar *tabind = NULL; /* tabindex argument */ dkChar *target = NULL; /* target argument */ dkChar *type = NULL; /* type argument */ dkChar *clptr = NULL; /* class argument */ dkChar *idptr = NULL; /* id argument */ dkChar *style = NULL; /* style argument */ size_t sz; /* Number of parameters */ size_t i; /* Traverse parameters */ int external = 0; /* Flag: External link */ int extspec = 0; /* Flag: External specified */ int titlespec = 0; /* Flag: Title specified */ int back = 0; $? "+ hbhtml_process_sp_a" nptr = job->currentnode; sz = DK3_SIZEOF(kv,dk3_key_value_t); if(dk3str_to_key_value(kv,&sz,pa,job->app)) { if(sz > 0) { for(i = 0; i < sz; i++) { if(kv[i].key) { switch(dk3str_array_abbr(hbhtml_a_keys, kv[i].key, dkT('$'), 0)) { case 0: { $? ". text" text = kv[i].val; } break; case 1: { $? ". title" title = kv[i].val; titlespec = 1; } break; case 2: { $? ". accesskey" accessk = kv[i].val; } break; case 3: { $? ". charset" charset = kv[i].val; } break; case 4: { $? ". coords" coords = kv[i].val; } break; case 5: { $? ". href" href= kv[i].val; } break; case 6: { $? ". hreflang" hrefl = kv[i].val; } break; case 7: { $? ". name" name = kv[i].val; } break; case 8: { $? ". onblur" onblur = kv[i].val; } break; case 9: { $? ". onfocus" onfocus = kv[i].val; } break; case 10: { $? ". rel" rel = kv[i].val; } break; case 11: { $? ". rev" rev = kv[i].val; } break; case 12: { $? ". shape" shape = kv[i].val; } break; case 13: { $? ". tabindex" tabind = kv[i].val; } break; case 14: { $? ". target" target = kv[i].val; } break; case 15: { $? ". type" type = kv[i].val; } break; case 16: { $? ". class" clptr = kv[i].val; } break; case 17: { $? ". id" idptr = kv[i].val; } break; case 18: { $? ". style" style = kv[i].val; } break; case 19: { if(kv[i].val) { if(dk3str_is_bool(kv[i].val)) { if(dk3str_is_on(kv[i].val)) { external = 1; extspec = 1; } else { external = 0; extspec = 1; } } } else { external = 1; extspec = 1; } } break; default: { dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,27,26,kv[i].key); } break; } } } } } else { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 40); } if(href) { if(!(extspec)) { external = hbhtml_check_link_for_external(href); } if(titlespec) { if(!(title)) { title = text; } if(!(title)) { title = href; } } back = 1; } else { if(name) { back = 1; } } if(back) { /* Write */ if(href) { fputs(hbhtml_c8_kw[39], job->of); if(!hbhtml_url_output_for_text(job, href)) { back = 0; } } else { fputs(hbhtml_c8_kw[74], job->of); if(!hbhtml_url_output_for_text(job, name)) { back = 0; } } if(target) { fputs(hbhtml_c8_kw[75], job->of); if(!hbhtml_url_output_for_text(job, target)) { back = 0; } } else { if(external) { fputs(hbhtml_c8_kw[108], job->of); } } if(type) { fputs(hbhtml_c8_kw[76], job->of); if(!hbhtml_url_output_for_text(job, type)) { back = 0; } } fputs(hbhtml_c8_kw[77], job->of); if(clptr) { if(!hbhtml_url_output_for_text(job, clptr)) { back = 0; } } else { if(external) { fputs(hbhtml_c8_kw[101], job->of); } else { fputs(hbhtml_c8_kw[100], job->of); } } if(idptr) { fputs(hbhtml_c8_kw[78], job->of); if(!hbhtml_url_output_for_text(job, idptr)) { back = 0; } } if(style) { fputs(hbhtml_c8_kw[79], job->of); if(!hbhtml_url_output_for_text(job, style)) { back = 0; } } if(hrefl) { fputs(hbhtml_c8_kw[80], job->of); if(!hbhtml_url_output_for_text(job, hrefl)) { back = 0; } } if(title) { fputs(hbhtml_c8_kw[81], job->of); if(!hbhtml_output_for_text(job, title)) { back = 0; } } if(onblur) { fputs(hbhtml_c8_kw[82], job->of); if(!hbhtml_url_output_for_text(job, onblur)) { back = 0; } } if(onfocus) { fputs(hbhtml_c8_kw[83], job->of); if(!hbhtml_url_output_for_text(job, onfocus)) { back = 0; } } if(rel) { fputs(hbhtml_c8_kw[84], job->of); if(!hbhtml_url_output_for_text(job, rel)) { back = 0; } } if(rev) { fputs(hbhtml_c8_kw[85], job->of); if(!hbhtml_url_output_for_text(job, rev)) { back = 0; } } if(shape) { fputs(hbhtml_c8_kw[86], job->of); if(!hbhtml_url_output_for_text(job, shape)) { back = 0; } } if(tabind) { fputs(hbhtml_c8_kw[87], job->of); if(!hbhtml_url_output_for_text(job, tabind)) { back = 0; } } if(accessk) { fputs(hbhtml_c8_kw[88], job->of); if(!hbhtml_url_output_for_text(job, accessk)) { back = 0; } } if(charset) { fputs(hbhtml_c8_kw[89], job->of); if(!hbhtml_url_output_for_text(job, charset)) { back = 0; } } if(coords) { fputs(hbhtml_c8_kw[90], job->of); if(!hbhtml_url_output_for_text(job, coords)) { back = 0; } } fputs(hbhtml_c8_kw[5], job->of); fputs(hbhtml_c8_kw[3], job->of); if(href) { if(text) { if(!hbhtml_output_for_text(job, text)) { back = 0; } } else { if(!hbhtml_output_for_text(job, href)) { back = 0; } } } fputs(hbhtml_c8_kw[41], job->of); if((href) && (external) && (text)) { /* Save link and write link number */ linkptr = dk3sto_it_find_like(nptr->i_lbyurl, href, 1); if(linkptr) { fprintf(job->of, hbhtml_c8_kw[91], (1UL + linkptr->lno)); } else { linkptr = hbnode_link_new(href, nptr->nextlink, job->app); if(linkptr) { if(dk3sto_add(nptr->s_lbyurl, linkptr)) { nptr->nextlink += 1UL; if(dk3sto_add(nptr->s_lbylno, linkptr)) { fprintf(job->of, hbhtml_c8_kw[91], (1UL + linkptr->lno)); } else { back = 0; } } else { back = 0; hbnode_link_delete(linkptr); linkptr = NULL; } } else { back = 0; } } } if((!(href)) && (name)) { if(text) { if(!hbhtml_output_for_text(job, text)) { back = 0; } } } if(href) { if(!hbtool_add_url(job, href)) { back = 0; } } } $? "- hbhtml_process_sp_a %d", back return back; } /** Process menuentry special command. @param job Job structure. @param pa Arguments. @return 1 on success, 0 on error (continue), -1 on error (exit). */ static int hbhtml_process_sp_menuentry(hb_job_t *job, dkChar *pa) { dk3_key_value_t kv[20]; /* Command parameters */ dkChar *items[DK3_SIZEOF(kv,dk3_key_value_t)]; size_t sz; /* Number of command parameters */ size_t i; /* Traverse command parameters */ size_t n_items = 0; /* number of items */ size_t cr; /* Current item index */ int back = 0; $? "+ hbhtml_process_sp_menuentry" sz = DK3_SIZEOF(kv,dk3_key_value_t); if(dk3str_to_key_value(kv,&sz,pa,job->app)) { if(sz > 0) { for(i = 0; i < sz; i++) { if(kv[i].key) { switch(dk3str_array_abbr(hbhtml_menuentry_keys,kv[i].key,dkT('$'),0)) { case 0: { if(kv[i].val) { if(n_items < DK3_SIZEOF(kv,dk3_key_value_t)) { items[n_items++] = kv[i].val; } else { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 41); } } } break; default: { dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,27,26,kv[i].key); back = 0; } break; } } } } } else { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 40); } if(n_items) { back = 1; fputs(hbhtml_c8_kw[92], job->of); if(!hbhtml_output_for_text(job, (job->msg)[60])) { back = 0; } fputs(hbhtml_c8_kw[22], job->of); for(cr = 0; cr < n_items; cr++) { fputs(hbhtml_c8_kw[94], job->of); if(cr) { for(i = 0; i < (cr - 1); i++) { fputs(hbhtml_c8_kw[98], job->of); } fputs(hbhtml_c8_kw[99], job->of); fprintf(job->of, hbhtml_c8_kw[96], (unsigned)(n_items - cr)); if(!hbhtml_output_for_text(job, items[cr])) { back = 0; } fputs(hbhtml_c8_kw[97], job->of); } else { fprintf(job->of, hbhtml_c8_kw[96], (unsigned)n_items); if(!hbhtml_output_for_text(job, items[cr])) { back = 0; } fputs(hbhtml_c8_kw[97], job->of); } fputs(hbhtml_c8_kw[95], job->of); } fputs(hbhtml_c8_kw[93], job->of); } else { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 42); } $? "- hbhtml_process_sp_menuentry %d", back return back; } /** Process index special command. @param job Job structure. @param pa Program arguments. @return 1 on success, 0 on error (continue), -1 on error (exit). */ static int hbhtml_process_sp_index(hb_job_t *job, dkChar *pa) { dk3_key_value_t kv[10]; /* Command parameters */ hb_node_t *nptr; /* Current node */ hb_index_entry_t *indptr; /* New index entry item */ dkChar *text = NULL; /* Text for index entry */ dkChar *name = NULL; /* Name for index entry */ size_t sz; /* Number of command paramters */ size_t i; /* Traverse command parameters */ int refer = 0; /* Flag: Refer to existing entry */ int back = 0; $? "+ hbhtml_process_sp_index" nptr = job->currentnode; sz = DK3_SIZEOF(kv,dk3_key_value_t); if(dk3str_to_key_value(kv,&sz,pa,job->app)) { if(sz > 0) { for(i = 0; i < sz; i++) { if(kv[i].key) { switch(dk3str_array_abbr(hbhtml_index_keys, kv[i].key, dkT('$'), 0)) { case 0: { text = kv[i].val; } break; case 1: { name = kv[i].val; } break; case 2: { if(kv[i].val) { if(dk3str_is_bool(kv[i].val)) { if(dk3str_is_on(kv[i].val)) { refer = 1; } else { refer = 0; } } else { /* ERROR: Not a boolean */ dk3app_log_i3(job->app, DK3_LL_WARNING, 146, 144, kv[i].val); } } else { refer = 1; } } break; } } } if(text) { if((job->options) & HB_JOB_OPT_CREATE_INDEX) { indptr = hbindex_new( text, nptr->outFileName, name, nptr->nextindex, job->app, nptr ); if(indptr) { if(dk3sto_add(job->s_index, indptr)) { back = 1; nptr->nextindex += 1UL; if(!((name) && (refer))) { fputs(hbhtml_c8_kw[74], job->of); if(!hb_index_write_anchor(job, indptr)) { back = 0; } fputs(hbhtml_c8_kw[51], job->of); fputs(hbhtml_c8_kw[52], job->of); } } else { hbindex_delete(indptr); } } } else { back = 1; } } else { /* ERROR: Missing text attribute! */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 48); } } } else { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 40); } $? "- hbhtml_process_sp_index %d", back return back; } /** Handle one source code line. @param obj Job structure. @param il Input line. @return 1 on success, 0 on error (continue), -1 on error (exit). */ static int hbhtml_sourcefile_line_handler(void *obj, dkChar *il) { hb_job_t *job; int back = 1; job = (hb_job_t *)obj; dk3str_delnl(il); $? "+ hbhtml_sourcefile_line_handler \"%!ds\"", il if (job->coli) { if (0 < dk3str_len(il)) { if (!hbhtml_coli_open(job)) { back = 0; } if(!hbhtml_output_for_text(job, il)) { back = 0; } if (!hbhtml_coli_close(job)) { back = 0; } } else { if (!hbhtml_coli_dummy(job)) { back = 0; } } } else { if(!hbhtml_output_for_text(job, il)) { back = 0; } } fputc('\n', job->of); $? "- hbhtml_sourcefile_line_handler %d", back return back; } /** Process sourcefile special command. @param job Job structure. @param pa Program arguemnts. @return 1 on success, 0 on error (continue), -1 on error (exit). */ static int html_process_sp_sourcefile(hb_job_t *job, dkChar *pa) { dkChar bu[4096]; /* Buffer for source file lines */ dk3_key_value_t kv[10]; /* Command parameters */ dkChar *file = NULL; /* Input file */ dkChar *type = NULL; /* Type argument */ dkChar *title = NULL; /* Title argument */ size_t sz; /* Number of command parameters */ size_t i; /* Traverse command parameters */ int lineno = 0; /* Flag: Write line numbers */ int back = 0; int res; /* Result from processing file */ int oldcode; /* Old code flag value */ $? "+ html_process_sp_sourcefile" if ((job->options) & HB_JOB_OPT_CODE_LINE_NUMBERS) { lineno = 1; } sz = DK3_SIZEOF(kv,dk3_key_value_t); if(dk3str_to_key_value(kv, &sz, pa, job->app)) { if(sz > 0) { for(i = 0; i < sz; i++) { if(kv[i].key) { switch(dk3str_array_abbr(hbhtml_sourcef_keys,kv[i].key,dkT('$'),0)) { case 0: { file = kv[i].val; } break; case 1: { type = kv[i].val; } break; case 2: { title = kv[i].val; } break; case 3: { if (kv[i].val) { if (dk3str_is_bool(kv[i].val)) { lineno = ((dk3str_is_on(kv[i].val)) ? 1 : 0); } else { /* WARNING: Not a boolean */ dk3app_log_i3(job->app, DK3_LL_WARNING, 146, 144, kv[i].val); } } else { lineno = 1; } } break; } } } } if(file) { back = 1; if(hbtool_add_file(job, file)) { fputs(hbhtml_c8_kw[102], job->of); fputs(hbhtml_c8_kw[103], job->of); if(!hbhtml_url_output_for_text(job, file)) { back = 0; } fputs(hbhtml_c8_kw[81], job->of); if(title) { if(!hbhtml_output_for_text(job, title)) { back = 0; } } else { if(!hbhtml_output_for_text(job, file)) { back = 0; } } fputs(hbhtml_c8_kw[76], job->of); if(type) { if(!hbhtml_output_for_text(job, type)) { back = 0; } } else { fputs(hbhtml_c8_kw[104], job->of); } fputs(hbhtml_c8_kw[51], job->of); if(!hbhtml_output_for_text(job, file)) { back = 0; } fputs(hbhtml_c8_kw[52], job->of); fputs(hbhtml_c8_kw[105], job->of); fputs(hbhtml_c8_kw[106], job->of); oldcode = (((job->options) & HB_JOB_OPT_CODE) ? 1 : 0); job->options |= HB_JOB_OPT_CODE; job->coli = ((lineno) ? 1 : 0); res = dk3stream_process_filename_lines_app( (void *)job, hbhtml_sourcefile_line_handler, file, bu, DK3_SIZEOF(bu,dkChar), dk3app_get_encoding(job->app), dk3app_get_input_file_encoding(job->app), job->app ); job->coli = 0; if(!(res)) { back = 0; } if(oldcode) { job->options |= HB_JOB_OPT_CODE; } else { job->options &= (~(HB_JOB_OPT_CODE)); } fputs(hbhtml_c8_kw[107], job->of); fputs(hbhtml_c8_kw[47], job->of); } else { back = 0; } } else { /* ERROR: No file name specified! */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 49); } } else { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 40); } $? "- html_process_sp_sourcefile %d", back return back; } /** Process sourcefile special command. @param job Job structure. @param pa Program arguemnts. @return 1 on success, 0 on error (continue), -1 on error (exit). */ static int html_process_sp_htmlname(hb_job_t *job, dkChar *pa) { dkChar buf[DK3_MAX_PATH]; size_t szbuf = DK3_SIZEOF(buf,dkChar); int back = 0; $? "+ html_process_sp_htmlname" if (NULL != job->currentnode) { if (0 != hbhtml_create_output_filename(buf, szbuf, job, job->currentnode)) { back = hbhtml_url_output_for_text(job, buf); if (0 == back) { $? "! failed to write text" job->exv = 1; } } else { $? "! filename conversion" job->exv = 1; } } else { $? "! no current node" } $? "- html_process_sp_htmlname %d", back return back; } /** Process sourcefile special command. @param job Job structure. @param pa Program arguemnts. @return 1 on success, 0 on error (continue), -1 on error (exit). */ static int html_process_sp_hint(hb_job_t *job, dkChar *pa) { dk3_key_value_t kv[30]; dkChar *hint_text = NULL; dkChar *hint_title = NULL; size_t sz; size_t i; int back = 0; sz = DK3_SIZEOF(kv,dk3_key_value_t); if (0 != dk3str_to_key_value(kv, &sz, pa, job->app)) { for (i = 0; i < sz; i++) { if (NULL != kv[i].key) { switch (dk3str_array_abbr(hbhtml_hint_keys, kv[i].key, dkT('$'), 0)) { case 0: { hint_text = kv[i].val; } break; case 1: { hint_title = kv[i].val; } break; default: { /* Warning: Unusable key */ dk3app_log_3(job->app, DK3_LL_WARNING, job->msg, 89, 90, kv[i].key); } break; } } } if (NULL != hint_text) { back = 1; if (NULL != hint_title) { if (EOF == fputs(hbhtml_c8_kw[151], job->of)) { back = 0; } if (0 ==hbhtml_output_for_text(job, hint_title)) { back = 0; } if (EOF == fputs(hbhtml_c8_kw[152], job->of)) { back = 0; } if (0 == hbhtml_output_for_text(job, hint_text)) { back = 0; } if (EOF == fputs(hbhtml_c8_kw[153], job->of)) { back = 0; } } else { dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 92); if (0 == hbhtml_output_for_text(job, hint_text)) { back = 0; } } } else { /* ERROR: No text */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 91); } } else { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 40); } if (0 == back) { job->exv = 1; } return back; } /** Process a special command. @param job Job structure. @param in_template Flag: Processing a template. @param p Previous node. @param n Next node. @return 1 on success, 0 on error (continue), -1 on error (exit). */ static int hbhtml_process_special( hb_job_t *job, int in_template, hb_node_t *p, hb_node_t *n ) { dkChar *pc; /* Special command name */ dkChar *pa; /* Start of command arguments */ dkChar *sc; /* Start of sub command. */ int ct; /* Command identifier */ int back = 0; $? "+ hbhtml_process_special" pc = dk3str_start(job->special, NULL); sc = NULL; if(pc) { pa = dk3str_next(pc, NULL); if(pa) { dk3str_chomp(pa, NULL); } sc = dk3str_chr(pc, dkT('.')); if(sc) { *(sc++) = dkT('\0'); } ct = dk3str_array_index(hbhtml_special_commands, pc, 0); $? ". ct = %d", ct switch(ct) { case 0: { $? ". contents" if(in_template) { back = hbhtml_process_sp_contents(job, p, n); } else { /* ERROR: Contents special not allowed in contents! */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 28); } } break; case 1: { $? ". title" back = hbhtml_process_sp_title(job); if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } } break; case 2: { $? ". image" back = hbhtml_process_sp_image(job, pa, sc, in_template); if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } } break; case 3: { $? ". menu" back = hbhtml_process_sp_menu(job, pa); if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } } break; case 4: { $? ". navigation" back = hbhtml_process_sp_navigation(job, pa, p, n); if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } } break; case 5: { /* links */ /* #### Probably not */ back = 1; } break; case 6: { $? ". author" back = hbhtml_process_sp_author(job, pa); if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } } break; case 7: { $? ". location" back = hbhtml_process_sp_location(job, pa); if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } } break; case 8: { $? ". date" back = hbhtml_process_sp_date(job, pa); if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } } break; case 9: { $? ". variable" back = hbhtml_process_sp_variable(job, pa); if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } } break; case 10: { hbhtml_process_sp_code(job, pa); back = 1; } break; case 11: { back = hbhtml_process_sp_a(job, pa); if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } } break; case 12: { back = hbhtml_process_sp_menuentry(job, pa); if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } } break; case 13: { if(0 == in_template) { back = hbhtml_process_sp_index(job, pa); if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } } else { /* ERROR: Can not be used in template */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 50); } } break; case 14: { back = html_process_sp_sourcefile(job, pa); if(1 != back) { dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39); } } break; case 15: { back = html_process_sp_htmlname(job, pa); } break; case 16: { back = html_process_sp_hint(job, pa); } break; default: { $? "! unknown command" back = 0; /* ERROR: Unknown special command. */ dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,29,26,pc); } break; } } else { back = 1; /* Empty special */ } $? "- hbhtml_process_special %d", back return back; } int hbhtml_line_handler(void *obj, dkChar *il) { dkChar xmsg[8]; /* Array for diagnostics */ hb_file_processor_t *proc; /* Line processor */ hb_job_t *job; /* Job */ dkChar *p1; /* Start of input line */ size_t pos; /* Non-whitespace position */ int i; /* Input classification */ int o; /* Reaction from state machine */ int ltl = 0; /* Flag: Error from shipout */ int back = 1; dkChar c; /* Character to ship out */ $? "+ hbhtml_line_handler \"%!ds\"", il pos = 0; proc = (hb_file_processor_t *)obj; job = proc->job; dk3str_delnl(il); hbhtml_stm1_reset(&(proc->stm)); job->shipused = 0; job->spused = 0; p1 = il; while(*p1) { c = *p1; i = hbhtml_classify_for_stm1(c); o = hbhtml_stm1_step(&(proc->stm), i); switch(o) { case STM1_O_ERROR: { /* ERROR: Parse error */ dk3app_log_3(job->app,DK3_LL_ERROR,job->msg,30,26,p1); back = -1; $? "! FATAL ERROR" } break; case STM1_O_NOTHING: { } break; case STM1_O_SHIPOUT: { if (!hbhtml_code_line_start(job)) { back = 0; } if(!(hbhtml_shipout(job, c))) { back = 0; $? "! ERROR" if(0 == ltl) { ltl = 1; /* ERROR: Line too long! */ } } } break; case STM1_O_BS_SHIPOUT: { switch(c) { case dkT('n'): { if (!hbhtml_code_line_start(job)) { back = 0; } if(!(hbhtml_shipout(job, dkT('\n')))) { back = 0; $? "! ERROR" if(0 == ltl) { ltl = 1; /* ERROR: Line too long! */ } } } break; case dkT('r'): { if (!hbhtml_code_line_start(job)) { back = 0; } if(!(hbhtml_shipout(job, dkT('\r')))) { back = 0; $? "! ERROR" if(0 == ltl) { ltl = 1; /* ERROR: Line too long! */ } } } break; case dkT('t'): { if (!hbhtml_code_line_start(job)) { back = 0; } if(!(hbhtml_shipout(job, dkT('\t')))) { back = 0; $? "! ERROR" if(0 == ltl) { ltl = 1; /* ERROR: Line too long! */ } } } break; case dkT('%'): case dkT('\\'): { if (!hbhtml_code_line_start(job)) { back = 0; } if(!(hbhtml_shipout(job, c))) { back = 0; $? "! ERROR" if(0 == ltl) { ltl = 1; /* ERROR: Line too long! */ } } } break; case dkT('.'): { /* We can escape a leading dot. */ if(1 < pos) { xmsg[0] = dkT('\\'); xmsg[1] = c; xmsg[2] = dkT('\0'); dk3app_log_3(job->app, DK3_LL_WARNING, job->msg, 63, 64, xmsg); } if (!hbhtml_code_line_start(job)) { back = 0; } if(!(hbhtml_shipout(job, c))) { back = 0; $? "! ERROR" if(0 == ltl) { ltl = 1; /* ERROR: Line too long! */ } } } break; default: { xmsg[0] = dkT('\\'); xmsg[1] = c; xmsg[2] = dkT('\0'); dk3app_log_3(job->app, DK3_LL_WARNING, job->msg, 63, 64, xmsg); if (!hbhtml_code_line_start(job)) { back = 0; } if(!(hbhtml_shipout(job, c))) { back = 0; $? "! ERROR" if(0 == ltl) { ltl = 1; /* ERROR: Line too long! */ } } } break; } } break; case STM1_O_PERCENT_SHIPOUT: { if (!hbhtml_code_line_start(job)) { back = 0; } if(!(hbhtml_shipout(job, dkT('%')))) { back = 0; $? "! ERROR" if(0 == ltl) { ltl = 1; } } if(!(hbhtml_shipout(job, c))) { back = 0; $? "! ERROR" if(0 == ltl) { ltl = 1; } } } break; case STM1_O_PERCENT: { if (!hbhtml_code_line_start(job)) { back = 0; } if(!(hbhtml_shipout(job, dkT('%')))) { back = 0; $? "! ERROR" if(0 == ltl) { ltl = 1; } } } break; case STM1_O_SWITCH: { hbhtml_flush_shipout(job); job->spused = 0; } break; case STM1_O_SPECIAL: { if(!hbhtml_add_to_special(job, c)) { back = 0; $? "! ERROR" if(0 == ltl) { ltl = 1; } } } break; case STM1_O_SPEC_BS: { switch(c) { case dkT('n'): { if(!hbhtml_add_to_special(job, dkT('\n'))) { back = 0; $? "! ERROR" if(0 == ltl) { ltl = 1; } } } break; case dkT('r'): { if(!hbhtml_add_to_special(job, dkT('\r'))) { back = 0; $? "! ERROR" if(0 == ltl) { ltl = 1; } } } break; case dkT('t'): { if(!hbhtml_add_to_special(job, dkT('\t'))) { back = 0; $? "! ERROR" if(0 == ltl) { ltl = 1; } } } break; default: { if(!hbhtml_add_to_special(job, c)) { back = 0; $? "! ERROR" if(0 == ltl) { ltl = 1; } } } break; } } break; case STM1_O_SPEC_PC_ADD: { if(!hbhtml_add_to_special(job, dkT('%'))) { back = 0; $? "! ERROR" if(0 == ltl) { ltl = 1; } } if(!hbhtml_add_to_special(job, c)) { back = 0; $? "! ERROR" if(0 == ltl) { ltl = 1; } } } break; case STM1_O_SPEC_PC: { if(!hbhtml_add_to_special(job, dkT('%'))) { back = 0; $? "! ERROR" if(0 == ltl) { ltl = 1; } } } break; case STM1_O_EXECUTE: { if((job->spused) < (job->bs)) { (job->special)[job->spused] = dkT('\0'); back = hbhtml_process_special(job,proc->in_template,proc->p,proc->n); } else { back = 0; $? "! ERROR" if(0 == ltl) { ltl = 1; } } job->spused = 0; job->shipused = 0; } break; } p1++; if((dkT(' ') != c) && (dkT('\t') != c)) { pos++; } } switch(proc->stm) { case STM1_ST_BS: { if (!hbhtml_code_line_start(job)) { back = 0; } if(!(hbhtml_shipout(job, dkT('\\')))) { back = 0; if(0 == ltl) { ltl = 1; } } } break; case STM1_ST_PERCENT: { if (!hbhtml_code_line_start(job)) { back = 0; } if(!(hbhtml_shipout(job, dkT('%')))) { back = 0; if(0 == ltl) { ltl = 1; } } } break; case STM1_ST_SPECIAL: case STM1_ST_SPEC_BS: case STM1_ST_SPEC_PC: { /* ERROR: Unfinished special command! */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 62); back = 0; } break; } if(ltl) { dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 31, 26, il); } hbhtml_flush_shipout(job); if (!hbhtml_code_line_end(job)) { back = 0; } if (EOF == fputc('\n', job->of)) { back = 0; $? "! ERROR Newline" } $? "- hbhtml_line_handler %d", back return back; } /** Write JS files to HTML header. @param job Job structure. @param nptr @return 1 on success, 0 on error. */ static int hbhtml_write_js_files(hb_job_t *job, hb_node_t *nptr) { hb_link_t *linkptr; /* File name data for JavaScript file */ int back = 1; /* Write parent JS files. */ if(nptr->parent) { if(!((nptr->options) & HB_NODE_OPT_STOP_JS_INHERITANCE)) { hbhtml_write_js_files(job, nptr->parent); } } /* Write node JS files. */ if((nptr->s_jsfiles) && (nptr->i_jsfiles)) { dk3sto_it_reset(nptr->i_jsfiles); while(NULL != (linkptr = (hb_link_t *)dk3sto_it_next(nptr->i_jsfiles))) { if(linkptr->url) { fputs(hbhtml_c8_kw[121], job->of); if(!hbhtml_url_output_for_text(job, linkptr->url)) { back = 0; } fputs(hbhtml_c8_kw[122], job->of); } } } return back; } /** Write one head navigation entry. @param job Job structure. @param nptr Node (may be NULL for impressum). @param url URL to use if nptr is NULL. @param titleind Title index if nptr is NULL. @param linkkwind Link keyword index. @param appendind Index for keyword index. */ static void hbhtml_one_head_navigation( hb_job_t *job, hb_node_t *nptr, dkChar const *url, size_t titleind, size_t linkkwind, size_t appendind ) { dkChar bu[DK3_MAX_PATH]; /* Buffer for output file name */ hb_node_t *jnptr; /* Jump node */ if(nptr) { jnptr = nptr; if(!(jnptr->filename)) { jnptr = jnptr->jumpnode; } if(hbhtml_create_output_filename(bu, DK3_SIZEOF(bu,dkChar), job, jnptr)) { fputs(hbhtml_c8_kw[123], job->of); fputs(hbhtml_c8_kw[linkkwind], job->of); fputs(hbhtml_c8_kw[124], job->of); if(!hbhtml_output_for_text(job, jnptr->title)) { job->exv = 1; } fputs(hbhtml_c8_kw[125], job->of); if(!hbhtml_url_output_for_text(job, bu)) { job->exv = 1; } if(appendind) { fputs(hbhtml_c8_kw[appendind], job->of); } fputs(hbhtml_c8_kw[126], job->of); } else { job->exv = 1; } } else { fputs(hbhtml_c8_kw[123], job->of); fputs(hbhtml_c8_kw[linkkwind], job->of); fputs(hbhtml_c8_kw[124], job->of); if(!hbhtml_output_for_text(job, (job->msg)[titleind])) { job->exv = 1; } fputs(hbhtml_c8_kw[125], job->of); if(!hbhtml_url_output_for_text(job, url)) { job->exv = 1; } if(appendind) { fputs(hbhtml_c8_kw[appendind], job->of); } fputs(hbhtml_c8_kw[126], job->of); } } /** Write navigation entries to HTML header. @param job Job structure. @param node Current node to write. @param prev Previous node. @param next Next node. */ static void hbhtml_write_head_navigation( hb_job_t *job, hb_node_t *node, hb_node_t *prev, hb_node_t *next ) { hb_node_t *nptr; /* Current node to process */ /* Navigation (links) author (impressum), contents, index, top, up, first, prev, next, last link rel="..." title="..." href="..." */ if(job->impressumnode) { nptr = job->impressumnode; hbhtml_one_head_navigation(job, nptr, NULL, 0, 127, 0); } else { if(job->impressumlink) { hbhtml_one_head_navigation(job, NULL, job->impressumlink, 61, 127, 0); } } if(job->rootnode) { hbhtml_one_head_navigation( job, job->rootnode, NULL, 0, 128, (((job->options) & HB_JOB_OPT_CREATE_TOC) ? 136 : 0) ); hbhtml_one_head_navigation( job, job->rootnode, NULL, 0, 129, (((job->options) & HB_JOB_OPT_CREATE_INDEX) ? 137 : 0) ); hbhtml_one_head_navigation(job, job->rootnode, NULL, 0, 130, 0); } nptr = node; nptr = nptr->parent; if(nptr) { while((!(nptr->filename)) && (nptr->parent)) { nptr = nptr->parent; } if(nptr) { hbhtml_one_head_navigation(job, nptr, NULL, 0, 131, 0); } } if(job->firstnode) { hbhtml_one_head_navigation(job, job->firstnode, NULL, 0, 132, 0); } if(prev) { hbhtml_one_head_navigation(job, prev, NULL, 0, 133, 0); } if(next) { hbhtml_one_head_navigation(job, next, NULL, 0, 134, 0); } if(job->lastnode) { hbhtml_one_head_navigation(job, job->lastnode, NULL, 0, 135, 0); } } /** Write HTML header @param job Job structure. @param nodeptr Current node to write. @param prev Previous node. @param next Next node. */ static void hbhtml_write_header( hb_job_t *job, hb_node_t *nodeptr, hb_node_t *prev, hb_node_t *next ) { dkChar const *ptr; /* Multiple text elements */ $? "+ hbhtml_write_header" fputs(hbhtml_c8_kw[15], job->of); /* Title */ fputs(hbhtml_c8_kw[19], job->of); hbhtml_output_for_text(job, hbconf_title(nodeptr)); fputs(hbhtml_c8_kw[20], job->of); /* Generator (comment) */ if((nodeptr->options) & HB_NODE_OPT_USE_TIDY) { fputs(hbhtml_c8_kw[17], job->of); } /* Generator (meta) */ fputs(hbhtml_c8_kw[18], job->of); /* Style (link) */ ptr = hbconf_stylefile(nodeptr); if(ptr) { if(!hbtool_add_file(job, ptr)) { job->exv = 1; } fputs(hbhtml_c8_kw[21], job->of); hbhtml_url_output_for_text(job, ptr); fputs(hbhtml_c8_kw[22], job->of); } /* Shortcut icon (link) */ ptr = hbconf_favicon(nodeptr); if(ptr) { fputs(hbhtml_c8_kw[27], job->of); hbhtml_url_output_for_text(job, ptr); fputs(hbhtml_c8_kw[28], job->of); } /* Navigation (links) */ hbhtml_write_head_navigation(job, nodeptr, prev, next); /* Character set (meta) */ if(HB_CS_UTF_8 == job->cs) { fputs(hbhtml_c8_kw[24], job->of); } else { fputs(hbhtml_c8_kw[23], job->of); } /* Author (meta) */ ptr = hbconf_author(nodeptr); if(ptr) { fputs(hbhtml_c8_kw[25], job->of); hbhtml_output_for_text(job, ptr); fputs(hbhtml_c8_kw[26], job->of); } /* Meta description tag */ if (NULL != nodeptr->metadesc) { fputs(hbhtml_c8_kw[154], job->of); hbhtml_output_for_text(job, nodeptr->metadesc); fputs(hbhtml_c8_kw[26], job->of); } /* Meta keywords tag. */ if (NULL != nodeptr->metakeyw) { fputs(hbhtml_c8_kw[155], job->of); hbhtml_output_for_text(job, nodeptr->metakeyw); fputs(hbhtml_c8_kw[26], job->of); } /* JavaScript files. */ (void)hbhtml_write_js_files(job, nodeptr); fputs(hbhtml_c8_kw[16], job->of); $? "- hbhtml_write_header" } /** Line handler processing function. @param obj Handler object. @param il Input line to process. @return 1 on success, 0 on error (continue), -1 on error (exit). */ static int hbhtml_spcl_handler(void *obj, dkChar *il) { hb_spc_reader_t *pspcr; hb_job_t *job = NULL; hb_node_t *nptr = NULL; hb_link_t *linkptr= NULL; dkChar *vptr = NULL; dkChar *cptr = NULL; size_t sl = 0; int back = 1; int idx = 0; $? "+ hbhtml_spcl_handler \"%!ds\"", il pspcr = (hb_spc_reader_t *)obj; if (NULL != pspcr) { job = pspcr->job; nptr = pspcr->nodeptr; pspcr->lineno += 1UL; dk3app_set_source_line(job->app, pspcr->lineno); idx = hbcont_metadata_index(il); if (0 <= idx) { $? ". meta data found" dk3str_delnl(il); sl = hbcont_metadata_length(idx); if (0 < sl) { sl++; vptr = dk3str_start(&(il[sl]), NULL); $? ". value \"%!ds\"", vptr } switch (idx) { case 0: { $? ". description" if (NULL != vptr) { $? ". value ok" cptr = dk3str_dup_app(vptr, job->app); if (NULL != cptr) { $? ". allocation ok" if (NULL != nptr->metadesc) { /* Warning: Overwriting description text */ dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 97); dk3mem_free(nptr->metadesc); } nptr->metadesc = cptr; } } else { /* ERROR: Missing description text */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 96); back = -1; } } break; case 1: { $? ". keywords" if (NULL != vptr) { $? ". value ok" cptr = dk3str_dup_app(vptr, job->app); if (NULL != cptr) { $? ". allocation ok" if (NULL != nptr->metakeyw) { /* Warning: Overwriting keywords */ dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 98); dk3mem_free(nptr->metakeyw); } nptr->metakeyw = cptr; } } else { /* ERROR: Missing keywords text */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 96); back = -1; } } break; case 2: { $? ". author" if (NULL != vptr) { cptr = dk3str_dup_app(vptr, job->app); if (NULL != cptr) { if (NULL != nptr->author) { if (0UL != nptr->objno) { dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 69); } dk3mem_free(nptr->author); } nptr->author = cptr; } else { back = -1; } } else { /* ERROR: Missing author name */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 96); back = -1; } } break; case 3: { $? ". title" if (NULL != vptr) { cptr = dk3str_dup_app(vptr, job->app); if (NULL != cptr) { if (NULL != nptr->fulltitle) { /* Warning: Overwriting title */ dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 70); dk3mem_free(nptr->fulltitle); } nptr->fulltitle = cptr; } else { back = -1; } } else { /* ERROR: Missing title text */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 96); back = -1; } } break; case 4: { $? ". short title" if (NULL != vptr) { cptr = dk3str_dup_app(vptr, job->app); if (NULL != cptr) { if (NULL != nptr->shorttitle) { /* Warning: Overwriting short title */ dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 75); dk3mem_free(nptr->shorttitle); } nptr->shorttitle = cptr; } else { back = -1; } } else { /* ERROR: Missing short title text */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 96); back = -1; } } break; case 5: { $? ". location" if (NULL != vptr) { cptr = dk3str_dup_app(vptr, job->app); if (NULL != cptr) { if (NULL != nptr->location) { /* Warning: Overwriting location */ dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 99); dk3mem_free(nptr->location); } nptr->location = cptr; } else { back = -1; } } else { /* ERROR: Missing location text */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 96); back = -1; } } break; case 6: { $? ". page-toc" if (NULL != vptr) { if (0 != dk3str_is_bool(vptr)) { if (0 != dk3str_is_on(vptr)) { (job->currentnode)->options |= HB_NODE_OPT_PAGE_TOC; } else { (job->currentnode)->options &= (~(HB_NODE_OPT_PAGE_TOC)); } } else { dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 144, vptr); back = -1; } } else { (job->currentnode)->options |= HB_NODE_OPT_PAGE_TOC; } } break; case 7: { $? ". replace-ampersand" if (NULL != vptr) { if (0 != dk3str_is_bool(vptr)) { if (0 != dk3str_is_on(vptr)) { (job->currentnode)->options |= HB_NODE_OPT_REPLACE_AMPERSAND; } else { (job->currentnode)->options &= (~(HB_NODE_OPT_REPLACE_AMPERSAND)); } } else { dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 144, vptr); back = -1; } } else { (job->currentnode)->options |= HB_NODE_OPT_REPLACE_AMPERSAND; } } break; case 8: { $? ". write-position" if (NULL != vptr) { if (0 != dk3str_is_bool(vptr)) { if (0 != dk3str_is_on(vptr)) { (job->currentnode)->options |= HB_NODE_OPT_HEADER_CHAIN; } else { (job->currentnode)->options &= (~(HB_NODE_OPT_HEADER_CHAIN)); } } else { dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 144, vptr); back = -1; } } else { (job->currentnode)->options |= HB_NODE_OPT_HEADER_CHAIN; } } break; case 9: { $? ". suffix" if (NULL != vptr) { cptr = dk3str_dup_app(vptr, job->app); if (NULL != cptr) { if (NULL != nptr->suffix) { /* Warning: Overwriting suffix */ dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 77); dk3mem_free(nptr->suffix); } nptr->suffix = cptr; } else { back = -1; } } else { /* ERROR: Missing suffix */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 96); back = -1; } } break; case 10: { $? ". shortcut-icon" if (NULL != vptr) { cptr = dk3str_dup_app(vptr, job->app); if (NULL != cptr) { dk3str_correct_filename(cptr); hbtool_correct_backslash_to_slash(cptr); if (NULL != nptr->favicon) { /* Warning: Overwriting favicon */ dk3app_log_1(job->app, DK3_LL_WARNING, job->msg, 82); dk3mem_free(nptr->favicon); } nptr->favicon = cptr; if (!(hbtool_add_file(job, cptr))) { back = -1; } if(!hbtool_check_filename_encoding(job, cptr)) { back = -1; } } else { back = -1; } } else { /* ERROR: Missing icon name */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 96); back = -1; } } break; case 11: { $? ". js-file" if (NULL != vptr) { if (NULL == nptr->s_jsfiles) { nptr->s_jsfiles = dk3sto_open_app(job->app); if (NULL != nptr->s_jsfiles) { dk3sto_set_comp(nptr->s_jsfiles, hbnode_link_compare, 2); } } if (NULL == nptr->i_jsfiles) { if (NULL != nptr->s_jsfiles) { nptr->i_jsfiles = dk3sto_it_open(nptr->s_jsfiles); } } if ((NULL != nptr->s_jsfiles) && (NULL != nptr->i_jsfiles)) { linkptr = hbnode_link_new(vptr, nptr->nextjs, job->app); if (NULL != linkptr) { if(dk3sto_add(nptr->s_jsfiles, linkptr)) { nptr->nextjs += 1UL; if(!hbtool_add_url(job, vptr)) { back = -1; } } else { hbnode_link_delete(linkptr); back = -1; } } else { back = -1; } } else { back = -1; } } else { /* ERROR: Missing file name */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 96); back = -1; } } break; case 12: { $? ". inherit-js" if (NULL != vptr) { if (0 != dk3str_is_bool(vptr)) { if (0 != dk3str_is_on(vptr)) { (job->currentnode)->options &= (~(HB_NODE_OPT_STOP_JS_INHERITANCE)); } else { (job->currentnode)->options |= HB_NODE_OPT_STOP_JS_INHERITANCE; } } else { dk3app_log_i3(job->app, DK3_LL_ERROR, 146, 144, vptr); back = -1; } } else { (job->currentnode)->options &= (~(HB_NODE_OPT_STOP_JS_INHERITANCE)); } } break; case 13: { $? ". context-number" long cn; if (NULL != vptr) { if (0 != dk3ma_l_from_string(&cn, vptr, NULL)) { nptr->contnum = cn; } else { dk3app_log_i1(job->app, DK3_LL_ERROR, 141); back = -1; } } else { /* ERROR: Missing number */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 96); back = -1; } } break; } } } $? "- hbhtml_spcl_handler %d", back return back; } /** Read special comments from input file for node. @param job Job structure. @param nodeptr Node to read file for. */ static void hbhtml_read_special_comments(hb_job_t *job, hb_node_t *nodeptr) { hb_spc_reader_t spcr; const dkChar *oldsourcefile; unsigned long oldsourceline; int inenc; $? "+ hbhtml_read_special_comments" if (NULL != nodeptr->filename) { $? ". have file name" spcr.job = job; spcr.nodeptr = nodeptr; spcr.lineno = 0UL; inenc = dk3app_get_input_file_encoding(job->app); if(0 <= job->iecmd) { inenc = job->iecmd; } if(0 <= nodeptr->inenc) { inenc = nodeptr->inenc; } oldsourcefile = dk3app_get_source_file(job->app); oldsourceline = dk3app_get_source_line(job->app); dk3app_set_source_file(job->app, nodeptr->filename); dk3app_set_source_line(job->app, 0UL); (void)dk3stream_process_filename_lines_app( (void *)(&spcr), hbhtml_spcl_handler, nodeptr->filename, job->ilfile, job->bs, dk3app_get_encoding(job->app), inenc, job->app ); dk3app_set_source_file(job->app, oldsourcefile); dk3app_set_source_line(job->app, oldsourceline); } $? "- hbhtml_read_special_comments" } /** Write one output file. @param job Job structure. @param nodeptr Current node to write. @param fn Output file name. @param p Previous node. @param n Next node. */ static void hbhtml_write_named_file( hb_job_t *job, hb_node_t *nodeptr, dkChar const *fn, hb_node_t *p, hb_node_t *n ) { hb_file_processor_t proc; /* Template file processor */ dkChar const *templateName; /* Template file name */ dkChar const *oldsourcefile; /* Old source file name */ unsigned long oldsourceline; /* Old source file line */ int inenc; /* Input encoding */ int res; /* Result from file processing */ $? "+ hbhtml_write_named_file" $? ". input file \"%!ds\"", TR_STR(nodeptr->filename) $? ". output file \"%!ds\"", fn oldsourcefile = dk3app_get_source_file(job->app); oldsourceline = dk3app_get_source_line(job->app); dk3app_set_source_line(job->app, nodeptr->lineno); nodeptr->outFileName = fn; job->currentnode = nodeptr; job->of = NULL; templateName = hbconf_node_template(job, nodeptr); if(templateName) { dk3app_set_source_file(job->app, templateName); job->options &= (~(HB_JOB_OPT_CODE)); job->of = dk3sf_fopen_app(fn, dkT("w"), job->app); if(job->of) { hbhtml_read_special_comments(job, nodeptr); fputs(hbhtml_c8_kw[11], job->of); hbhtml_write_header(job, nodeptr, p, n); fputs(hbhtml_c8_kw[13], job->of); proc.job = job; proc.in_template = 1; proc.stm = 0; proc.p = p; proc.n = n; inenc = dk3app_get_input_file_encoding(job->app); if(0 <= job->iecmd) { inenc = job->iecmd; } res = dk3stream_process_filename_lines_app( (void *)(&proc), hbhtml_line_handler, templateName, job->iltemplate, job->bs, dk3app_get_encoding(job->app), inenc, job->app ); fputs(hbhtml_c8_kw[14], job->of); fputs(hbhtml_c8_kw[12], job->of); if(1 != res) { job->exv = 1; $? "! ERROR" } if(!(dk3sf_fclose_fn_app(job->of, fn, job->app))) { job->exv = 1; $? "! ERROR" } } else { job->exv = 1; $? "! ERROR" } } else { /* ERROR: No template! */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 19); job->exv = 1; $? "! ERROR" } nodeptr->outFileName = NULL; dk3app_set_source_file(job->app, oldsourcefile); dk3app_set_source_line(job->app, oldsourceline); $? "- hbhtml_write_named_file" } /** Mark path to current node in parent nodes (set the curchild element). @param nodeptr Current node. */ static void hbhtml_mark_path(hb_node_t *nodeptr) { hb_node_t *cp; /* Current node */ $? "+ hbhtml_mark_path" cp = nodeptr; cp->curchild = NULL; while(cp) { if(cp->parent) { (cp->parent)->curchild = cp; } cp = cp->parent; } $? "- hbhtml_mark_path" } void hbhtml_write_file(hb_job_t *job, hb_node_t *nodeptr, hb_node_t *p, hb_node_t *n) { dkChar bu[DK3_MAX_PATH]; /* File name buffer. */ $? "+ hbhtml_write_file %lu \"%!ds\"", nodeptr->objno, TR_STR(nodeptr->title) /* Set things up for new file. */ job->coli = 0; job->cols = HB_COLIST_NONE; job->options &= (~(HB_JOB_OPT_CODE)); /* Process the file. */ hbhtml_mark_path(nodeptr); if(hbhtml_create_output_filename(bu, DK3_SIZEOF(bu,dkChar), job, nodeptr)) { $? ". have output file name" hbhtml_write_named_file(job, nodeptr, bu, p, n); } else { job->exv = 1; $? "! ERROR" } $? "- hbhtml_write_file" }