The "roadsign" style of navigational gadgets.
navigation_design *Roadsign::create(void) { navigation_design *ND = Nav::new(I"roadsign", TRUE, FALSE); METHOD_ADD(ND, RENDER_VOLUME_TITLE_MTID, Roadsign::roadsign_volume_title); METHOD_ADD(ND, RENDER_CHAPTER_TITLE_MTID, Roadsign::roadsign_chapter_title); METHOD_ADD(ND, RENDER_SECTION_TITLE_MTID, Roadsign::roadsign_section_title); METHOD_ADD(ND, RENDER_INDEX_TOP_MTID, Roadsign::roadsign_navigation_index_top); METHOD_ADD(ND, RENDER_NAV_MIDDLE_MTID, Roadsign::roadsign_navigation_middle); METHOD_ADD(ND, RENDER_EXAMPLE_TOP_MTID, Roadsign::roadsign_navigation_example_top); return ND; }
§2. Top. At the front end of a section, before any of its text.
void Roadsign::roadsign_volume_title(navigation_design *self, text_stream *OUT, volume *V) { Render a volume heading2.1; Render a chapter-contents table2.2; HTML_OPEN("p"); HTML_CLOSE("p"); Render the volume-top roadsign2.3; }
§2.1. Render a volume heading2.1 =
TEMPORARY_TEXT(partn) if (no_volumes > 1) Roadsign::roman_numeral(partn, V->allocation_id); HTML_OPEN_WITH("p", "class=\"volumeheading\""); WRITE("%S%S", partn, V->vol_title); HTML_CLOSE("p"); DISCARD_TEXT(partn)
- This code is used in §2.
§2.2. Some cumbersome Perl to produce a balanced two-column chapter listing:
Render a chapter-contents table2.2 =
HTML_OPEN_WITH("table", "class=\"centredtable\""); int nch = V->vol_chapter_count; int rows = nch/2; if (2 * rows < nch) rows++; for (int rc = 0; rc < rows; rc++) { chapter *C = V->chapters[rc]; chapter *OC = V->chapters[rc + rows]; HTML_OPEN("tr"); HTML_OPEN("td"); HTML::begin_link_with_class(OUT, I"standardlink", C->chapter_URL); HTML_OPEN_WITH("span", "class=\"chapterlisting\""); WRITE("%S", C->chapter_full_title); HTML_CLOSE("span"); HTML::end_link(OUT); WRITE("   </td>"); if (OC) { HTML_OPEN("td"); HTML::begin_link_with_class(OUT, I"standardlink", OC->chapter_URL); HTML_OPEN_WITH("span", "class=\"chapterlisting\""); WRITE("%S", OC->chapter_full_title); HTML_CLOSE("span"); HTML::end_link(OUT); WRITE("   </td>"); } HTML_CLOSE("tr"); } HTML_CLOSE("table");
- This code is used in §2.
§2.3. Render the volume-top roadsign2.3 =
Roadsign::roadsign_begin(OUT, 1); TEMPORARY_TEXT(txt) WRITE_TO(txt, "Start reading here: %c%S", SECTION_SYMBOL, V->sections[0]->title); Roadsign::roadsign_add_direction(OUT, I"arrow-right.png", txt, V->chapters[0]->chapter_URL); if (no_volumes > 1) { for (int v = 0; v < no_volumes; v++) { TEMPORARY_TEXT(icon) if (v < V->allocation_id) WRITE_TO(icon, "arrow-up"); if (v > V->allocation_id) WRITE_TO(icon, "arrow-down"); if (Str::len(icon) > 0) { volume *LV = volumes[v]; TEMPORARY_TEXT(txt) Roadsign::roman_numeral(txt, v); WRITE_TO(txt, "%S", LV->vol_title); TEMPORARY_TEXT(img) WRITE_TO(img, "%S.png", icon); Roadsign::roadsign_add_direction(OUT, img, txt, LV->vol_URL); DISCARD_TEXT(txt) DISCARD_TEXT(img) } DISCARD_TEXT(icon) } } if ((no_examples > 0) && (NUMBER_CREATED(index_lemma) > 0)) { Roadsign::roadsign_add_direction(OUT, I"arrow-down-right.png", I"Indexes of the examples and definitions", indoc_settings->examples_alphabetical_leafname); } else if (no_examples > 0) { Roadsign::roadsign_add_direction(OUT, I"arrow-down-right.png", I"Indexes of the examples", indoc_settings->examples_alphabetical_leafname); } else if (NUMBER_CREATED(index_lemma) > 0) { Roadsign::roadsign_add_direction(OUT, I"arrow-down-right.png", I"Index of definitions", indoc_settings->definitions_index_leafname); } Roadsign::roadsign_end(OUT, 1);
- This code is used in §2.
void Roadsign::roadsign_chapter_title(navigation_design *self, text_stream *OUT, volume *V, chapter *C) { Render a chapter heading3.1; Render a section-contents listing3.2; Roadsign::roadsign_chapter_jumps(OUT, V, C, 0); }
§3.1. Render a chapter heading3.1 =
HTML_OPEN_WITH("p", "class=\"chapterheading\""); if (Str::len(C->chapter_anchor) > 0) HTML::anchor(OUT, C->chapter_anchor); WRITE("%S", C->chapter_full_title); HTML_CLOSE("p");
- This code is used in §3.
§3.2. Render a section-contents listing3.2 =
HTML_OPEN_WITH("p", "class=\"chaptercontents\""); int lcount = 0; for (section *S = V->sections[0]; S; S = S->next_section) if (S->in_which_chapter == C) { if (lcount++ > 0) WRITE("; "); HTML::begin_link_with_class(OUT, I"standardlink", S->section_URL); HTML_OPEN_WITH("span", "class=\"chaptercontentsitem\""); WRITE("%c%S", SECTION_SYMBOL, S->title); HTML_CLOSE("span"); HTML::end_link(OUT); } HTML_CLOSE("p");
- This code is used in §3.
void Roadsign::roadsign_section_title(navigation_design *self, text_stream *OUT, volume *V, chapter *C, section *S) { 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"); }
§5. Index top. And this is a variant for index pages, such as the index of examples.
void Roadsign::roadsign_navigation_index_top(navigation_design *self, text_stream *OUT, text_stream *filename, text_stream *title) { HTML_OPEN_WITH("p", "class=\"chapterheading\""); WRITE("%S", title); HTML_CLOSE("p"); Roadsign::roadsign_begin(OUT, 1); if (no_examples > 0) { if (Str::ne(filename, indoc_settings->examples_alphabetical_leafname)) Roadsign::roadsign_add_direction(OUT, I"arrow-right.png", I"Examples in Alphabetical Order", indoc_settings->examples_alphabetical_leafname); if (Str::ne(filename, indoc_settings->examples_thematic_leafname)) Roadsign::roadsign_add_direction(OUT, I"arrow-right.png", I"Examples in Thematic Order", indoc_settings->examples_thematic_leafname); if (Str::ne(filename, indoc_settings->examples_numerical_leafname)) Roadsign::roadsign_add_direction(OUT, I"arrow-right.png", I"Examples in Numerical Order", indoc_settings->examples_numerical_leafname); } if (NUMBER_CREATED(index_lemma) > 0) if (Str::ne(filename, indoc_settings->definitions_index_leafname)) Roadsign::roadsign_add_direction(OUT, I"arrow-right.png", I"General Index", indoc_settings->definitions_index_leafname); for (int v = 0; v < no_volumes; v++) { volume *V = volumes[v]; TEMPORARY_TEXT(text) Roadsign::roman_numeral(text, v); WRITE_TO(text, "%S", V->vol_title); if (no_volumes == 1) Str::copy(text, I"Contents"); Roadsign::roadsign_add_direction(OUT, I"arrow-up-left.png", text, V->vol_URL); DISCARD_TEXT(text) } Roadsign::roadsign_end(OUT, 1); HTMLUtilities::ruled_line(OUT); }
§6. Middle. At the middle part, when the text is over, but before any example cues.
void Roadsign::roadsign_navigation_middle(navigation_design *self, text_stream *OUT, volume *V, section *S) { HTMLUtilities::ruled_line(OUT); HTML::begin_div_with_class_S(OUT, I"roadsigns", __FILE__, __LINE__); chapter *C = S->in_which_chapter; Roadsign::roadsign_begin(OUT, 0); Add home, back and forward directions to the roadsign6.1; if (indoc_settings->examples_mode == EXMODE_open_internal) Add directions to this section's examples to the roadsign6.2; Roadsign::roadsign_end(OUT, 0); HTMLUtilities::ruled_line(OUT); HTML::end_div(OUT); }
§6.1. Add home, back and forward directions to the roadsign6.1 =
TEMPORARY_TEXT(txt) WRITE_TO(txt, "Start of %S", C->chapter_full_title); Roadsign::roadsign_add_direction(OUT, I"arrow-up.png", txt, C->chapter_URL); DISCARD_TEXT(txt) if (S->previous_section) { chapter *to_chap = S->previous_section->in_which_chapter; TEMPORARY_TEXT(link) WRITE_TO(link, "Back to "); if (to_chap != C) WRITE_TO(link, "Chapter %d: %S: ", to_chap->chapter_number, to_chap->chapter_title); WRITE_TO(link, "%c%S", SECTION_SYMBOL, S->previous_section->title); Roadsign::roadsign_add_direction(OUT, I"arrow-left.png", link, S->previous_section->section_URL); DISCARD_TEXT(link) } if (S->next_section) { chapter *to_chap = S->next_section->in_which_chapter; TEMPORARY_TEXT(link) WRITE_TO(link, "Onward to "); if (to_chap != C) WRITE_TO(link, "Chapter %d: %S: ", to_chap->chapter_number, to_chap->chapter_title); WRITE_TO(link, "%c%S", SECTION_SYMBOL, S->next_section->title); Roadsign::roadsign_add_direction(OUT, I"arrow-right.png", link, S->next_section->section_URL); DISCARD_TEXT(link) }
- This code is used in §6.
§6.2. Add directions to this section's examples to the roadsign6.2 =
example *E; LOOP_OVER(E, example) { if (E->example_belongs_to_section[V->allocation_id] == S) { TEMPORARY_TEXT(stars) for (int starcc=0; starcc < E->ex_star_count; starcc++) HTMLUtilities::asterisk_image(stars, I"asterisk.png"); TEMPORARY_TEXT(pn) Str::copy(pn, E->ex_public_name); Rawtext::escape_HTML_characters_in(pn); TEMPORARY_TEXT(text) WRITE_TO(text, "Example %d: %S <b>%S</b>    %S", E->example_position[0], stars, pn, E->ex_outline); TEMPORARY_TEXT(url) Examples::goto_example_url(url, E, V); Roadsign::roadsign_add_direction(OUT, I"arrow-down.png", text, url); DISCARD_TEXT(text) DISCARD_TEXT(stars) DISCARD_TEXT(url) } }
- This code is used in §6.
§7. Example top. This is reached before the first example is rendered, provided at least one example will be:
void Roadsign::roadsign_navigation_example_top(navigation_design *self, text_stream *OUT, volume *V, section *S) { if (indoc_settings->examples_granularity == CHAPTER_GRANULARITY) Roadsign::roadsign_chapter_jumps(OUT, V, S->in_which_chapter, TRUE); }
void Roadsign::roadsign_chapter_jumps(OUTPUT_STREAM, volume *V, chapter *C, int bottom) { Roadsign::roadsign_begin(OUT, 1); int chc = V->vol_chapter_count; if ((chc > 1) && (bottom == FALSE)) { TEMPORARY_TEXT(text) WRITE_TO(text, "Contents of <i>%S</i>", V->vol_title); Roadsign::roadsign_add_direction(OUT, I"arrow-up-left.png", text, V->vol_URL); DISCARD_TEXT(text) if (C->previous_chapter) Roadsign::roadsign_add_direction(OUT, I"arrow-left.png", C->previous_chapter->chapter_full_title, C->previous_chapter->chapter_URL); } if (bottom == 1) Roadsign::roadsign_add_direction(OUT, I"arrow-up.png", I"Start of this chapter", C->chapter_URL); if (C->next_chapter) Roadsign::roadsign_add_direction(OUT, I"arrow-right.png", C->next_chapter->chapter_full_title, C->next_chapter->chapter_URL); if (no_examples > 0) Roadsign::roadsign_add_direction(OUT, I"arrow-down-right.png", I"Indexes of the examples", indoc_settings->examples_alphabetical_leafname); Roadsign::roadsign_end(OUT, 1); }
§9. And at a lower level: here's how a roadsign is made, as a table of links.
void Roadsign::roadsign_begin(OUTPUT_STREAM, int centred) { if (centred) HTML_OPEN_WITH("table", "class=\"centredtable\"") else HTML_OPEN("table"); }
§10. This is a 2-column table: the link image in column 1, the text in column 2.
void Roadsign::roadsign_add_direction(OUTPUT_STREAM, text_stream *icon, text_stream *text, text_stream *url) { HTML_OPEN("tr"); HTML_OPEN_WITH("td", "class=\"roadsigndirection\""); HTML::begin_link_with_class(OUT, I"standardlink", url); HTMLUtilities::image_element(OUT, icon); HTML::end_link(OUT); HTML_CLOSE("td"); HTML_OPEN("td"); HTML::begin_link_with_class(OUT, I"standardlink", url); WRITE("%S", text); HTML::end_link(OUT); HTML_CLOSE("td"); HTML_CLOSE("tr"); }
void Roadsign::roadsign_end(OUTPUT_STREAM, int cent) { HTML_CLOSE("table"); }
void Roadsign::roman_numeral(OUTPUT_STREAM, int v) { if (v == 0) WRITE("Part I. "); if (v == 1) WRITE("Part II. "); if (v == 2) WRITE("Part III. "); if (v == 3) WRITE("Part IV. "); if (v == 4) WRITE("Part V. "); if (v == 5) WRITE("Part VI. "); if (v == 6) WRITE("Part VII. "); if (v == 7) WRITE("Part VIII. "); if (v == 8) WRITE("Part IX. "); if (v == 9) WRITE("Part X. "); }