char *index_filename;
char *template_filename;
char *single_filename;
- char *template_fragment;
+ char **template_fragments;
+ int ntfragments;
char *head_end, *body_start, *body_end, *addr_start, *addr_end;
char *body_tag, *nav_attr;
wchar_t *author, *description;
paragraph *title, *text;
enum { NORMAL, TOP, INDEX } type;
int contents_depth;
- char *fragment;
+ char **fragments;
};
typedef struct {
htmlsect *sect, int depth);
static htmlfile *html_new_file(htmlfilelist *list, char *filename);
-static htmlsect *html_new_sect(htmlsectlist *list, paragraph *title);
+static htmlsect *html_new_sect(htmlsectlist *list, paragraph *title,
+ htmlconfig *cfg);
/* Flags for html_words() flags parameter */
#define NOTHING 0x00
ret.contents_filename = dupstr("Contents.html");
ret.index_filename = dupstr("IndexPage.html");
ret.template_filename = dupstr("%n.html");
- ret.template_fragment = dupstr("%b");
+ ret.ntfragments = 1;
+ ret.template_fragments = snewn(ret.ntfragments, char *);
+ ret.template_fragments[0] = dupstr("%b");
ret.head_end = ret.body_tag = ret.body_start = ret.body_end =
ret.addr_start = ret.addr_end = ret.nav_attr = NULL;
ret.author = ret.description = NULL;
sfree(ret.template_filename);
ret.template_filename = dupstr(adv(p->origkeyword));
} else if (!ustricmp(k, L"html-template-fragment")) {
- sfree(ret.template_fragment);
- ret.template_fragment = dupstr(adv(p->origkeyword));
+ char *frag = adv(p->origkeyword);
+ if (*frag) {
+ while (ret.ntfragments--)
+ sfree(ret.template_fragments[ret.ntfragments]);
+ sfree(ret.template_fragments);
+ ret.template_fragments = NULL;
+ ret.ntfragments = 0;
+ while (*frag) {
+ ret.ntfragments++;
+ ret.template_fragments =
+ sresize(ret.template_fragments,
+ ret.ntfragments, char *);
+ ret.template_fragments[ret.ntfragments-1] =
+ dupstr(frag);
+ frag = adv(frag);
+ }
+ } else
+ 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-suffix")) {
htmlconfig conf;
htmlfilelist files = { NULL, NULL, NULL, NULL, NULL };
htmlsectlist sects = { NULL, NULL }, nonsects = { NULL, NULL };
+ int has_index;
IGNORE(unused);
* source form but needs to be consistently mentioned in
* contents links.
*
- * While we're here, we'll also invent the HTML fragment name
+ * While we're here, we'll also invent the HTML fragment name(s)
* for each section.
*/
{
htmlsect *topsect, *sect;
int d;
- topsect = html_new_sect(§s, NULL);
+ topsect = html_new_sect(§s, NULL, &conf);
topsect->type = TOP;
topsect->title = NULL;
topsect->text = sourceform;
topsect->contents_depth = contents_depth(conf, 0);
html_file_section(&conf, &files, topsect, -1);
- topsect->fragment = NULL;
for (p = sourceform; p; p = p->next)
if (is_heading_type(p->type)) {
continue;
}
- sect = html_new_sect(§s, p);
+ sect = html_new_sect(§s, p, &conf);
sect->text = p->next;
sect->contents_depth = contents_depth(conf, d+1) - (d+1);
html_file_section(&conf, &files, sect, d);
- sect->fragment = html_format(p, conf.template_fragment);
- sect->fragment = html_sanitise_fragment(&files, sect->file,
- sect->fragment);
+ {
+ int i;
+ for (i=0; i < conf.ntfragments; i++) {
+ sect->fragments[i] =
+ html_format(p, conf.template_fragments[i]);
+ sect->fragments[i] =
+ html_sanitise_fragment(&files, sect->file,
+ sect->fragments[i]);
+ }
+ }
}
- /* And the index. */
- sect = html_new_sect(§s, NULL);
- sect->text = NULL;
- sect->type = INDEX;
- sect->parent = topsect;
- html_file_section(&conf, &files, sect, 0); /* peer of chapters */
- sect->fragment = utoa_dup(conf.index_text, CS_ASCII);
- sect->fragment = html_sanitise_fragment(&files, sect->file,
- sect->fragment);
- files.index = sect->file;
+ /* And the index, if we have one. */
+ has_index = (count234(idx->entries) > 0);
+ if (has_index) {
+ sect = html_new_sect(§s, NULL, &conf);
+ sect->text = NULL;
+ sect->type = INDEX;
+ sect->parent = topsect;
+ sect->contents_depth = 0;
+ html_file_section(&conf, &files, sect, 0); /* peer of chapters */
+ sect->fragments[0] = utoa_dup(conf.index_text, CS_ASCII);
+ sect->fragments[0] = html_sanitise_fragment(&files, sect->file,
+ sect->fragments[0]);
+ files.index = sect->file;
+ }
}
/*
* won't attempt to add it to the contents or
* anything weird like that).
*/
- sect = html_new_sect(&nonsects, p);
+ sect = html_new_sect(&nonsects, p, &conf);
sect->file = parent->file;
sect->parent = parent;
p->private_data = sect;
* Fragment IDs for these paragraphs will simply be
* `p' followed by an integer.
*/
- sect->fragment = snewn(40, char);
- sprintf(sect->fragment, "p%d",
+ sect->fragments[0] = snewn(40, char);
+ sprintf(sect->fragments[0], "p%d",
sect->file->last_fragment_number++);
- sect->fragment = html_sanitise_fragment(&files, sect->file,
- sect->fragment);
+ sect->fragments[0] = html_sanitise_fragment(&files, sect->file,
+ sect->fragments[0]);
}
}
}
if (conf.head_end)
html_raw(&ho, conf.head_end);
+ /*
+ * Add any <head> data defined in specific sections
+ * that go in this file. (This is mostly to allow <meta
+ * name="AppleTitle"> tags for Mac online help.)
+ */
+ for (s = sects.head; s; s = s->next) {
+ if (s->file == f && s->text) {
+ for (p = s->text;
+ p && (p == s->text || p->type == para_Title ||
+ !is_heading_type(p->type));
+ p = p->next) {
+ if (p->type == para_Config) {
+ if (!ustricmp(p->keyword, L"html-local-head")) {
+ html_raw(&ho, adv(p->origkeyword));
+ }
+ }
+ }
+ }
+ }
+
element_close(&ho, "head");
html_nl(&ho);
if (f != files.head)
element_close(&ho, "a");
- html_text(&ho, conf.nav_separator);
-
- if (f != files.index) {
- element_open(&ho, "a");
- element_attr(&ho, "href", files.index->filename);
+ if (has_index) {
+ html_text(&ho, conf.nav_separator);
+ if (f != files.index) {
+ element_open(&ho, "a");
+ element_attr(&ho, "href", files.index->filename);
+ }
+ html_text(&ho, conf.index_text);
+ if (f != files.index)
+ element_close(&ho, "a");
}
- html_text(&ho, conf.index_text);
- if (f != files.index)
- element_close(&ho, "a");
html_text(&ho, conf.nav_separator);
prevf = f;
/*
- * Write out a prefix TOC for the file.
+ * Write out a prefix TOC for the file (if a leaf file).
*
* We start by going through the section list and
* collecting the sections which need to be added to
*/
displaying = TRUE;
} else {
+ /*
+ * Doesn't belong in this file, but it may be
+ * a descendant of a section which does, in
+ * which case we should consider it for the
+ * main TOC of this file (for non-leaf files).
+ */
htmlsect *a, *ac;
int depth, adepth;
element_open(&ho, htag);
/*
- * Provide anchor for cross-links to target.
+ * Provide anchor(s) for cross-links to target.
*
* (Also we'll have to do this separately in
* other paragraph types - NumberedList and
* BiblioCited.)
*/
- if (s->fragment)
- html_fragment(&ho, s->fragment);
+ {
+ int i;
+ for (i=0; i < conf.ntfragments; i++)
+ if (s->fragments[i])
+ html_fragment(&ho, s->fragments[i]);
+ }
html_section_title(&ho, s, f, keywords, &conf, TRUE);
element_open(&ho, "p");
if (p->private_data) {
htmlsect *s = (htmlsect *)p->private_data;
- html_fragment(&ho, s->fragment);
+ int i;
+ for (i=0; i < conf.ntfragments; i++)
+ if (s->fragments[i])
+ html_fragment(&ho, s->fragments[i]);
}
html_nl(&ho);
html_words(&ho, p->kwtext, ALL,
element_open(&ho, "li");
if (p->private_data) {
htmlsect *s = (htmlsect *)p->private_data;
- html_fragment(&ho, s->fragment);
+ int i;
+ for (i=0; i < conf.ntfragments; i++)
+ if (s->fragments[i])
+ html_fragment(&ho, s->fragments[i]);
}
html_nl(&ho);
stackhead->itemtype = LI;
/*
* Free all the working data.
*/
- sfree(conf.asect);
- sfree(conf.single_filename);
- sfree(conf.contents_filename);
- sfree(conf.index_filename);
- sfree(conf.template_filename);
- sfree(conf.template_fragment);
{
htmlfragment *frag;
while ( (frag = (htmlfragment *)delpos234(files.frags, 0)) != NULL ) {
htmlsect *sect, *tmp;
sect = sects.head;
while (sect) {
+ int i;
tmp = sect->next;
- sfree(sect->fragment);
+ for (i=0; i < conf.ntfragments; i++)
+ sfree(sect->fragments[i]);
+ sfree(sect->fragments);
sfree(sect);
sect = tmp;
}
sect = nonsects.head;
while (sect) {
+ int i;
tmp = sect->next;
- sfree(sect->fragment);
+ for (i=0; i < conf.ntfragments; i++)
+ sfree(sect->fragments[i]);
+ sfree(sect->fragments);
sfree(sect);
sect = tmp;
}
sfree(hr);
}
}
+ sfree(conf.asect);
+ sfree(conf.single_filename);
+ sfree(conf.contents_filename);
+ sfree(conf.index_filename);
+ sfree(conf.template_filename);
+ while (conf.ntfragments--)
+ sfree(conf.template_fragments[conf.ntfragments]);
+ sfree(conf.template_fragments);
}
static void html_file_section(htmlconfig *cfg, htmlfilelist *files,
return ret;
}
-static htmlsect *html_new_sect(htmlsectlist *list, paragraph *title)
+static htmlsect *html_new_sect(htmlsectlist *list, paragraph *title,
+ htmlconfig *cfg)
{
htmlsect *ret = snew(htmlsect);
ret->parent = NULL;
ret->type = NORMAL;
+ ret->fragments = snewn(cfg->ntfragments, char *);
+ {
+ int i;
+ for (i=0; i < cfg->ntfragments; i++)
+ ret->fragments[i] = NULL;
+ }
+
return ret;
}
case word_LowerXref:
if (flags & LINKS) {
keyword *kwl = kw_lookup(keywords, w->text);
- paragraph *p = kwl->para;
- htmlsect *s = (htmlsect *)p->private_data;
+ paragraph *p;
+ htmlsect *s;
+
+ assert(kwl);
+ p = kwl->para;
+ s = (htmlsect *)p->private_data;
assert(s);
- html_href(ho, file, s->file, s->fragment);
+ html_href(ho, file, s->file, s->fragments[0]);
}
break;
case word_HyperEnd:
} else if (p->keyword && *p->keyword && fmt == 'k')
ws = p->keyword;
else
+ /* %N comes here; also failure cases of other fmts */
w = p->words;
if (ws) {
*q = '\0';
}
+ /* If there's nothing left, make something valid up */
+ if (!*text) {
+ static const char anonfrag[] = "anon";
+ text = sresize(text, lenof(anonfrag), char);
+ strcpy(text, anonfrag);
+ }
+
/*
* Now we check for clashes with other fragment names, and
* adjust this one if necessary by appending a hyphen followed
htmlfile *thisfile, keywordlist *keywords,
htmlconfig *cfg)
{
+ if (ho->contents_level >= depth && ho->contents_level > 0) {
+ element_close(ho, "li");
+ html_nl(ho);
+ }
+
while (ho->contents_level > depth) {
element_close(ho, "ul");
ho->contents_level--;
+ if (ho->contents_level > 0) {
+ element_close(ho, "li");
+ }
+ html_nl(ho);
}
while (ho->contents_level < depth) {
+ html_nl(ho);
element_open(ho, "ul");
+ html_nl(ho);
ho->contents_level++;
}
return;
element_open(ho, "li");
- html_href(ho, thisfile, s->file, s->fragment);
+ html_href(ho, thisfile, s->file, s->fragments[0]);
html_section_title(ho, s, thisfile, keywords, cfg, FALSE);
element_close(ho, "a");
- element_close(ho, "li");
+ /* <li> will be closed by a later invocation */
}
static void html_section_title(htmloutput *ho, htmlsect *s, htmlfile *thisfile,