1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-01 06:24:58 +03:00
inform7/inter/index-module/Chapter 3/Chart Element.w

424 lines
15 KiB
OpenEdge ABL
Raw Normal View History

2021-06-14 00:29:31 +03:00
[ChartElement::] Chart Element.
2019-02-05 02:44:07 +02:00
2021-06-14 00:29:31 +03:00
To write the Chart element (Ch) in the index.
2021-07-24 20:16:56 +03:00
@ This is a table of kinds of value, followed by a set of descriptions of each,
and it is quite dense with information.
2021-06-14 00:29:31 +03:00
=
2021-07-24 20:16:56 +03:00
void ChartElement::render(OUTPUT_STREAM, localisation_dictionary *D) {
inter_tree *I = InterpretIndex::get_tree();
2021-06-14 00:29:31 +03:00
tree_inventory *inv = Synoptic::inv(I);
TreeLists::sort(inv->kind_nodes, Synoptic::module_order);
2021-06-15 01:29:45 +03:00
TreeLists::sort(inv->instance_nodes, Synoptic::module_order);
2021-07-24 20:16:56 +03:00
HTML::begin_wide_html_table(OUT);
int pass = 1;
@<Add a dotty row to the chart of kinds@>;
@<Add a titling row to the chart of kinds@>;
@<Add a dotty row to the chart of kinds@>;
@<Add the rubric below the chart of kinds@>;
@<Run through the kinds in priority order@>;
@<Add a dotty row to the chart of kinds@>;
HTML::end_html_table(OUT);
pass = 2;
@<Run through the kinds in priority order@>;
@<Explain about covariance and contravariance@>;
2021-06-14 00:29:31 +03:00
}
2019-02-05 02:44:07 +02:00
2021-07-24 20:16:56 +03:00
@ Not all of the built-in kinds are indexed on the Kinds page. The ones
2019-02-05 02:44:07 +02:00
omitted are of no help to end users, and would only clutter up the table
with misleading entries. Remaining kinds are grouped together in
"priority" order, a device to enable the quasinumerical kinds to stick
together, the enumerative ones, and so on. A lower priority number puts you
higher up, but kinds with priority 0 do not appear in the index at all.
2021-06-14 00:29:31 +03:00
@d LOWEST_INDEX_PRIORITY 100
2021-07-24 20:16:56 +03:00
@<Run through the kinds in priority order@> =
for (int priority = 1; priority <= LOWEST_INDEX_PRIORITY; priority++) {
2021-07-25 00:04:35 +03:00
inter_package *pack;
LOOP_OVER_INVENTORY_PACKAGES(pack, i, inv->kind_nodes)
2021-06-14 00:29:31 +03:00
if ((Metadata::read_optional_numeric(pack, I"^is_base")) &&
(Metadata::read_optional_numeric(pack, I"^is_subkind_of_object") == 0) &&
(priority == (int) Metadata::read_optional_numeric(pack, I"^index_priority"))) {
if ((priority == 8) || (Metadata::read_optional_numeric(pack, I"^is_definite"))) {
2021-07-24 20:16:56 +03:00
@<Index this kind package@>;
2019-02-05 02:44:07 +02:00
}
}
if ((priority == 1) || (priority == 6) || (priority == 7)) {
if (pass == 1) {
@<Add a dotty row to the chart of kinds@>;
if (priority == 7) {
@<Add a second titling row to the chart of kinds@>;
@<Add a dotty row to the chart of kinds@>;
}
} else HTML_TAG("hr");
}
}
@ An atypical row:
@<Add a titling row to the chart of kinds@> =
HTML::first_html_column_nowrap(OUT, 0, "#e0e0e0");
2021-07-24 20:16:56 +03:00
WRITE("<b>");
Localisation::write_0(OUT, D, I"Index.Elements.Ch.BasicKinds");
WRITE("</b>");
ChartElement::index_kind_col_head(OUT, I"Index.Elements.Ch.DefaultColumn", "default", D);
ChartElement::index_kind_col_head(OUT, I"Index.Elements.Ch.RepeatColumn", "repeat", D);
ChartElement::index_kind_col_head(OUT, I"Index.Elements.Ch.PropsColumn", "props", D);
ChartElement::index_kind_col_head(OUT, I"Index.Elements.Ch.UnderColumn", "under", D);
2019-02-05 02:44:07 +02:00
HTML::end_html_row(OUT);
@ And another:
@<Add a second titling row to the chart of kinds@> =
HTML::first_html_column_nowrap(OUT, 0, "#e0e0e0");
2021-07-24 20:16:56 +03:00
WRITE("<b>");
Localisation::write_0(OUT, D, I"Index.Elements.Ch.NewKinds");
WRITE("</b>");
ChartElement::index_kind_col_head(OUT, I"Index.Elements.Ch.DefaultColumn", "default", D);
ChartElement::index_kind_col_head(OUT, NULL, NULL, D);
ChartElement::index_kind_col_head(OUT, NULL, NULL, D);
ChartElement::index_kind_col_head(OUT, NULL, NULL, D);
2019-02-05 02:44:07 +02:00
HTML::end_html_row(OUT);
@ A dotty row:
@<Add a dotty row to the chart of kinds@> =
HTML_OPEN_WITH("tr", "bgcolor=\"#888\"");
HTML_OPEN_WITH("td", "height=\"1\" colspan=\"5\" cellpadding=\"0\"");
HTML_CLOSE("td");
HTML_CLOSE("tr");
2021-07-24 20:16:56 +03:00
@ Note the named IDs here, which must match those linked from the titling
2019-02-05 02:44:07 +02:00
row.
@<Add the rubric below the chart of kinds@> =
HTML_OPEN_WITH("tr", "style=\"display:none\" id=\"default\"");
HTML_OPEN_WITH("td", "colspan=\"5\"");
2021-07-24 20:16:56 +03:00
Localisation::write_0(OUT, D, I"Index.Elements.Ch.DefaultGloss");
2019-02-05 02:44:07 +02:00
HTML_TAG("hr");
HTML_CLOSE("td");
HTML_CLOSE("tr");
HTML_OPEN_WITH("tr", "style=\"display:none\" id=\"repeat\"");
HTML_OPEN_WITH("td", "colspan=\"5\"");
2021-07-24 20:16:56 +03:00
Localisation::write_0(OUT, D, I"Index.Elements.Ch.RepeatGloss");
2019-02-05 02:44:07 +02:00
HTML_TAG("hr");
HTML_CLOSE("td");
HTML_CLOSE("tr");
HTML_OPEN_WITH("tr", "style=\"display:none\" id=\"props\"");
HTML_OPEN_WITH("td", "colspan=\"5\"");
2021-07-24 20:16:56 +03:00
Localisation::write_0(OUT, D, I"Index.Elements.Ch.PropsGloss");
2019-02-05 02:44:07 +02:00
HTML_TAG("hr");
HTML_CLOSE("td");
HTML_CLOSE("tr");
HTML_OPEN_WITH("tr", "style=\"display:none\" id=\"under\"");
HTML_OPEN_WITH("td", "colspan=\"5\"");
2021-07-24 20:16:56 +03:00
Localisation::write_0(OUT, D, I"Index.Elements.Ch.UnderGloss");
2019-02-05 02:44:07 +02:00
HTML_TAG("hr");
HTML_CLOSE("td");
HTML_CLOSE("tr");
2021-07-24 20:16:56 +03:00
@ So, the actual content, which is presented as a row of the table in pass 1,
or as paragraph of text in pass 2:
@<Index this kind package@> =
switch (pass) {
case 1: {
char *repeat = "cross", *props = "cross", *under = "cross";
int shaded = FALSE;
if (Metadata::read_optional_numeric(pack, I"^shaded_in_index")) shaded = TRUE;
if (Metadata::read_optional_numeric(pack, I"^finite_domain")) repeat = "tick";
if (Metadata::read_optional_numeric(pack, I"^has_properties")) props = "tick";
if (Metadata::read_optional_numeric(pack, I"^understandable")) under = "tick";
if (priority == 8) { repeat = NULL; props = NULL; under = NULL; }
ChartElement::begin_chart_row(OUT);
ChartElement::index_kind_name_cell(OUT, shaded, pack);
ChartElement::end_chart_row(OUT, shaded, pack, repeat, props, under);
break;
}
case 2: {
@<Write heading for the detailed index entry for this kind@>;
HTML::open_indented_p(OUT, 1, "tight");
@<Index kinds of kinds matched by this kind@>;
@<Index explanatory text supplied for a kind@>;
@<Index literal patterns which can specify this kind@>;
@<Index possible values of an enumerated kind@>;
HTML_CLOSE("p");
break;
}
}
if (Str::eq(Metadata::read_textual(pack, I"^printed_name"), I"object"))
ChartElement::index_subkinds(OUT, inv, pack, 2, pass, D);
2019-02-05 02:44:07 +02:00
@<Write heading for the detailed index entry for this kind@> =
2020-05-10 19:33:41 +03:00
HTML::open_indented_p(OUT, 1, "halftight");
2021-07-09 00:56:01 +03:00
IndexUtilities::anchor_numbered(OUT, i); /* ...the anchor to which the grey icon in the table led */
2021-07-24 20:16:56 +03:00
WRITE("<b>"); IndexUtilities::kind_name(OUT, pack, FALSE, TRUE); WRITE("</b>");
WRITE(" (<i>");
Localisation::write_0(OUT, D, I"Index.Elements.Ch.Plural");
WRITE("</i> ");
IndexUtilities::kind_name(OUT, pack, TRUE, FALSE); WRITE(")");
IndexUtilities::link_to_documentation(OUT, pack);
2019-02-05 02:44:07 +02:00
HTML_CLOSE("p");
2021-06-16 01:35:45 +03:00
text_stream *variance = Metadata::read_optional_textual(pack, I"^variance");
if (Str::len(variance) > 0) {
2020-05-10 19:33:41 +03:00
HTML::open_indented_p(OUT, 1, "tight");
2021-06-16 01:35:45 +03:00
WRITE("<i>%S&nbsp;", variance);
2019-02-05 02:44:07 +02:00
HTML_OPEN_WITH("a", "href=#contra>");
HTML_TAG_WITH("img", "border=0 src=inform:/doc_images/shelp.png");
HTML_CLOSE("a");
WRITE("</i>");
HTML_CLOSE("p");
}
@<Index literal patterns which can specify this kind@> =
2021-06-16 21:59:07 +03:00
text_stream *notation = Metadata::read_optional_textual(pack, I"^notation");
if (Str::len(notation) > 0) {
WRITE("%S", notation);
2019-02-05 02:44:07 +02:00
HTML_TAG("br");
}
@<Index kinds of kinds matched by this kind@> =
int f = FALSE;
WRITE("<i>Matches:</i> ");
2021-07-24 20:16:56 +03:00
inter_package *conf_pack;
LOOP_THROUGH_SUBPACKAGES(conf_pack, pack, I"_conformance") {
inter_symbol *xref = Metadata::read_optional_symbol(conf_pack, I"^conformed_to");
inter_package *other = Inter::Packages::container(xref->definition);
if (f) WRITE(", ");
IndexUtilities::kind_name(OUT, other, FALSE, TRUE);
f = TRUE;
2019-02-05 02:44:07 +02:00
}
HTML_TAG("br");
@<Index possible values of an enumerated kind@> =
2021-06-16 01:35:45 +03:00
if (Str::ne(Metadata::read_textual(pack, I"^printed_name"), I"object"))
if (Metadata::read_optional_numeric(pack, I"^instance_count") > 0)
ChartElement::index_instances(OUT, inv, pack, 1);
2019-02-05 02:44:07 +02:00
@<Index explanatory text supplied for a kind@> =
2021-06-15 01:29:45 +03:00
ChartElement::index_inferences(OUT, pack, FALSE);
2019-02-05 02:44:07 +02:00
@<Explain about covariance and contravariance@> =
HTML_OPEN("p");
HTML_TAG_WITH("a", "name=contra");
HTML_OPEN_WITH("span", "class=\"smaller\"");
2021-07-24 20:16:56 +03:00
Localisation::write_0(OUT, D, I"Index.Elements.Ch.CovarianceGloss");
2019-02-05 02:44:07 +02:00
HTML_CLOSE("span");
HTML_CLOSE("p");
@h Kind table construction.
First, here's the table cell for the heading at the top of a column: the
link is to the part of the rubric explaining what goes into the column.
=
2021-07-24 20:16:56 +03:00
void ChartElement::index_kind_col_head(OUTPUT_STREAM, text_stream *key, char *anchor,
localisation_dictionary *D) {
2019-02-05 02:44:07 +02:00
HTML::next_html_column_nowrap(OUT, 0);
2021-07-24 20:16:56 +03:00
WRITE("<i>");
if (Str::len(key) > 0) Localisation::write_0(OUT, D, key);
WRITE("</i>&nbsp;");
2019-02-05 02:44:07 +02:00
if (anchor) {
HTML_OPEN_WITH("a", "href=\"#\" onClick=\"showBasic('%s');\"", anchor);
HTML_TAG_WITH("img", "border=0 src=inform:/doc_images/shelp.png");
HTML_CLOSE("a");
}
}
@ Once we're past the heading row, each row is made in two parts: first this
is called --
=
int striper = FALSE;
2021-06-14 00:29:31 +03:00
void ChartElement::begin_chart_row(OUTPUT_STREAM) {
2019-02-05 02:44:07 +02:00
char *col = NULL;
if (striper) col = "#f0f0ff";
striper = striper?FALSE:TRUE;
HTML::first_html_column_nowrap(OUT, 0, col);
}
2021-07-24 20:16:56 +03:00
@ It's convenient to return the shadedness: a row is shaded if it's for a kind
which can have enumerated values but doesn't at the moment -- for instance, the
sound effects row is shaded if there are none.
2019-02-05 02:44:07 +02:00
=
2021-06-14 01:07:40 +03:00
int ChartElement::index_kind_name_cell(OUTPUT_STREAM, int shaded, inter_package *pack) {
2019-02-05 02:44:07 +02:00
if (shaded) HTML::begin_colour(OUT, I"808080");
2021-07-24 20:16:56 +03:00
IndexUtilities::kind_name(OUT, pack, FALSE, TRUE);
2021-06-14 01:07:40 +03:00
if (Metadata::read_optional_numeric(pack, I"^is_quasinumerical")) {
2019-02-05 02:44:07 +02:00
WRITE("&nbsp;");
HTML_OPEN_WITH("a", "href=\"Kinds.html?segment2\"");
HTML_TAG_WITH("img", "border=0 src=inform:/doc_images/calc1.png");
HTML_CLOSE("a");
}
2021-07-24 20:16:56 +03:00
IndexUtilities::link_to_documentation(OUT, pack);
2021-06-14 01:07:40 +03:00
int i = (int) Metadata::read_optional_numeric(pack, I"^instance_count");
2019-02-05 02:44:07 +02:00
if (i >= 1) WRITE(" [%d]", i);
2021-07-09 00:56:01 +03:00
IndexUtilities::below_link_numbered(OUT, pack->allocation_id);
2019-02-05 02:44:07 +02:00
if (shaded) HTML::end_colour(OUT);
return shaded;
}
@ Finally we close the name cell, add the remaining cells, and close out the
whole row.
=
2021-06-14 01:07:40 +03:00
void ChartElement::end_chart_row(OUTPUT_STREAM, int shaded, inter_package *pack,
char *tick1, char *tick2, char *tick3) {
if (tick1) HTML::next_html_column(OUT, 0);
else HTML::next_html_column_spanning(OUT, 0, 4);
if (shaded) HTML::begin_colour(OUT, I"808080");
WRITE("%S", Metadata::read_optional_textual(pack, I"^index_default"));
if (shaded) HTML::end_colour(OUT);
if (tick1) {
HTML::next_html_column_centred(OUT, 0);
if (tick1)
HTML_TAG_WITH("img",
"border=0 alt=\"%s\" src=inform:/doc_images/%s%s.png",
tick1, shaded?"grey":"", tick1);
HTML::next_html_column_centred(OUT, 0);
if (tick2)
HTML_TAG_WITH("img",
"border=0 alt=\"%s\" src=inform:/doc_images/%s%s.png",
tick2, shaded?"grey":"", tick2);
HTML::next_html_column_centred(OUT, 0);
if (tick3)
HTML_TAG_WITH("img",
"border=0 alt=\"%s\" src=inform:/doc_images/%s%s.png",
tick3, shaded?"grey":"", tick3);
}
HTML::end_html_row(OUT);
}
2021-07-24 20:16:56 +03:00
@h Recursing through subkinds.
The following limitation exists just to catch errors.
2021-06-14 00:29:31 +03:00
2021-06-15 01:29:45 +03:00
@d MAX_OBJECT_INDEX_DEPTH 10000
2021-06-14 00:29:31 +03:00
=
2021-07-24 20:16:56 +03:00
void ChartElement::index_subkinds(OUTPUT_STREAM, tree_inventory *inv, inter_package *pack,
int depth, int pass, localisation_dictionary *D) {
2021-07-25 00:04:35 +03:00
inter_package *subkind_pack;
LOOP_OVER_INVENTORY_PACKAGES(subkind_pack, i, inv->kind_nodes)
if ((Metadata::read_optional_numeric(subkind_pack, I"^is_base")) &&
(Metadata::read_optional_numeric(subkind_pack, I"^is_subkind_of_object"))) {
inter_symbol *super_weak = Metadata::read_optional_symbol(subkind_pack, I"^superkind");
2021-06-15 01:29:45 +03:00
if ((super_weak) && (Inter::Packages::container(super_weak->definition) == pack))
2021-07-25 00:04:35 +03:00
ChartElement::index_object_kind(OUT, inv, subkind_pack, depth, pass, D);
2021-06-15 01:29:45 +03:00
}
}
2021-07-24 20:16:56 +03:00
void ChartElement::index_object_kind(OUTPUT_STREAM, tree_inventory *inv,
inter_package *pack, int depth, int pass, localisation_dictionary *D) {
2021-06-14 11:00:18 +03:00
if (depth == MAX_OBJECT_INDEX_DEPTH) internal_error("MAX_OBJECT_INDEX_DEPTH exceeded");
2021-06-15 01:29:45 +03:00
inter_symbol *class_s = Metadata::read_optional_symbol(pack, I"^object_class");
if (class_s == NULL) internal_error("no class for object kind");
text_stream *anchor = class_s->symbol_name;
2021-06-14 11:00:18 +03:00
int shaded = FALSE;
@<Begin the object citation line@>;
@<Index the name part of the object citation@>;
@<Index the link icons part of the object citation@>;
@<End the object citation line@>;
if (pass == 2) @<Add a subsidiary paragraph of details about this object@>;
2021-07-24 20:16:56 +03:00
ChartElement::index_subkinds(OUT, inv, pack, depth+1, pass, D);
2021-06-14 11:00:18 +03:00
}
@<Begin the object citation line@> =
if (pass == 1) ChartElement::begin_chart_row(OUT);
if (pass == 2) {
HTML::open_indented_p(OUT, depth, "halftight");
2021-07-09 00:56:01 +03:00
IndexUtilities::anchor(OUT, anchor);
2021-06-14 11:00:18 +03:00
}
@<End the object citation line@> =
2021-06-15 01:29:45 +03:00
if (pass == 1) ChartElement::end_chart_row(OUT, shaded, pack, "tick", "tick", "tick");
if (pass == 2) HTML_CLOSE("p");
2021-06-14 11:00:18 +03:00
@<Index the name part of the object citation@> =
if (pass == 1) {
2021-06-15 01:29:45 +03:00
int c = (int) Metadata::read_optional_numeric(pack, I"^instance_count");
2021-06-14 11:00:18 +03:00
if ((c == 0) && (pass == 1)) shaded = TRUE;
if (shaded) HTML::begin_colour(OUT, I"808080");
@<Quote the name of the object being indexed@>;
if (shaded) HTML::end_colour(OUT);
if ((pass == 1) && (c > 0)) WRITE(" [%d]", c);
} else {
@<Quote the name of the object being indexed@>;
}
@<Quote the name of the object being indexed@> =
2021-06-15 01:29:45 +03:00
if (pass == 2) WRITE("<b>");
2021-07-24 20:16:56 +03:00
IndexUtilities::kind_name(OUT, pack, FALSE, FALSE);
2021-06-15 01:29:45 +03:00
if (pass == 2) WRITE("</b>");
if (pass == 2) {
2021-07-24 20:16:56 +03:00
WRITE(" (<i>");
Localisation::write_0(OUT, D, I"Index.Elements.Ch.Plural");
WRITE("</i> ");
IndexUtilities::kind_name(OUT, pack, TRUE, FALSE);
2021-06-15 01:29:45 +03:00
WRITE(")");
2021-06-14 11:00:18 +03:00
}
@<Index the link icons part of the object citation@> =
2021-07-24 20:16:56 +03:00
IndexUtilities::link_package(OUT, pack);
IndexUtilities::link_to_documentation(OUT, pack);
2021-07-09 00:56:01 +03:00
if (pass == 1) IndexUtilities::below_link(OUT, anchor);
2021-06-14 11:00:18 +03:00
@<Add a subsidiary paragraph of details about this object@> =
HTML::open_indented_p(OUT, depth, "tight");
2021-06-15 01:29:45 +03:00
ChartElement::index_inferences(OUT, pack, TRUE);
HTML_CLOSE("p");
ChartElement::index_instances(OUT, inv, pack, depth);
2021-06-14 11:00:18 +03:00
@ =
2021-07-24 20:16:56 +03:00
void ChartElement::index_instances(OUTPUT_STREAM, tree_inventory *inv, inter_package *pack,
int depth) {
2021-06-14 11:00:18 +03:00
HTML::open_indented_p(OUT, depth, "tight");
2021-06-15 01:29:45 +03:00
int c = (int) Metadata::read_optional_numeric(pack, I"^instance_count");
2021-06-14 11:00:18 +03:00
if (c >= 10) {
2021-07-24 20:16:56 +03:00
int xtra = IndexRules::extra_ID();
2021-07-09 00:56:01 +03:00
IndexUtilities::extra_link(OUT, xtra);
2021-06-14 11:00:18 +03:00
HTML::begin_colour(OUT, I"808080");
WRITE("%d ", c);
2021-07-24 20:16:56 +03:00
IndexUtilities::kind_name(OUT, pack, TRUE, FALSE);
2021-06-14 11:00:18 +03:00
HTML::end_colour(OUT);
HTML_CLOSE("p");
2021-07-09 00:56:01 +03:00
IndexUtilities::extra_div_open(OUT, xtra, depth+1, "e0e0e0");
2021-06-15 01:29:45 +03:00
@<Itemise the instances@>;
2021-07-09 00:56:01 +03:00
IndexUtilities::extra_div_close(OUT, "e0e0e0");
2021-06-14 11:00:18 +03:00
} else {
2021-06-15 01:29:45 +03:00
@<Itemise the instances@>;
HTML_CLOSE("p");
}
}
@<Itemise the instances@> =
2021-07-24 20:16:56 +03:00
int c = 0;
2021-07-25 00:04:35 +03:00
inter_package *I_pack;
LOOP_OVER_INVENTORY_PACKAGES(I_pack, i, inv->instance_nodes) {
2021-06-15 01:29:45 +03:00
inter_symbol *strong_kind_ID = Metadata::read_optional_symbol(I_pack, I"^kind_xref");
if ((strong_kind_ID) && (Inter::Packages::container(strong_kind_ID->definition) == pack)) {
2021-06-14 11:00:18 +03:00
if (c > 0) WRITE(", "); c++;
HTML::begin_colour(OUT, I"808080");
2021-06-15 01:29:45 +03:00
WRITE("%S", Metadata::read_optional_textual(I_pack, I"^name"));
2021-06-14 11:00:18 +03:00
HTML::end_colour(OUT);
2021-07-24 20:16:56 +03:00
IndexUtilities::link_package(OUT, I_pack);
2021-06-14 11:00:18 +03:00
}
}
2021-06-15 01:29:45 +03:00
2021-07-24 20:16:56 +03:00
@ Here |pack| can be either an instance or a kind package.
=
2021-06-15 01:29:45 +03:00
void ChartElement::index_inferences(OUTPUT_STREAM, inter_package *pack, int brief) {
2021-06-27 16:56:29 +03:00
text_stream *explanation = Metadata::read_optional_textual(pack, I"^specification");
if (Str::len(explanation) > 0) {
WRITE("%S", explanation);
HTML_TAG("br");
}
text_stream *material = NULL;
if (brief) material = Metadata::read_optional_textual(pack, I"^brief_inferences");
else material = Metadata::read_optional_textual(pack, I"^inferences");
WRITE("%S", material);
2021-06-14 11:00:18 +03:00
}