2019-02-05 02:44:07 +02:00
|
|
|
[ExamplesIndex::] Examples Index.
|
|
|
|
|
|
|
|
To produces the contents and indexing pages, for HTML output and
|
|
|
|
multiple-files mode only.
|
|
|
|
|
|
|
|
@ These structures are used to hold details needed for one or both of the
|
|
|
|
alphabetic and thematic example indexes.
|
|
|
|
|
|
|
|
=
|
|
|
|
typedef struct example_index_data {
|
|
|
|
int alpha_index_embolden;
|
|
|
|
struct text_stream *alpha_index_rubric;
|
|
|
|
struct text_stream *alpha_index_subtitle;
|
|
|
|
struct section *alpha_index_to_S;
|
|
|
|
struct example *alpha_index_to_E;
|
|
|
|
struct text_stream *sort_key;
|
2020-05-09 15:07:39 +03:00
|
|
|
CLASS_DEFINITION
|
2019-02-05 02:44:07 +02:00
|
|
|
} example_index_data;
|
|
|
|
|
|
|
|
dictionary *example_index_data_by_rubric = NULL;
|
|
|
|
|
|
|
|
@h Alphabetising the examples.
|
|
|
|
This is not quite an A-Z list of example names, because some examples are
|
|
|
|
allowed to be indexed twice, once under a literal name (say "Cloves")
|
|
|
|
and once under its point (say "Adverbs used in commands"). In addition to
|
|
|
|
that, some example snippets embedded in the body text of the manuals can
|
|
|
|
also appear here. So we actually maintain an alphabetical index able to
|
|
|
|
index examples under arbitrary, multiple descriptions.
|
|
|
|
|
|
|
|
=
|
|
|
|
void ExamplesIndex::add_to_alphabetic_examples_index(text_stream *given_rubric,
|
2023-07-24 13:56:58 +03:00
|
|
|
section *index_to_S, example *index_to_E, int bold_flag) {
|
2020-06-28 01:18:54 +03:00
|
|
|
TEMPORARY_TEXT(sort_key)
|
|
|
|
TEMPORARY_TEXT(subtitle)
|
2023-07-24 13:56:58 +03:00
|
|
|
Str::copy(sort_key, given_rubric);
|
2019-02-05 02:44:07 +02:00
|
|
|
IndexUtilities::improve_alphabetisation(sort_key);
|
|
|
|
|
|
|
|
example_index_data *eid = CREATE(example_index_data);
|
|
|
|
eid->alpha_index_embolden = bold_flag;
|
2023-07-24 13:56:58 +03:00
|
|
|
eid->alpha_index_rubric = Str::duplicate(given_rubric);
|
2019-02-05 02:44:07 +02:00
|
|
|
eid->alpha_index_subtitle = Str::duplicate(subtitle);
|
|
|
|
eid->alpha_index_to_S = index_to_S;
|
|
|
|
eid->alpha_index_to_E = index_to_E;
|
|
|
|
eid->sort_key = Str::duplicate(sort_key);
|
|
|
|
|
|
|
|
if (example_index_data_by_rubric == NULL)
|
|
|
|
example_index_data_by_rubric = Dictionaries::new(100, FALSE);
|
|
|
|
Dictionaries::create(example_index_data_by_rubric, sort_key);
|
|
|
|
Dictionaries::write_value(example_index_data_by_rubric, sort_key, (void *) eid);
|
2023-07-24 13:56:58 +03:00
|
|
|
}
|
2019-02-05 02:44:07 +02:00
|
|
|
|
|
|
|
@h Alphabetic index of examples.
|
|
|
|
|
|
|
|
=
|
|
|
|
void ExamplesIndex::write_alphabetical_examples_index(void) {
|
|
|
|
@<Stock the alphabetical index@>;
|
|
|
|
|
|
|
|
text_stream *OUT = IndexUtilities::open_page(
|
2019-02-16 19:29:02 +02:00
|
|
|
I"Alphabetical Index of Examples", indoc_settings->examples_alphabetical_leafname);
|
2019-02-05 02:44:07 +02:00
|
|
|
IndexUtilities::alphabet_row(OUT, 1);
|
|
|
|
HTML_OPEN_WITH("table", "class=\"indextable\"");
|
|
|
|
|
|
|
|
example_index_data **eid_list =
|
2020-05-18 01:10:11 +03:00
|
|
|
Memory::calloc(NUMBER_CREATED(example_index_data), sizeof(example_index_data *), ARRAY_SORTING_MREASON);
|
2019-02-05 02:44:07 +02:00
|
|
|
example_index_data *eid;
|
|
|
|
LOOP_OVER(eid, example_index_data) eid_list[eid->allocation_id] = eid;
|
|
|
|
qsort(eid_list, (size_t) NUMBER_CREATED(example_index_data), sizeof(example_index_data *),
|
|
|
|
ExamplesIndex::sort_comparison);
|
|
|
|
|
2020-06-28 01:18:54 +03:00
|
|
|
TEMPORARY_TEXT(current_subtitle)
|
2023-09-05 10:36:51 +03:00
|
|
|
inchar32_t current_letter = 0;
|
2019-02-05 02:44:07 +02:00
|
|
|
int first_letter_block = TRUE;
|
|
|
|
for (int i=0; i<NUMBER_CREATED(example_index_data); i++) {
|
|
|
|
example_index_data *eid = eid_list[i];
|
2023-09-05 10:36:51 +03:00
|
|
|
inchar32_t initial = Str::get_first_char(eid->sort_key);
|
2019-02-05 02:44:07 +02:00
|
|
|
if (Characters::isdigit(initial)) initial = '#';
|
|
|
|
if (initial != current_letter) @<Start a new letter block@>;
|
2020-06-28 01:18:54 +03:00
|
|
|
TEMPORARY_TEXT(url)
|
2019-02-05 02:44:07 +02:00
|
|
|
@<Work out the URL of this example@>;
|
|
|
|
@<Write an alphabetical-index entry@>;
|
2020-06-28 01:18:54 +03:00
|
|
|
DISCARD_TEXT(url)
|
2019-02-05 02:44:07 +02:00
|
|
|
}
|
|
|
|
@<End a letter block@>;
|
|
|
|
|
|
|
|
HTML_CLOSE("table");
|
|
|
|
HTML_OPEN("p"); HTML_CLOSE("p");
|
|
|
|
IndexUtilities::alphabet_row(OUT, 2);
|
|
|
|
IndexUtilities::close_page(OUT);
|
2020-05-18 01:10:11 +03:00
|
|
|
Memory::I7_free(eid_list, ARRAY_SORTING_MREASON,
|
2019-02-05 02:44:07 +02:00
|
|
|
NUMBER_CREATED(example_index_data)*((int) sizeof(example_index_data *)));
|
|
|
|
}
|
|
|
|
|
|
|
|
@<Stock the alphabetical index@> =
|
|
|
|
example *E;
|
2023-07-24 13:56:58 +03:00
|
|
|
LOOP_OVER(E, example) {
|
|
|
|
if (Str::len(E->ex_subtitle) > 0) {
|
|
|
|
TEMPORARY_TEXT(index_as)
|
|
|
|
WRITE_TO(index_as, "%S: %S", E->ex_public_name, E->ex_subtitle);
|
|
|
|
ExamplesIndex::add_to_alphabetic_examples_index(index_as, NULL, E, TRUE);
|
|
|
|
DISCARD_TEXT(index_as)
|
|
|
|
} else if (Str::eq(E->ex_index, E->ex_public_name)) {
|
|
|
|
ExamplesIndex::add_to_alphabetic_examples_index(E->ex_index, NULL, E, FALSE);
|
|
|
|
} else {
|
|
|
|
ExamplesIndex::add_to_alphabetic_examples_index(E->ex_public_name, NULL, E, TRUE);
|
|
|
|
if (Str::len(E->ex_index) > 0)
|
|
|
|
ExamplesIndex::add_to_alphabetic_examples_index(E->ex_index, NULL, E, FALSE);
|
|
|
|
}
|
|
|
|
}
|
2019-02-05 02:44:07 +02:00
|
|
|
|
|
|
|
@<Work out the URL of this example@> =
|
|
|
|
if (eid->alpha_index_to_S)
|
|
|
|
WRITE_TO(url, "%S", eid->alpha_index_to_S->section_URL);
|
|
|
|
else
|
|
|
|
Examples::goto_example_url(url, eid->alpha_index_to_E, volumes[0]);
|
|
|
|
|
|
|
|
@<Start a new letter block@> =
|
|
|
|
current_letter = initial;
|
|
|
|
if (first_letter_block == FALSE) { HTML_TAG("br"); @<End a letter block@>; }
|
2023-09-05 10:36:51 +03:00
|
|
|
inchar32_t uc_current_letter = Characters::toupper(current_letter);
|
2019-02-05 02:44:07 +02:00
|
|
|
HTML_OPEN("tr");
|
|
|
|
HTML_OPEN_WITH("td", "class=\"letterblock\"");
|
2020-06-28 01:18:54 +03:00
|
|
|
TEMPORARY_TEXT(inc)
|
2019-02-05 02:44:07 +02:00
|
|
|
PUT_TO(inc, uc_current_letter);
|
|
|
|
HTML::anchor(OUT, inc);
|
|
|
|
IndexUtilities::majuscule_heading(OUT, inc, TRUE);
|
|
|
|
IndexUtilities::note_letter(uc_current_letter);
|
2020-06-28 01:18:54 +03:00
|
|
|
DISCARD_TEXT(inc)
|
2019-02-05 02:44:07 +02:00
|
|
|
HTML_CLOSE("td");
|
|
|
|
HTML_OPEN("td");
|
|
|
|
first_letter_block = FALSE;
|
|
|
|
|
|
|
|
@<End a letter block@> =
|
|
|
|
HTML_CLOSE("td");
|
|
|
|
HTML_CLOSE("tr");
|
|
|
|
|
|
|
|
@<Write an alphabetical-index entry@> =
|
|
|
|
HTML_OPEN_WITH("p", "class=\"indexentry\"");
|
|
|
|
if (Str::len(eid->alpha_index_subtitle) > 0) {
|
|
|
|
if (Str::ne(eid->alpha_index_subtitle, current_subtitle)) {
|
|
|
|
WRITE("<b>%S</b><br />", eid->alpha_index_subtitle);
|
|
|
|
Str::copy(current_subtitle, eid->alpha_index_subtitle);
|
|
|
|
}
|
|
|
|
WRITE("    ");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (eid->alpha_index_embolden == TRUE) { HTML_OPEN("b"); }
|
2020-06-28 01:18:54 +03:00
|
|
|
TEMPORARY_TEXT(link_text)
|
2019-02-05 02:44:07 +02:00
|
|
|
Str::copy(link_text, eid->alpha_index_rubric);
|
|
|
|
Rawtext::escape_HTML_characters_in(link_text);
|
|
|
|
HTMLUtilities::general_link(OUT, I"standardlink", url, link_text);
|
2020-06-28 01:18:54 +03:00
|
|
|
DISCARD_TEXT(link_text)
|
2019-02-05 02:44:07 +02:00
|
|
|
|
|
|
|
if (eid->alpha_index_embolden == TRUE) { HTML_CLOSE("b"); }
|
|
|
|
HTML_CLOSE("p");
|
|
|
|
|
|
|
|
@ =
|
|
|
|
int ExamplesIndex::sort_comparison(const void *ent1, const void *ent2) {
|
|
|
|
const example_index_data *L1 = *((const example_index_data **) ent1);
|
|
|
|
const example_index_data *L2 = *((const example_index_data **) ent2);
|
|
|
|
return Str::cmp(L1->sort_key, L2->sort_key);
|
|
|
|
}
|
|
|
|
|
|
|
|
@h Thematic index of examples.
|
|
|
|
|
|
|
|
=
|
|
|
|
void ExamplesIndex::write_thematic_examples_index(void) {
|
|
|
|
text_stream *OUT = IndexUtilities::open_page(
|
2019-02-16 19:29:02 +02:00
|
|
|
I"Examples in Thematic Order", indoc_settings->examples_thematic_leafname);
|
2019-02-05 02:44:07 +02:00
|
|
|
ExamplesIndex::write_index_for_volume(OUT, volumes[1]);
|
|
|
|
IndexUtilities::close_page(OUT);
|
|
|
|
}
|
|
|
|
|
|
|
|
@h Numerical index of examples.
|
|
|
|
|
|
|
|
=
|
|
|
|
void ExamplesIndex::write_numerical_examples_index(void) {
|
|
|
|
text_stream *OUT = IndexUtilities::open_page(
|
2019-02-16 19:29:02 +02:00
|
|
|
I"Examples in Numerical Order", indoc_settings->examples_numerical_leafname);
|
2019-02-05 02:44:07 +02:00
|
|
|
ExamplesIndex::write_index_for_volume(OUT, volumes[0]);
|
|
|
|
IndexUtilities::close_page(OUT);
|
|
|
|
}
|
|
|
|
|
|
|
|
@ =
|
|
|
|
void ExamplesIndex::write_index_for_volume(OUTPUT_STREAM, volume *V) {
|
|
|
|
chapter *owning_chapter = NULL;
|
|
|
|
section *owning_section = NULL;
|
|
|
|
for (int n = 0; n < no_examples; n++) {
|
|
|
|
example *E = V->examples_sequence[n];
|
|
|
|
section *S = E->example_belongs_to_section[V->allocation_id];
|
|
|
|
chapter *C = S->in_which_chapter;
|
|
|
|
if (owning_chapter != C) {
|
|
|
|
if (owning_chapter != NULL) HTML_TAG("hr");
|
|
|
|
owning_chapter = C;
|
|
|
|
HTML_OPEN("p");
|
|
|
|
WRITE("<b>Chapter %d: %S</b>", C->chapter_number, C->chapter_title);
|
|
|
|
HTML_CLOSE("p");
|
|
|
|
}
|
|
|
|
if (owning_section != S) {
|
|
|
|
owning_section = S;
|
|
|
|
HTML_OPEN("p");
|
|
|
|
WRITE("<i>%c%S</i>", SECTION_SYMBOL, S->title);
|
|
|
|
HTML_CLOSE("p");
|
|
|
|
}
|
|
|
|
Examples::render_example_cue(OUT, E, V, TRUE);
|
|
|
|
}
|
|
|
|
}
|