diff --git a/docs/supervisor-module/7-ip2.html b/docs/supervisor-module/7-ip2.html
index 63e8eda3a..60b93a2a9 100644
--- a/docs/supervisor-module/7-ip2.html
+++ b/docs/supervisor-module/7-ip2.html
@@ -214,8 +214,7 @@ our E, and return 0 in response to the ECD call to prevent further ECD calls.
compatibility_specification *C = E->as_copy->edition->compatibility;
if (Str::len(C->parsed_from) > 0) {
- WRITE("%S ", C->parsed_from);
- ExtensionIndex::write_icons(OUT, C);
+ WRITE("%S", C->parsed_from);
}
- This code is used in §2.2.1.
diff --git a/docs/supervisor-module/7-tm.html b/docs/supervisor-module/7-tm.html
index 2ff395d29..21bfe9601 100644
--- a/docs/supervisor-module/7-tm.html
+++ b/docs/supervisor-module/7-tm.html
@@ -110,7 +110,7 @@ same either way. Here are the functions for (a) and (b) respectively:
void ExtensionWebsite::go(inform_project *proj, int force_update) {
ExtensionDictionary::read_from_file();
-
extension_census *C = ExtensionCensus::perform(proj);
+
ExtensionCensus::perform(proj);
Time-stamp extensions used in the project as being last used today2.1;
Write index pages2.2;
Write individual pages on individual extensions2.3;
@@ -140,9 +140,7 @@ documentation as used today until the next run, for obscure timing reasons.
- ExtensionIndex::write(ExtensionWebsite::index_URL(proj, I"Extensions.html"), HOME_EXTPAGE, C);
- if (proj == NULL)
- ExtensionIndex::write(ExtensionWebsite::index_URL(proj, I"ExtIndex.html"), INDEX_EXTPAGE, C);
+ ExtensionIndex::write(proj);
-filename *ExtensionWebsite::index_URL(inform_project *proj, text_stream *leaf) {
+filename *ExtensionWebsite::index_URL(inform_project *proj, text_stream *leaf) {
pathname *P = ExtensionWebsite::home_URL(proj);
if (P == NULL) return NULL;
return Filenames::in(P, leaf);
diff --git a/inbuild/supervisor-module/Chapter 1/Supervisor Module.w b/inbuild/supervisor-module/Chapter 1/Supervisor Module.w
index 76b009196..ffdf17083 100644
--- a/inbuild/supervisor-module/Chapter 1/Supervisor Module.w
+++ b/inbuild/supervisor-module/Chapter 1/Supervisor Module.w
@@ -21,6 +21,7 @@ which use this module:
@e extension_census_CLASS
@e extension_census_datum_CLASS
@e extension_dictionary_entry_CLASS
+@e extensions_key_item_CLASS
@e heading_CLASS
@e heading_tree_CLASS
@e inbuild_copy_CLASS
@@ -54,6 +55,7 @@ DECLARE_CLASS(element_activation)
DECLARE_CLASS(extension_census_datum)
DECLARE_CLASS(extension_census)
DECLARE_CLASS(extension_dictionary_entry)
+DECLARE_CLASS(extensions_key_item)
DECLARE_CLASS(heading_tree)
DECLARE_CLASS(heading)
DECLARE_CLASS(inbuild_copy)
diff --git a/inbuild/supervisor-module/Chapter 2/Works.w b/inbuild/supervisor-module/Chapter 2/Works.w
index 682804f4b..4515938f7 100644
--- a/inbuild/supervisor-module/Chapter 2/Works.w
+++ b/inbuild/supervisor-module/Chapter 2/Works.w
@@ -232,7 +232,7 @@ each extension's page is generated from its |inbuild_work|.
=
void Works::begin_extension_link(OUTPUT_STREAM, inbuild_work *work, text_stream *rubric) {
TEMPORARY_TEXT(link)
- WRITE_TO(link, "href='inform://Extensions/Extensions/");
+ WRITE_TO(link, "href='inform://Extensions/Documentation/");
Works::escape_apostrophes(link, work->author_name);
WRITE_TO(link, "/");
Works::escape_apostrophes(link, work->title);
diff --git a/inbuild/supervisor-module/Chapter 7/Census.w b/inbuild/supervisor-module/Chapter 7/Census.w
index 88f407653..b1b57209d 100644
--- a/inbuild/supervisor-module/Chapter 7/Census.w
+++ b/inbuild/supervisor-module/Chapter 7/Census.w
@@ -90,53 +90,6 @@ int ExtensionCensus::ecd_used(extension_census_datum *ecd) {
return E->has_historically_been_used;
}
-@ The following give some sorting criteria, and are functions fit to be
-handed to |qsort|.
-
-=
-int ExtensionCensus::compare_ecd_by_title(const void *ecd1, const void *ecd2) {
- extension_census_datum *e1 = *((extension_census_datum **) ecd1);
- extension_census_datum *e2 = *((extension_census_datum **) ecd2);
- inform_extension *E1 = Extensions::from_copy(e1->found_as->copy);
- inform_extension *E2 = Extensions::from_copy(e2->found_as->copy);
- return Extensions::compare_by_title(E2, E1);
-}
-
-int ExtensionCensus::compare_ecd_by_author(const void *ecd1, const void *ecd2) {
- extension_census_datum *e1 = *((extension_census_datum **) ecd1);
- extension_census_datum *e2 = *((extension_census_datum **) ecd2);
- inform_extension *E1 = Extensions::from_copy(e1->found_as->copy);
- inform_extension *E2 = Extensions::from_copy(e2->found_as->copy);
- return Extensions::compare_by_author(E2, E1);
-}
-
-int ExtensionCensus::compare_ecd_by_installation(const void *ecd1, const void *ecd2) {
- extension_census_datum *e1 = *((extension_census_datum **) ecd1);
- extension_census_datum *e2 = *((extension_census_datum **) ecd2);
- int d = ExtensionCensus::installation_region(e1) -
- ExtensionCensus::installation_region(e2);
- if (d != 0) return d;
- inform_extension *E1 = Extensions::from_copy(e1->found_as->copy);
- inform_extension *E2 = Extensions::from_copy(e2->found_as->copy);
- return Extensions::compare_by_edition(E1, E2);
-}
-
-int ExtensionCensus::compare_ecd_by_date(const void *ecd1, const void *ecd2) {
- extension_census_datum *e1 = *((extension_census_datum **) ecd1);
- extension_census_datum *e2 = *((extension_census_datum **) ecd2);
- inform_extension *E1 = Extensions::from_copy(e1->found_as->copy);
- inform_extension *E2 = Extensions::from_copy(e2->found_as->copy);
- return Extensions::compare_by_date(E1, E2);
-}
-
-int ExtensionCensus::compare_ecd_by_length(const void *ecd1, const void *ecd2) {
- extension_census_datum *e1 = *((extension_census_datum **) ecd1);
- extension_census_datum *e2 = *((extension_census_datum **) ecd2);
- inform_extension *E1 = Extensions::from_copy(e1->found_as->copy);
- inform_extension *E2 = Extensions::from_copy(e2->found_as->copy);
- return Extensions::compare_by_length(E1, E2);
-}
-
@h Performing the census.
For some reason a census often makes a good story (cf. Luke 2:1-5), but here
there's disappointingly little to tell, because the work is all done by a
diff --git a/inbuild/supervisor-module/Chapter 7/Index Pages.w b/inbuild/supervisor-module/Chapter 7/Index Pages.w
index bf9b383c1..e3c2a9352 100644
--- a/inbuild/supervisor-module/Chapter 7/Index Pages.w
+++ b/inbuild/supervisor-module/Chapter 7/Index Pages.w
@@ -2,25 +2,40 @@
To generate the two top-level pages in the extension mini-website.
-@h Writing the extensions home pages.
-There are two of these, both with the same surround:
-
-@e HOME_EXTPAGE from 1
-@e INDEX_EXTPAGE
+@h Writing the extensions home page.
+There were once two of these, but now there's just one.
=
-void ExtensionIndex::write(filename *F, int content, extension_census *C) {
+void ExtensionIndex::write(inform_project *proj) {
+ filename *F = ExtensionWebsite::index_URL(proj, I"Extensions.html");
if (F == NULL) return;
+
+ linked_list *L = NEW_LINKED_LIST(inbuild_search_result);
+ linked_list *U = NEW_LINKED_LIST(inbuild_copy);
+ linked_list *R = NEW_LINKED_LIST(inbuild_requirement);
+ @;
+
text_stream HOMEPAGE_struct;
text_stream *OUT = &HOMEPAGE_struct;
if (STREAM_OPEN_TO_FILE(OUT, F, UTF8_ENC) == FALSE) return;
-
InformPages::header(OUT, I"Extensions", JAVASCRIPT_FOR_EXTENSIONS_IRES, NULL);
@;
InformPages::footer(OUT);
STREAM_CLOSE(OUT);
}
+@ =
+ linked_list *search_list = NEW_LINKED_LIST(inbuild_nest);
+ inbuild_nest *materials = Projects::materials_nest(proj);
+ if (materials) ADD_TO_LINKED_LIST(materials, inbuild_nest, search_list);
+ inbuild_nest *internal = Supervisor::internal();
+ if (internal) ADD_TO_LINKED_LIST(internal, inbuild_nest, search_list);
+ if (LinkedLists::len(search_list) > 0) {
+ inbuild_requirement *req = Requirements::anything_of_genre(extension_bundle_genre);
+ Nests::search_for(req, search_list, L);
+ }
+ ExtensionIndex::find_used_extensions(proj, U, R);
+
@ =
HTML::begin_html_table(OUT, NULL, TRUE, 0, 4, 0, 0, 0);
HTML::first_html_column(OUT, 0);
@@ -31,186 +46,132 @@ void ExtensionIndex::write(filename *F, int content, extension_census *C) {
HTML_OPEN_WITH("div", "class=\"headingpanellayout headingpanelalt\"");
HTML_OPEN_WITH("div", "class=\"headingtext\"");
HTML::begin_span(OUT, I"headingpaneltextalt");
- WRITE("Installed Extensions");
+ WRITE("Extensions in this Project");
HTML::end_span(OUT);
HTML_CLOSE("div");
HTML_OPEN_WITH("div", "class=\"headingrubric\"");
HTML::begin_span(OUT, I"headingpanelrubricalt");
- WRITE("Bundles of extra rules or phrases to extend what Inform can do");
+ WRITE("Those installed and those used");
HTML::end_span(OUT);
HTML_CLOSE("div");
HTML_CLOSE("div");
- @;
+ @;
HTML::end_html_row(OUT);
HTML::end_html_table(OUT);
HTML_TAG("hr");
- @;
-
-@ =
- switch (content) {
- case HOME_EXTPAGE:
- @;
- @;
- break;
- case INDEX_EXTPAGE:
- HTML_OPEN("p");
- WRITE("Whenever an extension is used, its definitions are entered into the "
- "following index. (Thus, a newly installed but never-used extension "
- "is not indexed yet.).");
- HTML_CLOSE("p");
- break;
- }
-
-@ =
- switch (content) {
- case HOME_EXTPAGE: @; break;
- case INDEX_EXTPAGE: ExtensionDictionary::write_to_HTML(OUT); break;
- }
+ HTML_OPEN("p");
+ HTML_OPEN("b");
+ WRITE("The project '%S' currently uses...", proj->as_copy->edition->work->title);
+ HTML_CLOSE("b");
+ HTML_CLOSE("p");
+ int usage_state = TRUE;
+ @;
+ HTML_TAG("hr");
+ HTML_OPEN("p");
+ HTML_OPEN("b");
+ WRITE("These are available, but are not used by '%S'...", proj->as_copy->edition->work->title);
+ HTML_CLOSE("b");
+ HTML_CLOSE("p");
+ usage_state = FALSE;
+ @;
@ From here on, then, all the code in this section generates the main directory
page, not the index of terms, which is all handled by
//ExtensionDictionary::write_to_HTML//.
@ =
- int nps = 0, nbi = 0, ni = 0;
- extension_census_datum *ecd;
- LOOP_OVER(ecd, extension_census_datum) {
- if (Nests::get_tag(ecd->found_as->nest) == MATERIALS_NEST_TAG) nps++;
- else if (Nests::get_tag(ecd->found_as->nest) == INTERNAL_NEST_TAG) nbi++;
- else ni++;
+ int nbi = 0, nps = 0;
+ inbuild_search_result *ecd;
+ LOOP_OVER_LINKED_LIST(ecd, inbuild_search_result, L) {
+ if (Nests::get_tag(ecd->nest) == INTERNAL_NEST_TAG) nbi++;
+ else nps++;
}
+ HTML_OPEN("p");
+ pathname *P = Nests::get_location(Projects::materials_nest(proj));
+ P = Pathnames::down(P, I"Extensions");
+ PasteButtons::open_file(OUT, P, NULL, PROJECT_SPECIFIC_SYMBOL);
+ WRITE(" ");
+ if (nps > 0) {
+ WRITE("%d extension%s installed in the .materials folder for the "
+ "project '%S'. (Click the purple folder icon to show the location.)",
+ nps, (nps==1)?" is":"s are", proj->as_copy->edition->work->title);
+ } else {
+ WRITE("No extensions are installed in the .materials folder for the "
+ "project '%S'. (Click the purple folder icon to show the location. "
+ "Extensions should be put in the 'Extensions' subfolder of this: you "
+ "can put them there yourself, or use the Inform app to install them "
+ "for you.)", proj->as_copy->edition->work->title);
+ }
+ HTML_CLOSE("p");
+
HTML_OPEN("p");
HTML_TAG_WITH("img", "src='inform:/doc_images/builtin_ext.png' border=0");
- WRITE(" You have "
- "%d extensions built-in to this copy of Inform, marked with a grey folder "
- "icon in the catalogue below.",
- nbi);
+ WRITE(" ");
+ WRITE("As well as being able to use extensions installed into its own folder, "
+ "any project can use extensions which come built into the Inform app. There "
+ "are currently %d.", nbi);
HTML_CLOSE("p");
- HTML_OPEN("p");
- if (ni == 0) {
- HTML_TAG_WITH("img", "src='inform:/doc_images/folder4.png' border=0");
- WRITE(" You have no other extensions installed at present.");
- } else {
- #ifdef INDEX_MODULE
- PasteButtons::open_file(OUT, ExtensionCensus::external_path(C), NULL,
- "src='inform:/doc_images/folder4.png' border=0");
- #endif
- WRITE(" You have %d further extension%s installed. These are marked "
- "with a blue folder icon in the catalogue below. (Click it to see "
- "where the file is stored on your computer.) "
- "For more extensions, visit www.inform7.com.",
- ni, (ni==1)?"":"s");
- }
- HTML_CLOSE("p");
- if (nps > 0) {
- HTML_OPEN("p");
- #ifdef INDEX_MODULE
- PasteButtons::open_file(OUT, ExtensionCensus::internal_path(C),
- NULL, PROJECT_SPECIFIC_SYMBOL);
- #endif
- WRITE(" You have %d extension%s in the .materials folder for the "
- "current project. (Click the purple folder icon to show the "
- "location.) %s not available to other projects.",
- nps, (nps==1)?"":"s", (nps==1)?"This is":"These are");
- HTML_CLOSE("p");
- }
-
-@ We sometimes position a warning prominently at the top of the listing,
-because otherwise its position at the bottom will be invisible unless the user
-scrolls a long way:
-
-@ =
- if ((C->no_census_errors > 0) &&
- (NUMBER_CREATED(extension_census_datum) >= 20)) { /* it's a short page anyway */
- HTML_OPEN("p");
- HTML_TAG_WITH("img", "border=0 src=inform:/doc_images/misinstalled.png");
- WRITE(" "
- "Warning. One or more extensions are installed incorrectly: "
- "see details below.");
- HTML_CLOSE("p");
- }
@ The following is an alphabetised directory of extensions by author and then
title, along with some useful information about them, and then a list of
any oddities found in the external extensions area.
@ =
- int key_vms = FALSE, key_override = FALSE, key_builtin = FALSE,
- key_pspec = FALSE, key_bullet = FALSE;
- @;
- int no_entries = NUMBER_CREATED(extension_census_datum);
- extension_census_datum **sorted_census_results = Memory::calloc(no_entries,
- sizeof(extension_census_datum *), EXTENSION_DICTIONARY_MREASON);
- for (int d=1; d<=5; d++) {
+ linked_list *key_list = NEW_LINKED_LIST(extensions_key_item);
+ if (usage_state == FALSE) @;
+ int no_entries = LinkedLists::len(L);
+ inbuild_search_result **sorted_census_results = Memory::calloc(no_entries,
+ sizeof(inbuild_search_result *), EXTENSION_DICTIONARY_MREASON);
+ for (int d=((usage_state)?4:1); d<=((usage_state)?4:3); d++) {
@;
+ int no_entries_in_set = 0;
@;
@;
+ @;
+ @;
HTML_CLOSE("div");
}
- @;
- @;
Memory::I7_array_free(sorted_census_results, EXTENSION_DICTIONARY_MREASON,
- no_entries, sizeof(extension_census_datum *));
+ no_entries, sizeof(inbuild_search_result *));
@ I am the first to admit that this implementation is not inspired. There
-are five radio buttons, and number 2 is selected by default.
+are three radio buttons, and number 1 is selected by default.
@ =
HTML_OPEN("p");
- WRITE("Sort catalogue: ");
+ WRITE("Sort this list: ");
HTML_OPEN_WITH("a",
"href=\"#\" style=\"text-decoration: none\" "
"onclick=\"openExtra('disp1', 'plus1'); closeExtra('disp2', 'plus2'); "
- "closeExtra('disp3', 'plus3'); closeExtra('disp4', 'plus4'); "
- "closeExtra('disp5', 'plus5'); return false;\"");
- HTML_TAG_WITH("img", "border=0 id=\"plus1\" src=inform:/doc_images/extrarboff.png");
+ "closeExtra('disp3', 'plus3'); return false;\"");
+ HTML_TAG_WITH("img", "border=0 id=\"plus1\" src=inform:/doc_images/extrarbon.png");
WRITE(" By title");
HTML_CLOSE("a");
WRITE(" | ");
HTML_OPEN_WITH("a",
"href=\"#\" style=\"text-decoration: none\" "
"onclick=\"closeExtra('disp1', 'plus1'); openExtra('disp2', 'plus2'); "
- "closeExtra('disp3', 'plus3'); closeExtra('disp4', 'plus4'); "
- "closeExtra('disp5', 'plus5'); return false;\"");
- HTML_TAG_WITH("img", "border=0 id=\"plus2\" src=inform:/doc_images/extrarbon.png");
+ "closeExtra('disp3', 'plus3'); return false;\"");
+ HTML_TAG_WITH("img", "border=0 id=\"plus2\" src=inform:/doc_images/extrarboff.png");
WRITE(" By author");
HTML_CLOSE("a");
WRITE(" | ");
HTML_OPEN_WITH("a",
"href=\"#\" style=\"text-decoration: none\" "
"onclick=\"closeExtra('disp1', 'plus1'); closeExtra('disp2', 'plus2'); "
- "openExtra('disp3', 'plus3'); closeExtra('disp4', 'plus4'); "
- "closeExtra('disp5', 'plus5'); return false;\"");
+ "openExtra('disp3', 'plus3'); return false;\"");
HTML_TAG_WITH("img", "border=0 id=\"plus3\" src=inform:/doc_images/extrarboff.png");
- WRITE(" By installation");
- HTML_CLOSE("a");
- WRITE(" | ");
- HTML_OPEN_WITH("a",
- "href=\"#\" style=\"text-decoration: none\" "
- "onclick=\"closeExtra('disp1', 'plus1'); closeExtra('disp2', 'plus2'); "
- "closeExtra('disp3', 'plus3'); openExtra('disp4', 'plus4'); "
- "closeExtra('disp5', 'plus5'); return false;\"");
- HTML_TAG_WITH("img", "border=0 id=\"plus4\" src=inform:/doc_images/extrarboff.png");
- WRITE(" By date used");
- HTML_CLOSE("a");
- WRITE(" | ");
- HTML_OPEN_WITH("a",
- "href=\"#\" style=\"text-decoration: none\" "
- "onclick=\"closeExtra('disp1', 'plus1'); closeExtra('disp2', 'plus2'); "
- "closeExtra('disp3', 'plus3'); closeExtra('disp4', 'plus4'); "
- "openExtra('disp5', 'plus5'); return false;\"");
- HTML_TAG_WITH("img", "border=0 id=\"plus5\" src=inform:/doc_images/extrarboff.png");
- WRITE(" By word count");
+ WRITE(" By location");
HTML_CLOSE("a");
HTML_CLOSE("p");
-@ Consequently, of the five divisions, number 2 is shown and the others
+@ Consequently, of the three divisions, number 1 is shown and the others
hidden, by default.
@ =
char *display = "none";
- if (d == SORT_CE_BY_AUTHOR) display = "block";
+ if ((d == SORT_CE_BY_TITLE) || (d == SORT_CE_BY_USAGE)) display = "block";
HTML_OPEN_WITH("div", "id=\"disp%d\" style=\"display: %s;\"", d, display);
@ The key at the foot only explicates those symbols actually used, and
@@ -218,30 +179,13 @@ doesn't explicate the "unindexed" symbol at all, since that's actually
just a blank image used for horizontal spacing to keep margins straight.
@ =
- if ((key_builtin) || (key_override) || (key_bullet) || (key_vms) || (key_pspec)) {
+ if (LinkedLists::len(key_list) > 0) {
HTML_OPEN("p");
WRITE("Key: ");
- if (key_bullet) {
- HTML_TAG_WITH("img", "%s", INDEXED_SYMBOL);
- WRITE(" Used ");
- }
- if (key_builtin) {
- HTML_TAG_WITH("img", "%s", BUILT_IN_SYMBOL);
- WRITE(" Built in ");
- }
- if (key_pspec) {
- HTML_TAG_WITH("img", "%s", PROJECT_SPECIFIC_SYMBOL);
- WRITE(" Project specific ");
- }
- if (key_override) {
- HTML_TAG_WITH("img", "%s", OVERRIDING_SYMBOL);
- WRITE(" Your version overrides the one built in ");
- }
- if (key_vms) {
- #ifdef CORE_MODULE
- HTML_TAG("br");
- ExtensionIndex::write_key(OUT);
- #endif
+ extensions_key_item *eki;
+ LOOP_OVER_LINKED_LIST(eki, extensions_key_item, key_list) {
+ HTML_TAG_WITH("img", "%S", eki->image_URL);
+ WRITE(" %S ", eki->gloss);
}
HTML_CLOSE("p");
}
@@ -250,25 +194,32 @@ just a blank image used for horizontal spacing to keep margins straight.
of extensions found by the census:
@ =
- if (C->no_census_errors > 0) {
+ int no_census_errors = 0;
+ for (int i=0; icopy->errors_reading_source_text);
+ }
+ if (no_census_errors > 0) {
@;
- inbuild_search_result *R;
- LOOP_OVER_LINKED_LIST(R, inbuild_search_result, C->raw_data)
- if (LinkedLists::len(R->copy->errors_reading_source_text) > 0) {
+ for (int i=0; icopy->errors_reading_source_text) > 0) {
copy_error *CE;
LOOP_OVER_LINKED_LIST(CE, copy_error,
- R->copy->errors_reading_source_text) {
+ ecd->copy->errors_reading_source_text) {
#ifdef INDEX_MODULE
HTML::open_indented_p(OUT, 2, "hanging");
#endif
#ifndef INDEX_MODULE
HTML_OPEN("p");
#endif
- WRITE("%X - ", R->copy->edition->work);
+ WRITE("%X - ", ecd->copy->edition->work);
CopyErrors::write(OUT, CE);
HTML_CLOSE("p");
}
}
+ }
}
@ We only want to warn people here: not to stop them from using Inform
@@ -293,25 +244,32 @@ until they put matters right.
@d SORT_CE_BY_TITLE 1
@d SORT_CE_BY_AUTHOR 2
-@d SORT_CE_BY_INSTALL 3
-@d SORT_CE_BY_DATE 4
-@d SORT_CE_BY_LENGTH 5
+@d SORT_CE_BY_LOCATION 3
+@d SORT_CE_BY_USAGE 4
@ =
int i = 0;
- extension_census_datum *ecd;
- LOOP_OVER(ecd, extension_census_datum)
- sorted_census_results[i++] = ecd;
+ inbuild_search_result *ecd;
+ LOOP_OVER_LINKED_LIST(ecd, inbuild_search_result, L) {
+ int found = FALSE;
+ inbuild_copy *C;
+ LOOP_OVER_LINKED_LIST(C, inbuild_copy, U)
+ if (C == ecd->copy) {
+ found = TRUE;
+ break;
+ }
+ if (found == usage_state) sorted_census_results[i++] = ecd;
+ }
+ no_entries_in_set = i;
int (*criterion)(const void *, const void *) = NULL;
switch (d) {
- case SORT_CE_BY_TITLE: criterion = ExtensionCensus::compare_ecd_by_title; break;
- case SORT_CE_BY_AUTHOR: criterion = ExtensionCensus::compare_ecd_by_author; break;
- case SORT_CE_BY_INSTALL: criterion = ExtensionCensus::compare_ecd_by_installation; break;
- case SORT_CE_BY_DATE: criterion = ExtensionCensus::compare_ecd_by_date; break;
- case SORT_CE_BY_LENGTH: criterion = ExtensionCensus::compare_ecd_by_length; break;
+ case SORT_CE_BY_TITLE: criterion = ExtensionIndex::compare_ecd_by_title; break;
+ case SORT_CE_BY_AUTHOR: criterion = ExtensionIndex::compare_ecd_by_author; break;
+ case SORT_CE_BY_LOCATION: criterion = ExtensionIndex::compare_ecd_by_location; break;
+ case SORT_CE_BY_USAGE: criterion = ExtensionIndex::compare_ecd_by_title; break;
default: internal_error("no such sorting criterion");
}
- qsort(sorted_census_results, (size_t) no_entries, sizeof(extension_census_datum *),
+ qsort(sorted_census_results, (size_t) no_entries_in_set, sizeof(inbuild_search_result *),
criterion);
@ Standard rows have black text on striped background colours, these being
@@ -322,9 +280,8 @@ the usual ones seen in Mac OS X applications such as iTunes.
@;
int stripe = 0;
TEMPORARY_TEXT(current_author_name)
- int i, current_installation = -1;
- for (i=0; i;
stripe = 1 - stripe;
if (stripe == 0)
@@ -341,53 +298,39 @@ the usual ones seen in Mac OS X applications such as iTunes.
@ =
switch (d) {
case SORT_CE_BY_TITLE:
+ case SORT_CE_BY_USAGE:
@;
WRITE("Extensions in alphabetical order");
@;
break;
- case SORT_CE_BY_DATE:
+ case SORT_CE_BY_LOCATION:
@;
- WRITE("Extensions in order of date used (most recent first)");
- @;
- break;
- case SORT_CE_BY_LENGTH:
- @;
- WRITE("Extensions in order of word count (longest first)");
+ WRITE("Extensions grouped by location");
@;
break;
}
@ =
if ((d == SORT_CE_BY_AUTHOR) &&
- (Str::ne(current_author_name, ecd->found_as->copy->edition->work->author_name))) {
- Str::copy(current_author_name, ecd->found_as->copy->edition->work->author_name);
+ (Str::ne(current_author_name, ecd->copy->edition->work->author_name))) {
+ Str::copy(current_author_name, ecd->copy->edition->work->author_name);
@;
@;
@;
stripe = 0;
}
- if ((d == SORT_CE_BY_INSTALL) &&
- (ExtensionCensus::installation_region(ecd) != current_installation)) {
- current_installation = ExtensionCensus::installation_region(ecd);
- @;
- @;
- @;
- stripe = 0;
- }
@ =
@;
HTML::begin_span(OUT, I"smaller");
- WRITE("%d extensions installed", no_entries);
+ WRITE("%d extensions in total", no_entries_in_set);
HTML::end_span(OUT);
@;
@ Usually white text on a grey background.
@ =
- int span = 4;
- if (d == SORT_CE_BY_TITLE) span = 3;
- HTML::first_html_column_coloured(OUT, 0, I"tintedrow", span);
+ HTML::first_html_column_coloured(OUT, 0, I"tintedrow", 4);
HTML::begin_span(OUT, I"extensioncensusentry");
WRITE(" ");
@@ -398,103 +341,86 @@ the usual ones seen in Mac OS X applications such as iTunes.
@ Used only in "by author".
@ =
- WRITE("%S", ecd->found_as->copy->edition->work->raw_author_name);
-
- extension_census_datum *ecd2;
- int cu = 0, cn = 0, j;
- for (j = i; j < no_entries; j++) {
- ecd2 = sorted_census_results[j];
- if (Str::ne(current_author_name,
- ecd2->found_as->copy->edition->work->author_name)) break;
- if (ExtensionCensus::ecd_used(ecd2)) cu++;
- else cn++;
- }
- WRITE(" ");
- HTML::begin_span(OUT, I"smaller");
- WRITE("(%d extension%s", cu+cn, (cu+cn==1)?"":"s");
- if ((cu == 0) && (cn == 1)) WRITE(", unused");
- else if ((cu == 0) && (cn == 2)) WRITE(", both unused");
- else if ((cu == 0) && (cn > 2)) WRITE(", all unused");
- else if ((cn == 0) && (cu == 1)) WRITE(", used");
- else if ((cn == 0) && (cu == 2)) WRITE(", both used");
- else if ((cn == 0) && (cu > 2)) WRITE(", all used");
- else if (cn+cu > 0) WRITE(", %d used, %d unused", cu, cn);
- WRITE(")");
- HTML::end_span(OUT);
-
-@ Used only in "by installation".
-
-@ =
- switch (current_installation) {
- case 0:
- WRITE("Supplied in the .materials folder ");
- HTML::begin_span(OUT, I"smaller");
- WRITE("%p", ExtensionCensus::internal_path(C));
- HTML::end_span(OUT); break;
- case 1: WRITE("Built in to Inform"); break;
- case 2: WRITE("User installed but overriding a built-in extension"); break;
- case 3:
- WRITE("User installed ");
- HTML::begin_span(OUT, I"smaller");
- WRITE("%p", ExtensionCensus::external_path(C));
- HTML::end_span(OUT); break;
- }
+ WRITE("%S", ecd->copy->edition->work->raw_author_name);
@
@d UNINDEXED_SYMBOL "border=\"0\" src=\"inform:/doc_images/unindexed_bullet.png\""
@d INDEXED_SYMBOL "border=\"0\" src=\"inform:/doc_images/indexed_bullet.png\""
+@d PROBLEM_SYMBOL "border=\"0\" height=\"12\" src=\"inform:/doc_images/census_problem.png\""
+@d REVEAL_SYMBOL "border=\"0\" src=\"inform:/doc_images/Reveal.png\""
+@d HELP_SYMBOL "border=\"0\" src=\"inform:/doc_images/help.png\""
+@d PASTE_SYMBOL "border=\"0\" src=\"inform:/doc_images/paste.png\""
@ =
@;
HTML::next_html_column_nw(OUT, 0);
- if (d != SORT_CE_BY_TITLE) {
- @;
- HTML::next_html_column_nw(OUT, 0);
- }
+ @;
+ HTML::next_html_column_nw(OUT, 0);
@;
HTML::next_html_column_w(OUT, 0);
@;
-@ The appearance of the line is
-
->> (bullet) The Title (by The Author) (VM requirement icons)
-
-where all is optional except the title part.
-
@ =
- char *bulletornot = UNINDEXED_SYMBOL;
- if (ExtensionCensus::ecd_used(ecd)) {
- bulletornot = INDEXED_SYMBOL; key_bullet = TRUE;
- }
- WRITE(" ");
- HTML_TAG_WITH("img", "%s", bulletornot);
-
- Works::begin_extension_link(OUT,
- ecd->found_as->copy->edition->work, ExtensionCensus::ecd_rubric(ecd));
HTML::begin_span(OUT, I"extensionindexentry");
if (d != SORT_CE_BY_AUTHOR) {
- WRITE("%S", ecd->found_as->copy->edition->work->raw_title);
- if (Str::len(ecd->found_as->copy->edition->work->raw_title) +
- Str::len(ecd->found_as->copy->edition->work->raw_author_name) > 45) {
+ WRITE("%S", ecd->copy->edition->work->raw_title);
+ if (Str::len(ecd->copy->edition->work->raw_title) +
+ Str::len(ecd->copy->edition->work->raw_author_name) > 45) {
HTML_TAG("br");
WRITE(" ");
} else {
WRITE(" ");
}
- WRITE("by %S", ecd->found_as->copy->edition->work->raw_author_name);
+ WRITE("by %S", ecd->copy->edition->work->raw_author_name);
} else {
- WRITE("%S", ecd->found_as->copy->edition->work->raw_title);
+ WRITE("%S", ecd->copy->edition->work->raw_title);
}
HTML::end_span(OUT);
- Works::end_extension_link(OUT, ecd->found_as->copy->edition->work);
- compatibility_specification *C = ecd->found_as->copy->edition->compatibility;
- if (Str::len(C->parsed_from) > 0) {
- @;
- key_vms = TRUE;
+ filename *F = ExtensionWebsite::abs_page_URL(proj, ecd->copy->edition, -1);
+ if (TextFiles::exists(F)) {
+ WRITE(" ");
+ TEMPORARY_TEXT(link)
+ TEMPORARY_TEXT(URL)
+ WRITE_TO(URL, "%f", ExtensionWebsite::rel_page_URL(ecd->copy->edition, -1));
+ WRITE_TO(link, "href='inform:/");
+ Works::escape_apostrophes(link, URL);
+ WRITE_TO(link, "' style=\"text-decoration: none\"");
+ HTML_OPEN_WITH("a", "%S", link);
+ DISCARD_TEXT(link)
+ HTML_TAG_WITH("img", "%s", HELP_SYMBOL);
+ ExtensionIndex::add_to_key(key_list, HELP_SYMBOL, I"Documentation (click to read)");
+ HTML_CLOSE("a");
}
+ inform_extension *E = Extensions::from_copy(ecd->copy);
+ parse_node *at = Extensions::get_inclusion_sentence(E);
+ if (at) {
+ wording W = Node::get_text(at);
+ source_location sl = Lexer::word_location(Wordings::first_wn(W));
+ SourceLinks::link(OUT, sl, TRUE);
+ ExtensionIndex::add_to_key(key_list, REVEAL_SYMBOL, I"Included here (click to see)");
+ }
+
+ if (LinkedLists::len(ecd->copy->errors_reading_source_text) > 0) {
+ WRITE(" ");
+ HTML_TAG_WITH("img", "%s", PROBLEM_SYMBOL);
+ ExtensionIndex::add_to_key(key_list, PROBLEM_SYMBOL, I"Has errors (see below)");
+ } else if (usage_state == FALSE) {
+ WRITE(" ");
+ TEMPORARY_TEXT(inclusion_text)
+ WRITE_TO(inclusion_text, "Include %X.\n\n\n", ecd->copy->edition->work);
+ PasteButtons::paste_text(OUT, inclusion_text);
+ DISCARD_TEXT(inclusion_text)
+ ExtensionIndex::add_to_key(key_list, PASTE_SYMBOL,
+ I"Source text to Include this (click to paste in)");
+ }
+
+ compatibility_specification *C = ecd->copy->edition->compatibility;
+ if (Str::len(C->parsed_from) > 0)
+ @;
+
@ VM requirements are parsed by feeding them into the lexer and calling the
same routines as would be used when parsing headings about VM requirements
in a normal run of Inform. Note that because the requirements are in round
@@ -502,15 +428,12 @@ brackets, which the lexer will split off as distinct words, we can ignore
the first and last word and just look at what is in between:
@ =
- WRITE(" %S", C->parsed_from);
- #ifdef CORE_MODULE
- ExtensionIndex::write_icons(OUT, C);
- #endif
+ ExtensionIndex::write_icons(OUT, key_list, C);
@ =
HTML::begin_span(OUT, I"smaller");
- if (VersionNumbers::is_null(ecd->found_as->copy->edition->version) == FALSE)
- WRITE("v %v", &(ecd->found_as->copy->edition->version));
+ if (VersionNumbers::is_null(ecd->copy->edition->version) == FALSE)
+ WRITE("v %v", &(ecd->copy->edition->version));
else
WRITE("--");
HTML::end_span(OUT);
@@ -518,48 +441,72 @@ the first and last word and just look at what is in between:
@
@d BUILT_IN_SYMBOL "border=\"0\" src=\"inform:/doc_images/builtin_ext.png\""
-@d OVERRIDING_SYMBOL "border=\"0\" src=\"inform:/doc_images/override_ext.png\""
@d PROJECT_SPECIFIC_SYMBOL "border=\"0\" src=\"inform:/doc_images/pspec_ext.png\""
+@d ARCH_16_SYMBOL "border=\"0\" src=\"inform:/doc_images/vm_z8.png\""
+@d ARCH_32_SYMBOL "border=\"0\" src=\"inform:/doc_images/vm_glulx.png\""
@ =
char *opener = "src='inform:/doc_images/folder4.png' border=0";
- if (Nests::get_tag(ecd->found_as->nest) == INTERNAL_NEST_TAG) {
- opener = BUILT_IN_SYMBOL; key_builtin = TRUE;
+ if (Nests::get_tag(ecd->nest) == INTERNAL_NEST_TAG) {
+ opener = BUILT_IN_SYMBOL;
+ ExtensionIndex::add_to_key(key_list, BUILT_IN_SYMBOL, I"Built in");
}
- if (ecd->overriding_a_built_in_extension) {
- opener = OVERRIDING_SYMBOL; key_override = TRUE;
+ if (Nests::get_tag(ecd->nest) == MATERIALS_NEST_TAG) {
+ opener = PROJECT_SPECIFIC_SYMBOL;
+ ExtensionIndex::add_to_key(key_list, PROJECT_SPECIFIC_SYMBOL, I"Installed in .materials");
}
- if (Nests::get_tag(ecd->found_as->nest) == MATERIALS_NEST_TAG) {
- opener = PROJECT_SPECIFIC_SYMBOL; key_pspec = TRUE;
- }
- if (Nests::get_tag(ecd->found_as->nest) == INTERNAL_NEST_TAG)
+ if (Nests::get_tag(ecd->nest) == INTERNAL_NEST_TAG)
HTML_TAG_WITH("img", "%s", opener)
else {
#ifdef INDEX_MODULE
- pathname *area = ExtensionManager::path_within_nest(ecd->found_as->nest);
+ pathname *area = ExtensionManager::path_within_nest(ecd->nest);
PasteButtons::open_file(OUT, area,
- ecd->found_as->copy->edition->work->raw_author_name, opener);
+ ecd->copy->edition->work->raw_author_name, opener);
#endif
}
@ =
- inform_extension *E = Extensions::from_copy(ecd->found_as->copy);
HTML::begin_span(OUT, I"smaller");
- if ((d == SORT_CE_BY_DATE) || (d == SORT_CE_BY_INSTALL)) {
- WRITE("%S", Extensions::get_usage_date(E));
- } else if (d == SORT_CE_BY_LENGTH) {
- if (Extensions::get_word_count(E) == 0)
- WRITE("--");
+ if (d == SORT_CE_BY_LOCATION) {
+ if (Nests::get_tag(ecd->nest) == INTERNAL_NEST_TAG)
+ WRITE("Built in to Inform");
else
- WRITE("%d words", Extensions::get_word_count(E));
+ WRITE("Installed in this project");
} else {
- if (Str::len(ExtensionCensus::ecd_rubric(ecd)) > 0)
- WRITE("%S", ExtensionCensus::ecd_rubric(ecd));
+ if (Str::len(ExtensionIndex::ecd_rubric(ecd)) > 0)
+ WRITE("%S", ExtensionIndex::ecd_rubric(ecd));
else
WRITE("--");
}
HTML::end_span(OUT);
+@h The key.
+There is just no need to do this efficiently in either running time or memory.
+
+=
+typedef struct extensions_key_item {
+ struct text_stream *image_URL;
+ struct text_stream *gloss;
+ CLASS_DEFINITION
+} extensions_key_item;
+
+void ExtensionIndex::add_to_key(linked_list *L, char *URL, text_stream *gloss) {
+ TEMPORARY_TEXT(as_text)
+ WRITE_TO(as_text, "%s", URL);
+ int found = FALSE;
+ extensions_key_item *eki;
+ LOOP_OVER_LINKED_LIST(eki, extensions_key_item, L)
+ if (Str::eq(eki->image_URL, as_text))
+ found = TRUE;
+ if (found == FALSE) {
+ eki = CREATE(extensions_key_item);
+ eki->image_URL = Str::duplicate(as_text);
+ eki->gloss = Str::duplicate(gloss);
+ ADD_TO_LINKED_LIST(eki, extensions_key_item, L);
+ }
+ DISCARD_TEXT(as_text)
+}
+
@h Icons for virtual machines.
And everything else is cosmetic: printing, or showing icons to signify,
the current VM or some set of permitted VMs. The following plots the
@@ -573,45 +520,125 @@ void ExtensionIndex::plot_icon(OUTPUT_STREAM, target_vm *VM) {
}
}
-void ExtensionIndex::write_key(OUTPUT_STREAM) {
- WRITE("Extensions compatible with specific story file formats only: ");
- int i = 0;
- target_vm *VM;
- LOOP_OVER(VM, target_vm) {
- if (TargetVMs::debug_enabled(VM)) continue; /* avoids listing twice */
- if (i++ > 0) WRITE(", ");
- ExtensionIndex::plot_icon(OUT, VM);
- TargetVMs::write(OUT, VM);
- }
-}
-
@h Displaying VM restrictions.
Given a word range, we describe the result as concisely as we can with a
row of icons (but do not bother for the common case where some extension
has no restriction on its use).
=
-void ExtensionIndex::write_icons(OUTPUT_STREAM, compatibility_specification *C) {
- int something = FALSE, everything = TRUE;
+void ExtensionIndex::write_icons(OUTPUT_STREAM, linked_list *key_list,
+ compatibility_specification *C) {
+ int something_16 = FALSE, everything_16 = TRUE, something_32 = FALSE, everything_32 = TRUE;
target_vm *VM;
LOOP_OVER(VM, target_vm)
- if (Compatibility::test(C, VM))
- something = TRUE;
- else
- everything = FALSE;
- if (something == FALSE) WRITE("none");
- else if (everything == FALSE) {
+ if (Architectures::is_16_bit(VM->architecture)) {
+ if (Compatibility::test(C, VM))
+ something_16 = TRUE;
+ else
+ everything_16 = FALSE;
+ } else {
+ if (Compatibility::test(C, VM))
+ something_32 = TRUE;
+ else
+ everything_32 = FALSE;
+ }
+ if ((everything_16) && (everything_32)) return;
+ if ((everything_16) && (something_32 == FALSE)) {
WRITE(" ");
- dictionary *shown_already = Dictionaries::new(16, TRUE);
- LOOP_OVER(VM, target_vm)
- if (Compatibility::test(C, VM)) {
- text_stream *icon = VM->VM_image;
- if (Str::len(icon) > 0) {
- if (Dictionaries::find(shown_already, icon) == NULL) {
- ExtensionIndex::plot_icon(OUT, VM);
- WRITE_TO(Dictionaries::create_text(shown_already, icon), "X");
- }
+ HTML_TAG_WITH("img", "%s", ARCH_16_SYMBOL);
+ ExtensionIndex::add_to_key(key_list, ARCH_16_SYMBOL, I"Z-machine only (16-bit)");
+ return;
+ }
+ if ((everything_32) && (something_16 == FALSE)) {
+ WRITE(" ");
+ HTML_TAG_WITH("img", "%s", ARCH_32_SYMBOL);
+ ExtensionIndex::add_to_key(key_list, ARCH_32_SYMBOL, I"Glulx only (32-bit)");
+ return;
+ }
+ WRITE(" - %S ", C->parsed_from);
+ dictionary *shown_already = Dictionaries::new(16, TRUE);
+ LOOP_OVER(VM, target_vm)
+ if (Compatibility::test(C, VM)) {
+ text_stream *icon = VM->VM_image;
+ if (Str::len(icon) > 0) {
+ if (Dictionaries::find(shown_already, icon) == NULL) {
+ ExtensionIndex::plot_icon(OUT, VM);
+ WRITE_TO(Dictionaries::create_text(shown_already, icon), "X");
+ ExtensionIndex::add_to_key(key_list, ARCH_16_SYMBOL, I"Z-machine only (16-bit)");
+ ExtensionIndex::add_to_key(key_list, ARCH_32_SYMBOL, I"Glulx only (32-bit)");
}
}
- }
+ }
+}
+
+@
+
+=
+void ExtensionIndex::find_used_extensions(inform_project *proj,
+ linked_list *U, linked_list *R) {
+ build_vertex *V = Copies::construct_project_graph(proj->as_copy);
+ ExtensionIndex::find_used_extensions_r(V, Graphs::get_unique_graph_scan_count(), U, R);
+}
+
+void ExtensionIndex::find_used_extensions_r(build_vertex *V, int scan_count,
+ linked_list *U, linked_list *R) {
+ if (V->type == COPY_VERTEX) {
+ inbuild_copy *C = V->as_copy;
+ if ((C->edition->work->genre == extension_genre) ||
+ (C->edition->work->genre == extension_bundle_genre)) {
+ if (C->last_scanned != scan_count) {
+ ADD_TO_LINKED_LIST(C, inbuild_copy, U);
+ C->last_scanned = scan_count;
+ }
+ }
+ }
+ if (V->type == REQUIREMENT_VERTEX) {
+ if ((V->as_requirement->work->genre == extension_genre) ||
+ (V->as_requirement->work->genre == extension_bundle_genre)) {
+ ADD_TO_LINKED_LIST(V->as_requirement, inbuild_requirement, R);
+ }
+ }
+ build_vertex *W;
+ LOOP_OVER_LINKED_LIST(W, build_vertex, V->build_edges)
+ ExtensionIndex::find_used_extensions_r(W, scan_count, U, R);
+ LOOP_OVER_LINKED_LIST(W, build_vertex, V->use_edges)
+ ExtensionIndex::find_used_extensions_r(W, scan_count, U, R);
+}
+
+@h Sorting criteria.
+The following give some sorting criteria, and are functions fit to be
+handed to |qsort|.
+
+=
+int ExtensionIndex::compare_ecd_by_title(const void *ecd1, const void *ecd2) {
+ inbuild_search_result *e1 = *((inbuild_search_result **) ecd1);
+ inbuild_search_result *e2 = *((inbuild_search_result **) ecd2);
+ inform_extension *E1 = Extensions::from_copy(e1->copy);
+ inform_extension *E2 = Extensions::from_copy(e2->copy);
+ return Extensions::compare_by_title(E2, E1);
+}
+
+int ExtensionIndex::compare_ecd_by_author(const void *ecd1, const void *ecd2) {
+ inbuild_search_result *e1 = *((inbuild_search_result **) ecd1);
+ inbuild_search_result *e2 = *((inbuild_search_result **) ecd2);
+ inform_extension *E1 = Extensions::from_copy(e1->copy);
+ inform_extension *E2 = Extensions::from_copy(e2->copy);
+ return Extensions::compare_by_author(E2, E1);
+}
+
+int ExtensionIndex::compare_ecd_by_location(const void *ecd1, const void *ecd2) {
+ inbuild_search_result *e1 = *((inbuild_search_result **) ecd1);
+ inbuild_search_result *e2 = *((inbuild_search_result **) ecd2);
+ int d = Nests::get_tag(e1->nest) - Nests::get_tag(e2->nest);
+ if (d != 0) return d;
+ return ExtensionIndex::compare_ecd_by_title(ecd1, ecd2);
+}
+
+int ExtensionIndex::ecd_used(inbuild_search_result *ecd) {
+ inform_extension *E = Extensions::from_copy(ecd->copy);
+ return E->has_historically_been_used;
+}
+
+text_stream *ExtensionIndex::ecd_rubric(inbuild_search_result *ecd) {
+ return Extensions::get_rubric(Extensions::from_copy(ecd->copy));
}
diff --git a/inbuild/supervisor-module/Chapter 7/Individual Pages.w b/inbuild/supervisor-module/Chapter 7/Individual Pages.w
index bcf10d8ea..9b283e22b 100644
--- a/inbuild/supervisor-module/Chapter 7/Individual Pages.w
+++ b/inbuild/supervisor-module/Chapter 7/Individual Pages.w
@@ -134,8 +134,7 @@ our E, and return 0 in response to the ECD call to prevent further ECD calls.
@ =
compatibility_specification *C = E->as_copy->edition->compatibility;
if (Str::len(C->parsed_from) > 0) {
- WRITE("%S ", C->parsed_from);
- ExtensionIndex::write_icons(OUT, C);
+ WRITE("%S", C->parsed_from);
}
@ =
diff --git a/inbuild/supervisor-module/Chapter 7/The Mini-Website.w b/inbuild/supervisor-module/Chapter 7/The Mini-Website.w
index 28b084709..c89e7b948 100644
--- a/inbuild/supervisor-module/Chapter 7/The Mini-Website.w
+++ b/inbuild/supervisor-module/Chapter 7/The Mini-Website.w
@@ -48,7 +48,7 @@ void ExtensionWebsite::index_after_compilation(inform_project *proj) {
void ExtensionWebsite::go(inform_project *proj, int force_update) {
ExtensionDictionary::read_from_file();
- extension_census *C = ExtensionCensus::perform(proj);
+ ExtensionCensus::perform(proj);
@;
@;
@;
@@ -70,9 +70,7 @@ documentation as used today until the next run, for obscure timing reasons.
}
@ =
- ExtensionIndex::write(ExtensionWebsite::index_URL(proj, I"Extensions.html"), HOME_EXTPAGE, C);
- if (proj == NULL)
- ExtensionIndex::write(ExtensionWebsite::index_URL(proj, I"ExtIndex.html"), INDEX_EXTPAGE, C);
+ ExtensionIndex::write(proj);
@ Each extension gets its own page in the external documentation area, but
this page can have two forms:
@@ -194,3 +192,55 @@ filename *ExtensionWebsite::page_URL(inform_project *proj, inbuild_edition *edit
DISCARD_TEXT(leaf)
return F;
}
+
+filename *ExtensionWebsite::abs_page_URL(inform_project *proj, inbuild_edition *edition,
+ int eg_number) {
+ TEMPORARY_TEXT(leaf)
+ Editions::write_canonical_leaf(leaf, edition);
+
+ pathname *P;
+ if (proj) {
+ P = Projects::materials_path(proj);
+ if (P == NULL) return NULL;
+ P = Pathnames::down(P, I"Extensions");
+ P = Pathnames::down(P, I"Reserved");
+ P = Pathnames::down(P, I"Documentation");
+ } else {
+ P = ExtensionWebsite::home_URL(NULL);
+ if (P == NULL) return NULL;
+ P = Pathnames::down(P, I"Extensions");
+ }
+ P = Pathnames::down(P, edition->work->author_name);
+
+ if (proj) {
+ P = Pathnames::down(P, leaf);
+ Str::clear(leaf);
+ if (eg_number > 0) WRITE_TO(leaf, "eg%d.html", eg_number);
+ else WRITE_TO(leaf, "index.html");
+ } else {
+ if (eg_number > 0) WRITE_TO(leaf, "-eg%d", eg_number);
+ WRITE_TO(leaf, ".html");
+ }
+
+ filename *F = Filenames::in(P, leaf);
+ DISCARD_TEXT(leaf)
+ return F;
+}
+
+filename *ExtensionWebsite::rel_page_URL(inbuild_edition *edition, int eg_number) {
+ TEMPORARY_TEXT(leaf)
+ Editions::write_canonical_leaf(leaf, edition);
+
+ pathname *P = NULL;
+ P = Pathnames::down(P, I"Extensions");
+ P = Pathnames::down(P, I"Reserved");
+ P = Pathnames::down(P, I"Documentation");
+ P = Pathnames::down(P, edition->work->author_name);
+ P = Pathnames::down(P, leaf);
+ Str::clear(leaf);
+ if (eg_number > 0) WRITE_TO(leaf, "eg%d.html", eg_number);
+ else WRITE_TO(leaf, "index.html");
+ filename *F = Filenames::in(P, leaf);
+ DISCARD_TEXT(leaf)
+ return F;
+}
diff --git a/inform7/Downloads/excerpts-diagnostics.txt b/inform7/Downloads/excerpts-diagnostics.txt
index 70bb0c48d..f32a5041b 100644
--- a/inform7/Downloads/excerpts-diagnostics.txt
+++ b/inform7/Downloads/excerpts-diagnostics.txt
@@ -1,15 +1,15 @@
-Size of lexicon: 3129 excerpt meanings
- Stored among 846 words out of total vocabulary of 10735
- 716 words have a start list: longest belongs to report (with 293 meanings)
+Size of lexicon: 3141 excerpt meanings
+ Stored among 849 words out of total vocabulary of 10759
+ 719 words have a start list: longest belongs to report (with 293 meanings)
15 words have an end list: longest belongs to case (with 6 meanings)
29 words have a middle list: longest belongs to to (with 4 meanings)
108 words have a subset list: longest belongs to street (with 4 meanings)
-Number of attempts to retrieve: 110344
- of which unsuccessful: 92205
- of which successful: 18139
+Number of attempts to retrieve: 110380
+ of which unsuccessful: 92237
+ of which successful: 18143
-Total attempts to match against excerpt meanings: 276472
- of which, total with incorrect hash codes: 253735
- of which, total with correct hash codes: 22737
- of which, total which matched: 19906
+Total attempts to match against excerpt meanings: 279269
+ of which, total with incorrect hash codes: 256529
+ of which, total with correct hash codes: 22740
+ of which, total which matched: 19910
diff --git a/inform7/Downloads/preform-diagnostics.txt b/inform7/Downloads/preform-diagnostics.txt
index 45689c68b..e47025298 100644
--- a/inform7/Downloads/preform-diagnostics.txt
+++ b/inform7/Downloads/preform-diagnostics.txt
@@ -1,8 +1,8 @@
internal nti 6 constraint (none) extremes [1, 1]
- internal hits 1271/8468 nti 7 constraint (none) extremes [0, 0]
+ internal hits 1286/8506 nti 7 constraint (none) extremes [0, 0]
- internal hits 4004/8232 nti 8 constraint (none) extremes [0, 0]
+ internal hits 4025/8274 nti 8 constraint (none) extremes [0, 0]
hits 746/1492 nti 9 constraint (none) extremes [1, infinity)
English:
@@ -16,7 +16,7 @@
internal nti 10 constraint (none) extremes [1, 1]
- internal hits 3000/26140 nti 11 constraint (none) extremes [1, 1]
+ internal hits 3005/26102 nti 11 constraint (none) extremes [1, 1]
internal nti 12 constraint (none) extremes [1, 1]
@@ -24,7 +24,7 @@
internal nti 14 constraint (none) extremes [1, 1]
- internal hits 2/13760 nti 15 constraint (none) extremes [0, 0]
+ internal hits 2/13822 nti 15 constraint (none) extremes [0, 0]
hits 0/18 nti 16 constraint DS = {16} extremes [3, infinity)
English:
@@ -76,17 +76,17 @@
* : {...}
constraint DS = {21} extremes [3, infinity)
- hits 448/2596 nti 23 constraint DS = {22, 23} extremes [6, infinity)
+ hits 468/3140 nti 23 constraint DS = {22, 23} extremes [6, infinity)
English:
{...} ( )
- (hits 425/887) (matched long text) constraint DS = {22, 23} extremes [6, infinity)
+ (hits 433/922) (matched long text) constraint DS = {22, 23} extremes [6, infinity)
{...} -- --
- (hits 23/462) (matched long text) constraint DS = {22, 23} extremes [6, infinity)
+ (hits 35/489) (matched long text) constraint DS = {22, 23} extremes [6, infinity)
- hits 481/1192 nti 22 constraint DS = {22} extremes [3, 3]
+ hits 501/1232 nti 22 constraint DS = {22} extremes [3, 3]
English:
documented at {###}
- (hits 481/485) (matched: 'documented at ph_say') constraint DS = {22} extremes [3, 3]
+ (hits 501/505) (matched: 'documented at ph_say') constraint DS = {22} extremes [3, 3]
nti 24 constraint DS = {24} extremes [2, infinity)
English:
@@ -4750,7 +4750,7 @@
twelfth
constraint CS = {7} extremes [1, 1]
- internal hits 200/25948 nti r0 constraint CS = {r0} extremes [1, 1]
+ internal hits 200/25956 nti r0 constraint CS = {r0} extremes [1, 1]
internal nti r1 constraint CS = {r1} extremes [1, 1]
@@ -4758,12 +4758,12 @@
internal hits 0/264 nti 30 constraint (none) extremes [1, infinity)
- hits 37459/74918 nti 27 constraint (none) extremes [1, infinity)
+ hits 37487/74974 nti 27 constraint (none) extremes [1, infinity)
English:
{...}
- (hits 7998/37459) (matched long text) constraint (none) extremes [2, infinity)
+ (hits 7999/37487) (matched long text) constraint (none) extremes [2, infinity)
{...}
- (hits 29461/29461) (matched long text) constraint (none) extremes [1, infinity)
+ (hits 29488/29488) (matched long text) constraint (none) extremes [1, infinity)
nti 28 constraint (none) extremes [1, infinity)
English:
@@ -4772,23 +4772,23 @@
{...}
constraint (none) extremes [1, infinity)
- hits 86205/172410 nti 29 constraint (none) extremes [1, infinity)
+ hits 86238/172476 nti 29 constraint (none) extremes [1, infinity)
English:
{...}
- (hits 16328/49251) (matched long text) constraint (none) extremes [2, infinity)
+ (hits 16328/49288) (matched long text) constraint (none) extremes [2, infinity)
{...}
- (hits 69877/69877) (matched long text) constraint (none) extremes [1, infinity)
+ (hits 69910/69910) (matched long text) constraint (none) extremes [1, infinity)
nti 30 constraint (none) extremes [2, infinity)
English:
{...}
constraint (none) extremes [2, infinity)
- internal hits 16857/102752 nti r2 constraint (none) extremes [1, 1]
+ internal hits 16859/102844 nti r2 constraint (none) extremes [1, 1]
- internal hits 20758/244740 nti r2 constraint (none) extremes [1, 1]
+ internal hits 20769/244906 nti r2 constraint (none) extremes [1, 1]
- internal hits 2341/44114 nti r2 constraint (none) extremes [1, 1]
+ internal hits 2345/44134 nti r2 constraint (none) extremes [1, 1]
nti r2 constraint CS = {r2} extremes [6, 6]
English:
@@ -4849,10 +4849,10 @@
other than
constraint CS = {8} extremes [2, 2]
- hits 16/22548 nti 9 constraint DS = {9} extremes [2, infinity)
+ hits 16/22556 nti 9 constraint DS = {9} extremes [2, infinity)
English:
not {...}
- (hits 16/6568) (matched long text) constraint DS = {9} extremes [2, infinity)
+ (hits 16/6572) (matched long text) constraint DS = {9} extremes [2, infinity)
hits 111/222 nti 10 constraint (none) extremes [1, infinity)
English:
@@ -4863,10 +4863,10 @@
{...}
(hits 111/111) (matched: 'dvd carried by the person asked') constraint (none) extremes [1, infinity)
- hits 0/22262 nti 11 constraint DS = {11} extremes [2, infinity)
+ hits 0/22270 nti 11 constraint DS = {11} extremes [2, infinity)
English:
no one {***}
- (hits 0/3797) constraint DS = {11} extremes [2, infinity)
+ (hits 0/3799) constraint DS = {11} extremes [2, infinity)
internal hits 123/1378 nti 6 constraint (none) extremes [1, 1]
@@ -4937,7 +4937,7 @@
internal hits 16/128 nti 7 constraint FS = {7} extremes [1, infinity)
- internal hits 1/9132 nti 8 constraint FS = {8} extremes [1, infinity)
+ internal hits 1/9184 nti 8 constraint FS = {8} extremes [1, infinity)
internal hits 0/2400 nti 9 constraint FS = {9} extremes [1, infinity)
@@ -4957,22 +4957,22 @@
internal nti 12 constraint DS = {12} extremes [1, infinity)
- internal hits 662/19746 nti 13 constraint DS = {13} extremes [1, infinity)
+ internal hits 662/19764 nti 13 constraint DS = {13} extremes [1, infinity)
- internal hits 258/8476 nti 14 constraint DS = {14} extremes [1, infinity)
+ internal hits 258/8478 nti 14 constraint DS = {14} extremes [1, infinity)
- hits 67/2522 nti 19 constraint CS = {19} extremes [1, 1]
+ hits 67/2518 nti 19 constraint CS = {19} extremes [1, 1]
English:
always/certainly
- (hits 10/374) (matched: 'always') constraint CS = {19} extremes [1, 1]
+ (hits 10/375) (matched: 'always') constraint CS = {19} extremes [1, 1]
usually/normally
- (hits 53/364) (matched: 'usually') constraint CS = {19} extremes [1, 1]
+ (hits 53/365) (matched: 'usually') constraint CS = {19} extremes [1, 1]
rarely/seldom
- (hits 0/311) constraint CS = {19} extremes [1, 1]
+ (hits 0/312) constraint CS = {19} extremes [1, 1]
never
- (hits 4/311) (matched: 'never') constraint CS = {19} extremes [1, 1]
+ (hits 4/312) (matched: 'never') constraint CS = {19} extremes [1, 1]
initially
- (hits 0/307) constraint CS = {19} extremes [1, 1]
+ (hits 0/308) constraint CS = {19} extremes [1, 1]
hits 0/4402 nti 20 constraint DS = {20} extremes [1, infinity)
English:
@@ -5041,10 +5041,10 @@
constraint CS = {r0} extremes [1, 1]
- hits 3290/6580 nti 21 constraint (none) extremes [1, infinity)
+ hits 3302/6604 nti 21 constraint (none) extremes [1, infinity)
English:
{...}
- (hits 3290/3290) (matched long text) constraint (none) extremes [1, infinity)
+ (hits 3302/3302) (matched long text) constraint (none) extremes [1, infinity)
hits 60/120 nti 22 constraint (none) extremes [0, infinity)
English:
@@ -5053,21 +5053,21 @@
(hits 60/60) (matched: 'fixed in place') constraint (none) extremes [1, infinity)
- hits 33/157704 nti 25 constraint CS = {25} extremes [1, 1]
+ hits 33/155704 nti 25 constraint CS = {25} extremes [1, 1]
English:
there
(hits 33/84) (matched: 'there') constraint CS = {25} extremes [1, 1]
- hits 2210/4420 nti 23 constraint (none) extremes [1, infinity)
+ hits 2224/4448 nti 23 constraint (none) extremes [1, infinity)
English:
{...}
- (hits 99/2210) (matched: '"(considering the first sixteen objects only)[command clarification break]" ( a )') constraint (none) extremes [1, infinity)
+ (hits 99/2224) (matched: '"(considering the first sixteen objects only)[command clarification break]" ( a )') constraint (none) extremes [1, infinity)
- (hits 323/1485) (matched: 'an action based rule producing nothing that varies') constraint (none) extremes [2, infinity)
+ (hits 324/1494) (matched: 'an action based rule producing nothing that varies') constraint (none) extremes [2, infinity)
- (hits 725/1162) (matched long text) constraint (none) extremes [2, infinity)
+ (hits 731/1170) (matched long text) constraint (none) extremes [2, infinity)
- (hits 1063/1063) (matched long text) constraint (none) extremes [1, infinity)
+ (hits 1070/1070) (matched long text) constraint (none) extremes [1, infinity)
hits 255/510 nti 24 constraint (none) extremes [0, infinity)
English:
@@ -5108,44 +5108,44 @@
_{,/or}
(hits 60/69) (matched: 'or unmarked for listing') constraint DS = {27} extremes [2, infinity)
- hits 461/922 nti 27 constraint (none) extremes [1, infinity)
+ hits 463/926 nti 27 constraint (none) extremes [1, infinity)
English:
constraint CS = {25} extremes [1, 1]
- (hits 0/461) constraint (none) extremes [1, infinity)
+ (hits 0/463) constraint (none) extremes [1, infinity)
- (hits 461/461) (matched long text) constraint (none) extremes [1, infinity)
+ (hits 463/463) (matched long text) constraint (none) extremes [1, infinity)
- hits 577/1154 nti 28 constraint (none) extremes [1, infinity)
+ hits 579/1158 nti 28 constraint (none) extremes [1, infinity)
English:
- (hits 0/577) constraint (none) extremes [1, infinity)
+ (hits 0/579) constraint (none) extremes [1, infinity)
- (hits 577/577) (matched long text) constraint (none) extremes [1, infinity)
+ (hits 579/579) (matched long text) constraint (none) extremes [1, infinity)
- hits 0/922 nti 29 constraint (none) extremes [1, infinity)
+ hits 0/926 nti 29 constraint (none) extremes [1, infinity)
English:
constraint CS = {28} extremes [1, 2]
{***}
- (hits 0/454) constraint (none) extremes [1, infinity)
+ (hits 0/455) constraint (none) extremes [1, infinity)
- (hits 0/368) constraint DS = {14} extremes [2, infinity)
+ (hits 0/369) constraint DS = {14} extremes [2, infinity)
- hits 0/1964 nti 30 constraint (none) extremes [1, infinity)
+ hits 0/1968 nti 30 constraint (none) extremes [1, infinity)
English:
constraint CS = {28} extremes [1, 2]
- (hits 0/982) constraint (none) extremes [1, infinity)
+ (hits 0/984) constraint (none) extremes [1, infinity)
- hits 101/1170 nti 10 constraint CS = {10} extremes [1, 1]
+ hits 101/1172 nti 10 constraint CS = {10} extremes [1, 1]
English:
thing/something
(hits 101/105) (matched: 'thing') constraint CS = {10} extremes [1, 1]
- internal hits 484/24772 nti 6 constraint (none) extremes [1, 1]
+ internal hits 485/24790 nti 6 constraint (none) extremes [1, 1]
nti 28 constraint CS = {28} extremes [1, 2]
English:
@@ -5156,33 +5156,33 @@
initially carried
constraint CS = {28} extremes [2, 2]
- hits 0/2700 nti 9 constraint DS = {14} extremes [2, infinity)
+ hits 0/2706 nti 9 constraint DS = {14} extremes [2, infinity)
English:
_,/and {...}
- (hits 0/533) constraint DS = {9, 14} extremes [3, infinity)
+ (hits 0/534) constraint DS = {9, 14} extremes [3, infinity)
_,/and
- (hits 0/583) constraint DS = {9, 14} extremes [2, infinity)
+ (hits 0/584) constraint DS = {9, 14} extremes [2, infinity)
- (hits 0/876) constraint DS = {14} extremes [2, infinity)
+ (hits 0/877) constraint DS = {14} extremes [2, infinity)
- hits 1469/2938 nti 8 constraint (none) extremes [1, infinity)
+ hits 1473/2946 nti 8 constraint (none) extremes [1, infinity)
English:
{...}
- (hits 174/1469) (matched long text) constraint (none) extremes [1, infinity)
+ (hits 174/1473) (matched long text) constraint (none) extremes [1, infinity)
{called}
- (hits 57/637) (matched long text) constraint DS = {8} extremes [1, infinity)
+ (hits 57/642) (matched long text) constraint DS = {8} extremes [1, infinity)
- (hits 0/221) constraint DS = {30} extremes [2, infinity)
+ (hits 0/224) constraint DS = {30} extremes [2, infinity)
- (hits 87/538) (matched long text) constraint DS = {6} extremes [1, infinity)
+ (hits 87/541) (matched long text) constraint DS = {6} extremes [1, infinity)
- (hits 30/336) (matched: 'a kind of supporter that is portable') constraint DS = {7} extremes [1, infinity)
+ (hits 30/340) (matched: 'a kind of supporter that is portable') constraint DS = {7} extremes [1, infinity)
(hits 4/349) (matched: 'it') constraint (none) extremes [1, 1]
(hits 0/345) constraint (none) extremes [1, 1]
- (hits 1117/1117) (matched long text) constraint (none) extremes [1, infinity)
+ (hits 1121/1121) (matched long text) constraint (none) extremes [1, infinity)
hits 431/862 nti 7 constraint (none) extremes [0, infinity)
English:
@@ -5193,16 +5193,16 @@
(hits 431/431) (matched long text) constraint (none) extremes [1, infinity)
- hits 0/8614 nti 30 constraint DS = {30} extremes [2, infinity)
+ hits 0/8642 nti 30 constraint DS = {30} extremes [2, infinity)
English:
it with action {***}
- (hits 0/3689) constraint DS = {30} extremes [3, infinity)
+ (hits 0/3697) constraint DS = {30} extremes [3, infinity)
{with/having} (/) {***}
- (hits 0/3806) constraint DS = {30} extremes [2, infinity)
+ (hits 0/3816) constraint DS = {30} extremes [2, infinity)
{with/having} {...} ( )
- (hits 0/3439) constraint DS = {30} extremes [5, infinity)
+ (hits 0/3443) constraint DS = {30} extremes [5, infinity)
{with/having}
- (hits 0/3806) constraint DS = {30} extremes [2, infinity)
+ (hits 0/3816) constraint DS = {30} extremes [2, infinity)
nti 8 constraint (none) extremes [1, infinity)
English:
@@ -5225,60 +5225,60 @@
{...}
constraint (none) extremes [1, infinity)
- hits 174/3644 nti 6 constraint DS = {6} extremes [1, infinity)
+ hits 174/3682 nti 6 constraint DS = {6} extremes [1, infinity)
English:
, _{and}
- (hits 8/1022) (matched: ', and didn't understand addressee's last name error') constraint DS = {6} extremes [2, infinity)
+ (hits 8/1036) (matched: ', and didn't understand addressee's last name error') constraint DS = {6} extremes [2, infinity)
_{,/and}
- (hits 166/1112) (matched long text) constraint DS = {6} extremes [1, infinity)
+ (hits 166/1127) (matched long text) constraint DS = {6} extremes [1, infinity)
- hits 30/672 nti 10 constraint DS = {7} extremes [1, infinity)
+ hits 30/680 nti 10 constraint DS = {7} extremes [1, infinity)
English:
- (hits 30/328) (matched: 'a kind of supporter that is portable') constraint DS = {7} extremes [2, infinity)
+ (hits 30/332) (matched: 'a kind of supporter that is portable') constraint DS = {7} extremes [2, infinity)
- (hits 0/306) constraint DS = {7} extremes [1, infinity)
+ (hits 0/310) constraint DS = {7} extremes [1, infinity)
- hits 30/804 nti 7 constraint DS = {7} extremes [1, infinity)
+ hits 30/816 nti 7 constraint DS = {7} extremes [1, infinity)
English:
kind/kinds
(hits 4/12) (matched: 'kind') constraint CS = {7} extremes [1, 1]
kind/kinds of
- (hits 26/340) (matched: 'kind of supporter that is portable') constraint DS = {7} extremes [2, infinity)
+ (hits 26/346) (matched: 'kind of supporter that is portable') constraint DS = {7} extremes [2, infinity)
internal nti 11 constraint (none) extremes [1, infinity)
- internal hits 1427/2854 nti 12 constraint (none) extremes [1, infinity)
+ internal hits 1433/2866 nti 12 constraint (none) extremes [1, infinity)
- hits 0/2916 nti 13 constraint DS = {19} extremes [2, infinity)
+ hits 0/2926 nti 13 constraint DS = {19} extremes [2, infinity)
English:
{...}
- (hits 0/503) constraint DS = {19} extremes [2, infinity)
+ (hits 0/501) constraint DS = {19} extremes [2, infinity)
- hits 67/2916 nti 14 constraint DS = {19} extremes [2, infinity)
+ hits 67/2926 nti 14 constraint DS = {19} extremes [2, infinity)
English:
{...}
(hits 67/758) (matched: 'usually table of general chitchat') constraint DS = {19} extremes [2, infinity)
- hits 796/25740 nti 11 constraint CS = {11} extremes [1, 1]
+ hits 796/25782 nti 11 constraint CS = {11} extremes [1, 1]
English:
which/who/that
- (hits 796/5858) (matched: 'which') constraint CS = {11} extremes [1, 1]
+ (hits 796/5867) (matched: 'which') constraint CS = {11} extremes [1, 1]
- hits 3/2886 nti 15 constraint DS = {11} extremes [2, infinity)
+ hits 3/2898 nti 15 constraint DS = {11} extremes [2, infinity)
English:
{...}
- (hits 3/707) (matched: 'the asking which') constraint DS = {11} extremes [2, infinity)
+ (hits 3/713) (matched: 'the asking which') constraint DS = {11} extremes [2, infinity)
nti 12 constraint DS = {12} extremes [3, infinity)
English:
{...} called {...}
constraint DS = {12} extremes [3, infinity)
- hits 194/9104 nti 13 constraint DS = {13} extremes [2, infinity)
+ hits 194/9162 nti 13 constraint DS = {13} extremes [2, infinity)
English:
of {...}
- (hits 194/2279) (matched long text) constraint DS = {13} extremes [2, infinity)
+ (hits 194/2295) (matched long text) constraint DS = {13} extremes [2, infinity)
hits 5/60 nti 14 constraint CS = {14} extremes [2, 2]
English:
@@ -5293,9 +5293,9 @@
grammatical case
(hits 1/1) (matched: 'grammatical case') constraint CS = {14} extremes [2, 2]
- internal hits 2504/44400 nti 16 constraint (none) extremes [0, 0]
+ internal hits 2522/44448 nti 16 constraint (none) extremes [0, 0]
- internal hits 169/338 nti 17 constraint (none) extremes [1, infinity)
+ internal hits 175/350 nti 17 constraint (none) extremes [1, infinity)
hits 24/68 nti 16 constraint DS = {16} extremes [3, infinity)
English:
@@ -5319,20 +5319,20 @@
(hits 5/5) (matched: 'value of kind k') constraint (none) extremes [1, infinity)
- hits 5883/107450 nti r5 constraint (none) extremes [1, infinity)
+ hits 5893/107530 nti r5 constraint (none) extremes [1, infinity)
English:
( )
- (hits 0/2332) constraint DS = {r5} & CW = {r2, r5} extremes [3, infinity)
+ (hits 0/2337) constraint DS = {r5} & CW = {r2, r5} extremes [3, infinity)
^
- (hits 1594/11897) (matched: 'k') constraint CW = {r2, r5} extremes [1, infinity)
+ (hits 1594/11909) (matched: 'k') constraint CW = {r2, r5} extremes [1, infinity)
- (hits 202/10303) (matched: 'sayable value of kind k') constraint CW = {r2, r5} extremes [1, infinity)
+ (hits 202/10315) (matched: 'sayable value of kind k') constraint CW = {r2, r5} extremes [1, infinity)
- (hits 3726/10101) (matched: 'an ice cream cone') constraint CW = {r2, r5} extremes [1, infinity)
+ (hits 3735/10113) (matched: 'an ice cream cone') constraint CW = {r2, r5} extremes [1, infinity)
- (hits 2/16834) (matched: 'object-based rulebook') constraint DS = {r5} extremes [2, infinity)
+ (hits 2/16859) (matched: 'object-based rulebook') constraint DS = {r5} extremes [2, infinity)
- (hits 359/6373) (matched long text) constraint CW = {r2, r5} extremes [1, infinity)
+ (hits 360/6376) (matched long text) constraint CW = {r2, r5} extremes [1, infinity)
hits 40/338 nti 18 constraint (none) extremes [1, infinity)
English:
@@ -5341,16 +5341,16 @@