1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-05-19 09:28:51 +03:00
inform7/docs/html-module/2-pb.html
2023-09-29 21:55:46 +01:00

326 lines
50 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Paste Buttons</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
function togglePopup(material_id) {
var popup = document.getElementById(material_id);
popup.classList.toggle("show");
}
</script>
<link href="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body class="commentary-font">
<nav role="navigation">
<h1><a href="../index.html">
<img src="../docs-assets/Inform.png" height=72">
</a></h1>
<ul><li><a href="../index.html">home</a></li>
</ul><h2>Compiler</h2><ul>
<li><a href="../structure.html">structure</a></li>
<li><a href="../inbuildn.html">inbuild</a></li>
<li><a href="../inform7n.html">inform7</a></li>
<li><a href="../intern.html">inter</a></li>
<li><a href="../services.html">services</a></li>
<li><a href="../secrets.html">secrets</a></li>
</ul><h2>Other Tools</h2><ul>
<li><a href="../inblorbn.html">inblorb</a></li>
<li><a href="../indocn.html">indoc</a></li>
<li><a href="../inform6.html">inform6</a></li>
<li><a href="../inpolicyn.html">inpolicy</a></li>
</ul><h2>Resources</h2><ul>
<li><a href="../extensions.html">extensions</a></li>
<li><a href="../kits.html">kits</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inform"><img src="../docs-assets/github.png" height=18> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="../../../inweb/index.html">inweb</a></li>
<li><a href="../../../intest/index.html">intest</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of 'Paste Buttons' generated by Inweb-->
<div class="breadcrumbs">
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../services.html">Services</a></li><li><a href="index.html">html</a></li><li><a href="index.html#2">Chapter 2: Intranet</a></li><li><b>Paste Buttons</b></li></ul></div>
<p class="purpose">HTML for a button which, when clicked, pastes Inform source text into the Source panel of the application, or opens a file or folder on the host computer.</p>
<ul class="toc"><li><a href="2-pb.html#SP1">&#167;1. Pastes and their notation</a></li><li><a href="2-pb.html#SP3">&#167;3. Buttons</a></li><li><a href="2-pb.html#SP6">&#167;6. File-opener buttons</a></li></ul><hr class="tocbar">
<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. Pastes and their notation. </b>A paste button is intended to be such that the user clicks it, and some
text is inserted at the current cursor position in the Source panel of the
Inform application.
</p>
<p class="commentary">This is done with Javascript which looks something like this:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> var myProject = window.Project;</span>
<span class="plain-syntax"> myProject.selectView('source');</span>
<span class="plain-syntax"> myProject.pasteCode('Trying Taking Manhattan');</span>
</pre>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. </b>The challenges here are that (a) the code to be pasted may be, say, as much
as 5K in size, and that (b) it needs to include some special characters,
escaped in a way which the app has to deal with correctly. This has proved
a challenge because, historically, different Javascript implementations
have handled escape characters in quoted text differently. (For instance, some
allowing a double-quote <span class="extract"><span class="extract-syntax">"</span></span> to appear as a literal in single-quoted text, others
requiring <span class="extract"><span class="extract-syntax">&amp;quot;</span></span> to be used, and others not recognising HTML entities such as
<span class="extract"><span class="extract-syntax">&amp;quot;</span></span> at all.)
</p>
<p class="commentary">To avoid this issue, Inform adopted a notation of its own in 2007. All
Inform GUI apps have to follow this rule when reading the argument to
<span class="extract"><span class="extract-syntax">pasteCode</span></span>:
</p>
<p class="commentary">Each instance of <span class="extract"><span class="extract-syntax">[=0xHHHH=]</span></span> is replaced with the Unicode character whose
hexadecimal code is <span class="extract"><span class="extract-syntax">HHHH</span></span>; there will always be four digits, with leading
zeros as needed, and <span class="extract"><span class="extract-syntax">A</span></span> to <span class="extract"><span class="extract-syntax">F</span></span> will be written in upper case. The only
Unicode characters with codes below <span class="extract"><span class="extract-syntax">0x0020</span></span> which must be handled are
newline, <span class="extract"><span class="extract-syntax">0x000A</span></span>, and tab, <span class="extract"><span class="extract-syntax">0x0009</span></span>.
</p>
<p class="commentary">And any Inform tool generating such an argument &mdash; either the renderer below,
or the one in <a href="../indoc/index.html" class="internal">indoc</a>, which also generates pastes &mdash; must use this notation
to escape every instance of the following problematic characters:
</p>
<ul class="items"><li>(a) every tab is escaped to <span class="extract"><span class="extract-syntax">[=0x0009=]</span></span>;
</li><li>(b) every newline is escaped to <span class="extract"><span class="extract-syntax">[=0x000A=]</span></span>;
</li><li>(c) every double quotation mark is escaped to <span class="extract"><span class="extract-syntax">[=0x0022=]</span></span>;
</li><li>(d) every ampersand is escaped to <span class="extract"><span class="extract-syntax">[=0x0026=]</span></span>;
</li><li>(e) every single quotation mark is escaped to <span class="extract"><span class="extract-syntax">[=0x0027=]</span></span>;
</li><li>(f) every less than sign is escaped to <span class="extract"><span class="extract-syntax">[=0x003C=]</span></span>;
</li><li>(g) every greater than sign is escaped to <span class="extract"><span class="extract-syntax">[=0x003E=]</span></span>;
</li><li>(h) every backslash is escaped to <span class="extract"><span class="extract-syntax">[=0x005C=]</span></span>.
</li></ul>
<p class="commentary">It may also choose to escape other character codes, as it prefers, but will
never generate any codes below <span class="extract"><span class="extract-syntax">0x0020</span></span> other than newline, <span class="extract"><span class="extract-syntax">0x000A</span></span>, and tab,
<span class="extract"><span class="extract-syntax">0x0009</span></span>.
</p>
<p class="commentary">The app can therefore assume that none of these problematic characters occur
in raw form in the argument to <span class="extract"><span class="extract-syntax">pasteCode</span></span>.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">PasteButtons::put_code_char</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">PasteButtons::put_code_char</span></span>:<br/><a href="2-pb.html#SP5">&#167;5</a>, <a href="2-pb.html#SP5_1">&#167;5.1</a>, <a href="2-pb.html#SP5_1_1">&#167;5.1.1</a>, <a href="2-pb.html#SP5_1_2">&#167;5.1.2</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">OUTPUT_STREAM</span><span class="plain-syntax">, </span><span class="identifier-syntax">inchar32_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax">(</span><span class="identifier-syntax">c</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'\t'</span><span class="plain-syntax">: </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"[=0x0009=]"</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'\n'</span><span class="plain-syntax">: </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">NEWLINE_IN_STRING:</span><span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"[=0x000A=]"</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'"'</span><span class="plain-syntax">: </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"[=0x0022=]"</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'&amp;'</span><span class="plain-syntax">: </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"[=0x0026=]"</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'\''</span><span class="plain-syntax">: </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"[=0x0027=]"</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'&lt;'</span><span class="plain-syntax">: </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"[=0x003C=]"</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'&gt;'</span><span class="plain-syntax">: </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"[=0x003E=]"</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="character-syntax">'\\'</span><span class="plain-syntax">: </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"[=0x005C=]"</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">default:</span><span class="plain-syntax"> </span><span class="identifier-syntax">PUT</span><span class="plain-syntax">(</span><span class="identifier-syntax">c</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. Buttons. </b>The button is simply an image with a link using the <span class="extract"><span class="extract-syntax">javascript:</span></span> protocol
to call a suitable function.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">PasteButtons::paste_W</span><span class="plain-syntax">(</span><span class="identifier-syntax">OUTPUT_STREAM</span><span class="plain-syntax">, </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="2-pb.html#SP3" class="function-link"><span class="function-syntax">PasteButtons::paste_inner</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">), </span><span class="identifier-syntax">Wordings::last_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">), </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">PasteButtons::paste_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">OUTPUT_STREAM</span><span class="plain-syntax">, </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">alt_stream</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="2-pb.html#SP3" class="function-link"><span class="function-syntax">PasteButtons::paste_inner</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, -1, -1, </span><span class="identifier-syntax">alt_stream</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">PasteButtons::paste_text_using</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">PasteButtons::paste_text_using</span></span>:<br/><a href="2-pb.html#SP4">&#167;4</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">OUTPUT_STREAM</span><span class="plain-syntax">, </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">alt_stream</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">paste_icon</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="2-pb.html#SP3" class="function-link"><span class="function-syntax">PasteButtons::paste_inner</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, -1, -1, </span><span class="identifier-syntax">alt_stream</span><span class="plain-syntax">, </span><span class="identifier-syntax">paste_icon</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">PasteButtons::paste_inner</span><span class="plain-syntax">(</span><span class="identifier-syntax">OUTPUT_STREAM</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">to</span><span class="plain-syntax">, </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">alt_stream</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">paste_icon</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">link</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">link</span><span class="plain-syntax">, </span><span class="string-syntax">"class=\"actionlink\" href=\"javascript:pasteCode("</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="2-pb.html#SP5" class="function-link"><span class="function-syntax">PasteButtons::argument</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">link</span><span class="plain-syntax">, </span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="identifier-syntax">to</span><span class="plain-syntax">, </span><span class="identifier-syntax">alt_stream</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">link</span><span class="plain-syntax">, </span><span class="string-syntax">")\""</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">HTML_OPEN_WITH</span><span class="plain-syntax">(</span><span class="string-syntax">"a"</span><span class="plain-syntax">, </span><span class="string-syntax">"%S"</span><span class="plain-syntax">, </span><span class="identifier-syntax">link</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">DISCARD_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">link</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Str::len</span><span class="plain-syntax">(</span><span class="identifier-syntax">paste_icon</span><span class="plain-syntax">) == </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">HTML_TAG_WITH</span><span class="plain-syntax">(</span><span class="string-syntax">"img"</span><span class="plain-syntax">, </span><span class="string-syntax">"border=0 src=inform:/doc_images/paste.png"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"%S"</span><span class="plain-syntax">, </span><span class="identifier-syntax">paste_icon</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">HTML_CLOSE</span><span class="plain-syntax">(</span><span class="string-syntax">"a"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. </b>This is a new-look paste button, using a "command-V" ideograph rather than
a somewhat enigmatic icon.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">PasteButtons::paste_text_new_style</span><span class="plain-syntax">(</span><span class="identifier-syntax">OUTPUT_STREAM</span><span class="plain-syntax">, </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">matter</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">paste</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="2-pb.html#SP4" class="function-link"><span class="function-syntax">PasteButtons::paste_ideograph</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">paste</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="2-pb.html#SP3" class="function-link"><span class="function-syntax">PasteButtons::paste_text_using</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="identifier-syntax">matter</span><span class="plain-syntax">, </span><span class="identifier-syntax">paste</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">DISCARD_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">paste</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"&amp;nbsp;"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">PasteButtons::paste_ideograph</span><span class="plain-syntax">(</span><span class="identifier-syntax">OUTPUT_STREAM</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;span class=\"actionbutton\"&gt;paste&lt;/span&gt;"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>&#167;5. </b>In the following, the source of the text can be either a range of words
from the lexer (as for instance when a portion of an extension is being
typeset as documentation, with an example that can be pasted), or can
be a C string: if the latter, then its encoding must be ISO Latin-1.
The conversion to UTF-8 is performed in <span class="extract"><span class="extract-syntax">PasteButtons::put_code_char</span></span> below.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">PasteButtons::argument</span><button class="popup" onclick="togglePopup('usagePopup3')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup3">Usage of <span class="code-font"><span class="function-syntax">PasteButtons::argument</span></span>:<br/><a href="2-pb.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">OUTPUT_STREAM</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">to</span><span class="plain-syntax">, </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">alt_stream</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"'"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">alt_stream</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_THROUGH_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">pos</span><span class="plain-syntax">, </span><span class="identifier-syntax">alt_stream</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="2-pb.html#SP2" class="function-link"><span class="function-syntax">PasteButtons::put_code_char</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="identifier-syntax">Str::get</span><span class="plain-syntax">(</span><span class="identifier-syntax">pos</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="named-paragraph-container code-font"><a href="2-pb.html#SP5_1" class="named-paragraph-link"><span class="named-paragraph">Write word range as Javascript string</span><span class="named-paragraph-number">5.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"'"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5_1" class="paragraph-anchor"></a><b>&#167;5.1. </b>Writing a word range is much harder. In effect, we have to provide an
inverse function for the lexer, which converted raw source text to nicely
packaged up words.
</p>
<p class="commentary">See Lexer for details of how words are stored, and in particular for the
<span class="extract"><span class="extract-syntax">lw_break</span></span> character, which is <span class="extract"><span class="extract-syntax">'\t'</span></span> when the word followed a tab, but is
<span class="extract"><span class="extract-syntax">'1'</span></span> to <span class="extract"><span class="extract-syntax">'9'</span></span> when it followed a newline plus that many tabs. We need
this because lexing has otherwise removed whitespace from the source, and
we need it back again if we're to paste a faithful Javascript representation:
otherwise the tabs used as column-dividers in tables will not come through,
for instance. Moreover, indentation from the left margin is used to make
prettier pastes (which respect the layout of the original examples from
which the paste has been made), and for that we need the <span class="extract"><span class="extract-syntax">'1'</span></span> to <span class="extract"><span class="extract-syntax">'9'</span></span>
possibilities.
</p>
<p class="commentary">Note that we expect the material pasted to be indented at 1 tab stop from
the margin already, because it will almost always be a source text within
an example, where any matter unindented will be commentary rather than
source text. Thus a single tab after a newline is not significant, and we
only need to supply extra Javascript tabs when the indentation is 2 tab
stops or more.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Write word range as Javascript string</span><span class="named-paragraph-number">5.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">, </span><span class="identifier-syntax">suppress_space</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">, </span><span class="identifier-syntax">follows_paragraph_break</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">close_I6_position</span><span class="plain-syntax"> = -1;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">i</span><span class="plain-syntax">=</span><span class="identifier-syntax">from</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;=</span><span class="identifier-syntax">to</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">j</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">inchar32_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Lexer::word_raw_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">) == </span><span class="identifier-syntax">PARBREAK_V</span><span class="plain-syntax">) { </span><span class="comment-syntax"> marker for a paragraph break</span>
<span class="plain-syntax"> </span><a href="2-pb.html#SP2" class="function-link"><span class="function-syntax">PasteButtons::put_code_char</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="character-syntax">'\n'</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="2-pb.html#SP2" class="function-link"><span class="function-syntax">PasteButtons::put_code_char</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="character-syntax">'\n'</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">suppress_space</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">follows_paragraph_break</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">) == </span><span class="identifier-syntax">PARBREAK_V</span><span class="plain-syntax">) </span><span class="identifier-syntax">i</span><span class="plain-syntax">++; </span><span class="identifier-syntax">i</span><span class="plain-syntax">--; </span><span class="comment-syntax"> elide multiple breaks</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">continue</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">indentation</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Lexer::indentation_level</span><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">indentation</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) { </span><span class="comment-syntax"> number of tab stops of indentation on this para</span>
<span class="plain-syntax"> </span><a href="2-pb.html#SP2" class="function-link"><span class="function-syntax">PasteButtons::put_code_char</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="character-syntax">'\n'</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">j</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">j</span><span class="plain-syntax">&lt;</span><span class="identifier-syntax">indentation</span><span class="plain-syntax">-1; </span><span class="identifier-syntax">j</span><span class="plain-syntax">++) </span><a href="2-pb.html#SP2" class="function-link"><span class="function-syntax">PasteButtons::put_code_char</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="character-syntax">'\t'</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">suppress_space</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">Lexer::break_before</span><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">) == </span><span class="character-syntax">'\t'</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">follows_paragraph_break</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><a href="2-pb.html#SP2" class="function-link"><span class="function-syntax">PasteButtons::put_code_char</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="character-syntax">'\t'</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">suppress_space</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">follows_paragraph_break</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">suppress_space</span><span class="plain-syntax">==</span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-pb.html#SP5_1_1" class="named-paragraph-link"><span class="named-paragraph">Restore inter-word spaces unless this would be unnatural</span><span class="named-paragraph-number">5.1.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">suppress_space</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">j</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">j</span><span class="plain-syntax">]; </span><span class="identifier-syntax">j</span><span class="plain-syntax">++) </span><a href="2-pb.html#SP2" class="function-link"><span class="function-syntax">PasteButtons::put_code_char</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="identifier-syntax">p</span><span class="plain-syntax">[</span><span class="identifier-syntax">j</span><span class="plain-syntax">]);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-pb.html#SP5_1_2" class="named-paragraph-link"><span class="named-paragraph">Insert a close-literal-I6 escape sequence if necessary</span><span class="named-paragraph-number">5.1.2</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><a href="2-pb.html#SP2" class="function-link"><span class="function-syntax">PasteButtons::put_code_char</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="character-syntax">'\n'</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="2-pb.html#SP2" class="function-link"><span class="function-syntax">PasteButtons::put_code_char</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="character-syntax">'\n'</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pb.html#SP5">&#167;5</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP5_1_1" class="paragraph-anchor"></a><b>&#167;5.1.1. </b>The lexer also broke words around punctuation marks, so that, for instance,
"fish, finger" would have been lexed as <span class="extract"><span class="extract-syntax">fish , finger</span></span> &mdash; three words.
But we want to restore the more natural spacing.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Restore inter-word spaces unless this would be unnatural</span><span class="named-paragraph-number">5.1.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">i</span><span class="plain-syntax">&gt;</span><span class="identifier-syntax">from</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> &amp;&amp; ((</span><span class="identifier-syntax">p</span><span class="plain-syntax">[1] != </span><span class="constant-syntax">0</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">Lexer::is_punctuation</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">[0]) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) ||</span>
<span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax">[0] == </span><span class="character-syntax">'('</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">p</span><span class="plain-syntax">[0] == </span><span class="character-syntax">'{'</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">p</span><span class="plain-syntax">[0] == </span><span class="character-syntax">'}'</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> &amp;&amp; (</span><span class="identifier-syntax">compare_word</span><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">-1, </span><span class="identifier-syntax">OPENBRACKET_V</span><span class="plain-syntax">)==</span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><a href="2-pb.html#SP2" class="function-link"><span class="function-syntax">PasteButtons::put_code_char</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="character-syntax">' '</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pb.html#SP5_1">&#167;5.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP5_1_2" class="paragraph-anchor"></a><b>&#167;5.1.2. </b>Finally, the lexer rendered a literal I6 inclusion in the form <span class="extract"><span class="extract-syntax">(- self=2;</span></span>
as a sequence of two lexical words: <span class="extract"><span class="extract-syntax">(-</span></span> and then <span class="extract"><span class="extract-syntax">self=2;</span></span>. In order
to paste back safely, we must supplement this with the closure <span class="extract"><span class="extract-syntax">-)</span></span> once
again:
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Insert a close-literal-I6 escape sequence if necessary</span><span class="named-paragraph-number">5.1.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Lexer::word</span><span class="plain-syntax">(</span><span class="identifier-syntax">i</span><span class="plain-syntax">) == </span><span class="identifier-syntax">OPENI6_V</span><span class="plain-syntax">) </span><span class="identifier-syntax">close_I6_position</span><span class="plain-syntax"> = </span><span class="identifier-syntax">i</span><span class="plain-syntax">+1;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">close_I6_position</span><span class="plain-syntax"> == </span><span class="identifier-syntax">i</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="2-pb.html#SP2" class="function-link"><span class="function-syntax">PasteButtons::put_code_char</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="character-syntax">'-'</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="2-pb.html#SP2" class="function-link"><span class="function-syntax">PasteButtons::put_code_char</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="character-syntax">')'</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="2-pb.html#SP2" class="function-link"><span class="function-syntax">PasteButtons::put_code_char</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="character-syntax">' '</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pb.html#SP5_1">&#167;5.1</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP6" class="paragraph-anchor"></a><b>&#167;6. File-opener buttons. </b>Nothing to do with pastes: this is a completely different sort of button,
though also powered by Javascript. It opens a file or folder on the host
filing system.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">PasteButtons::open_file</span><span class="plain-syntax">(</span><span class="identifier-syntax">OUTPUT_STREAM</span><span class="plain-syntax">, </span><span class="identifier-syntax">pathname</span><span class="plain-syntax"> *</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">leaf</span><span class="plain-syntax">, </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">contents</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">fn</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">leaf</span><span class="plain-syntax">) </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">fn</span><span class="plain-syntax">, </span><span class="string-syntax">"%f"</span><span class="plain-syntax">, </span><span class="identifier-syntax">Filenames::in</span><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="identifier-syntax">leaf</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">fn</span><span class="plain-syntax">, </span><span class="string-syntax">"%p"</span><span class="plain-syntax">, </span><span class="identifier-syntax">P</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">PLATFORM_WINDOWS</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_THROUGH_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">pos</span><span class="plain-syntax">, </span><span class="identifier-syntax">fn</span><span class="plain-syntax">) </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Str::get</span><span class="plain-syntax">(</span><span class="identifier-syntax">pos</span><span class="plain-syntax">) == </span><span class="character-syntax">'\\'</span><span class="plain-syntax">) </span><span class="identifier-syntax">Str::put</span><span class="plain-syntax">(</span><span class="identifier-syntax">pos</span><span class="plain-syntax">, </span><span class="character-syntax">'/'</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">HTML_OPEN_WITH</span><span class="plain-syntax">(</span><span class="string-syntax">"a"</span><span class="plain-syntax">, </span><span class="string-syntax">"href='javascript:project().openFile(\"%S\")'"</span><span class="plain-syntax">, </span><span class="identifier-syntax">fn</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">HTML_TAG_WITH</span><span class="plain-syntax">(</span><span class="string-syntax">"img"</span><span class="plain-syntax">, </span><span class="string-syntax">"%s"</span><span class="plain-syntax">, </span><span class="identifier-syntax">contents</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">HTML_CLOSE</span><span class="plain-syntax">(</span><span class="string-syntax">"a"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">DISCARD_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">fn</span><span class="plain-syntax">)</span>
<span class="plain-syntax">}</span>
</pre>
<nav role="progress"><div class="progresscontainer">
<ul class="progressbar"><li class="progressprev"><a href="2-sl.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-hm.html">1</a></li><li class="progresscurrentchapter">2</li><li class="progresssection"><a href="2-ip.html">ip</a></li><li class="progresssection"><a href="2-sl.html">sl</a></li><li class="progresscurrent">pb</li><li class="progresssection"><a href="2-if.html">if</a></li><li class="progresssection"><a href="2-dr.html">dr</a></li><li class="progresssection"><a href="2-lcl.html">lcl</a></li><li class="progressnext"><a href="2-if.html">&#10095;</a></li></ul></div>
</nav><!--End of weave-->
</main>
</body>
</html>