The "midnight" style of navigational gadgets.


§1. 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;
    }

The function Midnight::create is used in 4/nd (§1).

§2. 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");
        text_stream *linkleft = NULL;
        text_stream *linkright = NULL;
        <Work out URLs for the preceding and following sections 2.1>;
        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");
    }

The function Midnight::midnight_section_title is used in §1.

§2.1. <Work out URLs for the preceding and following sections 2.1> =

        if (S->previous_section) linkleft = S->previous_section->section_URL;
        if (S->next_section) linkright = S->next_section->section_URL;

This code is used in §2.

§3. 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);
    }

The function Midnight::midnight_navigation_index_top is used in §1.

§4. 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);
    }

The function Midnight::midnight_navigation_middle is used in §1.

§5. 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");
        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);
    }

The function Midnight::midnight_navigation_bottom is used in §1.

§6. 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);
    }

The function Midnight::midnight_banner is used in §2, §3.

§7. 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");
    }

The function Midnight::midnight_contents_column_banner is used in §9.3.2, §9.4.

§8. 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");
    }

The function Midnight::midnight_navigation_contents_files is used in §1.

The function Midnight::midnight_navigation_contents_heading is used in §1.

§9. 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_folder(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");
        <Begin the HTML page for the contents 9.1>;
        Nav::navigation_contents_heading(OUT, V);

        for (int column = 0; column < no_volumes; column++)
            if ((column == V->allocation_id) || (self->columnar))
                <Render this column of the contents 9.3>;
        <Render any tailpiece at the foot of the contents 9.4>;

        <End the HTML page for the contents 9.2>;
        DISCARD_TEXT(title);
        Streams::close(OUT);
    }

The function Midnight::write_contents_page is used in §8, 4/ca (§8), 4/ct (§7).

§9.1. <Begin the HTML page for the contents 9.1> =

        TEMPORARY_TEXT(xxx);
        HTMLUtilities::get_tt_matter(xxx, 1, 1);
        if (Str::len(xxx) > 0) {
            Regexp::replace(xxx, L"%[SUBHEADING%]", NULL, 0);
            wchar_t replacement[1024];
            TEMPORARY_TEXT(rep);
            WRITE_TO(rep, "<title>%S</title>", title);
            Str::copy_to_wide_string(replacement, rep, 1024);
            DISCARD_TEXT(rep);
            Regexp::replace(xxx, L"<title>%c*</title>", 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);

This code is used in §9.

§9.2. <End the HTML page for the contents 9.2> =

        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);

This code is used in §9.

§9.3. <Render this column of the contents 9.3> =

        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\"");
            <Render a heavyweight column of links 9.3.2>;
            HTML_CLOSE("td");
        } else <Render a lightweight list of simple links 9.3.1>;

This code is used in §9.

§9.3.1. <Render a lightweight list of simple links 9.3.1> =

        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 code is used in §9.3.

§9.3.2. This is almost as simple, but now the lines linking to sections within a chapter are grouped into a <div> 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.

<Render a heavyweight column of links 9.3.2> =

        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);
                }
                <Render a chapter link 9.3.2.1>;
            }
            <Render a section link 9.3.2.2>;
        }
        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("<i>Index</i>");
            HTML_CLOSE("p");
            <Render links to example indexes 9.3.2.3>;
        }
        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");

This code is used in §9.3.

§9.3.2.1. <Render a chapter link 9.3.2.1> =

        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, "<b>Chapter %d</b>", C->chapter_number);
        else WRITE_TO(theprefix, "<b>%d</b>", C->chapter_number);
        match_results mr = Regexp::create_mr();
        if (Regexp::match(&mr, thetitle, L"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.&#160;%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);

This code is used in §9.3.2.

§9.3.2.2. <Render a section link 9.3.2.2> =

        TEMPORARY_TEXT(txt);
        WRITE_TO(txt, "%c%S", SECTION_SYMBOL, S->title);
        Midnight::mc_link_B(OUT, S->section_URL, txt);
        DISCARD_TEXT(txt);

This code is used in §9.3.2.

§9.4. 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.

<Render any tailpiece at the foot of the contents 9.4> =

        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("<i>for more extensions, visit:</i>");
                HTML_TAG("br");
                WRITE("<b>www.inform7.com</b>");
                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);
                    <Render links to example indexes 9.3.2.3>;
                } 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");
        }

This code is used in §9.

§9.3.2.3. <Render links to example indexes 9.3.2.3> =

        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");

This code is used in §9.3.2, §9.4.

§10. 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");
    }

The function Midnight::mc_link_A is used in §9.3.2, §9.4, §9.3.2.3.

The function Midnight::mc_link_B is used in §9.3.2.2.