1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-06-29 05:24:57 +03:00

Second thoughts on localisation syntax

This commit is contained in:
Graham Nelson 2021-07-21 23:21:56 +01:00
parent 3afc083fb3
commit 73700426b3
9 changed files with 252 additions and 270 deletions

View file

@ -1,187 +1,135 @@
%%Contents
%Index.Pages.Contents.Title = Contents Index
%Index.Pages.Contents.Caption = How the source text is organised
%Title = Contents Index
%Caption = How the source text is organised
%Index.Elements.C.Title = Contents
%Index.Elements.C.Heading = Like the contents page of a book.|About headings<HEADINGS>; About extensions<EXTENSIONS>
%%C
%Index.Elements.Cd.Title = Card
%Index.Elements.Cd.Heading = How this project might be filed in a library catalogue.|About the Library Card<LCARDS>; About IFIDs<IFIDS>
%Title = Contents
%Heading = Like the contents page of a book.|About headings<HEADINGS>; About extensions<EXTENSIONS>
%Index.Elements.Tb.Title = Tables
%Index.Elements.Tb.Heading = Tables of information in the source text.|About tables<TABLES>
%%Cd
%Index.Elements.Fi.Title = Figures
%Index.Elements.Fi.Heading = The figures, sound effects or external files used.|About figures<FIGURES>; About sounds<SOUNDS>; About files<EFILES>
%Title = Card
%Heading = How this project might be filed in a library catalogue.|About the Library Card<LCARDS>; About IFIDs<IFIDS>
%Index.Elements.In.Title = Innards
%Index.Elements.In.Heading = Technicalities about the story file being produced.|About the story file<STORYFILES>; About use options<OPTIONS>
%%Tb
%Index.Pages.Actions.Title = Actions Index
%Index.Pages.Actions.Caption = Things that people can try to do
%Title = Tables
%Heading = Tables of information in the source text.|About tables<TABLES>
%Index.Elements.A1.Title = Grouped
%Index.Elements.A1.Heading = With similar actions grouped together|About actions<ACTIONS>; New actions<NEWACTIONS>; Out of world actions (in red)<OUTOFWORLD>
%%Fi
%Index.Elements.A2.Title = Alphabetic
%Index.Elements.A2.Heading = Listed in alphabetical order|About actions<ACTIONS>; New actions<NEWACTIONS>; Out of world actions (in red)<OUTOFWORLD>
%Title = Figures
%Heading = The figures, sound effects or external files used.|About figures<FIGURES>; About sounds<SOUNDS>; About files<EFILES>
%Index.Elements.A2.Light = requires light
%Index.Elements.A2.Touchable = touchable
%Index.Elements.A2.Carried = carried
%%In
%Index.Elements.Bh.Title = Behaviour
%Index.Elements.Bh.Heading = Kinds of action, grouped under common names|About kinds of action<KACTIONS>
%Title = Innards
%Heading = Technicalities about the story file being produced.|About the story file<STORYFILES>; About use options<OPTIONS>
%Index.Elements.Bh.None = No names for kinds of action have yet been defined.
%Index.Elements.Bh.Defined = defined as any of the following acts
%%Actions
%Index.Elements.Cm.Title = Commands
%Index.Elements.Cm.Heading = Commands which the player can type|About commands<UNDERSTANDING>
%Title = Actions Index
%Caption = Things that people can try to do
%Index.Elements.To.Title = Tokens
%Index.Elements.To.Heading = Those square-bracketed pieces inside Understand grammar|About tokens<TOKENS>; New tokens<NEWTOKENS>
%%A1
%Index.Pages.Kinds.Title = Kinds Index
%Index.Pages.Kinds.Caption = All the different sorts of value
%Title = Grouped
%Heading = With similar actions grouped together|About actions<ACTIONS>; New actions<NEWACTIONS>; Out of world actions (in red)<OUTOFWORLD>
%Index.Elements.Ch.Title = Chart
%Index.Elements.Ch.Heading = A chart of all the kinds|About kinds<KINDS>; New kinds of object<NEWKINDS>; Other new kinds<KINDSVALUE>
%%A2
%Index.Elements.Ar.Title = Arithmetic
%Index.Elements.Ar.Heading = Which values can be added up, multiplied and so on|About arithmetic<ARITHMETIC>
%Title = Alphabetic
%Heading = Listed in alphabetical order|About actions<ACTIONS>; New actions<NEWACTIONS>; Out of world actions (in red)<OUTOFWORLD>
%Index.Elements.Ar.Calculator =
Kinds of value marked with the calculator symbol are numerical -
these are values we can add, multiply and so on. The range of these
numbers depends on the Format setting for the project (Glulx format
supports much higher numbers than Z-code).
%Index.Elements.Ar.Dimensionless = dimensionless
%Light = requires light
%Touchable = touchable
%Carried = carried
%Index.Elements.Vl.Title = Values
%Index.Elements.Vl.Heading = Values which vary during play, and equations.|About variables<VARIABLES>
%%Bh
%Index.Pages.Phrasebook.Title = Phrasebook Index
%Index.Pages.Phrasebook.Caption = A short dictionary
%Title = Behaviour
%Heading = Kinds of action, grouped under common names|About kinds of action<KACTIONS>
%Index.Elements.Ph.Title = Phrases
%Index.Elements.Ph.Heading = A guide to the phrases allowed|About phrases<PHRASES>
%%Cm
%Index.Elements.Lx.Title = Lexicon
%Index.Elements.Lx.Heading = Words used in descriptions|About descriptions<DESCRIPTIONS>
%Title = Commands
%Heading = Commands which the player can type|About commands<UNDERSTANDING>
%Index.Elements.Lx.ToBe = *1, to be
%Index.Elements.Lx.KindOf = a kind of *1
%Index.Elements.Lx/ValueOf = value of *1
%%To
%Index.Elements.Rl.Title = Relations
%Index.Elements.Rl.Heading = Relations give meaning to verbs|About relations<RELATIONS>
%Title = Tokens
%Heading = Those square-bracketed pieces inside Understand grammar|About tokens<TOKENS>; New tokens<NEWTOKENS>
%Index.Elements.Vb.Title = Verbs
%Index.Elements.Vb.Heading = A table of verbs|About verbs<VERBS>
%%Kinds
%Index.Pages.Rules.Title = Rules Index
%Index.Pages.Rules.Caption = And the rulebooks they belong to
%Title = Kinds Index
%Caption = All the different sorts of value
%Index.Elements.St.Title = Standards
%Index.Elements.St.Heading = From the Standard Rules|About rulebooks<RULEBOOKS>; About activities<ACTIVITIES>; Moving or abolishing rules<RLISTING>
%%Ch
%Title = Chart
%Heading = A chart of all the kinds|About kinds<KINDS>; New kinds of object<NEWKINDS>; Other new kinds<KINDSVALUE>
%%Ar
%Title = Arithmetic
%Heading = Which values can be added up, multiplied and so on|About arithmetic<ARITHMETIC>
%%Vl
%Title = Values
%Heading = Values which vary during play, and equations.|About variables<VARIABLES>
%%Phrasebook
%Title = Phrasebook Index
%Caption = A short dictionary
%%Ph
%Title = Phrases
%Heading = A guide to the phrases allowed|About phrases<PHRASES>
%%Lx
%Title = Lexicon
%Heading = Words used in descriptions|About descriptions<DESCRIPTIONS>
%ToBe = *1, to be
%KindOf = a kind of *1
%ValueOf = value of *1
%%Rl
%Title = Relations
%Heading = Relations give meaning to verbs|About relations<RELATIONS>
%%Vb
%Title = Verbs
%Heading = A table of verbs|About verbs<VERBS>
%%Rules
%Title = Rules Index
%Caption = And the rulebooks they belong to
%%St
%Title = Standards
%Heading = From the Standard Rules|About rulebooks<RULEBOOKS>; About activities<ACTIVITIES>; Moving or abolishing rules<RLISTING>
%Check =
%Index.Elements.St.Check =
Check rules are tied to specific actions, and there are too many to index here.
For instance, the check taking rules can only ever affect the taking action, so
they are indexed on the detailed index page for taking.
%CarryOut =
%Index.Elements.St..CarryOut =
Carry out rules are tied to specific actions, and there are too many to index here.
%Report =
%Index.Elements.St..Report =
Report rules are tied to specific actions, and there are too many to index here.
%%Xt
%Index.Elements.Xt.Title = Extras
%Index.Elements.Xt.Heading = Further rulebooks, from the source or extensions|About rulebooks<RULEBOOKS>; About activities<ACTIVITIES>; Moving or abolishing rules<RLISTING>
%Title = Extras
%Heading = Further rulebooks, from the source or extensions|About rulebooks<RULEBOOKS>; About activities<ACTIVITIES>; Moving or abolishing rules<RLISTING>
%Index.Pages.Scenes.Title = Scenes Index
%Index.Pages.Scenes.Caption = Like scenes in a movie
%%Scenes
%Index.Elements.Pl.Title = Plot
%Index.Elements.Pl.Heading = A map of how the scenes begin and end|About scenes<SCENESINTRO>; How they link together<LINKINGSCENES>
%Title = Scenes Index
%Caption = Like scenes in a movie
%Index.Elements.Ev.Title = Events
%Index.Elements.Ev.Heading = Timed events, if any|About timed events<TIMEDEVENTS>
%%Pl
%Index.Elements.RS.Title = Rules
%Index.Elements.RS.Heading = General rules about scenes
%Title = Plot
%Heading = A map of how the scenes begin and end|About scenes<SCENESINTRO>; How they link together<LINKINGSCENES>
%Index.Elements.RS.Empty = There are no rules in this rulebook.
%Index.Elements.RS.Nameless = nameless
%Index.Elements.RS.Unlist = The *1 is not listed in the *2.
%Index.Elements.RS.During = during *1
%Index.Elements.RS.Response = The *1 response (*2) is "New text.".
%Index.Elements.RS.Outcome = outcome
%Index.Elements.RS.Success = a success
%Index.Elements.RS.Failure = a failure
%Index.Elements.RS.NoOutcome = no outcome
%Index.Elements.RS.DefaultSuccess = default outcome is success
%Index.Elements.RS.DefaultFailure = default outcome is failure
%Index.Elements.RS.Activity = activity
%Index.Elements.RS.BeforeActivity = Before *1
%Index.Elements.RS.ForActivity = Rule for *1
%Index.Elements.RS.AfterActivity = After *1
%%Ev
%Index.Pages.World.Title = World Index
%Index.Pages.World.Caption = Like locations, props and actors in a movie
%Title = Events
%Heading = Timed events, if any|About timed events<TIMEDEVENTS>
%Index.Elements.Mp,Title = Map
%Index.Elements.Mp.Heading = A map of the world
%%RS
%Title = Rules
%Heading = General rules about scenes
%Empty = There are no rules in this rulebook.
%Nameless = nameless
%Unlist = The *1 is not listed in the *2.
%During = during *1
%Response = The *1 response (*2) is "New text.".
%Outcome = outcome
%Success = a success
%Failure = a failure
%NoOutcome = no outcome
%DefaultSuccess = default outcome is success
%DefaultFailure = default outcome is failure
%Activity = activity
%BeforeActivity = Before *1
%ForActivity = Rule for *1
%AfterActivity = After *1
%%World
%Title = World Index
%Caption = Like locations, props and actors in a movie
%%Mp
%Title = Map
%Heading = A map of the world
%%Gz
%Title = Gazetteer
%Heading = An A-Z of places, things, people and so on
%Index.Elements.Gz.Title = Gazetteer
%Index.Elements.Index.Elements.Tb.Heading = An A-Z of places, things, people and so on

