X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/halibut/blobdiff_plain/b0fe32e877d8145d6cdb23981b46b3d37319acc8..0dfaac7284d7f1a54e957bba4a881d93328c1630:/bk_html.c diff --git a/bk_html.c b/bk_html.c index 433dde1..e3202a5 100644 --- a/bk_html.c +++ b/bk_html.c @@ -37,7 +37,7 @@ (p)->type == para_Title ? -1 : 0 ) typedef struct { - int just_numbers; + int number_at_all, just_numbers; wchar_t *number_suffix; } sectlevel; @@ -49,6 +49,7 @@ typedef struct { int address_section, visible_version_id; int leaf_contains_contents, leaf_smallest_contents; int navlinks; + int rellinks; char *contents_filename; char *index_filename; char *template_filename; @@ -60,7 +61,7 @@ typedef struct { char *body_tag, *nav_attr; wchar_t *author, *description; wchar_t *index_text, *contents_text, *preamble_text, *title_separator; - wchar_t *nav_prev_text, *nav_next_text, *nav_separator; + wchar_t *nav_prev_text, *nav_next_text, *nav_up_text, *nav_separator; wchar_t *index_main_sep, *index_multi_sep; wchar_t *pre_versionid, *post_versionid; int restrict_charset, output_charset; @@ -247,10 +248,12 @@ static htmlconfig html_configure(paragraph *source) { */ ret.leaf_level = 2; ret.achapter.just_numbers = FALSE; + ret.achapter.number_at_all = TRUE; ret.achapter.number_suffix = L": "; ret.nasect = 1; ret.asect = snewn(ret.nasect, sectlevel); ret.asect[0].just_numbers = TRUE; + ret.asect[0].number_at_all = TRUE; ret.asect[0].number_suffix = L" "; ret.ncdepths = 0; ret.contents_depths = 0; @@ -259,6 +262,7 @@ static htmlconfig html_configure(paragraph *source) { ret.leaf_contains_contents = FALSE; ret.leaf_smallest_contents = 4; ret.navlinks = TRUE; + ret.rellinks = TRUE; ret.single_filename = dupstr("Manual.html"); ret.contents_filename = dupstr("Contents.html"); ret.index_filename = dupstr("IndexPage.html"); @@ -280,6 +284,7 @@ static htmlconfig html_configure(paragraph *source) { ret.title_separator = L" - "; ret.nav_prev_text = L"Previous"; ret.nav_next_text = L"Next"; + ret.nav_up_text = L"Up"; ret.nav_separator = L" | "; ret.index_main_sep = L": "; ret.index_multi_sep = L", "; @@ -379,8 +384,12 @@ static htmlconfig html_configure(paragraph *source) { error(err_cfginsufarg, &p->fpos, p->origkeyword, 1); } else if (!ustricmp(k, L"html-chapter-numeric")) { ret.achapter.just_numbers = utob(uadv(k)); + } else if (!ustricmp(k, L"html-chapter-shownumber")) { + ret.achapter.number_at_all = utob(uadv(k)); } else if (!ustricmp(k, L"html-suppress-navlinks")) { ret.navlinks = !utob(uadv(k)); + } else if (!ustricmp(k, L"html-rellinks")) { + ret.rellinks = utob(uadv(k)); } else if (!ustricmp(k, L"html-chapter-suffix")) { ret.achapter.number_suffix = uadv(k); } else if (!ustricmp(k, L"html-leaf-level")) { @@ -406,6 +415,21 @@ static htmlconfig html_configure(paragraph *source) { ret.nasect = n+1; } ret.asect[n].just_numbers = utob(q); + } else if (!ustricmp(k, L"html-section-shownumber")) { + wchar_t *q = uadv(k); + int n = 0; + if (uisdigit(*q)) { + n = utoi(q); + q = uadv(q); + } + if (n >= ret.nasect) { + int i; + ret.asect = sresize(ret.asect, n+1, sectlevel); + for (i = ret.nasect; i <= n; i++) + ret.asect[i] = ret.asect[ret.nasect-1]; + ret.nasect = n+1; + } + ret.asect[n].number_at_all = utob(q); } else if (!ustricmp(k, L"html-section-suffix")) { wchar_t *q = uadv(k); int n = 0; @@ -490,6 +514,8 @@ static htmlconfig html_configure(paragraph *source) { ret.nav_prev_text = uadv(k); } else if (!ustricmp(k, L"html-nav-next-text")) { ret.nav_next_text = uadv(k); + } else if (!ustricmp(k, L"html-nav-up-text")) { + ret.nav_up_text = uadv(k); } else if (!ustricmp(k, L"html-nav-separator")) { ret.nav_separator = uadv(k); } else if (!ustricmp(k, L"html-index-main-separator")) { @@ -858,7 +884,10 @@ void html_backend(paragraph *sourceform, keywordlist *keywords, #define listname(lt) ( (lt)==UL ? "ul" : (lt)==OL ? "ol" : "dl" ) #define itemname(lt) ( (lt)==LI ? "li" : (lt)==DT ? "dt" : "dd" ) - ho.fp = fopen(f->filename, "w"); + if (!strcmp(f->filename, "-")) + ho.fp = stdout; + else + ho.fp = fopen(f->filename, "w"); if (!ho.fp) error(err_cantopenw, f->filename); @@ -957,6 +986,49 @@ void html_backend(paragraph *sourceform, keywordlist *keywords, element_close(&ho, "title"); html_nl(&ho); + if (conf.rellinks) { + + if (prevf) { + element_empty(&ho, "link"); + element_attr(&ho, "rel", "previous"); + element_attr(&ho, "href", prevf->filename); + html_nl(&ho); + } + + if (f != files.head) { + element_empty(&ho, "link"); + element_attr(&ho, "rel", "ToC"); + element_attr(&ho, "href", files.head->filename); + html_nl(&ho); + } + + if (conf.leaf_level > 0) { + htmlsect *p = f->first->parent; + assert(p == f->last->parent); + if (p) { + element_empty(&ho, "link"); + element_attr(&ho, "rel", "up"); + element_attr(&ho, "href", p->file->filename); + html_nl(&ho); + } + } + + if (has_index && files.index && f != files.index) { + element_empty(&ho, "link"); + element_attr(&ho, "rel", "index"); + element_attr(&ho, "href", files.index->filename); + html_nl(&ho); + } + + if (f->next) { + element_empty(&ho, "link"); + element_attr(&ho, "rel", "next"); + element_attr(&ho, "href", f->next->filename); + html_nl(&ho); + } + + } + if (conf.head_end) html_raw(&ho, conf.head_end); @@ -1019,6 +1091,22 @@ void html_backend(paragraph *sourceform, keywordlist *keywords, if (f != files.head) element_close(&ho, "a"); + /* We don't bother with "Up" links for leaf-level 1, + * as they would be identical to the "Contents" links. */ + if (conf.leaf_level >= 2) { + htmlsect *p = f->first->parent; + assert(p == f->last->parent); + html_text(&ho, conf.nav_separator); + if (p) { + element_open(&ho, "a"); + element_attr(&ho, "href", p->file->filename); + } + html_text(&ho, conf.nav_up_text); + if (p) { + element_close(&ho, "a"); + } + } + if (has_index && files.index) { html_text(&ho, conf.nav_separator); if (f != files.index) { @@ -1580,6 +1668,8 @@ void html_backend(paragraph *sourceform, keywordlist *keywords, /* * Output the MS HTML Help supporting files, if requested. + * + * A good unofficial reference for these is . */ if (conf.hhp_filename) { htmlfile *f; @@ -1599,6 +1689,8 @@ void html_backend(paragraph *sourceform, keywordlist *keywords, fprintf(ho.fp, "[OPTIONS]\n" + /* Binary TOC required for Next/Previous nav to work */ + "Binary TOC=Yes\n" "Compatibility=1.1 or later\n" "Compiled file=%s\n" "Default Window=main\n" @@ -1633,7 +1725,17 @@ void html_backend(paragraph *sourceform, keywordlist *keywords, NULL, keywords, &conf); fprintf(ho.fp, "\",\"%s\",\"%s\",\"%s\",,,,,," - "0x42520,,0x3876,,,,,,,,0\n", + /* This first magic number is fsWinProperties, controlling + * Navigation Pane options and the like. + * Constants HHWIN_PROP_* in htmlhelp.h. */ + "0x62520,," + /* This second number is fsToolBarFlags, mainly controlling + * toolbar buttons. Constants HHWIN_BUTTON_*. + * NOTE: there are two pairs of bits for Next/Previous + * buttons: 7/8 (which do nothing useful), and 21/22 + * (which work). (Neither of these are exposed in the HHW + * UI, but they work fine in HH.) We use the latter. */ + "0x60304e,,,,,,,,0\n", conf.hhc_filename ? conf.hhc_filename : "", hhk_filename ? hhk_filename : "", files.head->filename); @@ -2074,7 +2176,7 @@ static void html_words(htmloutput *ho, word *words, int flags, htmlfile *file, keywordlist *keywords, htmlconfig *cfg) { word *w; - char *c; + char *c, *c2, *p, *q; int style, type; for (w = words; w; w = w->next) switch (w->type) { @@ -2082,7 +2184,20 @@ static void html_words(htmloutput *ho, word *words, int flags, if (flags & LINKS) { element_open(ho, "a"); c = utoa_dup(w->text, CS_ASCII); - element_attr(ho, "href", c); + c2 = snewn(1 + 10*strlen(c), char); + for (p = c, q = c2; *p; p++) { + if (*p == '&') + q += sprintf(q, "&"); + else if (*p == '<') + q += sprintf(q, "<"); + else if (*p == '>') + q += sprintf(q, ">"); + else + *q++ = *p; + } + *q = '\0'; + element_attr(ho, "href", c2); + sfree(c2); sfree(c); } break; @@ -2408,7 +2523,7 @@ static void html_text_limit_internal(htmloutput *ho, wchar_t const *text, static void cleanup(htmloutput *ho) { return_to_neutral(ho); - if (ho->fp) + if (ho->fp && ho->fp != stdout) fclose(ho->fp); } @@ -2686,7 +2801,7 @@ static void html_section_title(htmloutput *ho, htmlsect *s, htmlfile *thisfile, else sl = &cfg->asect[cfg->nasect-1]; - if (!sl) + if (!sl || !sl->number_at_all) number = NULL; else if (sl->just_numbers) number = s->title->kwtext2;