1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 18:14:21 +03:00
inform7/docs/index-module/2-hf.html
2019-04-22 15:42:10 +01:00

640 lines
77 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>1/im</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<!--Weave of '2/hf' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">&#9733;</a></li><li><a href="index.html">index</a></li><li><a href="index.html#2">Chapter 2: HTML</a></li><li><b>HTML Files</b></li></ul><p class="purpose">To provide utilities for writing HTML files such as the problems report, the extension documentation, the index files and so forth.</p>
<ul class="toc"><li><a href="#SP2">&#167;2. The "inform:" URL scheme</a></li><li><a href="#SP3">&#167;3. The "source:" URL scheme</a></li><li><a href="#SP4">&#167;4. Icons with and without tooltips</a></li><li><a href="#SP5">&#167;5. Outcome images</a></li><li><a href="#SP6">&#167;6. Header and footer</a></li><li><a href="#SP7">&#167;7. HTML paragraphs with indentation</a></li><li><a href="#SP8">&#167;8. Writing HTML characters</a></li><li><a href="#SP9">&#167;9. Writing streams in XML-escaped form</a></li><li><a href="#SP10">&#167;10. Bibliographic text</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. </b>Inform documentation &mdash; its HTML text and the images, etc., used within
it &mdash; is stored in two areas: "built-in" and "external". The built-in
area is expected to be within the Inform 7 application itself. For
instance, on OS X, this is at:
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">...wherever.../Inform.app/Contents/Resources/</span></code> and/or
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">...wherever.../Inform.app/Contents/Resources/English.lproj/</span></code>
</p>
<p class="inwebparagraph">(The duplication is a complication to do with localisation which we
can ignore here.) The material stored in this built-in area is fixed: the
Inform application needs to work even if stored on a read-only disc, or
where the user has insufficient permissions to alter it. NI itself neither
reads from, nor writes to, any file in the built-in documentation area.
</p>
<p class="inwebparagraph">Documentation for the installed extensions does, however, change: it is
written by NI as and when necessary. This is the material making up the
"external" area, and it needs to be somewhere which the user certainly
has the necessary permissions to write to. For instance:
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">~/Library/Inform/Documentation/</span></code> (OS X)
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">My Documents\Inform\Documentation\| (Windows)
</span></code></p>
<p class="inwebparagraph">Pages in these two areas, built-in and external, need to link to each other by
links: in addition, pages in the external area need access to images stored in
the built-in area.
</p>
<p class="inwebparagraph">The other HTML files written by NI are stored within the relevant
project's bundle: these are the report of Problems (if any) and the
Index. They, too, need access to images stored in the built-in area.
</p>
<p class="inwebparagraph">The problem we face is that these three mini-websites &mdash; the built-in
documentation, the external documentation, and the project-specific
pages &mdash; are written by tools which cannot know the correct file URLs.
(For instance, it would not even help for the application to tell NI
where the built-in area is: because the HTML written by NI would then
cease to work if the user moved the application elsewhere in the
filing system after NI had run.)
</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. The "inform:" URL scheme. </b>We solve this by requiring that the Inform 7 application must support
a new URL scheme.
</p>
<p class="inwebparagraph"></p>
<ul class="items"><li>(a) <code class="display"><span class="extract">&lt;inform://...&gt;</span></code> is interpreted as a file in the built-in documentation
area, except that
</li></ul>
<ul class="items"><li>(b) <code class="display"><span class="extract">&lt;inform://Extensions/...whatever...&gt;</span></code> should be fetched by first
checking for "...whatever..." in the external area, and then &mdash; if
that fails &mdash; also checking for "...whatever..." in the <code class="display"><span class="extract">ExtnDocs</span></code>
subfolder of the built-in area.
</li></ul>
<p class="inwebparagraph">For instance, Inform 7 for OS X would look for <code class="display"><span class="extract">inform://Extensions/magic.png</span></code>
at the following locations:
</p>
<p class="inwebparagraph"></p>
<ul class="items"><li>(i) <code class="display"><span class="extract">~/Library/Inform/Documentation/magic.png</span></code>
</li></ul>
<ul class="items"><li>(ii) <code class="display"><span class="extract">.../Inform.app/Contents/Resources/ExtnDocs/magic.png</span></code>
</li></ul>
<p class="inwebparagraph">If no file was found in either place, the link should simply do nothing:
the application is required not to produce a 404 error page, or to
blank out the page currently showing.
</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. The "source:" URL scheme. </b>The other non-standard Inform URL scheme is "source:", which is used
for a link which, when clicked, opens the Source panel with the given
line made visible.
</p>
<p class="inwebparagraph">For instance, line 21 of file <code class="display"><span class="extract">Bits and Pieces/marbles.txt</span></code> has URL
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">source:Bits and Pieces/marbles.txt#line14</span></code>
</p>
<p class="inwebparagraph">Filenames are given relative to the current project bundle. However, if only
a leafname is supplied, then this is read as a file within the <code class="display"><span class="extract">Source</span></code>
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 <code class="display"><span class="extract">Source/story.ni</span></code> has URL
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">source:story.ni#line14</span></code>
</p>
<p class="inwebparagraph">The following routine writes the clickable source-reference icon, and
is the only place in NI where "source:" is used.
</p>
<p class="inwebparagraph">Source which is generated internally to NI cannot be opened in the Source
panel, for obvious reasons, so we produce nothing if the location is internal.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">source_link_case</span><span class="plain"> = 0;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">HTMLFiles::set_source_link_case</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="identifier">source_link_case</span><span class="plain"> = </span><span class="identifier">Characters::toupper</span><span class="plain">(</span><span class="identifier">Str::get_first_char</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">HTMLFiles::html_source_link</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="identifier">source_location</span><span class="plain"> </span><span class="identifier">sl</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">nonbreaking_space</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sl</span><span class="plain">.</span><span class="identifier">file_of_origin</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">fn</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">fn</span><span class="plain">, </span><span class="string">"%f"</span><span class="plain">, </span><span class="identifier">TextFromFiles::get_filename</span><span class="plain">(</span><span class="identifier">sl</span><span class="plain">.</span><span class="identifier">file_of_origin</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pathname_of_project</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">pp</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">pp</span><span class="plain">, </span><span class="string">"%p"</span><span class="plain">, </span><span class="identifier">pathname_of_project</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = </span><span class="identifier">Str::len</span><span class="plain">(</span><span class="identifier">pp</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::prefix_eq</span><span class="plain">(</span><span class="identifier">fn</span><span class="plain">, </span><span class="identifier">pp</span><span class="plain">, </span><span class="identifier">N</span><span class="plain">))</span>
<span class="identifier">Str::delete_n_characters</span><span class="plain">(</span><span class="identifier">fn</span><span class="plain">, </span><span class="identifier">N</span><span class="plain">+1);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">pp</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Str::begins_with_wide_string</span><span class="plain">(</span><span class="identifier">fn</span><span class="plain">, </span><span class="identifier">L</span><span class="string">"Source"</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Str::get_at</span><span class="plain">(</span><span class="identifier">fn</span><span class="plain">, 6) == </span><span class="identifier">FOLDER_SEPARATOR</span><span class="plain">))</span>
<span class="identifier">Str::delete_n_characters</span><span class="plain">(</span><span class="identifier">fn</span><span class="plain">, 7);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">nonbreaking_space</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;nbsp;"</span><span class="plain">); </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" "</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">source_link_case</span><span class="plain">)</span>
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"a"</span><span class="plain">, </span><span class="string">"href=\</span><span class="plain">"</span><span class="string">source:%S?case=%c#line%d\</span><span class="plain">"</span><span class="string">"</span><span class="plain">, </span><span class="identifier">fn</span><span class="plain">, </span><span class="identifier">source_link_case</span><span class="plain">, </span><span class="identifier">sl</span><span class="plain">.</span><span class="identifier">line_number</span><span class="plain">)</span>
<span class="reserved">else</span>
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"a"</span><span class="plain">, </span><span class="string">"href=\</span><span class="plain">"</span><span class="string">source:%S#line%d\</span><span class="plain">"</span><span class="string">"</span><span class="plain">, </span><span class="identifier">fn</span><span class="plain">, </span><span class="identifier">sl</span><span class="plain">.</span><span class="identifier">line_number</span><span class="plain">);</span>
<span class="identifier">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"img"</span><span class="plain">, </span><span class="string">"border=0 src=inform:/doc_images/Reveal.png"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"a"</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">fn</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function HTMLFiles::set_source_link_case appears nowhere else.</p>
<p class="endnote">The function HTMLFiles::html_source_link is used in <a href="#SP8">&#167;8</a>, 3/ifs (<a href="3-ifs.html#SP10">&#167;10</a>).</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. Icons with and without tooltips. </b>Tooltips are the evanescent pop-up windows which appear, a little behind the
mouse arrow, when it is poised waiting over the icon. (We make heavy use of
these in the World index, for instance, to clarify what abbreviations mean.)
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">HTMLFiles::html_icon_with_tooltip</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">icon_name</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">tip</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">tip2</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">img</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">img</span><span class="plain">, </span><span class="string">"border=0 src=inform:/doc_images/%s "</span><span class="plain">, </span><span class="identifier">icon_name</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tip</span><span class="plain">) {</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">img</span><span class="plain">, </span><span class="string">"title=\</span><span class="plain">"</span><span class="string">%s"</span><span class="plain">, </span><span class="identifier">tip</span><span class="plain">); </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">tip2</span><span class="plain">) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">img</span><span class="plain">, </span><span class="string">" %s"</span><span class="plain">, </span><span class="identifier">tip2</span><span class="plain">); </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">img</span><span class="plain">, </span><span class="string">"\</span><span class="plain">"</span><span class="string">"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"img"</span><span class="plain">, </span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">img</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">img</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function HTMLFiles::html_icon_with_tooltip is used in <a href="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. Outcome images. </b>These are the two images used on the Problems page to visually indicate
success or failure. We also use special images on special occasions.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">CENTRED_OUTCOME_IMAGE_STYLE</span><span class="plain"> 1</span>
<span class="definitionkeyword">define</span> <span class="constant">SIDE_OUTCOME_IMAGE_STYLE</span><span class="plain"> 2</span>
</pre>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">outcome_image_style</span><span class="plain"> = </span><span class="constant">SIDE_OUTCOME_IMAGE_STYLE</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">HTMLFiles::html_outcome_image</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">image</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">verdict</span><span class="plain">) {</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">vn</span><span class="plain"> = </span><span class="string">""</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">internal_error_thrown</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">Time::feast</span><span class="plain">()) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">CHRISTMAS_FEAST</span><span class="plain">: </span><span class="identifier">vn</span><span class="plain"> = </span><span class="string">"_2"</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">EASTER_FEAST</span><span class="plain">: </span><span class="identifier">vn</span><span class="plain"> = </span><span class="string">"_3"</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">vn</span><span class="plain">[0]) </span><span class="identifier">outcome_image_style</span><span class="plain"> = </span><span class="constant">CENTRED_OUTCOME_IMAGE_STYLE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">Problems::Issue::issue_problems_banner</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">verdict</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">outcome_image_style</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">CENTRED_OUTCOME_IMAGE_STYLE</span><span class="plain">:</span>
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"center"</span><span class="plain">);</span>
<span class="identifier">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"img"</span><span class="plain">, </span><span class="string">"src=inform:/outcome_images/%s%s.png border=0"</span><span class="plain">, </span><span class="identifier">image</span><span class="plain">, </span><span class="identifier">vn</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"center"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">SIDE_OUTCOME_IMAGE_STYLE</span><span class="plain">:</span>
<span class="identifier">HTML::begin_html_table</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">, 0, 4, 0, 0, 0);</span>
<span class="identifier">HTML::first_html_column</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 110);</span>
<span class="identifier">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"img"</span><span class="plain">,</span>
<span class="string">"src=inform:/outcome_images/%s%s@2x.png border=1 width=100 height=100"</span><span class="plain">, </span><span class="identifier">image</span><span class="plain">, </span><span class="identifier">vn</span><span class="plain">);</span>
<span class="identifier">HTML::next_html_column</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 0);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">HTML::comment</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"HEADNOTE"</span><span class="plain">);</span>
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">, </span><span class="string">"style=\</span><span class="plain">"</span><span class="string">margin-top:0;\</span><span class="plain">"</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"(Each time &lt;b&gt;Go&lt;/b&gt; or &lt;b&gt;Replay&lt;/b&gt; is clicked, Inform tries to "</span>
<span class="string">"translate the source text into a working story, and updates this report.)"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
<span class="identifier">HTML::comment</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"PROBLEMS BEGIN"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">HTMLFiles::outcome_image_tail</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">outcome_image_style</span><span class="plain"> == </span><span class="constant">SIDE_OUTCOME_IMAGE_STYLE</span><span class="plain">) {</span>
<span class="identifier">HTML::comment</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"PROBLEMS END"</span><span class="plain">);</span>
<span class="identifier">HTML::end_html_row</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
<span class="identifier">HTML::end_html_table</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
<span class="identifier">HTML::comment</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"FOOTNOTE"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function HTMLFiles::html_outcome_image appears nowhere else.</p>
<p class="endnote">The function HTMLFiles::outcome_image_tail appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. Header and footer. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">HTMLFiles::html_header</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">title</span><span class="plain">) {</span>
<span class="identifier">HTML::declare_as_HTML</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="identifier">HTML::begin_head</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">HTML::incorporate_CSS</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">,</span>
<span class="identifier">Filenames::in_folder</span><span class="plain">(</span><span class="identifier">pathname_of_HTML_models</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"main.css"</span><span class="plain">));</span>
<span class="identifier">HTML::incorporate_javascript</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">,</span>
<span class="identifier">Filenames::in_folder</span><span class="plain">(</span><span class="identifier">pathname_of_HTML_models</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"main.js"</span><span class="plain">));</span>
<span class="functiontext">Index::scripting</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
<span class="identifier">HTML::end_head</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
<span class="identifier">HTML::begin_body</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">HTML::comment</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"CONTENT BEGINS"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">HTMLFiles::html_footer</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">HTML::comment</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"CONTENT ENDS"</span><span class="plain">);</span>
<span class="identifier">HTML::end_body</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function HTMLFiles::html_header is used in 3/ifs (<a href="3-ifs.html#SP4">&#167;4</a>).</p>
<p class="endnote">The function HTMLFiles::html_footer is used in 3/ifs (<a href="3-ifs.html#SP9">&#167;9</a>).</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. HTML paragraphs with indentation. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">HTMLFiles::open_para</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">depth</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">class</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">margin</span><span class="plain"> = </span><span class="identifier">depth</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">margin</span><span class="plain"> &lt; 1) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"minimal HTML indentation is 1"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">margin</span><span class="plain"> &gt; 9) </span><span class="identifier">margin</span><span class="plain"> = 9;</span>
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">, </span><span class="string">"class=\</span><span class="plain">"</span><span class="string">%sin%d\</span><span class="plain">"</span><span class="string">"</span><span class="plain">, </span><span class="identifier">class</span><span class="plain">, </span><span class="identifier">margin</span><span class="plain">);</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">depth</span><span class="plain"> &gt; 9) { </span><span class="identifier">depth</span><span class="plain">--; </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;"</span><span class="plain">); }</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function HTMLFiles::open_para is used in 3/ifs (<a href="3-ifs.html#SP14">&#167;14</a>).</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. Writing HTML characters. </b>The following routine is a low-level filter which takes ISO Latin-1
characters one at a time, feeding them out to the given stream with any
unsafe characters converted to suitable HTML elements. (The stream writer
will transcode to UTF-8 encoding, since all HTML file streams written by
Inform are declared as having the UTF-8 character encoding.)
</p>
<p class="inwebparagraph">Recall that a source reference is fed into <code class="display"><span class="extract">HTMLFiles::char_out</span></code> as the
following stream of characters:
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">*source text*Source/story.ni*14*</span></code>
</p>
<p class="inwebparagraph">(with <code class="display"><span class="extract">SOURCE_REF_CHAR</span></code> used in place of the asterisk).
</p>
<p class="inwebparagraph">When we notice the trigger character, we cease to output HTML and instead
buffer up the reference until we reach the terminating trigger character:
we then parse a little, tidy up and send it to <code class="display"><span class="extract">HTMLFiles::html_source_link</span></code> to be
turned into a <code class="display"><span class="extract">source:</span></code> link.
</p>
<pre class="display">
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">source_ref_fields</span><span class="plain">[3] = { </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain"> }; </span> <span class="comment">paraphrase, filename, line</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">source_ref_field</span><span class="plain"> = -1; </span> <span class="comment">which field we are buffering</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">HTMLFiles::char_out</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">charcode</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">source_ref_field</span><span class="plain"> &gt;= 0) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">source_ref_fields</span><span class="plain">[</span><span class="identifier">source_ref_field</span><span class="plain">] == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">source_ref_fields</span><span class="plain">[</span><span class="identifier">source_ref_field</span><span class="plain">] = </span><span class="identifier">Str::new</span><span class="plain">();</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">charcode</span><span class="plain"> != </span><span class="identifier">SOURCE_REF_CHAR</span><span class="plain">) { </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">source_ref_fields</span><span class="plain">[</span><span class="identifier">source_ref_field</span><span class="plain">], </span><span class="identifier">charcode</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">; }</span>
<span class="plain">}</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">charcode</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'"'</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;quot;"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'&lt;'</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;lt;"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'&gt;'</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;gt;"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'&amp;'</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;amp;"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NEWLINE_IN_STRING</span><span class="plain">: </span><span class="identifier">HTML_TAG</span><span class="plain">(</span><span class="string">"br"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">FORCE_NEW_PARA_CHAR</span><span class="plain">: </span><span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">); </span><span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">, </span><span class="string">"class=\</span><span class="plain">"</span><span class="string">in2\</span><span class="plain">"</span><span class="string">"</span><span class="plain">);</span>
<span class="functiontext">HTMLFiles::html_icon_with_tooltip</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="string">"ornament_flower.png"</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;nbsp;"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">SOURCE_REF_CHAR</span><span class="plain">:</span>
<span class="identifier">source_ref_field</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">source_ref_field</span><span class="plain"> == 3) {</span>
<span class="identifier">source_ref_field</span><span class="plain"> = -1;</span>
<span class="identifier">source_location</span><span class="plain"> </span><span class="identifier">sl</span><span class="plain">;</span>
<span class="identifier">sl</span><span class="plain">.</span><span class="identifier">file_of_origin</span><span class="plain"> = </span><span class="identifier">TextFromFiles::filename_to_source_file</span><span class="plain">(</span><span class="identifier">source_ref_fields</span><span class="plain">[1]);</span>
<span class="identifier">sl</span><span class="plain">.</span><span class="identifier">line_number</span><span class="plain"> = </span><span class="identifier">Str::atoi</span><span class="plain">(</span><span class="identifier">source_ref_fields</span><span class="plain">[2], 0);</span>
<span class="functiontext">HTMLFiles::html_source_link</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">sl</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">Str::clear</span><span class="plain">(</span><span class="identifier">source_ref_fields</span><span class="plain">[</span><span class="identifier">source_ref_field</span><span class="plain">]);</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="reserved">default</span><span class="plain">:</span>
<span class="identifier">PUT</span><span class="plain">(</span><span class="identifier">charcode</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function HTMLFiles::char_out is used in 2/hd (<a href="2-hd.html#SP8_5">&#167;8.5</a>).</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. Writing streams in XML-escaped form. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">HTMLFiles::write_xml_safe_text</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">txt</span><span class="plain">) {</span>
<span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">txt</span><span class="plain">) {</span>
<span class="identifier">wchar_t</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="identifier">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">c</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'&amp;'</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;amp;"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'&lt;'</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;lt;"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'&gt;'</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;gt;"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">default</span><span class="plain">: </span><span class="identifier">PUT</span><span class="plain">(</span><span class="identifier">c</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function HTMLFiles::write_xml_safe_text appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. Bibliographic text. </b>"Bibliographic text" is text used in bibliographic data about the work
of IF compiled: for instance, in the iFiction record, or in the Library
Card section of the HTML index. Note that the exact output format depends
on global variables, which allow the bibliographic text writing code to
configure NI for its current purposes. On non-empty strings this routine
therefore splits into one of three independent methods.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">HTMLFiles::compile_bibliographic_text</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">TEST_COMPILATION_MODE</span><span class="plain">(</span><span class="identifier">COMPILE_TEXT_TO_XML_CMODE</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Compile bibliographic text as XML respecting Treaty of Babel rules</span> <span class="cwebmacronumber">10.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">TEST_COMPILATION_MODE</span><span class="plain">(</span><span class="identifier">TRUNCATE_TEXT_CMODE</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Compile bibliographic text as a truncated filename</span> <span class="cwebmacronumber">10.4</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">TEST_COMPILATION_MODE</span><span class="plain">(</span><span class="identifier">COMPILE_TEXT_TO_I6_CMODE</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Compile bibliographic text as an I6 string</span> <span class="cwebmacronumber">10.3</span>&gt;
&lt;<span class="cwebmacro">Compile bibliographic text as HTML</span> <span class="cwebmacronumber">10.2</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function HTMLFiles::compile_bibliographic_text appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP10_1"></a><b>&#167;10.1. </b>This looks like a standard routine for converting ISO Latin-1 to UTF-8
with XML escapes, but there are a few conventions on whitespace, too, in order
to comply with a strict reading of the Treaty of Babel. (This is intended
for fields in iFiction records.)
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Compile bibliographic text as XML respecting Treaty of Babel rules</span> <span class="cwebmacronumber">10.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = 0, </span><span class="identifier">i2</span><span class="plain"> = </span><span class="identifier">Wide::len</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)-1, </span><span class="identifier">snl</span><span class="plain">, </span><span class="identifier">wsc</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">p</span><span class="plain">[0] == </span><span class="character">'"'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i2</span><span class="plain">] == </span><span class="character">'"'</span><span class="plain">)) { </span><span class="identifier">i</span><span class="plain">++; </span><span class="identifier">i2</span><span class="plain">--; } </span> <span class="comment">omit surrounding double-quotes</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">Characters::is_babel_whitespace</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">])) </span><span class="identifier">i</span><span class="plain">++; </span> <span class="comment">omit leading whitespace</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">i2</span><span class="plain">&gt;=0) &amp;&amp; (</span><span class="identifier">Characters::is_babel_whitespace</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i2</span><span class="plain">]))) </span><span class="identifier">i2</span><span class="plain">--; </span> <span class="comment">omit trailing whitespace</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">snl</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">wsc</span><span class="plain"> = 0; </span><span class="identifier">i</span><span class="plain">&lt;=</span><span class="identifier">i2</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">' '</span><span class="plain">: </span><span class="reserved">case</span><span class="plain"> </span><span class="character">'\</span><span class="plain">x</span><span class="character">0a'</span><span class="plain">: </span><span class="reserved">case</span><span class="plain"> </span><span class="character">'\</span><span class="plain">x</span><span class="character">0d'</span><span class="plain">: </span><span class="reserved">case</span><span class="plain"> </span><span class="character">'\</span><span class="plain">t</span><span class="character">'</span><span class="plain">:</span>
<span class="identifier">snl</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">wsc</span><span class="plain">++;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">] == </span><span class="character">' '</span><span class="plain">) || (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">] == </span><span class="character">'\</span><span class="plain">x</span><span class="character">0a'</span><span class="plain">) || (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">] == </span><span class="character">'\</span><span class="plain">x</span><span class="character">0d'</span><span class="plain">) || (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">] == </span><span class="character">'\</span><span class="plain">t</span><span class="character">'</span><span class="plain">)) </span><span class="identifier">k</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">wsc</span><span class="plain"> == 1) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">] != </span><span class="identifier">NEWLINE_IN_STRING</span><span class="plain">)) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" "</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NEWLINE_IN_STRING</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">snl</span><span class="plain">) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;br/&gt;"</span><span class="plain">);</span>
<span class="identifier">snl</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="identifier">wsc</span><span class="plain"> = 1; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'['</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1] == </span><span class="character">'\</span><span class="plain">'</span><span class="character">'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+2] == </span><span class="character">']'</span><span class="plain">)) {</span>
<span class="identifier">i</span><span class="plain"> += 2;</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"'"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">n</span><span class="plain"> = </span><span class="identifier">CompiledText::expand_unisub</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">n</span><span class="plain"> &gt;= 0) { </span><span class="identifier">i</span><span class="plain"> = </span><span class="identifier">n</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">; }</span>
<span class="comment">and otherwise fall through to the default case</span>
<span class="reserved">default</span><span class="plain">:</span>
<span class="identifier">snl</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">wsc</span><span class="plain"> = 0;</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'&amp;'</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;amp;"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'&lt;'</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;lt;"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'&gt;'</span><span class="plain">: </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;gt;"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">default</span><span class="plain">: </span><span class="identifier">PUT</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP10_2"></a><b>&#167;10.2. </b>In the HTML version, we want to respect the forcing of newlines, and
also the <code class="display"><span class="extract">[']</span></code> escape to obtain a literal single quotation mark.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Compile bibliographic text as HTML</span> <span class="cwebmacronumber">10.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">whitespace_count</span><span class="plain">=0;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">[0] == </span><span class="character">'"'</span><span class="plain">) </span><span class="identifier">p</span><span class="plain">++;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] == </span><span class="character">'"'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1] == 0)) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">' '</span><span class="plain">: </span><span class="reserved">case</span><span class="plain"> </span><span class="character">'\</span><span class="plain">x</span><span class="character">0a'</span><span class="plain">: </span><span class="reserved">case</span><span class="plain"> </span><span class="character">'\</span><span class="plain">x</span><span class="character">0d'</span><span class="plain">: </span><span class="reserved">case</span><span class="plain"> </span><span class="character">'\</span><span class="plain">t</span><span class="character">'</span><span class="plain">:</span>
<span class="identifier">whitespace_count</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">whitespace_count</span><span class="plain"> == 1) </span><span class="identifier">PUT</span><span class="plain">(</span><span class="character">' '</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">NEWLINE_IN_STRING</span><span class="plain">:</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1] == </span><span class="identifier">NEWLINE_IN_STRING</span><span class="plain">) </span><span class="identifier">i</span><span class="plain">++;</span>
<span class="identifier">PUT</span><span class="plain">(</span><span class="character">'&lt;'</span><span class="plain">);</span>
<span class="identifier">PUT</span><span class="plain">(</span><span class="character">'p'</span><span class="plain">);</span>
<span class="identifier">PUT</span><span class="plain">(</span><span class="character">'&gt;'</span><span class="plain">);</span>
<span class="identifier">whitespace_count</span><span class="plain"> = 1;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'['</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1] == </span><span class="character">'\</span><span class="plain">'</span><span class="character">'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+2] == </span><span class="character">']'</span><span class="plain">)) {</span>
<span class="identifier">i</span><span class="plain"> += 2;</span>
<span class="identifier">PUT</span><span class="plain">(</span><span class="character">'\</span><span class="plain">'</span><span class="character">'</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">n</span><span class="plain"> = </span><span class="identifier">CompiledText::expand_unisub</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">n</span><span class="plain"> &gt;= 0) { </span><span class="identifier">i</span><span class="plain"> = </span><span class="identifier">n</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">; }</span>
<span class="comment">and otherwise fall through to the default case</span>
<span class="reserved">default</span><span class="plain">:</span>
<span class="identifier">whitespace_count</span><span class="plain"> = 0;</span>
<span class="identifier">PUT</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP10_3"></a><b>&#167;10.3. </b>In the Inform 6 string version, we suppress the forcing of newlines, but
otherwise it's much the same.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Compile bibliographic text as an I6 string</span> <span class="cwebmacronumber">10.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">whitespace_count</span><span class="plain">=0;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">[0] == </span><span class="character">'"'</span><span class="plain">) </span><span class="identifier">p</span><span class="plain">++;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] == </span><span class="character">'"'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1] == 0)) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">' '</span><span class="plain">: </span><span class="reserved">case</span><span class="plain"> </span><span class="character">'\</span><span class="plain">x</span><span class="character">0a'</span><span class="plain">: </span><span class="reserved">case</span><span class="plain"> </span><span class="character">'\</span><span class="plain">x</span><span class="character">0d'</span><span class="plain">: </span><span class="reserved">case</span><span class="plain"> </span><span class="character">'\</span><span class="plain">t</span><span class="character">'</span><span class="plain">: </span><span class="reserved">case</span><span class="plain"> </span><span class="identifier">NEWLINE_IN_STRING</span><span class="plain">:</span>
<span class="identifier">whitespace_count</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">whitespace_count</span><span class="plain"> == 1) </span><span class="identifier">PUT</span><span class="plain">(</span><span class="character">' '</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'['</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1] == </span><span class="character">'\</span><span class="plain">'</span><span class="character">'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+2] == </span><span class="character">']'</span><span class="plain">)) {</span>
<span class="identifier">i</span><span class="plain"> += 2;</span>
<span class="identifier">PUT</span><span class="plain">(</span><span class="character">'\</span><span class="plain">'</span><span class="character">'</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">} </span> <span class="comment">and otherwise fall through to the default case</span>
<span class="reserved">default</span><span class="plain">:</span>
<span class="identifier">whitespace_count</span><span class="plain"> = 0;</span>
<span class="identifier">PUT</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP10_4"></a><b>&#167;10.4. </b>This code is used to work out a good filename for something given a name
inside NI. For instance, if a project is called
</p>
<blockquote>
<p>"St. Bartholemew's Fair: \'Etude for a Push-Me/Pull-You Machine"</p>
</blockquote>
<p class="inwebparagraph">then what would be a good filename for its released story file?
</p>
<p class="inwebparagraph">In the filename version we must forcibly truncate the text to ensure
that it does not exceed a certain length, and must also make it filename-safe,
omitting characters used as folder separators on various platforms and
(for good measure) removing accents from accented letters, so that we can
arrive at a sequence of ASCII characters. Each run of whitespace is also
converted to a single space. If this would result in an empty text or only
a single space, we return the text "story" instead.
</p>
<p class="inwebparagraph">Our example (if not truncated) then emerges as:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">St- Bartholemew's Fair- Etude for a Push-Me-Pull-You Machine</span>
</pre>
<p class="inwebparagraph">Note that we do not write any filename extension (e.g., <code class="display"><span class="extract">.z5</span></code>) here.
</p>
<p class="inwebparagraph">We change possible filename separators or extension indicators to hyphens,
and remove accents from each possible ISO Latin-1 accented letter. This does
still mean that the OE and AE digraphs will simply be omitted, while the
German eszet will be barbarously shortened to a single "s", but life is
just too short to care overmuch about this.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Compile bibliographic text as a truncated filename</span> <span class="cwebmacronumber">10.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">pos</span><span class="plain"> = </span><span class="identifier">STREAM_EXTENT</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">), </span><span class="identifier">whitespace_count</span><span class="plain">=0, </span><span class="identifier">black_chars_written</span><span class="plain"> = 0;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = 100;</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
<span class="identifier">N</span><span class="plain"> = </span><span class="identifier">BIBLIOGRAPHIC_TEXT_TRUNCATION</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">[0] == </span><span class="character">'"'</span><span class="plain">) </span><span class="identifier">p</span><span class="plain">++;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">STREAM_EXTENT</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">) - </span><span class="identifier">pos</span><span class="plain"> &gt;= </span><span class="identifier">N</span><span class="plain">) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] == </span><span class="character">'"'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1] == 0)) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">' '</span><span class="plain">: </span><span class="reserved">case</span><span class="plain"> </span><span class="character">'\</span><span class="plain">x</span><span class="character">0a'</span><span class="plain">: </span><span class="reserved">case</span><span class="plain"> </span><span class="character">'\</span><span class="plain">x</span><span class="character">0d'</span><span class="plain">: </span><span class="reserved">case</span><span class="plain"> </span><span class="character">'\</span><span class="plain">t</span><span class="character">'</span><span class="plain">: </span><span class="reserved">case</span><span class="plain"> </span><span class="identifier">NEWLINE_IN_STRING</span><span class="plain">:</span>
<span class="identifier">whitespace_count</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">whitespace_count</span><span class="plain"> == 1) </span><span class="identifier">PUT</span><span class="plain">(</span><span class="character">' '</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'?'</span><span class="plain">: </span><span class="reserved">case</span><span class="plain"> </span><span class="character">'*'</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1]) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">+1] != </span><span class="character">'\</span><span class="plain">"</span><span class="character">'</span><span class="plain">)) </span><span class="identifier">PUT</span><span class="plain">(</span><span class="character">'-'</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">default</span><span class="plain">: {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">charcode</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">];</span>
<span class="identifier">charcode</span><span class="plain"> = </span><span class="identifier">Characters::make_filename_safe</span><span class="plain">(</span><span class="identifier">charcode</span><span class="plain">);</span>
<span class="identifier">whitespace_count</span><span class="plain"> = 0;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">charcode</span><span class="plain"> &lt; 128) {</span>
<span class="identifier">PUT</span><span class="plain">(</span><span class="identifier">charcode</span><span class="plain">); </span><span class="identifier">black_chars_written</span><span class="plain">++;</span>
<span class="plain">}</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">black_chars_written</span><span class="plain"> == 0) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"story"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10">&#167;10</a>.</p>
<hr class="tocbar">
<ul class="toc"><li><i>(This section begins Chapter 2: HTML.)</i></li><li><a href="2-jp.html">Continue with 'Javascript Pastes'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</body>
</html>