2020-05-10 19:33:41 +03:00
|
|
|
[SourceLinks::] Source Links.
|
|
|
|
|
|
|
|
To provide HTML links to an Inform source text, using the non-standard
|
|
|
|
"source" protocol.
|
|
|
|
|
|
|
|
@ Index and Problem pages generated by //inform7//, via the //index// and
|
|
|
|
//problems// modules, frequently need to have clickable icons linking to
|
|
|
|
positions in the source text; when these are clicked in the Inform UI
|
|
|
|
applications, the Source panel opens at the appropriate line.
|
|
|
|
|
|
|
|
This is done with a non-standard HTML protocol called |source:|, one of
|
|
|
|
two which the Inform UI apps must provide special handling for. For instance,
|
|
|
|
line 21 of file |Bits and Pieces/marbles.txt| has URL:
|
|
|
|
= (text)
|
|
|
|
source:Bits and Pieces/marbles.txt#line14
|
|
|
|
=
|
|
|
|
When an Inform app is viewing an extension project, there can also be
|
|
|
|
references to individual examples in that extension, and these are referred
|
|
|
|
to as "cases" since they are test cases when the app is testing the extension.
|
|
|
|
For example,
|
|
|
|
= (text)
|
|
|
|
source:Locksmith.i7x?case=B#line7
|
|
|
|
=
|
|
|
|
refers to line 7 of Example B of |Locksmith.i7x|.
|
|
|
|
|
|
|
|
@ Locations are given relative to the current project bundle. However, if
|
|
|
|
only a leafname is supplied, then this is read as a file within the |Source|
|
|
|
|
subfolder of the project bundle. (Thus it is not possible to have a
|
|
|
|
source link to a source file at the root of the project bundle: but this is
|
|
|
|
no loss, since source is not allowed to be kept there.) For instance,
|
|
|
|
line 14 of file |Source/story.ni| has URL
|
|
|
|
= (text)
|
|
|
|
source:story.ni#line14
|
|
|
|
=
|
|
|
|
The following routine writes the clickable source-reference icon, and
|
|
|
|
is the only place in Inform where |source:| URLs are generated.
|
|
|
|
|
|
|
|
=
|
2023-09-05 10:36:51 +03:00
|
|
|
inchar32_t source_link_case = 0;
|
2020-05-10 19:33:41 +03:00
|
|
|
void SourceLinks::set_case(text_stream *p) {
|
|
|
|
source_link_case = Characters::toupper(Str::get_first_char(p));
|
|
|
|
}
|
|
|
|
|
|
|
|
void SourceLinks::link(OUTPUT_STREAM, source_location sl, int nonbreaking_space) {
|
|
|
|
if (sl.file_of_origin) {
|
2020-06-28 01:18:54 +03:00
|
|
|
TEMPORARY_TEXT(fn)
|
2020-05-10 19:33:41 +03:00
|
|
|
WRITE_TO(fn, "%f", TextFromFiles::get_filename(sl.file_of_origin));
|
|
|
|
@<Truncate the path according to the current abbreviation@>;
|
|
|
|
@<Remove indication that the path is inside the Source directory@>;
|
|
|
|
if (nonbreaking_space) WRITE(" "); else WRITE(" ");
|
|
|
|
if (source_link_case)
|
|
|
|
HTML_OPEN_WITH("a", "href=\"source:%S?case=%c#line%d\"",
|
|
|
|
fn, source_link_case, sl.line_number)
|
|
|
|
else
|
|
|
|
HTML_OPEN_WITH("a", "href=\"source:%S#line%d\"", fn, sl.line_number);
|
|
|
|
HTML_TAG_WITH("img", "border=0 src=inform:/doc_images/Reveal.png");
|
|
|
|
HTML_CLOSE("a");
|
2020-06-28 01:18:54 +03:00
|
|
|
DISCARD_TEXT(fn)
|
2020-05-10 19:33:41 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@ This rather clumsily simplifies links to make them relative.
|
|
|
|
|
|
|
|
@<Truncate the path according to the current abbreviation@> =
|
|
|
|
pathname *abbrev = HTML::get_link_abbreviation_path();
|
|
|
|
if (abbrev) {
|
2020-06-28 01:18:54 +03:00
|
|
|
TEMPORARY_TEXT(pp)
|
2020-05-10 19:33:41 +03:00
|
|
|
WRITE_TO(pp, "%p", abbrev);
|
|
|
|
int N = Str::len(pp);
|
|
|
|
if (Str::prefix_eq(fn, pp, N)) Str::delete_n_characters(fn, N+1);
|
2020-06-28 01:18:54 +03:00
|
|
|
DISCARD_TEXT(pp)
|
2020-05-10 19:33:41 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
@<Remove indication that the path is inside the Source directory@> =
|
2023-09-05 10:36:51 +03:00
|
|
|
if ((Str::begins_with_wide_string(fn, U"Source")) &&
|
2020-07-07 01:00:03 +03:00
|
|
|
(Platform::is_folder_separator(Str::get_at(fn, 6))))
|
2020-05-10 19:33:41 +03:00
|
|
|
Str::delete_n_characters(fn, 7);
|