[Midnight::] Codename Midnight. The "midnight" style of navigational gadgets. @h Creation. = navigation_design *Midnight::create(void) { navigation_design *ND = Nav::new(I"midnight", FALSE, FALSE); ND->columnar = TRUE; METHOD_ADD(ND, RENDER_SECTION_TITLE_MTID, Midnight::midnight_section_title); METHOD_ADD(ND, RENDER_INDEX_TOP_MTID, Midnight::midnight_navigation_index_top); METHOD_ADD(ND, RENDER_NAV_MIDDLE_MTID, Midnight::midnight_navigation_middle); METHOD_ADD(ND, RENDER_NAV_BOTTOM_MTID, Midnight::midnight_navigation_bottom); METHOD_ADD(ND, RENDER_CONTENTS_MTID, Midnight::midnight_navigation_contents_files); METHOD_ADD(ND, RENDER_CONTENTS_HEADING_MTID, Midnight::midnight_navigation_contents_heading); return ND; } @h Top. At the front end of a section, before any of its text. Midnight doesn't have volume or chapter titles as such, since the banner heading includes these anyway. = void Midnight::midnight_section_title(navigation_design *self, text_stream *OUT, volume *V, chapter *C, section *S) { if (S->begins_which_chapter == NULL) { TEMPORARY_TEXT(comment) WRITE_TO(comment, "START IGNORE %d", S->number_within_volume); HTML::comment(OUT, comment); DISCARD_TEXT(comment) } HTML::begin_div_with_class_S(OUT, I"bookheader", __FILE__, __LINE__); text_stream *linkleft = NULL; text_stream *linkright = NULL; @; TEMPORARY_TEXT(leaf) WRITE_TO(leaf, "%S.html", indoc_settings->contents_leafname); Midnight::midnight_banner(OUT, S->in_which_chapter->chapter_full_title, V, leaf, linkleft, linkright); HTML::end_div(OUT); if (S->begins_which_chapter == NULL) HTML::comment(OUT, I"END IGNORE"); HTML_OPEN_WITH("p", "class=\"sectionheading\""); if (Str::len(S->section_anchor) > 0) HTML::anchor(OUT, S->section_anchor); WRITE("%c%S", SECTION_SYMBOL, S->title); HTML_CLOSE("p"); } @ = if (S->previous_section) linkleft = S->previous_section->section_URL; if (S->next_section) linkright = S->next_section->section_URL; @h Index top. And this is a variant for index pages, such as the index of examples. = void Midnight::midnight_navigation_index_top(navigation_design *self, text_stream *OUT, text_stream *filename, text_stream *title) { Midnight::midnight_banner(OUT, title, 0, NULL, NULL, NULL); } @h Middle. At the middle part, when the text is over, but before any example cues. = void Midnight::midnight_navigation_middle(navigation_design *self, text_stream *OUT, volume *V, section *S) { HTMLUtilities::ruled_line(OUT); } @h Bottom. At the end of the section, after any example cues and perhaps also example bodied. (In a section with no examples, this immediately follows the middle.) = void Midnight::midnight_navigation_bottom(navigation_design *self, text_stream *OUT, volume *V, section *S) { HTML::begin_div_with_class_S(OUT, I"bookfooter", __FILE__, __LINE__); HTML_OPEN_WITH("table", "class=\"fullwidth\""); HTML_OPEN("tr"); HTML_OPEN_WITH("td", "class=\"footerprevious\""); if (S->previous_section) HTMLUtilities::general_link(OUT, I"footerlink", S->previous_section->section_URL, I"Previous"); HTML_CLOSE("td"); HTML_OPEN_WITH("td", "class=\"footercontents\""); TEMPORARY_TEXT(url) WRITE_TO(url, "%S.html", indoc_settings->contents_leafname); HTMLUtilities::general_link(OUT, I"footerlink", url, I"Contents"); DISCARD_TEXT(url) HTML_CLOSE("td"); HTML_OPEN_WITH("td", "class=\"footernext\""); if (S->next_section) HTMLUtilities::general_link(OUT, I"footerlink", S->next_section->section_URL, I"Next"); else { HTML_OPEN_WITH("span", "class=\"footernonlink\""); WRITE("End"); HTML_CLOSE("span"); } HTML_CLOSE("td"); HTML_CLOSE("tr"); HTML_CLOSE("table"); HTML::end_div(OUT); } @h Banners. These are the black, status-line-like banners with navigation icons at the top of every Midnight page. = void Midnight::midnight_banner(OUTPUT_STREAM, text_stream *title, volume *V, text_stream *linkcentre, text_stream *linkleft, text_stream *linkright) { TEMPORARY_TEXT(url) WRITE_TO(url, "%S.html", indoc_settings->contents_leafname); HTML_OPEN_WITH("table", "class=\"fullwidth midnightblack\""); HTML_OPEN("tr"); HTML_OPEN_WITH("td", "class=\"midnightbannerleftcell\""); if (Str::len(linkleft) > 0) { TEMPORARY_TEXT(img) HTMLUtilities::image_with_id(img, I"Hookleft.png", I"hookleft"); HTMLUtilities::general_link(OUT, I"standardlink", linkleft, img); DISCARD_TEXT(img) } HTML_CLOSE("td"); HTML_OPEN_WITH("td", "class=\"midnightbannercentrecell\""); if (Str::len(linkcentre) > 0) HTML::begin_link_with_class(OUT, I"standardlink", url); HTML_OPEN_WITH("span", "class=\"midnightbannertext\""); WRITE("%S", title); HTML_CLOSE("span"); if (Str::len(linkcentre) > 0) HTML::end_link(OUT); HTML_CLOSE("td"); HTML_OPEN_WITH("td", "class=\"midnightbannerrightcell\""); TEMPORARY_TEXT(img) HTMLUtilities::image_with_id(img, I"Hookup.png", I"hookup"); HTMLUtilities::general_link(OUT, I"standardlink", url, img); DISCARD_TEXT(img) if (Str::len(linkright) > 0) { TEMPORARY_TEXT(img) HTMLUtilities::image_with_id(img, I"Hookright.png", I"hookright"); HTMLUtilities::general_link(OUT, I"standardlink", linkright, img); DISCARD_TEXT(img) } HTML_CLOSE("td"); HTML_CLOSE("tr"); HTML_CLOSE("table"); DISCARD_TEXT(url) } @ And this is a similar design motif used in Midnight contents pages: see below. = void Midnight::midnight_contents_column_banner(OUTPUT_STREAM, text_stream *title, volume *V, text_stream *extra) { HTML_OPEN_WITH("table", "class=\"fullwidth midnightblack\""); HTML_OPEN("tr"); HTML_OPEN_WITH("td", "class=\"midnightbannerleftcell\""); WRITE("%S", extra); HTML_CLOSE("td"); HTML_OPEN_WITH("td", "class=\"midnightbannercentrecell\""); HTML_OPEN_WITH("span", "class=\"midnightbannertext\""); WRITE("%S", title); HTML_CLOSE("span"); HTML_CLOSE("td"); HTML_CLOSE("tr"); HTML_CLOSE("table"); } @h Contents page. Midnight provides a contents page of its very own. = void Midnight::midnight_navigation_contents_files(navigation_design *self) { Midnight::write_contents_page(self, volumes[0]); } void Midnight::midnight_navigation_contents_heading(navigation_design *self, text_stream *OUT, volume *V) { WRITE("\n\n"); HTML_OPEN_WITH("table", "class=\"fullwidth\""); HTML_OPEN("tr"); } @ Contents pages are only produced in some styles, and they're really index pages of links. In light mode, we get just a simple listing of the contents of the current volume; in heavy mode, it's a two-column table, with the contents of each volume side by side. = void Midnight::write_contents_page(navigation_design *self, volume *V) { TEMPORARY_TEXT(leafname) WRITE_TO(leafname, "%S%S.html", V->vol_prefix, indoc_settings->contents_leafname); filename *F = Filenames::in(indoc_settings->destination, leafname); text_stream C_struct; text_stream *OUT = &C_struct; if (Streams::open_to_file(OUT, F, UTF8_ENC) == FALSE) Errors::fatal_with_file("can't write contents file", F); if (indoc_settings->wrapper == WRAPPER_epub) Epub::note_page(indoc_settings->ebook, F, I"Contents", I"toc"); TEMPORARY_TEXT(title) WRITE_TO(title, "Contents"); @; Nav::navigation_contents_heading(OUT, V); for (int column = 0; column < no_volumes; column++) if ((column == V->allocation_id) || (self->columnar)) @; @; @; DISCARD_TEXT(title) Streams::close(OUT); } @ = TEMPORARY_TEXT(xxx) HTMLUtilities::get_tt_matter(xxx, 1, 1); if (Str::len(xxx) > 0) { Regexp::replace(xxx, U"%[SUBHEADING%]", NULL, 0); inchar32_t replacement[1024]; TEMPORARY_TEXT(rep) WRITE_TO(rep, "%S", title); Str::copy_to_wide_string(replacement, rep, 1024); DISCARD_TEXT(rep) Regexp::replace(xxx, U"%c*", replacement, REP_REPEATING); WRITE("%S", xxx); } else { HTMLUtilities::begin_file(OUT, volumes[0]); HTMLUtilities::write_title(OUT, title); if (indoc_settings->javascript) { HTML::open_javascript(OUT, FALSE); HTMLUtilities::write_javascript_for_buttons(OUT); HTMLUtilities::write_javascript_for_contents_buttons(OUT); HTML::close_javascript(OUT); } HTML::end_head(OUT); HTML::begin_body(OUT, self->contents_body_class); } DISCARD_TEXT(xxx) @ = TEMPORARY_TEXT(tail) HTMLUtilities::get_tt_matter(tail, 1, 0); if (Str::len(tail) > 0) WRITE("%S", tail); else HTML::end_body(OUT); DISCARD_TEXT(tail) @ = if (self->columnar) { if (no_volumes == 1) HTML_OPEN("td") else if (column == 0) HTML_OPEN_WITH("td", "class=\"midnightlefthalfpage\"") else HTML_OPEN_WITH("td", "class=\"midnightrighthalfpage\""); @; HTML_CLOSE("td"); } else @; @ = for (section *S = volumes[column]->sections[0]; S; S = S->next_section) { chapter *C = S->begins_which_chapter; if (C) { HTML_OPEN("h3"); WRITE("Chapter %d. %S", C->chapter_number, C->chapter_title); HTML_CLOSE("h3"); } TEMPORARY_TEXT(destination) WRITE_TO(destination, "%S", S->section_URL); TEMPORARY_TEXT(description) WRITE_TO(description, "%S. %S", S->label, S->title); HTMLUtilities::general_link(OUT, I"standardlink", destination, description); DISCARD_TEXT(description) DISCARD_TEXT(destination) HTML_TAG("br"); } if (indoc_settings->html_for_Inform_application) HTMLUtilities::textual_link(OUT, indoc_settings->link_to_extensions_index, I"Installed Extensions"); HTMLUtilities::textual_link(OUT, indoc_settings->examples_alphabetical_leafname, I"Alphabetical Index of Examples"); HTMLUtilities::textual_link(OUT, indoc_settings->examples_numerical_leafname, I"Numerical Index of Examples"); HTMLUtilities::textual_link(OUT, indoc_settings->examples_thematic_leafname, I"Thematic Index of Examples"); if (NUMBER_CREATED(index_lemma) > 0) HTMLUtilities::textual_link(OUT, indoc_settings->definitions_index_leafname, I"General Index"); volume *OV = volumes[0]; if (V == volumes[0]) OV = volumes[1]; TEMPORARY_TEXT(url) WRITE_TO(url, "%Sindex.html", OV->vol_prefix); HTMLUtilities::textual_link(OUT, url, OV->vol_title); DISCARD_TEXT(url) @ This is almost as simple, but now the lines linking to sections within a chapter are grouped into a |
| for that chapter, which can be hidden or revealed -- it contains "extra" material, as we put it. We assume here that there are fewer than 1000 chapters in each volume; there are in practice about 25. @ = volume *X = V; if (column == 1) X = volumes[1-V->allocation_id]; TEMPORARY_TEXT(extra) if (indoc_settings->contents_expandable) HTMLUtilities::all_extras_link(extra, X->vol_abbrev); Midnight::midnight_contents_column_banner(OUT, X->vol_title, X, extra); DISCARD_TEXT(extra) int extra_count = 0; for (section *S = volumes[column]->sections[0]; S; S = S->next_section) { chapter *C = S->begins_which_chapter; if (C) { if ((extra_count > 0) && (indoc_settings->contents_expandable)) { HTML::end_div(OUT); } @; } @; } if ((extra_count > 0) && (indoc_settings->contents_expandable)) { HTML::end_div(OUT); } if ((column == no_volumes - 1) && (indoc_settings->html_for_Inform_application == FALSE) && (no_examples > 0)) { HTML_OPEN_WITH("p", "class=\"midnightcontentsA\""); WRITE("Index"); HTML_CLOSE("p"); @; } if (indoc_settings->html_for_Inform_application) { if (column == 0) { Midnight::mc_link_A(OUT, indoc_settings->examples_numerical_leafname, I"Numerical Index of Examples"); } else { Midnight::mc_link_A(OUT, indoc_settings->examples_thematic_leafname, I"Thematic Index of Examples"); } } WRITE("\n"); @ = int id = column*1000 + extra_count++; HTML_OPEN_WITH("p", "class=\"midnightcontentsA\""); if (indoc_settings->contents_expandable) HTMLUtilities::extra_link(OUT, id); TEMPORARY_TEXT(thetitle) Str::copy(thetitle, C->chapter_title); TEMPORARY_TEXT(theprefix) if (no_volumes == 1) WRITE_TO(theprefix, "Chapter %d", C->chapter_number); else WRITE_TO(theprefix, "%d", C->chapter_number); match_results mr = Regexp::create_mr(); if (Regexp::match(&mr, thetitle, U"Appendix: (%c*)")) { Str::clear(theprefix); Str::copy(theprefix, I"Appendix"); Str::clear(thetitle); Str::copy(thetitle, mr.exp[0]); } Regexp::dispose_of(&mr); TEMPORARY_TEXT(txt) WRITE_TO(txt, "%S. %S", theprefix, thetitle); HTMLUtilities::general_link(OUT, I"standardlink", S->section_URL, txt); DISCARD_TEXT(txt) HTML_CLOSE("p"); if (indoc_settings->contents_expandable) HTMLUtilities::extra_div_open(OUT, id); DISCARD_TEXT(theprefix) DISCARD_TEXT(thetitle) @ = TEMPORARY_TEXT(txt) WRITE_TO(txt, "%c%S", SECTION_SYMBOL, S->title); Midnight::mc_link_B(OUT, S->section_URL, txt); DISCARD_TEXT(txt) @ In Midnight mode, this is where the extra indexes are listed in the contents: some in the left-hand (WWI) column, others in the right-hand (RB). This is done with a second row of the table whose first row contains the chapter contents cells. @ = if (self->columnar) { HTML_CLOSE("tr"); if ((indoc_settings->assume_Public_Library == FALSE) && (indoc_settings->html_for_Inform_application)) { HTML_OPEN("tr"); HTML_OPEN_WITH("td", "class=\"midnightlefthalfpage\""); Midnight::midnight_contents_column_banner(OUT, I"Extensions", volumes[0], NULL); Midnight::mc_link_A(OUT, indoc_settings->link_to_extensions_index, I"Installed Extensions"); HTML_OPEN_WITH("p", "class=\"midnightcontentsA\""); WRITE("for more extensions, visit:"); HTML_TAG("br"); WRITE("www.inform7.com"); HTML_CLOSE("p"); HTML_CLOSE("td"); HTML_OPEN_WITH("td", "class=\"midnightrighthalfpage\""); if (no_examples > 0) { Midnight::midnight_contents_column_banner(OUT, I"Indexes", volumes[1], NULL); @; } else { Midnight::midnight_contents_column_banner(OUT, NULL, volumes[1], NULL); } if (NUMBER_CREATED(index_lemma) > 0) { Midnight::mc_link_A(OUT, indoc_settings->definitions_index_leafname, I"General Index"); } HTML_CLOSE("td"); HTML_CLOSE("tr"); } HTML_CLOSE("table"); } @ = Midnight::mc_link_A(OUT, indoc_settings->examples_alphabetical_leafname, I"Alphabetical Index of Examples"); Midnight::mc_link_A(OUT, indoc_settings->examples_numerical_leafname, I"Numerical Index of Examples"); Midnight::mc_link_A(OUT, indoc_settings->examples_thematic_leafname, I"Thematic Index of Examples"); @ And here are the level A and B contents entry link paragraphs: = void Midnight::mc_link_A(OUTPUT_STREAM, text_stream *to, text_stream *text) { HTML_OPEN_WITH("p", "class=\"midnightcontentsA\""); HTMLUtilities::general_link(OUT, I"standardlink", to, text); HTML_CLOSE("p"); } void Midnight::mc_link_B(OUTPUT_STREAM, text_stream *to, text_stream *text) { HTML_OPEN_WITH("p", "class=\"midnightcontentsB\""); HTMLUtilities::general_link(OUT, I"standardlink", to, text); HTML_CLOSE("p"); }