View file

@ -93,8 +93,13 @@ will be |Kinds.html| either way.
@<Register a new index page@> =
text_stream *col = mr.exp[1];
text_stream *key = mr.exp[0];
text_stream *heading = Localisation::read(D, key, I"Title");
text_stream *explanation = Localisation::read(D, key, I"Caption");
TEMPORARY_TEXT(path)
WRITE_TO(path, "Index.Pages.%S.Title", key);
text_stream *heading = Localisation::read(D, path);
Str::clear(path);
WRITE_TO(path, "Index.Pages.%S.Caption", key);
text_stream *explanation = Localisation::read(D, path);
DISCARD_TEXT(path)
index_page *new_page = InterpretIndex::register_page(col, heading, explanation, key);
ADD_TO_LINKED_LIST(new_page, index_page, igs->pages);
@ -102,20 +107,29 @@ will be |Kinds.html| either way.
if (LinkedLists::len(igs->pages) == 0) internal_error("element without page");
index_page *latest = LAST_IN_LINKED_LIST(index_page, igs->pages);
text_stream *elt = mr.exp[0];
TEMPORARY_TEXT(tkey)
TEMPORARY_TEXT(hkey)
WRITE_TO(tkey, "Index.Elements.%S.Title", elt);
WRITE_TO(hkey, "Index.Elements.%S.Heading", elt);
InterpretIndex::register_element(elt, latest,
Localisation::read(D, elt, I"Title"),
Localisation::read(D, elt, I"Heading"));
Localisation::read(D, tkey),
Localisation::read(D, hkey));
DISCARD_TEXT(tkey)
DISCARD_TEXT(hkey)
@<Actually generate the index files@> =
index_page *page;
LOOP_OVER_LINKED_LIST(page, index_page, igs.pages) {
TEMPORARY_TEXT(leafname)
WRITE_TO(leafname, "%S.html", page->page_leafname);
TEMPORARY_TEXT(key)
WRITE_TO(key, "Index.Pages.%S.Title", page->page_leafname);
text_stream *OUT =
InterpretIndex::open_file(page, leafname,
Localisation::read(D, page->page_leafname, I"Title"), -1, D);
Localisation::read(D, key), -1, D);
Elements::periodic_table(OUT, page, leafname, D);
InterpretIndex::close_index_file(OUT);
DISCARD_TEXT(key)
DISCARD_TEXT(leafname)
}
GroupedElement::detail_pages(D);

View file

@ -189,7 +189,7 @@ void IndexRules::rulebook_box(OUTPUT_STREAM, tree_inventory *inv,
TEMPORARY_TEXT(textual_name)
if (Str::len(titling_text) > 0) WRITE_TO(textual_name, "%S", titling_text);
else WRITE_TO(textual_name, "%S", Localisation::read(LD, I"RS", I"Nameless"));
else Localisation::write_0(textual_name, LD, I"Index.Elements.RS.Nameless");
string_position start = Str::start(textual_name);
Str::put(start, Characters::tolower(Str::get(start)));
@ -235,7 +235,7 @@ void IndexRules::rulebook_box(OUTPUT_STREAM, tree_inventory *inv,
if (n == 0) {
HTML::open_indented_p(OUT, 2, "tight");
WRITE("%S", Localisation::read(LD, I"RS", I"Empty"));
Localisation::write_0(OUT, LD, I"Index.Elements.RS.Empty");
HTML_CLOSE("p");
} else if (disclaimer_instead) {
HTML::open_indented_p(OUT, 2, "tight"); WRITE("%S", disclaimer_instead); HTML_CLOSE("p");
@ -363,7 +363,7 @@ int IndexRules::index_rule(OUTPUT_STREAM, inter_tree *I, inter_package *R,
WRITE("<i>%S", italicised_text);
if (rc.scene_context) {
WRITE(" ");
Localisation::write_1(OUT, LD, I"RS", I"During",
Localisation::write_1(OUT, LD, I"Index.Elements.RS.During",
PlotElement::scene_name(rc.scene_context));
}
WRITE("</i>&nbsp;&nbsp;");
@ -384,7 +384,7 @@ int IndexRules::index_rule(OUTPUT_STREAM, inter_tree *I, inter_package *R,
WRITE("&nbsp;<i>name</i> ");
Str::clear(S);
Localisation::write_2(S, LD, I"RS", I"Unlist", name,
Localisation::write_2(S, LD, I"Index.Elements.RS.Response", name,
Metadata::read_optional_textual(owner, I"^printed_name"));
PasteButtons::paste_text(OUT, S);
WRITE("&nbsp;<i>unlist</i>");
@ -491,7 +491,7 @@ void IndexRules::index_response(OUTPUT_STREAM, inter_package *rule_pack,
Str::clear(S);
TEMPORARY_TEXT(letter)
WRITE_TO(letter, "%c", 'A' + marker);
Localisation::write_2(S, LD, I"RS", I"Response",
Localisation::write_2(S, LD, I"Index.Elements.RS.Response",
Metadata::read_textual(rule_pack, I"^name"), letter);
PasteButtons::paste_text(OUT, S);
WRITE("&nbsp;<i>set</i>");
@ -510,7 +510,7 @@ void IndexRules::index_outcomes(OUTPUT_STREAM, inter_tree *I, inter_package *rb_
if (Inter::Packages::type(entry) == wanted) {
HTML::open_indented_p(OUT, 2, "hanging");
WRITE("<i>");
Localisation::write_0(OUT, LD, I"RS", I"Outcome");
Localisation::write_0(OUT, LD, I"Index.Elements.RS.Outcome");
WRITE("</i>&nbsp;&nbsp;");
int is_def = (int) Metadata::read_optional_numeric(entry, I"^is_default");
if (is_def) WRITE("<b>");
@ -518,11 +518,11 @@ void IndexRules::index_outcomes(OUTPUT_STREAM, inter_tree *I, inter_package *rb_
if (is_def) WRITE("</b> (default)");
WRITE(" - <i>");
if (Metadata::read_optional_numeric(entry, I"^succeeds"))
Localisation::write_0(OUT, LD, I"RS", I"Success");
Localisation::write_0(OUT, LD, I"Index.Elements.RS.Success");
else if (Metadata::read_optional_numeric(entry, I"^fails"))
Localisation::write_0(OUT, LD, I"RS", I"Failure");
Localisation::write_0(OUT, LD, I"Index.Elements.RS.Failure");
else
Localisation::write_0(OUT, LD, I"RS", I"NoOutcome");
Localisation::write_0(OUT, LD, I"Index.Elements.RS.NoOutcome");
WRITE("</i>");
HTML_CLOSE("p");
}
@ -532,14 +532,14 @@ void IndexRules::index_outcomes(OUTPUT_STREAM, inter_tree *I, inter_package *rb_
if (Metadata::read_optional_numeric(rb_pack, I"^default_succeeds")) {
HTML::open_indented_p(OUT, 2, "hanging");
WRITE("<i>");
Localisation::write_0(OUT, LD, I"RS", I"DefaultSuccess");
Localisation::write_0(OUT, LD, I"Index.Elements.RS.DefaultSuccess");
WRITE("</i>");
HTML_CLOSE("p");
}
if (Metadata::read_optional_numeric(rb_pack, I"^default_fails")) {
HTML::open_indented_p(OUT, 2, "hanging");
WRITE("<i>");
Localisation::write_0(OUT, LD, I"RS", I"DefaultFailure");
Localisation::write_0(OUT, LD, I"Index.Elements.RS.DefaultFailure");
WRITE("</i>");
HTML_CLOSE("p");
}
@ -619,15 +619,15 @@ void IndexRules::activity_box(OUTPUT_STREAM, inter_tree *I, inter_package *av_pa
HTML::open_indented_p(OUT, 1, "tight");
TEMPORARY_TEXT(skeleton)
Localisation::write_1(skeleton, LD, I"RS", I"BeforeActivity", textual_name);
Localisation::write_1(skeleton, LD, I"Index.Elements.RS.BeforeActivity", textual_name);
PasteButtons::paste_text(OUT, skeleton);
WRITE(":&nbsp;<i>b</i> ");
Str::clear(skeleton);
Localisation::write_1(skeleton, LD, I"RS", I"ForActivity", textual_name);
Localisation::write_1(skeleton, LD, I"Index.Elements.RS.ForActivity", textual_name);
PasteButtons::paste_text(OUT, skeleton);
WRITE(":&nbsp;<i>f</i> ");
Str::clear(skeleton);
Localisation::write_1(skeleton, LD, I"RS", I"AfterActivity", textual_name);
Localisation::write_1(skeleton, LD, I"Index.Elements.RS.AfterActivity", textual_name);
PasteButtons::paste_text(OUT, skeleton);
WRITE(":&nbsp;<i>a</i>");
DISCARD_TEXT(skeleton)
@ -663,6 +663,6 @@ void IndexRules::activity_box(OUTPUT_STREAM, inter_tree *I, inter_package *av_pa
@<Write the titling line of an activity rules box@> =
if (Str::len(doc_link) > 0) IndexUtilities::DocReferences::link(OUT, doc_link);
WRITE(" ... ");
Localisation::write_0(OUT, LD, I"RS", I"Activity");
Localisation::write_0(OUT, LD, I"Index.Elements.RS.Activity");
int at = (int) Metadata::read_optional_numeric(av_pack, I"^at");
if (at > 0) IndexUtilities::link(OUT, at);

View file

@ -264,7 +264,7 @@ eds. Howarth and Lyons (1996).
@<Text of the actual lexicon entry@> =
if (lex->part_of_speech == PREP_TLEXE)
Localisation::write_1(OUT, LD, I"Lx", I"ToBe", lex->lemma);
Localisation::write_1(OUT, LD, I"Index.Elements.Lx.ToBe", lex->lemma);
else
WRITE("%S", lex->lemma);
@ -298,7 +298,7 @@ source text: so any single link would be potentially misleading.
@<Definition of common noun entry@> =
@<Begin definition text@>;
WRITE(", ");
Localisation::write_1(OUT, LD, I"Lx", I"KindOf",
Localisation::write_1(OUT, LD, I"Index.Elements.Lx.KindOf",
Metadata::read_optional_textual(lex->lex_package, I"^index_superkind"));
@<End definition text@>;
@ -320,7 +320,7 @@ different contexts. We want to quote all of those.
@<Definition of enumerated instance entry@> =
@<Begin definition text@>;
WRITE(", ");
Localisation::write_1(OUT, LD, I"Lx", I"ValueOf",
Localisation::write_1(OUT, LD, I"Index.Elements.Lx.ValueOf",
Metadata::read_optional_textual(lex->lex_package, I"^index_kind"));
@<End definition text@>;

View file

@ -30,45 +30,52 @@ typedef struct localisation_dictionary {
localisation_dictionary *Localisation::new(void) {
localisation_dictionary *D = CREATE(localisation_dictionary);
D->texts = Dictionaries::new(32, TRUE);
D->texts = Dictionaries::new(256, TRUE);
return D;
}
@ We think of the dictionary as structured into a two-level hierarchy: for
each different |context| there is an independent set of key-value pairs.
Thus |title| in the context |Phrasebook| is not the same as |title| in the
context |Kinds|, say.
If this had to hold an enormous number of contexts, and had to be accessed
quickly, we could implement that as a dictionary of dictionaries, using the
|context| and then the |key| in turn to find values. But that's overkill here.
@ We think of the dictionary as structured into a hierarchy: for example,
a typical entry might be |Index.Pages.Kinds.Caption|. At present, we do not
take advantage of this to make a more efficient search (one could imagine
a tree structure of dictionaries): we just use these path-like identifiers
as keys to a single dictionary. If we ever need really large localisatiom
dictionaries, we might revisit this.
=
text_stream *Localisation::read(localisation_dictionary *D, text_stream *context,
text_stream *key) {
TEMPORARY_TEXT(true_key)
WRITE_TO(true_key, "%S-%S", context, key);
text_stream *text = Dictionaries::get_text(D->texts, true_key);
DISCARD_TEXT(true_key)
return text;
text_stream *Localisation::read(localisation_dictionary *D, text_stream *key) {
return Dictionaries::get_text(D->texts, key);
}
void Localisation::write(localisation_dictionary *D, text_stream *context,
void Localisation::define(localisation_dictionary *D,
text_stream *key, text_stream *value) {
TEMPORARY_TEXT(true_key)
WRITE_TO(true_key, "%S-%S", context, key);
text_stream *to = Dictionaries::create_text(D->texts, true_key);
text_stream *to = Dictionaries::create_text(D->texts, key);
WRITE_TO(to, "%S", value);
DISCARD_TEXT(true_key)
}
@ As noted above, the user is more likely to stock a dictionary by calling the
following to read it in from a UTF-8-encoded Unicode text file. Lines are assumed
to be terminated with either |0x0a| or |0x0d|.
The format is simple. Contexts are introduced with |%%NAME|, where |NAME| is
the context name; keys by |%KEY = ...|, where |KEY| is the key name and |...|
the text going into it.
The format is simple:
(*) If the first non-whitespace character on a line is a |#|, then the line is
a comment and is ignored.
(*) If the first non-whitespace character on a line is a |%|, then the line is
expected to take the form |%KEY = ...|, where |...| is the text value for this
key. This text continues on what may be multiple lines until the next key;
and any white space at the start or end is ignored.
So, for example:
= (text)
# This is a comment line
%Index.Elements.Cm.Title = Commands
%Index.Elements.Cm.Heading =
Commands which the player can type
=
And the following function reads such a file into an existing dictionary. Note
that it can be used to read several files in turn into the same dictionary;
if later files define the same keys as earlier ones, their new texts override
the earlier ones.
=
int Localisation::stock_from_file(filename *localisation_file, localisation_dictionary *D) {
@ -77,16 +84,17 @@ int Localisation::stock_from_file(filename *localisation_file, localisation_dict
LOG("Failed to load localisation file at: %f\n", localisation_file);
return FALSE;
}
int col = 1, line = 1;
int col = 1, line = 1, nwsol = FALSE; /* "non white space on line" */
unicode_file_buffer ufb = TextFiles::create_ufb();
wchar_t cr;
TEMPORARY_TEXT(context)
TEMPORARY_TEXT(key)
TEMPORARY_TEXT(value)
do {
@<Read next character@>;
if (cr == EOF) break;
if (cr == '%') @<Read up to the next white space as a key@>;
if ((cr == '#') && (nwsol == FALSE)) @<Read up to end of line as a comment@>
else if ((cr == '%') && (nwsol == FALSE)) @<Read up to the next white space as a key@>
else if (Characters::is_whitespace(cr) == FALSE) nwsol = TRUE;
if (cr == EOF) break;
if (Str::len(key) > 0) {
if ((Characters::is_whitespace(cr) == FALSE) || (Str::len(value) > 0))
@ -99,7 +107,6 @@ int Localisation::stock_from_file(filename *localisation_file, localisation_dict
}
} while (cr != EOF);
if (Str::len(key) > 0) @<Write key-value pair@>;
DISCARD_TEXT(context)
DISCARD_TEXT(key)
DISCARD_TEXT(value)
fclose(Input_File);
@ -108,34 +115,28 @@ int Localisation::stock_from_file(filename *localisation_file, localisation_dict
@<Read next character@> =
cr = TextFiles::utf8_fgetc(Input_File, NULL, FALSE, &ufb);
col++; if ((cr == 10) || (cr == 13)) { col = 0; line++; }
col++;
if ((cr == 10) || (cr == 13)) { col = 0; nwsol = FALSE; line++; }
@<Read up to the next white space as a key@> =
if (Str::len(key) > 0) @<Write key-value pair@>;
Str::clear(key);
Str::clear(value);
int double_mode = FALSE;
while (TRUE) {
@<Read next character@>;
if ((cr == '%') && (Str::len(key) == 0)) { double_mode = TRUE; continue; }
if ((cr == '=') || (cr == EOF)) break;
if (Characters::is_whitespace(cr)) {
if (double_mode) break;
continue;
}
PUT_TO(key, cr);
if (Characters::is_whitespace(cr) == FALSE) PUT_TO(key, cr);
}
if (double_mode) {
Str::clear(context);
WRITE_TO(context, "%S", key);
Str::clear(key);
} else if (cr == '=') {
if (cr == '=') {
while (TRUE) {
@<Read next character@>;
if (Characters::is_whitespace(cr)) continue;
break;
}
}
@<Read up to end of line as a comment@> =
while (col != 0) @<Read next character@>;
@<Write key-value pair@> =
Str::trim_white_space(value);
@ -145,13 +146,8 @@ int Localisation::stock_from_file(filename *localisation_file, localisation_dict
WRITE_TO(err, "key '%%%S' has no text", key);
Localisation::error(localisation_file, line, col, err);
DISCARD_TEXT(err)
} else if (Str::len(context) == 0) {
TEMPORARY_TEXT(err)
WRITE_TO(err, "key '%%%S' does not have a %%%%CONTEXT", key);
Localisation::error(localisation_file, line, col, err);
DISCARD_TEXT(err)
} else {
Localisation::write(D, context, key, value);
Localisation::define(D, key, value);
}
@ The function above is very forgiving, in that it never throws syntax errors.
@ -167,29 +163,26 @@ void Localisation::error(filename *F, int line, int col, text_stream *err) {
@
=
void Localisation::write_0(OUTPUT_STREAM, localisation_dictionary *D,
text_stream *context, text_stream *key) {
void Localisation::write_0(OUTPUT_STREAM, localisation_dictionary *D, text_stream *key) {
text_stream *vals[10];
@<Vacate the vals@>;
Localisation::write_general(OUT, D, context, key, vals);
Localisation::write_general(OUT, D, key, vals);
}
void Localisation::write_1(OUTPUT_STREAM, localisation_dictionary *D,
text_stream *context, text_stream *key,
void Localisation::write_1(OUTPUT_STREAM, localisation_dictionary *D, text_stream *key,
text_stream *val1) {
text_stream *vals[10];
@<Vacate the vals@>;
vals[1] = val1;
Localisation::write_general(OUT, D, context, key, vals);
Localisation::write_general(OUT, D, key, vals);
}
void Localisation::write_2(OUTPUT_STREAM, localisation_dictionary *D,
text_stream *context, text_stream *key,
void Localisation::write_2(OUTPUT_STREAM, localisation_dictionary *D, text_stream *key,
text_stream *val1, text_stream *val2) {
text_stream *vals[10];
@<Vacate the vals@>;
vals[1] = val1; vals[2] = val2;
Localisation::write_general(OUT, D, context, key, vals);
Localisation::write_general(OUT, D, key, vals);
}
@<Vacate the vals@> =
@ -199,8 +192,8 @@ void Localisation::write_2(OUTPUT_STREAM, localisation_dictionary *D,
=
void Localisation::write_general(OUTPUT_STREAM, localisation_dictionary *D,
text_stream *context, text_stream *key, text_stream **vals) {
text_stream *prototype = Localisation::read(D, context, key);
text_stream *key, text_stream **vals) {
text_stream *prototype = Localisation::read(D, key);
for (int i=0; i<Str::len(prototype); i++) {
wchar_t c = Str::get_at(prototype, i);
if (c == '*') {

View file

@ -2,7 +2,9 @@
To write the Alphabetic actions element (A2) in the index.
@ =
@ This element is a simple three-column table.
=
void AlphabeticElement::render(OUTPUT_STREAM, localisation_dictionary *LD) {
inter_tree *I = InterpretIndex::get_tree();
tree_inventory *inv = Synoptic::inv(I);
@ -18,7 +20,6 @@ void AlphabeticElement::render(OUTPUT_STREAM, localisation_dictionary *LD) {
HTML::end_html_row(OUT);
for (int i=0; i<TreeLists::len(inv->action_nodes); i++) {
inter_package *an_pack = Inter::Package::defined_by_frame(inv->action_nodes->list[i].node);
HTML::first_html_column(OUT, 0);
inter_ti oow = Metadata::read_optional_numeric(an_pack, I"^out_of_world");
inter_ti requires_light = Metadata::read_numeric(an_pack, I"^requires_light");
inter_ti can_have_noun = Metadata::read_numeric(an_pack, I"^can_have_noun");
@ -27,45 +28,61 @@ void AlphabeticElement::render(OUTPUT_STREAM, localisation_dictionary *LD) {
inter_ti second_access = Metadata::read_numeric(an_pack, I"^second_access");
inter_symbol *noun_kind = Metadata::read_symbol(an_pack, I"^noun_kind");
inter_symbol *second_kind = Metadata::read_symbol(an_pack, I"^second_kind");
if (oow) HTML::begin_colour(OUT, I"800000");
WRITE("%S", Metadata::read_optional_textual(an_pack, I"^name"));
if (oow) HTML::end_colour(OUT);
IndexUtilities::detail_link(OUT, "A", i, TRUE);
if (requires_light) AlphabeticElement::note(OUT, I"Light", LD);
HTML::first_html_column(OUT, 0);
@<Action column@>;
HTML::next_html_column(OUT, 0);
if (can_have_noun == 0) {
WRITE("&mdash;");
} else {
if (noun_access == REQUIRES_ACCESS) AlphabeticElement::note(OUT, I"Touchable", LD);
if (noun_access == REQUIRES_POSSESSION) AlphabeticElement::note(OUT, I"Carried", LD);
WRITE("<b>");
ChartElement::index_kind(OUT, Inter::Packages::container(noun_kind->definition), FALSE, FALSE);
WRITE("</b>");
}
@<Noun column@>;
HTML::next_html_column(OUT, 0);
if (can_have_second == 0) {
WRITE("&mdash;");
} else {
if (second_access == REQUIRES_ACCESS) AlphabeticElement::note(OUT, I"Touchable", LD);
if (second_access == REQUIRES_POSSESSION) AlphabeticElement::note(OUT, I"Carried", LD);
WRITE("<b>");
ChartElement::index_kind(OUT, Inter::Packages::container(second_kind->definition), FALSE, FALSE);
WRITE("</b>");
}
@<Second noun column@>;
HTML::end_html_row(OUT);
}
HTML::end_html_table(OUT);
}
@<Action column@> =
if (oow) HTML::begin_colour(OUT, I"800000");
WRITE("%S", Metadata::read_optional_textual(an_pack, I"^name"));
if (oow) HTML::end_colour(OUT);
IndexUtilities::detail_link(OUT, "A", i, TRUE);
if (requires_light) AlphabeticElement::note(OUT, I"Light", LD);
@<Noun column@> =
if (can_have_noun == 0) {
WRITE("&mdash;");
} else {
if (noun_access == REQUIRES_ACCESS) AlphabeticElement::note(OUT, I"Touchable", LD);
if (noun_access == REQUIRES_POSSESSION) AlphabeticElement::note(OUT, I"Carried", LD);
WRITE("<b>");
ChartElement::index_kind(OUT, Inter::Packages::container(noun_kind->definition), FALSE, FALSE);
WRITE("</b>");
}
@<Second noun column@> =
if (can_have_second == 0) {
WRITE("&mdash;");
} else {
if (second_access == REQUIRES_ACCESS) AlphabeticElement::note(OUT, I"Touchable", LD);
if (second_access == REQUIRES_POSSESSION) AlphabeticElement::note(OUT, I"Carried", LD);
WRITE("<b>");
ChartElement::index_kind(OUT, Inter::Packages::container(second_kind->definition), FALSE, FALSE);
WRITE("</b>");
}
@ =
void AlphabeticElement::note(OUTPUT_STREAM, text_stream *key, localisation_dictionary *LD) {
TEMPORARY_TEXT(full)
WRITE_TO(full, "Index.Elements.A2.%S", key);
WRITE("<i>");
Localisation::write_0(OUT, LD, I"A2", key);
Localisation::write_0(OUT, LD, full);
WRITE("</i> ");
DISCARD_TEXT(full)
}
@ This comparison function sorts actions in alphabetical order of name; by
default the inventory would have them in declaration order.
=
int AlphabeticElement::alphabetical_order(const void *ent1, const void *ent2) {
itl_entry *E1 = (itl_entry *) ent1;
itl_entry *E2 = (itl_entry *) ent2;

View file

@ -24,10 +24,7 @@ void ArithmeticElement::render(OUTPUT_STREAM, localisation_dictionary *LD) {
HTML::first_html_column(OUT, 0);
HTML_TAG_WITH("img", "border=0 src=inform:/doc_images/calc2.png");
WRITE("&nbsp;");
WRITE("Kinds of value marked with the calculator symbol are numerical - "
"these are values we can add, multiply and so on. The range of these "
"numbers depends on the Format setting for the project (Glulx format "
"supports much higher numbers than Z-code).");
Localisation::write_0(OUT, LD, I"Index.Elements.Ar.Calculator");
HTML::end_html_row(OUT);
HTML::end_html_table(OUT);
HTML_CLOSE("p");
@ -56,14 +53,23 @@ void ArithmeticElement::render(OUTPUT_STREAM, localisation_dictionary *LD) {
HTML::next_html_column(OUT, 0);
WRITE("%S", Metadata::read_optional_textual(pack, I"^max_value"));
HTML::next_html_column(OUT, 0);
text_stream *dims = Metadata::read_optional_textual(pack, I"^dimensions");
if (Str::len(dims) > 0) WRITE("%S", dims); else WRITE("<i>dimensionless</i>");
@<Dimensions column@>;
HTML::end_html_row(OUT);
}
}
HTML::end_html_table(OUT);
HTML_CLOSE("p");
@<Dimensions column@> =
text_stream *dims = Metadata::read_optional_textual(pack, I"^dimensions");
if (Str::len(dims) > 0) {
WRITE("%S", dims);
} else {
WRITE("<i>");
Localisation::write_0(OUT, LD, I"Index.Elements.Ar.Dimensionless");
WRITE("</i>");
}
@ This is simply a table of all the multiplications declared in the source
text, sorted into kind order of left and then right operand.
@ -75,7 +81,8 @@ text, sorted into kind order of left and then right operand.
HTML_OPEN("p");
HTML::begin_plain_html_table(OUT);
for (int i=0; i<TreeLists::len(inv->multiplication_rule_nodes); i++) {
inter_package *pack = Inter::Package::defined_by_frame(inv->multiplication_rule_nodes->list[i].node);
inter_package *pack =
Inter::Package::defined_by_frame(inv->multiplication_rule_nodes->list[i].node);
HTML::first_html_column(OUT, 0);
int at = (int) Metadata::read_optional_numeric(pack, I"^at");
if (at > 0) IndexUtilities::link(OUT, at);

View file

@ -13,23 +13,27 @@ void BehaviourElement::render(OUTPUT_STREAM, localisation_dictionary *LD) {
if (num_naps == 0) {
HTML_OPEN("p");
WRITE("No names for kinds of action have yet been defined.");
Localisation::write_0(OUT, LD, I"Index.Elements.Bh.None");
HTML_CLOSE("p");
} else {
TreeLists::sort(inv->named_action_pattern_nodes, Synoptic::module_order);
for (int i=0; i<TreeLists::len(inv->named_action_pattern_nodes); i++) {
inter_package *pack = Inter::Package::defined_by_frame(inv->named_action_pattern_nodes->list[i].node);
inter_package *pack =
Inter::Package::defined_by_frame(inv->named_action_pattern_nodes->list[i].node);
text_stream *name = Metadata::read_optional_textual(pack, I"^name");
int at = (int) Metadata::read_optional_numeric(pack, I"^at");
HTML_OPEN("p"); WRITE("<b>%S</b>", name);
IndexUtilities::link(OUT, at);
HTML_TAG("br");
WRITE("&nbsp;&nbsp;<i>defined as any of the following acts:</i>\n");
WRITE("&nbsp;&nbsp;<i>");
Localisation::write_0(OUT, LD, I"Index.Elements.Bh.Defined");
WRITE(":</i>\n");
inter_tree_node *D = Inter::Packages::definition(pack);
LOOP_THROUGH_INTER_CHILDREN(C, D) {
if (C->W.data[ID_IFLD] == PACKAGE_IST) {
inter_package *entry = Inter::Package::defined_by_frame(C);
if (Inter::Packages::type(entry) == PackageTypes::get(I, I"_named_action_pattern_entry")) {
if (Inter::Packages::type(entry) ==
PackageTypes::get(I, I"_named_action_pattern_entry")) {
text_stream *text = Metadata::read_optional_textual(entry, I"^text");
HTML_TAG("br");
WRITE("&nbsp;&nbsp;&nbsp;&nbsp;%S", text);
@ -42,4 +46,3 @@ void BehaviourElement::render(OUTPUT_STREAM, localisation_dictionary *LD) {
}
}
}

View file

@ -92,13 +92,13 @@ void StandardsElement::render(OUTPUT_STREAM, localisation_dictionary *LD) {
IndexRules::rulebook_box(OUT, inv, I"Instead", I"rules_instead",
IndexRules::find_rulebook(inv, I"instead"), NULL, 1, TRUE, LD);
IndexRules::rulebook_box(OUT, inv, I"Check", NULL, NULL,
Localisation::read(LD, I"St", I"Check"), 1, TRUE, LD);
Localisation::read(LD, I"Index.Elements.St.Check"), 1, TRUE, LD);
IndexRules::rulebook_box(OUT, inv, I"Carry out", NULL, NULL,
Localisation::read(LD, I"St", I"CarryOut"), 1, TRUE, LD);
Localisation::read(LD, I"Index.Elements.St.CarryOut"), 1, TRUE, LD);
IndexRules::rulebook_box(OUT, inv, I"After", I"rules_after",
IndexRules::find_rulebook(inv, I"after"), NULL, 1, TRUE, LD);
IndexRules::rulebook_box(OUT, inv, I"Report", NULL, NULL,
Localisation::read(LD, I"St", I"Report"), 1, TRUE, LD);
Localisation::read(LD, I"Index.Elements.St.Report"), 1, TRUE, LD);
@<Index the segment for the action processing rulebooks@> =
HTML_OPEN("p"); WRITE("<b>How actions are processed</b>"); HTML_CLOSE("p");