about summary refs log tree commit diff stats
path: root/html
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-07-01 10:19:04 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-07-01 10:19:04 -0700
commit62a52ffbfe2880fe754732ca3417eab96ff83738 (patch)
tree0aa59103af2256769a0792a6378babd6cad0eba0 /html
parent7ed2441bb547fb799bdd553e4f89c48fee7b60db (diff)
downloadmu-62a52ffbfe2880fe754732ca3417eab96ff83738.tar.gz
1690
Diffstat (limited to 'html')
-rw-r--r--html/002test.cc.html2
-rw-r--r--html/003trace.cc.html9
-rw-r--r--html/003trace.test.cc.html5
-rw-r--r--html/011load.cc.html2
-rw-r--r--html/014types.cc.html134
-rw-r--r--html/030container.cc.html1
-rw-r--r--html/033length.cc.html64
-rw-r--r--html/041name.cc.html36
-rw-r--r--html/043space.cc.html3
-rw-r--r--html/050scenario.cc.html22
-rw-r--r--html/070display.cc.html64
-rw-r--r--html/071print.mu.html54
-rw-r--r--html/072scenario_screen.cc.html22
-rw-r--r--html/074console.mu.html (renamed from html/074keyboard.mu.html)2
-rw-r--r--html/075scenario_console.cc.html4
-rw-r--r--html/075scenario_keyboard.cc.html119
-rw-r--r--html/076scenario_keyboard_test.mu.html57
-rw-r--r--html/077mouse.cc.html68
-rw-r--r--html/077trace_browser.cc.html236
-rw-r--r--html/078run_interactive.cc.html159
-rw-r--r--html/edit.mu.html1487
-rw-r--r--html/factorial.mu.html2
-rw-r--r--html/keyboard.mu.html51
-rw-r--r--html/mouse.mu.html46
24 files changed, 1612 insertions, 1037 deletions
diff --git a/html/002test.cc.html b/html/002test.cc.html
index c37f136f..4c280e92 100644
--- a/html/002test.cc.html
+++ b/html/002test.cc.html
@@ -87,7 +87,7 @@ if <span class="Delimiter">(</span>Run_tests<span class="Delimiter">)</span> <sp
   time_t t<span class="Delimiter">;</span> time<span class="Delimiter">(</span>&amp;t<span class="Delimiter">);</span>
   cerr &lt;&lt; <span class="Constant">&quot;C tests: &quot;</span> &lt;&lt; ctime<span class="Delimiter">(</span>&amp;t<span class="Delimiter">);</span>
   for <span class="Delimiter">(</span>size_t i=<span class="Constant">0</span><span class="Delimiter">;</span> i &lt; sizeof<span class="Delimiter">(</span>Tests<span class="Delimiter">)</span>/sizeof<span class="Delimiter">(</span>Tests[<span class="Constant">0</span>]<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-<span class="CommentedCode">//?     cerr &lt;&lt; i &lt;&lt; '\n'; //? 1</span>
+<span class="CommentedCode">//?     cerr &lt;&lt; i &lt;&lt; '\n'; //? 2</span>
     run_test<span class="Delimiter">(</span>i<span class="Delimiter">);</span>
   <span class="Delimiter">}</span>
   <span class="Comment">// End Tests</span>
diff --git a/html/003trace.cc.html b/html/003trace.cc.html
index 80552b36..a94ed6b1 100644
--- a/html/003trace.cc.html
+++ b/html/003trace.cc.html
@@ -189,7 +189,7 @@ trace_stream* Trace_stream = <span class="Constant">NULL</span><span class="Deli
 <span class="PreProc">#define trace(</span><span class="Delimiter">...</span><span class="PreProc">)  !Trace_stream ? cerr </span><span class="Comment">/*</span><span class="Comment">print nothing</span><span class="Comment">*/</span><span class="PreProc"> : Trace_stream</span><span class="Delimiter">-&gt;</span><span class="PreProc">stream(__VA_ARGS__)</span>
 <span class="Comment">// Warnings should go straight to cerr by default since calls to trace() have</span>
 <span class="Comment">// some unfriendly constraints (they delay printing, they can't nest)</span>
-<span class="PreProc">#define raise  ((!Trace_stream || !Hide_warnings) ? cerr </span><span class="Comment">/*</span><span class="Comment">do print</span><span class="Comment">*/</span><span class="PreProc"> : Trace_stream</span><span class="Delimiter">-&gt;</span><span class="PreProc">stream(</span><span class="Constant">&quot;warn&quot;</span><span class="PreProc">))</span>
+<span class="PreProc">#define raise  ((!Trace_stream || !Hide_warnings) ? (tb_shutdown()</span><span class="Delimiter">,</span><span class="PreProc">cerr) </span><span class="Comment">/*</span><span class="Comment">do print</span><span class="Comment">*/</span><span class="PreProc"> : Trace_stream</span><span class="Delimiter">-&gt;</span><span class="PreProc">stream(</span><span class="Constant">&quot;warn&quot;</span><span class="PreProc">))</span>
 
 <span class="Comment">// A separate helper for debugging. We should only trace domain-specific</span>
 <span class="Comment">// facts. For everything else use log.</span>
@@ -298,9 +298,12 @@ int trace_count<span class="Delimiter">(</span>string layer<span class="Delimite
   Trace_stream<span class="Delimiter">-&gt;</span>newline<span class="Delimiter">();</span>
   long result = <span class="Constant">0</span><span class="Delimiter">;</span>
   for <span class="Delimiter">(</span>vector&lt;trace_line&gt;::iterator p = Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>begin<span class="Delimiter">();</span> p != Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>end<span class="Delimiter">();</span> ++p<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    if <span class="Delimiter">(</span>layer == p<span class="Delimiter">-&gt;</span>label<span class="Delimiter">)</span>
-      if <span class="Delimiter">(</span>line == <span class="Constant">&quot;&quot;</span> || line == p<span class="Delimiter">-&gt;</span>contents<span class="Delimiter">)</span>
+    if <span class="Delimiter">(</span>layer == p<span class="Delimiter">-&gt;</span>label<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+<span class="CommentedCode">//?       cerr &lt;&lt; &quot;a: &quot; &lt;&lt; line &lt;&lt; &quot;$\n&quot;; //? 1</span>
+<span class="CommentedCode">//?       cerr &lt;&lt; &quot;b: &quot; &lt;&lt; trim(p-&gt;contents) &lt;&lt; &quot;$\n&quot;; //? 1</span>
+      if <span class="Delimiter">(</span>line == <span class="Constant">&quot;&quot;</span> || line == trim<span class="Delimiter">(</span>p<span class="Delimiter">-&gt;</span>contents<span class="Delimiter">))</span>
         ++result<span class="Delimiter">;</span>
+    <span class="Delimiter">}</span>
   <span class="Delimiter">}</span>
   <span class="Identifier">return</span> result<span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
diff --git a/html/003trace.test.cc.html b/html/003trace.test.cc.html
index 91391d7b..f8de30f2 100644
--- a/html/003trace.test.cc.html
+++ b/html/003trace.test.cc.html
@@ -81,6 +81,11 @@ void test_trace_supports_count2<span class="Delimiter">()</span> <span class="De
   CHECK_EQ<span class="Delimiter">(</span>trace_count<span class="Delimiter">(</span><span class="Constant">&quot;test layer 1&quot;</span><span class="Delimiter">),</span> <span class="Constant">2</span><span class="Delimiter">);</span>
 <span class="Delimiter">}</span>
 
+void test_trace_count_ignores_trailing_whitespace<span class="Delimiter">()</span> <span class="Delimiter">{</span>
+  trace<span class="Delimiter">(</span><span class="Constant">&quot;test layer 1&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;foo</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span>
+  CHECK<span class="Delimiter">(</span>trace_count<span class="Delimiter">(</span><span class="Constant">&quot;test layer 1&quot;</span><span class="Delimiter">,</span> <span class="Constant">&quot;foo&quot;</span><span class="Delimiter">)</span> == <span class="Constant">1</span><span class="Delimiter">);</span>
+<span class="Delimiter">}</span>
+
 <span class="Comment">// pending: DUMP tests</span>
 <span class="Comment">// pending: readable_contents() adds newline if necessary.</span>
 <span class="Comment">// pending: raise also prints to stderr.</span>
diff --git a/html/011load.cc.html b/html/011load.cc.html
index 3259becc..83b4d64c 100644
--- a/html/011load.cc.html
+++ b/html/011load.cc.html
@@ -147,6 +147,8 @@ bool next_instruction<span class="Delimiter">(</span>istream&amp; in<span class=
     ++p<span class="Delimiter">;</span>  <span class="Comment">// skip &lt;-</span>
   <span class="Delimiter">}</span>
 
+  if <span class="Delimiter">(</span>p == words<span class="Delimiter">.</span>end<span class="Delimiter">())</span>
+    raise &lt;&lt; <span class="Constant">&quot;instruction prematurely ended with '&lt;-'</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span> &lt;&lt; die<span class="Delimiter">();</span>
   curr<span class="Delimiter">-&gt;</span>name = *p<span class="Delimiter">;</span>
   if <span class="Delimiter">(</span>Recipe_number<span class="Delimiter">.</span>find<span class="Delimiter">(</span>*p<span class="Delimiter">)</span> == Recipe_number<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span>
     Recipe_number[*p] = Next_recipe_number++<span class="Delimiter">;</span>
diff --git a/html/014types.cc.html b/html/014types.cc.html
deleted file mode 100644
index 596ac7dc..00000000
--- a/html/014types.cc.html
+++ /dev/null
@@ -1,134 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-<meta http-equiv="content-type" content="text/html; charset=UTF-8">
-<title>Mu - 014types.cc</title>
-<meta name="Generator" content="Vim/7.4">
-<meta name="plugin-version" content="vim7.4_v1">
-<meta name="syntax" content="cpp">
-<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
-<meta name="colorscheme" content="minimal">
-<style type="text/css">
-<!--
-pre { white-space: pre-wrap; font-family: monospace; color: #d0d0d0; background-color: #000000; }
-body { font-family: monospace; color: #d0d0d0; background-color: #000000; }
-* { font-size: 1.05em; }
-.cSpecial { color: #008000; }
-.Identifier { color: #008080; }
-.Constant { color: #00a0a0; }
-.Comment { color: #9090ff; }
-.Delimiter { color: #a04060; }
-.SalientComment { color: #00ffff; }
-.Comment { color: #9090ff; }
-.traceContains { color: #008000; }
--->
-</style>
-
-<script type='text/javascript'>
-<!--
-
--->
-</script>
-</head>
-<body>
-<pre id='vimCodeElement'>
-<span class="Comment">//: Textual form for types.</span>
-
-<span class="Delimiter">:(scenarios load)</span>
-<span class="Delimiter">:(scenario container)</span>
-container foo [
-  x:integer
-  y:integer
-]
-<span class="traceContains">+parse: reading container foo</span>
-<span class="traceContains">+parse:   element name: x</span>
-<span class="traceContains">+parse:   type: 1</span>
-<span class="traceContains">+parse:   element name: y</span>
-<span class="traceContains">+parse:   type: 1</span>
-
-<span class="Delimiter">:(before &quot;End Command Handlers&quot;)</span>
-else if <span class="Delimiter">(</span>command == <span class="Constant">&quot;container&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
-  insert_container<span class="Delimiter">(</span>command<span class="Delimiter">,</span> container<span class="Delimiter">,</span> in<span class="Delimiter">);</span>
-<span class="Delimiter">}</span>
-
-<span class="Delimiter">:(code)</span>
-void insert_container<span class="Delimiter">(</span>const string&amp; command<span class="Delimiter">,</span> kind_of_type kind<span class="Delimiter">,</span> istream&amp; in<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-  skip_whitespace<span class="Delimiter">(</span>in<span class="Delimiter">);</span>
-  string name = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span>
-  trace<span class="Delimiter">(</span><span class="Constant">&quot;parse&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;reading &quot;</span> &lt;&lt; command &lt;&lt; <span class="Constant">' '</span> &lt;&lt; name<span class="Delimiter">;</span>
-<span class="CommentedCode">//?   cout &lt;&lt; name &lt;&lt; '\n'; //? 1</span>
-  assert<span class="Delimiter">(</span>Type_number<span class="Delimiter">.</span>find<span class="Delimiter">(</span>name<span class="Delimiter">)</span> == Type_number<span class="Delimiter">.</span>end<span class="Delimiter">());</span>
-  Type_number[name] = Next_type_number++<span class="Delimiter">;</span>
-  skip_bracket<span class="Delimiter">(</span>in<span class="Delimiter">,</span> <span class="Constant">&quot;'container' must begin with '['&quot;</span><span class="Delimiter">);</span>
-  assert<span class="Delimiter">(</span>Type<span class="Delimiter">.</span>find<span class="Delimiter">(</span>Type_number[name]<span class="Delimiter">)</span> == Type<span class="Delimiter">.</span>end<span class="Delimiter">());</span>
-  type_info&amp; t = Type[Type_number[name]]<span class="Delimiter">;</span>
-  recently_added_types<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Type_number[name]<span class="Delimiter">);</span>
-  t<span class="Delimiter">.</span>name = name<span class="Delimiter">;</span>
-  t<span class="Delimiter">.</span>kind = kind<span class="Delimiter">;</span>
-  while <span class="Delimiter">(</span>!in<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Delimiter">{</span>
-    skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span>
-    string element = next_word<span class="Delimiter">(</span>in<span class="Delimiter">);</span>
-    if <span class="Delimiter">(</span>element == <span class="Constant">&quot;]&quot;</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span>
-    istringstream inner<span class="Delimiter">(</span>element<span class="Delimiter">);</span>
-    t<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>slurp_until<span class="Delimiter">(</span>inner<span class="Delimiter">,</span> <span class="Constant">':'</span><span class="Delimiter">));</span>
-    trace<span class="Delimiter">(</span><span class="Constant">&quot;parse&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;  element name: &quot;</span> &lt;&lt; t<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>back<span class="Delimiter">();</span>
-    vector&lt;type_number&gt; types<span class="Delimiter">;</span>
-    while <span class="Delimiter">(</span>!inner<span class="Delimiter">.</span>eof<span class="Delimiter">())</span> <span class="Delimiter">{</span>
-      string type_name = slurp_until<span class="Delimiter">(</span>inner<span class="Delimiter">,</span> <span class="Constant">':'</span><span class="Delimiter">);</span>
-      if <span class="Delimiter">(</span>Type_number<span class="Delimiter">.</span>find<span class="Delimiter">(</span>type_name<span class="Delimiter">)</span> == Type_number<span class="Delimiter">.</span>end<span class="Delimiter">())</span>
-        raise &lt;&lt; <span class="Constant">&quot;unknown type &quot;</span> &lt;&lt; type_name &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
-      types<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>Type_number[type_name]<span class="Delimiter">);</span>
-      trace<span class="Delimiter">(</span><span class="Constant">&quot;parse&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;  type: &quot;</span> &lt;&lt; types<span class="Delimiter">.</span>back<span class="Delimiter">();</span>
-    <span class="Delimiter">}</span>
-    t<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>types<span class="Delimiter">);</span>
-  <span class="Delimiter">}</span>
-  assert<span class="Delimiter">(</span>t<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>size<span class="Delimiter">()</span> == t<span class="Delimiter">.</span>element_names<span class="Delimiter">.</span>size<span class="Delimiter">());</span>
-  t<span class="Delimiter">.</span>size = t<span class="Delimiter">.</span>elements<span class="Delimiter">.</span>size<span class="Delimiter">();</span>
-<span class="Delimiter">}</span>
-
-<span class="SalientComment">//:: Similarly for exclusive_container.</span>
-
-<span class="Delimiter">:(scenario exclusive_container)</span>
-exclusive-container foo [
-  x:integer
-  y:integer
-]
-<span class="traceContains">+parse: reading exclusive-container foo</span>
-<span class="traceContains">+parse:   element name: x</span>
-<span class="traceContains">+parse:   type: 1</span>
-<span class="traceContains">+parse:   element name: y</span>
-<span class="traceContains">+parse:   type: 1</span>
-
-<span class="Delimiter">:(before &quot;End Command Handlers&quot;)</span>
-else if <span class="Delimiter">(</span>command == <span class="Constant">&quot;exclusive-container&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
-  insert_container<span class="Delimiter">(</span>command<span class="Delimiter">,</span> exclusive_container<span class="Delimiter">,</span> in<span class="Delimiter">);</span>
-<span class="Delimiter">}</span>
-
-<span class="SalientComment">//:: ensure types created in one scenario don't leak outside it.</span>
-<span class="Delimiter">:(before &quot;End Globals&quot;)</span>
-vector&lt;type_number&gt; recently_added_types<span class="Delimiter">;</span>
-<span class="Delimiter">:(before &quot;End Setup&quot;)</span>
-for <span class="Delimiter">(</span>index_t i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; recently_added_types<span class="Delimiter">.</span>size<span class="Delimiter">();</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-<span class="CommentedCode">//?   cout &lt;&lt; &quot;erasing &quot; &lt;&lt; Type[recently_added_types[i]].name &lt;&lt; '\n'; //? 1</span>
-  Type_number<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>Type[recently_added_types[i]]<span class="Delimiter">.</span>name<span class="Delimiter">);</span>
-  Type<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>recently_added_types[i]<span class="Delimiter">);</span>
-<span class="Delimiter">}</span>
-recently_added_types<span class="Delimiter">.</span>clear<span class="Delimiter">();</span>
-<span class="Comment">//: lastly, ensure scenarios are consistent by always starting them at the</span>
-<span class="Comment">//: same type number.</span>
-Next_type_number = <span class="Constant">1000</span><span class="Delimiter">;</span>
-<span class="Delimiter">:(before &quot;End Test Run Initialization&quot;)</span>
-assert<span class="Delimiter">(</span>Next_type_number &lt; <span class="Constant">1000</span><span class="Delimiter">);</span>
-<span class="Delimiter">:(before &quot;End Setup&quot;)</span>
-Next_type_number = <span class="Constant">1000</span><span class="Delimiter">;</span>
-
-<span class="Delimiter">:(code)</span>
-void skip_bracket<span class="Delimiter">(</span>istream&amp; in<span class="Delimiter">,</span> string message<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-  skip_whitespace_and_comments<span class="Delimiter">(</span>in<span class="Delimiter">);</span>
-  if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>get<span class="Delimiter">()</span> != <span class="Constant">'['</span><span class="Delimiter">)</span>
-    raise &lt;&lt; message &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
-<span class="Delimiter">}</span>
-</pre>
-</body>
-</html>
-<!-- vim: set foldmethod=manual : -->
diff --git a/html/030container.cc.html b/html/030container.cc.html
index 15a0c8ab..0cbe190a 100644
--- a/html/030container.cc.html
+++ b/html/030container.cc.html
@@ -344,6 +344,7 @@ container bar [
   x:number
 ]
 <span class="traceAbsent">-warn: unknown type: bar</span>
+$warn: <span class="Constant">0</span>
 
 <span class="Delimiter">:(after &quot;int main&quot;)</span>
   Transform<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>check_invalid_types<span class="Delimiter">);</span>
diff --git a/html/033length.cc.html b/html/033length.cc.html
deleted file mode 100644
index 033a29f2..00000000
--- a/html/033length.cc.html
+++ /dev/null
@@ -1,64 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-<meta http-equiv="content-type" content="text/html; charset=UTF-8">
-<title>Mu - 033length.cc</title>
-<meta name="Generator" content="Vim/7.4">
-<meta name="plugin-version" content="vim7.4_v1">
-<meta name="syntax" content="cpp">
-<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
-<meta name="colorscheme" content="minimal">
-<style type="text/css">
-<!--
-pre { white-space: pre-wrap; font-family: monospace; color: #d0d0d0; background-color: #000000; }
-body { font-family: monospace; color: #d0d0d0; background-color: #000000; }
-* { font-size: 1.05em; }
-.cSpecial { color: #008000; }
-.Constant { color: #00a0a0; }
-.Comment { color: #9090ff; }
-.Delimiter { color: #a04060; }
-.Special { color: #ff6060; }
-.Identifier { color: #008080; }
-.traceContains { color: #008000; }
--->
-</style>
-
-<script type='text/javascript'>
-<!--
-
--->
-</script>
-</head>
-<body>
-<pre id='vimCodeElement'>
-<span class="Comment">//: Recipe to compute the length of an array.</span>
-
-<span class="Delimiter">:(scenario array_length)</span>
-recipe main [
-  <span class="Constant">1</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">3</span>:literal  <span class="Comment"># length</span>
-  <span class="Constant">2</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">14</span>:literal
-  <span class="Constant">3</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">15</span>:literal
-  <span class="Constant">4</span>:number<span class="Special"> &lt;- </span>copy <span class="Constant">16</span>:literal
-  <span class="Constant">5</span>:number<span class="Special"> &lt;- </span>length <span class="Constant">1</span>:array:number
-]
-<span class="traceContains">+mem: storing 3 in location 5</span>
-
-<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
-LENGTH<span class="Delimiter">,</span>
-<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
-Recipe_number[<span class="Constant">&quot;length&quot;</span>] = LENGTH<span class="Delimiter">;</span>
-<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
-case LENGTH: <span class="Delimiter">{</span>
-  reagent x = canonize<span class="Delimiter">(</span>current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span>
-  if <span class="Delimiter">(</span>x<span class="Delimiter">.</span>types<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span> != Type_number[<span class="Constant">&quot;array&quot;</span>]<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    raise &lt;&lt; <span class="Constant">&quot;tried to calculate length of non-array &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
-    <span class="Identifier">break</span><span class="Delimiter">;</span>
-  <span class="Delimiter">}</span>
-  products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span>
-  products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>Memory[x<span class="Delimiter">.</span>value]<span class="Delimiter">);</span>
-  <span class="Identifier">break</span><span class="Delimiter">;</span>
-<span class="Delimiter">}</span>
-</pre>
-</body>
-</html>
-<!-- vim: set foldmethod=manual : -->
diff --git a/html/041name.cc.html b/html/041name.cc.html
index 36e19a86..f465a974 100644
--- a/html/041name.cc.html
+++ b/html/041name.cc.html
@@ -105,6 +105,8 @@ void transform_names<span class="Delimiter">(</span>const recipe_number r<span c
 void check_metadata<span class="Delimiter">(</span>map&lt;string<span class="Delimiter">,</span> vector&lt;type_number&gt; &gt;&amp; metadata<span class="Delimiter">,</span> const reagent&amp; x<span class="Delimiter">,</span> const recipe_number r<span class="Delimiter">)</span> <span class="Delimiter">{</span>
   if <span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span>
   if <span class="Delimiter">(</span>is_raw<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span>
+  <span class="Comment">// if you use raw locations you're probably doing something unsafe</span>
+  if <span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span>x<span class="Delimiter">.</span>name<span class="Delimiter">))</span> <span class="Identifier">return</span><span class="Delimiter">;</span>
   if <span class="Delimiter">(</span>metadata<span class="Delimiter">.</span>find<span class="Delimiter">(</span>x<span class="Delimiter">.</span>name<span class="Delimiter">)</span> == metadata<span class="Delimiter">.</span>end<span class="Delimiter">())</span>
     metadata[x<span class="Delimiter">.</span>name] = x<span class="Delimiter">.</span>types<span class="Delimiter">;</span>
   if <span class="Delimiter">(</span>metadata[x<span class="Delimiter">.</span>name] != x<span class="Delimiter">.</span>types<span class="Delimiter">)</span>
@@ -214,6 +216,7 @@ recipe main [
   x:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:number/<span class="Special">raw</span>
 ]
 <span class="traceAbsent">-warn: mixing variable names and numeric addresses in main</span>
+$warn: <span class="Constant">0</span>
 
 <span class="Delimiter">:(scenario convert_names_does_not_warn_when_mixing_names_and_literals)</span>
 <span class="Special">% Hide_warnings = true;</span>
@@ -221,13 +224,7 @@ recipe main [
   x:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:literal
 ]
 <span class="traceAbsent">-warn: mixing variable names and numeric addresses in main</span>
-
-<span class="Delimiter">:(scenario convert_names_does_not_warn_when_mixing_special_names_and_numeric_locations)</span>
-<span class="Special">% Hide_warnings = true;</span>
-recipe main [
-  screen:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:number
-]
-<span class="traceAbsent">-warn: mixing variable names and numeric addresses in main</span>
+$warn: <span class="Constant">0</span>
 
 <span class="Delimiter">:(scenario convert_names_warns_on_reusing_name_with_different_type)</span>
 <span class="Special">% Hide_warnings = true;</span>
@@ -259,12 +256,14 @@ if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation
   <span class="Comment">// at least 2 args, and second arg is offset</span>
   assert<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> &gt;= <span class="Constant">2</span><span class="Delimiter">);</span>
 <span class="CommentedCode">//?   cout &lt;&lt; inst.ingredients.at(1).to_string() &lt;&lt; '\n'; //? 1</span>
-  assert<span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)));</span>
-  if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name<span class="Delimiter">.</span>find_first_not_of<span class="Delimiter">(</span><span class="Constant">&quot;0123456789&quot;</span><span class="Delimiter">)</span> == string::npos<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span>
-  <span class="Comment">// since first non-address in base type must be a container, we don't have to canonize</span>
-  type_number base_type = skip_addresses<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>types<span class="Delimiter">);</span>
-  inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>set_value<span class="Delimiter">(</span>find_element_name<span class="Delimiter">(</span>base_type<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name<span class="Delimiter">));</span>
-  trace<span class="Delimiter">(</span><span class="Constant">&quot;name&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;element &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; of type &quot;</span> &lt;&lt; Type[base_type]<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot; is at offset &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>value<span class="Delimiter">;</span>
+  if <span class="Delimiter">(</span>!is_literal<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)))</span>
+    raise &lt;&lt; inst<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: expected literal; got &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="cSpecial">'\n'</span> &lt;&lt; die<span class="Delimiter">();</span>
+  if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name<span class="Delimiter">.</span>find_first_not_of<span class="Delimiter">(</span><span class="Constant">&quot;0123456789&quot;</span><span class="Delimiter">)</span> != string::npos<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    <span class="Comment">// since first non-address in base type must be a container, we don't have to canonize</span>
+    type_number base_type = skip_addresses<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>types<span class="Delimiter">);</span>
+    inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>set_value<span class="Delimiter">(</span>find_element_name<span class="Delimiter">(</span>base_type<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name<span class="Delimiter">));</span>
+    trace<span class="Delimiter">(</span><span class="Constant">&quot;name&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;element &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; of type &quot;</span> &lt;&lt; Type[base_type]<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot; is at offset &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>value<span class="Delimiter">;</span>
+  <span class="Delimiter">}</span>
 <span class="Delimiter">}</span>
 
 <span class="Comment">//: this test is actually illegal so can't call run</span>
@@ -296,11 +295,12 @@ if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>operation
   <span class="Comment">// at least 2 args, and second arg is offset</span>
   assert<span class="Delimiter">(</span>SIZE<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">)</span> &gt;= <span class="Constant">2</span><span class="Delimiter">);</span>
   assert<span class="Delimiter">(</span>is_literal<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)));</span>
-  if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name<span class="Delimiter">.</span>find_first_not_of<span class="Delimiter">(</span><span class="Constant">&quot;0123456789&quot;</span><span class="Delimiter">)</span> == string::npos<span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span>
-  <span class="Comment">// since first non-address in base type must be an exclusive container, we don't have to canonize</span>
-  type_number base_type = skip_addresses<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>types<span class="Delimiter">);</span>
-  inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>set_value<span class="Delimiter">(</span>find_element_name<span class="Delimiter">(</span>base_type<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name<span class="Delimiter">));</span>
-  trace<span class="Delimiter">(</span><span class="Constant">&quot;name&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;variant &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; of type &quot;</span> &lt;&lt; Type[base_type]<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot; has tag &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>value<span class="Delimiter">;</span>
+  if <span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name<span class="Delimiter">.</span>find_first_not_of<span class="Delimiter">(</span><span class="Constant">&quot;0123456789&quot;</span><span class="Delimiter">)</span> != string::npos<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+    <span class="Comment">// since first non-address in base type must be an exclusive container, we don't have to canonize</span>
+    type_number base_type = skip_addresses<span class="Delimiter">(</span>inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>types<span class="Delimiter">);</span>
+    inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>set_value<span class="Delimiter">(</span>find_element_name<span class="Delimiter">(</span>base_type<span class="Delimiter">,</span> inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name<span class="Delimiter">));</span>
+    trace<span class="Delimiter">(</span><span class="Constant">&quot;name&quot;</span><span class="Delimiter">)</span> &lt;&lt; <span class="Constant">&quot;variant &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; of type &quot;</span> &lt;&lt; Type[base_type]<span class="Delimiter">.</span>name &lt;&lt; <span class="Constant">&quot; has tag &quot;</span> &lt;&lt; inst<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>value<span class="Delimiter">;</span>
+  <span class="Delimiter">}</span>
 <span class="Delimiter">}</span>
 </pre>
 </body>
diff --git a/html/043space.cc.html b/html/043space.cc.html
index e0e8910d..f43b35a5 100644
--- a/html/043space.cc.html
+++ b/html/043space.cc.html
@@ -91,7 +91,8 @@ reagent absolutize<span class="Delimiter">(</span>reagent x<span class="Delimite
 <span class="CommentedCode">//?   cout &lt;&lt; is_raw(x) &lt;&lt; '\n'; //? 1</span>
   if <span class="Delimiter">(</span>is_raw<span class="Delimiter">(</span>x<span class="Delimiter">)</span> || is_dummy<span class="Delimiter">(</span>x<span class="Delimiter">))</span> <span class="Identifier">return</span> x<span class="Delimiter">;</span>
 <span class="CommentedCode">//?   cout &lt;&lt; &quot;not raw: &quot; &lt;&lt; x.to_string() &lt;&lt; '\n'; //? 1</span>
-  assert<span class="Delimiter">(</span>x<span class="Delimiter">.</span>initialized<span class="Delimiter">);</span>
+  if <span class="Delimiter">(</span>!x<span class="Delimiter">.</span>initialized<span class="Delimiter">)</span>
+    raise &lt;&lt; current_instruction<span class="Delimiter">().</span>to_string<span class="Delimiter">()</span> &lt;&lt; <span class="Constant">&quot;: reagent not initialized: &quot;</span> &lt;&lt; x<span class="Delimiter">.</span>to_string<span class="Delimiter">()</span> &lt;&lt; die<span class="Delimiter">();</span>
   reagent r = x<span class="Delimiter">;</span>
   r<span class="Delimiter">.</span>set_value<span class="Delimiter">(</span>address<span class="Delimiter">(</span>r<span class="Delimiter">.</span>value<span class="Delimiter">,</span> space_base<span class="Delimiter">(</span>r<span class="Delimiter">)));</span>
 <span class="CommentedCode">//?   cout &lt;&lt; &quot;after absolutize: &quot; &lt;&lt; r.value &lt;&lt; '\n'; //? 1</span>
diff --git a/html/050scenario.cc.html b/html/050scenario.cc.html
index 43054dff..d49f477e 100644
--- a/html/050scenario.cc.html
+++ b/html/050scenario.cc.html
@@ -168,16 +168,17 @@ const scenario* Current_scenario = <span class="Constant">NULL</span><span class
 void run_mu_scenario<span class="Delimiter">(</span>const scenario&amp; s<span class="Delimiter">)</span> <span class="Delimiter">{</span>
   Current_scenario = &amp;s<span class="Delimiter">;</span>
   bool not_already_inside_test = !Trace_stream<span class="Delimiter">;</span>
-<span class="CommentedCode">//?   cerr &lt;&lt; s.name &lt;&lt; '\n'; //? 4</span>
+<span class="CommentedCode">//?   cerr &lt;&lt; s.name &lt;&lt; '\n'; //? 6</span>
   if <span class="Delimiter">(</span>not_already_inside_test<span class="Delimiter">)</span> <span class="Delimiter">{</span>
     Trace_file = s<span class="Delimiter">.</span>name<span class="Delimiter">;</span>
     Trace_stream = new trace_stream<span class="Delimiter">;</span>
     setup<span class="Delimiter">();</span>
   <span class="Delimiter">}</span>
-<span class="CommentedCode">//?   cerr &lt;&lt; '^' &lt;&lt; s.to_run &lt;&lt; &quot;$\n&quot;; //? 4</span>
   assert<span class="Delimiter">(</span>Routines<span class="Delimiter">.</span>empty<span class="Delimiter">());</span>
-  run<span class="Delimiter">(</span><span class="Constant">&quot;recipe &quot;</span>+s<span class="Delimiter">.</span>name+<span class="Constant">&quot; [ &quot;</span> + s<span class="Delimiter">.</span>to_run + <span class="Constant">&quot; ]&quot;</span><span class="Delimiter">);</span>
-<span class="CommentedCode">//?   cerr &lt;&lt; s.name &lt;&lt; &quot; done\n&quot;; //? 1</span>
+  vector&lt;recipe_number&gt; tmp = load<span class="Delimiter">(</span><span class="Constant">&quot;recipe &quot;</span>+s<span class="Delimiter">.</span>name+<span class="Constant">&quot; [ &quot;</span>+s<span class="Delimiter">.</span>to_run+<span class="Constant">&quot; ]&quot;</span><span class="Delimiter">);</span>
+  bind_special_scenario_names<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span>
+  transform_all<span class="Delimiter">();</span>
+  run<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>front<span class="Delimiter">());</span>
   if <span class="Delimiter">(</span>not_already_inside_test &amp;&amp; Trace_stream<span class="Delimiter">)</span> <span class="Delimiter">{</span>
     teardown<span class="Delimiter">();</span>
     ofstream fout<span class="Delimiter">((</span>Trace_dir+Trace_file<span class="Delimiter">).</span>c_str<span class="Delimiter">());</span>
@@ -216,14 +217,21 @@ case RUN: <span class="Delimiter">{</span>
   tmp &lt;&lt; <span class="Constant">&quot;recipe run&quot;</span> &lt;&lt; Next_recipe_number &lt;&lt; <span class="Constant">&quot; [ &quot;</span> &lt;&lt; current_instruction<span class="Delimiter">().</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>name &lt;&lt; <span class="Constant">&quot; ]&quot;</span><span class="Delimiter">;</span>
 <span class="CommentedCode">//?   Show_rest_of_stream = true; //? 1</span>
   vector&lt;recipe_number&gt; tmp_recipe = load<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>str<span class="Delimiter">());</span>
-  <span class="Comment">// Predefined Scenario Locals In Run.</span>
-  <span class="Comment">// End Predefined Scenario Locals In Run.</span>
+  bind_special_scenario_names<span class="Delimiter">(</span>tmp_recipe<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span>
   transform_all<span class="Delimiter">();</span>
 <span class="CommentedCode">//?   cout &lt;&lt; tmp_recipe.at(0) &lt;&lt; ' ' &lt;&lt; Recipe_number[&quot;main&quot;] &lt;&lt; '\n'; //? 1</span>
   Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>push_front<span class="Delimiter">(</span>call<span class="Delimiter">(</span>tmp_recipe<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)));</span>
   <span class="Identifier">continue</span><span class="Delimiter">;</span>  <span class="Comment">// not done with caller; don't increment current_step_index()</span>
 <span class="Delimiter">}</span>
 
+<span class="Comment">// Some variables for fake resources always get special addresses in</span>
+<span class="Comment">// scenarios.</span>
+<span class="Delimiter">:(code)</span>
+void bind_special_scenario_names<span class="Delimiter">(</span>recipe_number r<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+  <span class="Comment">// Special Scenario Variable Names(r)</span>
+  <span class="Comment">// End Special Scenario Variable Names(r)</span>
+<span class="Delimiter">}</span>
+
 <span class="Delimiter">:(scenario run_multiple)</span>
 recipe main [
   run [
@@ -486,6 +494,7 @@ recipe main [
   ]
 ]
 <span class="traceAbsent">-warn: missing [b] in trace layer a</span>
+$warn: <span class="Constant">0</span>
 
 <span class="Comment">//: 'trace-should-not-contain' is like the '-' lines in our scenarios so far</span>
 <span class="Comment">//: Each trace line is separately checked for absense. Order is *not*</span>
@@ -538,6 +547,7 @@ recipe main [
   ]
 ]
 <span class="traceAbsent">-warn: unexpected [b] in trace layer a</span>
+$warn: <span class="Constant">0</span>
 
 <span class="Delimiter">:(scenario trace_negative_check_warns_on_any_unexpected_line)</span>
 <span class="Special">% Hide_warnings = true;</span>
diff --git a/html/070display.cc.html b/html/070display.cc.html
index 4dee20e2..3d6669ff 100644
--- a/html/070display.cc.html
+++ b/html/070display.cc.html
@@ -41,6 +41,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 
 <span class="Delimiter">:(before &quot;End Globals&quot;)</span>
 long long int Display_row = <span class="Constant">0</span><span class="Delimiter">,</span> Display_column = <span class="Constant">0</span><span class="Delimiter">;</span>
+bool Autodisplay = <span class="Constant">true</span><span class="Delimiter">;</span>
 
 <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
 OPEN_CONSOLE<span class="Delimiter">,</span>
@@ -90,7 +91,7 @@ case CLEAR_LINE_ON_DISPLAY: <span class="Delimiter">{</span>
     tb_change_cell<span class="Delimiter">(</span>x<span class="Delimiter">,</span> Display_row<span class="Delimiter">,</span> <span class="Constant">' '</span><span class="Delimiter">,</span> TB_WHITE<span class="Delimiter">,</span> TB_BLACK<span class="Delimiter">);</span>
   <span class="Delimiter">}</span>
   tb_set_cursor<span class="Delimiter">(</span>Display_column<span class="Delimiter">,</span> Display_row<span class="Delimiter">);</span>
-  tb_present<span class="Delimiter">();</span>
+  if <span class="Delimiter">(</span>Autodisplay<span class="Delimiter">)</span> tb_present<span class="Delimiter">();</span>
   <span class="Identifier">break</span><span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
 
@@ -113,7 +114,7 @@ case PRINT_CHARACTER_TO_DISPLAY: <span class="Delimiter">{</span>
       Display_column = <span class="Constant">0</span><span class="Delimiter">;</span>
       ++Display_row<span class="Delimiter">;</span>
       tb_set_cursor<span class="Delimiter">(</span>Display_column<span class="Delimiter">,</span> Display_row<span class="Delimiter">);</span>
-      tb_present<span class="Delimiter">();</span>
+      if <span class="Delimiter">(</span>Autodisplay<span class="Delimiter">)</span> tb_present<span class="Delimiter">();</span>
     <span class="Delimiter">}</span>
     <span class="Identifier">break</span><span class="Delimiter">;</span>
   <span class="Delimiter">}</span>
@@ -122,7 +123,7 @@ case PRINT_CHARACTER_TO_DISPLAY: <span class="Delimiter">{</span>
       tb_change_cell<span class="Delimiter">(</span>Display_column-<span class="Constant">1</span><span class="Delimiter">,</span> Display_row<span class="Delimiter">,</span> <span class="Constant">' '</span><span class="Delimiter">,</span> TB_WHITE<span class="Delimiter">,</span> TB_BLACK<span class="Delimiter">);</span>
       --Display_column<span class="Delimiter">;</span>
       tb_set_cursor<span class="Delimiter">(</span>Display_column<span class="Delimiter">,</span> Display_row<span class="Delimiter">);</span>
-      tb_present<span class="Delimiter">();</span>
+      if <span class="Delimiter">(</span>Autodisplay<span class="Delimiter">)</span> tb_present<span class="Delimiter">();</span>
     <span class="Delimiter">}</span>
     <span class="Identifier">break</span><span class="Delimiter">;</span>
   <span class="Delimiter">}</span>
@@ -139,7 +140,7 @@ case PRINT_CHARACTER_TO_DISPLAY: <span class="Delimiter">{</span>
     ++Display_column<span class="Delimiter">;</span>
     tb_set_cursor<span class="Delimiter">(</span>Display_column<span class="Delimiter">,</span> Display_row<span class="Delimiter">);</span>
   <span class="Delimiter">}</span>
-  tb_present<span class="Delimiter">();</span>
+  if <span class="Delimiter">(</span>Autodisplay<span class="Delimiter">)</span> tb_present<span class="Delimiter">();</span>
   <span class="Identifier">break</span><span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
 
@@ -166,7 +167,7 @@ case MOVE_CURSOR_ON_DISPLAY: <span class="Delimiter">{</span>
   assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)));</span>
   Display_column = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
   tb_set_cursor<span class="Delimiter">(</span>Display_column<span class="Delimiter">,</span> Display_row<span class="Delimiter">);</span>
-  tb_present<span class="Delimiter">();</span>
+  if <span class="Delimiter">(</span>Autodisplay<span class="Delimiter">)</span> tb_present<span class="Delimiter">();</span>
   <span class="Identifier">break</span><span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
 
@@ -181,7 +182,7 @@ case MOVE_CURSOR_DOWN_ON_DISPLAY: <span class="Delimiter">{</span>
   if <span class="Delimiter">(</span>Display_row &lt; height-<span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
     Display_row++<span class="Delimiter">;</span>
     tb_set_cursor<span class="Delimiter">(</span>Display_column<span class="Delimiter">,</span> Display_row<span class="Delimiter">);</span>
-    tb_present<span class="Delimiter">();</span>
+    if <span class="Delimiter">(</span>Autodisplay<span class="Delimiter">)</span> tb_present<span class="Delimiter">();</span>
   <span class="Delimiter">}</span>
   <span class="Identifier">break</span><span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
@@ -195,7 +196,7 @@ case MOVE_CURSOR_UP_ON_DISPLAY: <span class="Delimiter">{</span>
   if <span class="Delimiter">(</span>Display_row &gt; <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
     Display_row--<span class="Delimiter">;</span>
     tb_set_cursor<span class="Delimiter">(</span>Display_column<span class="Delimiter">,</span> Display_row<span class="Delimiter">);</span>
-    tb_present<span class="Delimiter">();</span>
+    if <span class="Delimiter">(</span>Autodisplay<span class="Delimiter">)</span> tb_present<span class="Delimiter">();</span>
   <span class="Delimiter">}</span>
   <span class="Identifier">break</span><span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
@@ -211,7 +212,7 @@ case MOVE_CURSOR_RIGHT_ON_DISPLAY: <span class="Delimiter">{</span>
   if <span class="Delimiter">(</span>Display_column &lt; width-<span class="Constant">1</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
     Display_column++<span class="Delimiter">;</span>
     tb_set_cursor<span class="Delimiter">(</span>Display_column<span class="Delimiter">,</span> Display_row<span class="Delimiter">);</span>
-    tb_present<span class="Delimiter">();</span>
+    if <span class="Delimiter">(</span>Autodisplay<span class="Delimiter">)</span> tb_present<span class="Delimiter">();</span>
   <span class="Delimiter">}</span>
   <span class="Identifier">break</span><span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
@@ -225,7 +226,7 @@ case MOVE_CURSOR_LEFT_ON_DISPLAY: <span class="Delimiter">{</span>
   if <span class="Delimiter">(</span>Display_column &gt; <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
     Display_column--<span class="Delimiter">;</span>
     tb_set_cursor<span class="Delimiter">(</span>Display_column<span class="Delimiter">,</span> Display_row<span class="Delimiter">);</span>
-    tb_present<span class="Delimiter">();</span>
+    if <span class="Delimiter">(</span>Autodisplay<span class="Delimiter">)</span> tb_present<span class="Delimiter">();</span>
   <span class="Delimiter">}</span>
   <span class="Identifier">break</span><span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
@@ -252,6 +253,47 @@ case DISPLAY_HEIGHT: <span class="Delimiter">{</span>
   <span class="Identifier">break</span><span class="Delimiter">;</span>
 <span class="Delimiter">}</span>
 
+<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
+HIDE_CURSOR_ON_DISPLAY<span class="Delimiter">,</span>
+<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
+Recipe_number[<span class="Constant">&quot;hide-cursor-on-display&quot;</span>] = HIDE_CURSOR_ON_DISPLAY<span class="Delimiter">;</span>
+<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
+case HIDE_CURSOR_ON_DISPLAY: <span class="Delimiter">{</span>
+  tb_set_cursor<span class="Delimiter">(</span>TB_HIDE_CURSOR<span class="Delimiter">,</span> TB_HIDE_CURSOR<span class="Delimiter">);</span>
+  <span class="Identifier">break</span><span class="Delimiter">;</span>
+<span class="Delimiter">}</span>
+
+<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
+SHOW_CURSOR_ON_DISPLAY<span class="Delimiter">,</span>
+<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
+Recipe_number[<span class="Constant">&quot;show-cursor-on-display&quot;</span>] = SHOW_CURSOR_ON_DISPLAY<span class="Delimiter">;</span>
+<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
+case SHOW_CURSOR_ON_DISPLAY: <span class="Delimiter">{</span>
+  tb_set_cursor<span class="Delimiter">(</span>Display_row<span class="Delimiter">,</span> Display_column<span class="Delimiter">);</span>
+  <span class="Identifier">break</span><span class="Delimiter">;</span>
+<span class="Delimiter">}</span>
+
+<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
+HIDE_DISPLAY<span class="Delimiter">,</span>
+<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
+Recipe_number[<span class="Constant">&quot;hide-display&quot;</span>] = HIDE_DISPLAY<span class="Delimiter">;</span>
+<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
+case HIDE_DISPLAY: <span class="Delimiter">{</span>
+  Autodisplay = <span class="Constant">false</span><span class="Delimiter">;</span>
+  <span class="Identifier">break</span><span class="Delimiter">;</span>
+<span class="Delimiter">}</span>
+
+<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
+SHOW_DISPLAY<span class="Delimiter">,</span>
+<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
+Recipe_number[<span class="Constant">&quot;show-display&quot;</span>] = SHOW_DISPLAY<span class="Delimiter">;</span>
+<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
+case SHOW_DISPLAY: <span class="Delimiter">{</span>
+  Autodisplay = <span class="Constant">true</span><span class="Delimiter">;</span>
+  tb_present<span class="Delimiter">();</span>
+  <span class="Identifier">break</span><span class="Delimiter">;</span>
+<span class="Delimiter">}</span>
+
 <span class="SalientComment">//:: Keyboard/mouse management</span>
 
 <span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
@@ -304,7 +346,9 @@ case CHECK_FOR_INTERACTION: <span class="Delimiter">{</span>
     <span class="Identifier">break</span><span class="Delimiter">;</span>
   <span class="Delimiter">}</span>
   if <span class="Delimiter">(</span>event_type == TB_EVENT_MOUSE<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">mouse event</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">);</span>
+<span class="CommentedCode">//?     tb_shutdown(); //? 1</span>
+<span class="CommentedCode">//?     cerr &lt;&lt; &quot;AAA\n&quot;; //? 1</span>
+    products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">touch event</span><span class="Comment">*/</span><span class="Constant">2</span><span class="Delimiter">);</span>
     products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>event<span class="Delimiter">.</span>key<span class="Delimiter">);</span>  <span class="Comment">// which button, etc.</span>
     products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>event<span class="Delimiter">.</span>y<span class="Delimiter">);</span>  <span class="Comment">// row</span>
     products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>event<span class="Delimiter">.</span>x<span class="Delimiter">);</span>  <span class="Comment">// column</span>
diff --git a/html/071print.mu.html b/html/071print.mu.html
index 033d0d4f..7fe33765 100644
--- a/html/071print.mu.html
+++ b/html/071print.mu.html
@@ -55,6 +55,8 @@ container screen-cell [
   width:address:number/deref<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   height:address:number<span class="Special"> &lt;- </span>get-address result:address:screen/deref, num-rows:offset
   height:address:number/deref<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+<span class="CommentedCode">#?   $print height:address:number/deref, [ </span>
+<span class="CommentedCode">#? ] #? 1</span>
   row:address:number<span class="Special"> &lt;- </span>get-address result:address:screen/deref, cursor-row:offset
   row:address:number/deref<span class="Special"> &lt;- </span>copy <span class="Constant">0:literal</span>
   column:address:number<span class="Special"> &lt;- </span>get-address result:address:screen/deref, cursor-column:offset
@@ -567,6 +569,58 @@ container screen-cell [
   <span class="muControl">reply</span> height:number
 ]
 
+<span class="muRecipe">recipe</span> hide-cursor [
+  <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new location:type, <span class="Constant">30:literal</span>
+  x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Comment"># if x exists (not real display), do nothing</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> x:address:screen
+    <span class="muControl">reply</span> x:address:screen
+  <span class="Delimiter">}</span>
+  <span class="Comment"># otherwise, real screen</span>
+  hide-cursor-on-display
+  <span class="muControl">reply</span> x:address:screen
+]
+
+<span class="muRecipe">recipe</span> show-cursor [
+  <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new location:type, <span class="Constant">30:literal</span>
+  x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Comment"># if x exists (not real display), do nothing</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> x:address:screen
+    <span class="muControl">reply</span> x:address:screen
+  <span class="Delimiter">}</span>
+  <span class="Comment"># otherwise, real screen</span>
+  show-cursor-on-display
+  <span class="muControl">reply</span> x:address:screen
+]
+
+<span class="muRecipe">recipe</span> hide-screen [
+  <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new location:type, <span class="Constant">30:literal</span>
+  x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Comment"># if x exists (not real display), do nothing</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> x:address:screen
+    <span class="muControl">reply</span> x:address:screen
+  <span class="Delimiter">}</span>
+  <span class="Comment"># otherwise, real screen</span>
+  hide-display
+  <span class="muControl">reply</span> x:address:screen
+]
+
+<span class="muRecipe">recipe</span> show-screen [
+  <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new location:type, <span class="Constant">30:literal</span>
+  x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Comment"># if x exists (not real display), do nothing</span>
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> x:address:screen
+    <span class="muControl">reply</span> x:address:screen
+  <span class="Delimiter">}</span>
+  <span class="Comment"># otherwise, real screen</span>
+  show-display
+  <span class="muControl">reply</span> x:address:screen
+]
+
 <span class="muRecipe">recipe</span> print-string [
   <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new location:type, <span class="Constant">30:literal</span>
   x:address:screen<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
diff --git a/html/072scenario_screen.cc.html b/html/072scenario_screen.cc.html
index e436cfe6..f5210f0b 100644
--- a/html/072scenario_screen.cc.html
+++ b/html/072scenario_screen.cc.html
@@ -16,6 +16,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 .traceContains { color: #008000; }
 .cSpecial { color: #008000; }
 .Constant { color: #00a0a0; }
+.traceAbsent { color: #c00000; }
 .Comment { color: #9090ff; }
 .Delimiter { color: #a04060; }
 .Special { color: #ff6060; }
@@ -141,6 +142,16 @@ scenario screen-in-scenario-color [
 <span class="Delimiter">:(before &quot;End is_special_name Cases&quot;)</span>
 if <span class="Delimiter">(</span>s == <span class="Constant">&quot;screen&quot;</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span>
 
+<span class="Delimiter">:(scenarios run)</span>
+<span class="Delimiter">:(scenario convert_names_does_not_warn_when_mixing_special_names_and_numeric_locations)</span>
+<span class="Special">% Hide_warnings = true;</span>
+recipe main [
+  screen:number<span class="Special"> &lt;- </span>copy <span class="Constant">1</span>:number
+]
+<span class="traceAbsent">-warn: mixing variable names and numeric addresses in main</span>
+$warn: <span class="Constant">0</span>
+<span class="Delimiter">:(scenarios run_mu_scenario)</span>
+
 <span class="Delimiter">:(before &quot;End Globals&quot;)</span>
 <span class="Comment">// Scenarios may not define default-space, so they should fit within the</span>
 <span class="Comment">// initial area of memory reserved for tests. We'll put the predefined</span>
@@ -159,8 +170,8 @@ assert<span class="Delimiter">(</span>Name[tmp_recipe<span class="Delimiter">.</
 <span class="Comment">// Scenario Globals.</span>
 const long long int SCREEN = Next_predefined_global_for_scenarios++<span class="Delimiter">;</span>
 <span class="Comment">// End Scenario Globals.</span>
-<span class="Delimiter">:(before &quot;End Predefined Scenario Locals In Run&quot;)</span>
-Name[tmp_recipe<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span>][<span class="Constant">&quot;screen&quot;</span>] = SCREEN<span class="Delimiter">;</span>
+<span class="Delimiter">:(before &quot;End Special Scenario Variable Names(r)&quot;)</span>
+Name[r][<span class="Constant">&quot;screen&quot;</span>] = SCREEN<span class="Delimiter">;</span>
 
 <span class="Delimiter">:(before &quot;End Rewrite Instruction(curr)&quot;)</span>
 <span class="Comment">// rewrite `assume-screen width, height` to</span>
@@ -231,7 +242,9 @@ void check_screen<span class="Delimiter">(</span>const string&amp; expected_cont
   raw_string_stream cursor<span class="Delimiter">(</span>expected_contents<span class="Delimiter">);</span>
   <span class="Comment">// todo: too-long expected_contents should fail</span>
   long long int addr = screen_data_start+<span class="Constant">1</span><span class="Delimiter">;</span>  <span class="Comment">// skip length</span>
+<span class="CommentedCode">//?   cerr &lt;&lt; &quot;screen height &quot; &lt;&lt; screen_height &lt;&lt; '\n'; //? 1</span>
   for <span class="Delimiter">(</span>long long int row = <span class="Constant">0</span><span class="Delimiter">;</span> row &lt; screen_height<span class="Delimiter">;</span> ++row<span class="Delimiter">)</span> <span class="Delimiter">{</span>
+<span class="CommentedCode">//?     cerr &lt;&lt; &quot;row: &quot; &lt;&lt; row &lt;&lt; '\n'; //? 1</span>
     cursor<span class="Delimiter">.</span>skip_whitespace_and_comments<span class="Delimiter">();</span>
     if <span class="Delimiter">(</span>cursor<span class="Delimiter">.</span>at_end<span class="Delimiter">())</span> <span class="Identifier">break</span><span class="Delimiter">;</span>
     assert<span class="Delimiter">(</span>cursor<span class="Delimiter">.</span>get<span class="Delimiter">()</span> == <span class="Constant">'.'</span><span class="Delimiter">);</span>
@@ -299,6 +312,8 @@ void check_screen<span class="Delimiter">(</span>const string&amp; expected_cont
 raw_string_stream::raw_string_stream<span class="Delimiter">(</span>const string&amp; backing<span class="Delimiter">)</span> :index<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">),</span> max<span class="Delimiter">(</span>backing<span class="Delimiter">.</span>size<span class="Delimiter">()),</span> buf<span class="Delimiter">(</span>backing<span class="Delimiter">.</span>c_str<span class="Delimiter">())</span> <span class="Delimiter">{}</span>
 
 bool raw_string_stream::at_end<span class="Delimiter">()</span> const <span class="Delimiter">{</span>
+<span class="CommentedCode">//?   cerr &lt;&lt; index &lt;&lt; ' ' &lt;&lt; max &lt;&lt; '\n'; //? 1</span>
+<span class="CommentedCode">//?   cerr &lt;&lt; buf &lt;&lt; &quot;$\n&quot;; //? 1</span>
   if <span class="Delimiter">(</span>index &gt;= max<span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span>
   if <span class="Delimiter">(</span>tb_utf8_char_length<span class="Delimiter">(</span>buf[index]<span class="Delimiter">)</span> &gt; max-index<span class="Delimiter">)</span> <span class="Delimiter">{</span>
     raise &lt;&lt; <span class="Constant">&quot;unicode string seems corrupted at index &quot;</span>&lt;&lt; index &lt;&lt; <span class="Constant">&quot; character &quot;</span> &lt;&lt; static_cast&lt;int&gt;<span class="Delimiter">(</span>buf[index]<span class="Delimiter">)</span> &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
@@ -363,6 +378,7 @@ void dump_screen<span class="Delimiter">()</span> <span class="Delimiter">{</spa
   long long int curr = screen_data_start+<span class="Constant">1</span><span class="Delimiter">;</span>  <span class="Comment">// skip length</span>
   for <span class="Delimiter">(</span>long long int row = <span class="Constant">0</span><span class="Delimiter">;</span> row &lt; screen_height<span class="Delimiter">;</span> ++row<span class="Delimiter">)</span> <span class="Delimiter">{</span>
 <span class="CommentedCode">//?     cerr &lt;&lt; curr &lt;&lt; &quot;:\n&quot;; //? 2</span>
+    cerr &lt;&lt; <span class="Constant">'.'</span><span class="Delimiter">;</span>
     for <span class="Delimiter">(</span>long long int col = <span class="Constant">0</span><span class="Delimiter">;</span> col &lt; screen_width<span class="Delimiter">;</span> ++col<span class="Delimiter">)</span> <span class="Delimiter">{</span>
       if <span class="Delimiter">(</span>Memory[curr]<span class="Delimiter">)</span>
         cerr &lt;&lt; to_unicode<span class="Delimiter">(</span>Memory[curr]<span class="Delimiter">);</span>
@@ -370,7 +386,7 @@ void dump_screen<span class="Delimiter">()</span> <span class="Delimiter">{</spa
         cerr &lt;&lt; <span class="Constant">' '</span><span class="Delimiter">;</span>
       curr += <span class="Comment">/*</span><span class="Comment">size of screen-cell</span><span class="Comment">*/</span><span class="Constant">2</span><span class="Delimiter">;</span>
     <span class="Delimiter">}</span>
-    cerr &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
+    cerr &lt;&lt; <span class="Constant">&quot;.</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span>
   <span class="Delimiter">}</span>
 <span class="Delimiter">}</span>
 </pre>
diff --git a/html/074keyboard.mu.html b/html/074console.mu.html
index a34bc859..651fa9a6 100644
--- a/html/074keyboard.mu.html
+++ b/html/074console.mu.html
@@ -2,7 +2,7 @@
 <html>
 <head>
 <meta http-equiv="content-type" content="text/html; charset=UTF-8">
-<title>Mu - 074keyboard.mu</title>
+<title>Mu - 074console.mu</title>
 <meta name="Generator" content="Vim/7.4">
 <meta name="plugin-version" content="vim7.4_v1">
 <meta name="syntax" content="none">
diff --git a/html/075scenario_console.cc.html b/html/075scenario_console.cc.html
index c131ed57..fe3b2adc 100644
--- a/html/075scenario_console.cc.html
+++ b/html/075scenario_console.cc.html
@@ -64,8 +64,8 @@ scenario keyboard-in-scenario [
 
 <span class="Delimiter">:(before &quot;End Scenario Globals&quot;)</span>
 const long long int CONSOLE = Next_predefined_global_for_scenarios++<span class="Delimiter">;</span>
-<span class="Delimiter">:(before &quot;End Predefined Scenario Locals In Run&quot;)</span>
-Name[tmp_recipe<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span>][<span class="Constant">&quot;console&quot;</span>] = CONSOLE<span class="Delimiter">;</span>
+<span class="Delimiter">:(before &quot;End Special Scenario Variable Names(r)&quot;)</span>
+Name[r][<span class="Constant">&quot;console&quot;</span>] = CONSOLE<span class="Delimiter">;</span>
 
 <span class="Comment">//: allow naming just for 'console'</span>
 <span class="Delimiter">:(before &quot;End is_special_name Cases&quot;)</span>
diff --git a/html/075scenario_keyboard.cc.html b/html/075scenario_keyboard.cc.html
deleted file mode 100644
index 7657b451..00000000
--- a/html/075scenario_keyboard.cc.html
+++ /dev/null
@@ -1,119 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-<meta http-equiv="content-type" content="text/html; charset=UTF-8">
-<title>Mu - 075scenario_keyboard.cc</title>
-<meta name="Generator" content="Vim/7.4">
-<meta name="plugin-version" content="vim7.4_v1">
-<meta name="syntax" content="cpp">
-<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
-<meta name="colorscheme" content="minimal">
-<style type="text/css">
-<!--
-pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
-body { font-family: monospace; color: #eeeeee; background-color: #080808; }
-* { font-size: 1.05em; }
-.Constant { color: #00a0a0; }
-.Comment { color: #9090ff; }
-.Delimiter { color: #a04060; }
-.Special { color: #ff6060; }
-.Identifier { color: #804000; }
-.Comment { color: #9090ff; }
--->
-</style>
-
-<script type='text/javascript'>
-<!--
-
--->
-</script>
-</head>
-<body>
-<pre id='vimCodeElement'>
-<span class="Comment">//: Clean syntax to manipulate and check the keyboard in scenarios.</span>
-<span class="Comment">//: Instruction 'assume-keyboard' implicitly creates a variable called</span>
-<span class="Comment">//: 'keyboard' that is accessible inside other 'run' instructions in the</span>
-<span class="Comment">//: scenario. Like with the fake screen, 'assume-keyboard' transparently</span>
-<span class="Comment">//: supports unicode.</span>
-
-<span class="Delimiter">:(scenarios run_mu_scenario)</span>
-<span class="Delimiter">:(scenario keyboard_in_scenario)</span>
-scenario keyboard-in-scenario [
-  assume-keyboard [abc]
-  run [
-    <span class="Constant">1</span>:character<span class="Delimiter">,</span> <span class="Constant">2</span>:boolean<span class="Delimiter">,</span> keyboard:address<span class="Special"> &lt;- </span>read-key keyboard:address
-    <span class="Constant">3</span>:character<span class="Delimiter">,</span> <span class="Constant">4</span>:boolean<span class="Delimiter">,</span> keyboard:address<span class="Special"> &lt;- </span>read-key keyboard:address
-    <span class="Constant">5</span>:character<span class="Delimiter">,</span> <span class="Constant">6</span>:boolean<span class="Delimiter">,</span> keyboard:address<span class="Special"> &lt;- </span>read-key keyboard:address
-    <span class="Constant">7</span>:character<span class="Delimiter">,</span> <span class="Constant">8</span>:boolean<span class="Delimiter">,</span> keyboard:address<span class="Special"> &lt;- </span>read-key keyboard:address
-  ]
-  memory-should-contain [
-    <span class="Constant">1</span><span class="Special"> &lt;- </span><span class="Constant">97</span>  <span class="Comment"># 'a'</span>
-    <span class="Constant">2</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
-    <span class="Constant">3</span><span class="Special"> &lt;- </span><span class="Constant">98</span>  <span class="Comment"># 'b'</span>
-    <span class="Constant">4</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
-    <span class="Constant">5</span><span class="Special"> &lt;- </span><span class="Constant">99</span>  <span class="Comment"># 'c'</span>
-    <span class="Constant">6</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
-    <span class="Constant">7</span><span class="Special"> &lt;- </span><span class="Constant">0</span>  <span class="Comment"># eof</span>
-    <span class="Constant">8</span><span class="Special"> &lt;- </span><span class="Constant">1</span>
-  ]
-]
-
-<span class="Delimiter">:(before &quot;End Scenario Globals&quot;)</span>
-const long long int KEYBOARD = Next_predefined_global_for_scenarios++<span class="Delimiter">;</span>
-<span class="Delimiter">:(before &quot;End Predefined Scenario Locals In Run&quot;)</span>
-Name[tmp_recipe<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)</span>][<span class="Constant">&quot;keyboard&quot;</span>] = KEYBOARD<span class="Delimiter">;</span>
-
-<span class="Comment">//: allow naming just for 'keyword'</span>
-<span class="Delimiter">:(before &quot;End is_special_name Cases&quot;)</span>
-if <span class="Delimiter">(</span>s == <span class="Constant">&quot;keyboard&quot;</span><span class="Delimiter">)</span> <span class="Identifier">return</span> <span class="Constant">true</span><span class="Delimiter">;</span>
-
-<span class="Delimiter">:(before &quot;End Rewrite Instruction(curr)&quot;)</span>
-<span class="Comment">// rewrite `assume-keyboard string` to</span>
-<span class="Comment">//   ```</span>
-<span class="Comment">//   keyboard:address &lt;- new string  # hacky reuse of location</span>
-<span class="Comment">//   keyboard:address &lt;- init-fake-keyboard keyboard:address</span>
-<span class="Comment">//   ```</span>
-if <span class="Delimiter">(</span>curr<span class="Delimiter">.</span>name == <span class="Constant">&quot;assume-keyboard&quot;</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
-  <span class="Comment">// insert first instruction</span>
-  curr<span class="Delimiter">.</span>operation = Recipe_number[<span class="Constant">&quot;new&quot;</span>]<span class="Delimiter">;</span>
-  assert<span class="Delimiter">(</span>curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">());</span>
-  curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">&quot;keyboard:address&quot;</span><span class="Delimiter">));</span>
-  curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>set_value<span class="Delimiter">(</span>KEYBOARD<span class="Delimiter">);</span>
-  result<span class="Delimiter">.</span>steps<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>curr<span class="Delimiter">);</span>  <span class="Comment">// hacky that &quot;Rewrite Instruction&quot; is converting to multiple instructions</span>
-  <span class="Comment">// leave second instruction in curr</span>
-  curr<span class="Delimiter">.</span>clear<span class="Delimiter">();</span>
-  curr<span class="Delimiter">.</span>operation = Recipe_number[<span class="Constant">&quot;init-fake-keyboard&quot;</span>]<span class="Delimiter">;</span>
-  curr<span class="Delimiter">.</span>name = <span class="Constant">&quot;init-fake-keyboard&quot;</span><span class="Delimiter">;</span>
-  assert<span class="Delimiter">(</span>curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>empty<span class="Delimiter">());</span>
-  curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">&quot;keyboard:address&quot;</span><span class="Delimiter">));</span>
-  curr<span class="Delimiter">.</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>set_value<span class="Delimiter">(</span>KEYBOARD<span class="Delimiter">);</span>
-  assert<span class="Delimiter">(</span>curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>empty<span class="Delimiter">());</span>
-  curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>push_back<span class="Delimiter">(</span>reagent<span class="Delimiter">(</span><span class="Constant">&quot;keyboard:address&quot;</span><span class="Delimiter">));</span>
-  curr<span class="Delimiter">.</span>products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>set_value<span class="Delimiter">(</span>KEYBOARD<span class="Delimiter">);</span>
-<span class="Delimiter">}</span>
-
-<span class="Comment">//: Since we don't yet have a clean way to represent characters like backspace</span>
-<span class="Comment">//: in literal strings we can't easily pretend they were typed into the fake</span>
-<span class="Comment">//: keyboard. So we'll use special unicode characters in the literal and then</span>
-<span class="Comment">//: manually replace them with backspace.</span>
-<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
-REPLACE_IN_KEYBOARD<span class="Delimiter">,</span>
-<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
-Recipe_number[<span class="Constant">&quot;replace-in-keyboard&quot;</span>] = REPLACE_IN_KEYBOARD<span class="Delimiter">;</span>
-<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
-case REPLACE_IN_KEYBOARD: <span class="Delimiter">{</span>
-  long long int size = Memory[KEYBOARD]<span class="Delimiter">;</span>
-  assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)));</span>
-  assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">)));</span>
-  for <span class="Delimiter">(</span>long long int curr = KEYBOARD+<span class="Constant">1</span><span class="Delimiter">;</span> curr &lt;= KEYBOARD+size<span class="Delimiter">;</span> ++curr<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    if <span class="Delimiter">(</span>Memory[curr] == ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">))</span> <span class="Delimiter">{</span>
-<span class="CommentedCode">//?       cerr &lt;&lt; &quot;replacing\n&quot;; //? 1</span>
-      Memory[curr] = ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">);</span>
-    <span class="Delimiter">}</span>
-  <span class="Delimiter">}</span>
-  <span class="Identifier">break</span><span class="Delimiter">;</span>
-<span class="Delimiter">}</span>
-</pre>
-</body>
-</html>
-<!-- vim: set foldmethod=manual : -->
diff --git a/html/076scenario_keyboard_test.mu.html b/html/076scenario_keyboard_test.mu.html
deleted file mode 100644
index ec148812..00000000
--- a/html/076scenario_keyboard_test.mu.html
+++ /dev/null
@@ -1,57 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-<meta http-equiv="content-type" content="text/html; charset=UTF-8">
-<title>Mu - 076scenario_keyboard_test.mu</title>
-<meta name="Generator" content="Vim/7.4">
-<meta name="plugin-version" content="vim7.4_v1">
-<meta name="syntax" content="none">
-<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
-<meta name="colorscheme" content="minimal">
-<style type="text/css">
-<!--
-pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
-body { font-family: monospace; color: #eeeeee; background-color: #080808; }
-* { font-size: 1.05em; }
-.muScenario { color: #00af00; }
-.Comment { color: #9090ff; }
-.Constant { color: #00a0a0; }
-.Special { color: #ff6060; }
--->
-</style>
-
-<script type='text/javascript'>
-<!--
-
--->
-</script>
-</head>
-<body>
-<pre id='vimCodeElement'>
-<span class="Comment"># To check our support for keyboards in scenarios, rewrite tests from</span>
-<span class="Comment"># scenario_keyboard.mu</span>
-<span class="Comment"># Tests for keyboard interface.</span>
-
-<span class="muScenario">scenario</span> read-key-in-mu [
-  assume-keyboard <span class="Constant">[abc]</span>
-  run [
-    1:character, 2:boolean, keyboard:address<span class="Special"> &lt;- </span>read-key keyboard:address
-    3:character, 4:boolean, keyboard:address<span class="Special"> &lt;- </span>read-key keyboard:address
-    5:character, 6:boolean, keyboard:address<span class="Special"> &lt;- </span>read-key keyboard:address
-    7:character, 8:boolean, keyboard:address<span class="Special"> &lt;- </span>read-key keyboard:address
-  ]
-  memory-should-contain [
-    1<span class="Special"> &lt;- </span>97  <span class="Comment"># 'a'</span>
-    2<span class="Special"> &lt;- </span>1
-    3<span class="Special"> &lt;- </span>98  <span class="Comment"># 'b'</span>
-    4<span class="Special"> &lt;- </span>1
-    5<span class="Special"> &lt;- </span>99  <span class="Comment"># 'c'</span>
-    6<span class="Special"> &lt;- </span>1
-    7<span class="Special"> &lt;- </span>0  <span class="Comment"># eof</span>
-    8<span class="Special"> &lt;- </span>1
-  ]
-]
-</pre>
-</body>
-</html>
-<!-- vim: set foldmethod=manual : -->
diff --git a/html/077mouse.cc.html b/html/077mouse.cc.html
deleted file mode 100644
index bf7f11b8..00000000
--- a/html/077mouse.cc.html
+++ /dev/null
@@ -1,68 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-<meta http-equiv="content-type" content="text/html; charset=UTF-8">
-<title>Mu - 077mouse.cc</title>
-<meta name="Generator" content="Vim/7.4">
-<meta name="plugin-version" content="vim7.4_v1">
-<meta name="syntax" content="cpp">
-<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
-<meta name="colorscheme" content="minimal">
-<style type="text/css">
-<!--
-pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
-body { font-family: monospace; color: #eeeeee; background-color: #080808; }
-* { font-size: 1.05em; }
-.Constant { color: #00a0a0; }
-.Comment { color: #9090ff; }
-.Delimiter { color: #a04060; }
-.Identifier { color: #804000; }
-.Comment { color: #9090ff; }
--->
-</style>
-
-<script type='text/javascript'>
-<!--
-
--->
-</script>
-</head>
-<body>
-<pre id='vimCodeElement'>
-<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
-READ_KEYBOARD_OR_MOUSE_EVENT<span class="Delimiter">,</span>
-<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
-Recipe_number[<span class="Constant">&quot;read-keyboard-or-mouse-event&quot;</span>] = READ_KEYBOARD_OR_MOUSE_EVENT<span class="Delimiter">;</span>
-<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
-case READ_KEYBOARD_OR_MOUSE_EVENT: <span class="Delimiter">{</span>
-  products<span class="Delimiter">.</span>resize<span class="Delimiter">(</span><span class="Constant">2</span><span class="Delimiter">);</span>  <span class="Comment">// result and status</span>
-  tb_event event<span class="Delimiter">;</span>
-  int event_type = tb_peek_event<span class="Delimiter">(</span>&amp;event<span class="Delimiter">,</span> <span class="Constant">5</span><span class="Comment">/*</span><span class="Comment">ms</span><span class="Comment">*/</span><span class="Delimiter">);</span>
-  if <span class="Delimiter">(</span>event_type == TB_EVENT_KEY<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">keyboard event</span><span class="Comment">*/</span><span class="Constant">0</span><span class="Delimiter">);</span>
-    long long key = event<span class="Delimiter">.</span>key ? event<span class="Delimiter">.</span>key : event<span class="Delimiter">.</span>ch<span class="Delimiter">;</span>
-    if <span class="Delimiter">(</span>key == TB_KEY_CTRL_C<span class="Delimiter">)</span> tb_shutdown<span class="Delimiter">(),</span> exit<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">);</span>
-    if <span class="Delimiter">(</span>key == TB_KEY_BACKSPACE2<span class="Delimiter">)</span> key = TB_KEY_BACKSPACE<span class="Delimiter">;</span>
-    if <span class="Delimiter">(</span>key == TB_KEY_CARRIAGE_RETURN<span class="Delimiter">)</span> key = TB_KEY_NEWLINE<span class="Delimiter">;</span>
-    products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>key<span class="Delimiter">);</span>
-    products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">found</span><span class="Comment">*/</span><span class="Constant">true</span><span class="Delimiter">);</span>
-    <span class="Identifier">break</span><span class="Delimiter">;</span>
-  <span class="Delimiter">}</span>
-  if <span class="Delimiter">(</span>event_type == TB_EVENT_MOUSE<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">mouse event</span><span class="Comment">*/</span><span class="Constant">1</span><span class="Delimiter">);</span>
-<span class="CommentedCode">//?     tb_shutdown(); //? 1</span>
-<span class="CommentedCode">//?     cerr &lt;&lt; event_type &lt;&lt; ' ' &lt;&lt; event.key &lt;&lt; ' ' &lt;&lt; event.y &lt;&lt; ' ' &lt;&lt; event.x &lt;&lt; '\n'; //? 1</span>
-<span class="CommentedCode">//?     exit(0); //? 1</span>
-    products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>event<span class="Delimiter">.</span>key<span class="Delimiter">);</span>  <span class="Comment">// which button, etc.</span>
-    products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>event<span class="Delimiter">.</span>y<span class="Delimiter">);</span>  <span class="Comment">// row</span>
-    products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span>event<span class="Delimiter">.</span>x<span class="Delimiter">);</span>  <span class="Comment">// column</span>
-    products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">found</span><span class="Comment">*/</span><span class="Constant">true</span><span class="Delimiter">);</span>
-    <span class="Identifier">break</span><span class="Delimiter">;</span>
-  <span class="Delimiter">}</span>
-  products<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">1</span><span class="Delimiter">).</span>push_back<span class="Delimiter">(</span><span class="Comment">/*</span><span class="Comment">found</span><span class="Comment">*/</span><span class="Constant">false</span><span class="Delimiter">);</span>
-  <span class="Identifier">break</span><span class="Delimiter">;</span>
-<span class="Delimiter">}</span>
-</pre>
-</body>
-</html>
-<!-- vim: set foldmethod=manual : -->
diff --git a/html/077trace_browser.cc.html b/html/077trace_browser.cc.html
deleted file mode 100644
index 8fa5bf00..00000000
--- a/html/077trace_browser.cc.html
+++ /dev/null
@@ -1,236 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-<meta http-equiv="content-type" content="text/html; charset=UTF-8">
-<title>Mu - 077trace_browser.cc</title>
-<meta name="Generator" content="Vim/7.4">
-<meta name="plugin-version" content="vim7.4_v1">
-<meta name="syntax" content="cpp">
-<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
-<meta name="colorscheme" content="minimal">
-<style type="text/css">
-<!--
-pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
-body { font-family: monospace; color: #eeeeee; background-color: #080808; }
-* { font-size: 1.05em; }
-.cSpecial { color: #008000; }
-.Constant { color: #00a0a0; }
-.Comment { color: #9090ff; }
-.Delimiter { color: #a04060; }
-.Identifier { color: #008080; }
-.Comment { color: #9090ff; }
--->
-</style>
-
-<script type='text/javascript'>
-<!--
-
--->
-</script>
-</head>
-<body>
-<pre id='vimCodeElement'>
-<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
-_BROWSE_TRACE<span class="Delimiter">,</span>
-<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
-Recipe_number[<span class="Constant">&quot;$browse-trace&quot;</span>] = _BROWSE_TRACE<span class="Delimiter">;</span>
-<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
-case _BROWSE_TRACE: <span class="Delimiter">{</span>
-  start_trace_browser<span class="Delimiter">();</span>
-  <span class="Identifier">break</span><span class="Delimiter">;</span>
-<span class="Delimiter">}</span>
-
-<span class="Delimiter">:(before &quot;End Globals&quot;)</span>
-set&lt;long long int&gt; Visible<span class="Delimiter">;</span>
-long long int Top_of_screen = <span class="Constant">0</span><span class="Delimiter">;</span>
-long long int Last_printed_row = <span class="Constant">0</span><span class="Delimiter">;</span>
-map&lt;int<span class="Delimiter">,</span> long long int&gt; Trace_index<span class="Delimiter">;</span>  <span class="Comment">// screen row -&gt; trace index</span>
-
-<span class="Delimiter">:(code)</span>
-void start_trace_browser<span class="Delimiter">()</span> <span class="Delimiter">{</span>
-  if <span class="Delimiter">(</span>!Trace_stream<span class="Delimiter">)</span> <span class="Identifier">return</span><span class="Delimiter">;</span>
-  cerr &lt;&lt; <span class="Constant">&quot;computing depth to display</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span>
-  long long int min_depth = <span class="Constant">9999</span><span class="Delimiter">;</span>
-  for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    trace_line&amp; curr_line = Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span>
-    if <span class="Delimiter">(</span>curr_line<span class="Delimiter">.</span>depth == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span>
-    if <span class="Delimiter">(</span>curr_line<span class="Delimiter">.</span>depth &lt; min_depth<span class="Delimiter">)</span> min_depth = curr_line<span class="Delimiter">.</span>depth<span class="Delimiter">;</span>
-  <span class="Delimiter">}</span>
-  cerr &lt;&lt; <span class="Constant">&quot;depth is &quot;</span> &lt;&lt; min_depth &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
-  cerr &lt;&lt; <span class="Constant">&quot;computing lines to display</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">;</span>
-  for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    if <span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">).</span>depth == min_depth<span class="Delimiter">)</span>
-      Visible<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>i<span class="Delimiter">);</span>
-  <span class="Delimiter">}</span>
-  tb_init<span class="Delimiter">();</span>
-  Display_row = Display_column = <span class="Constant">0</span><span class="Delimiter">;</span>
-  tb_event event<span class="Delimiter">;</span>
-  Top_of_screen = <span class="Constant">0</span><span class="Delimiter">;</span>
-  refresh_screen_rows<span class="Delimiter">();</span>
-  while <span class="Delimiter">(</span><span class="Constant">true</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    render<span class="Delimiter">();</span>
-    do <span class="Delimiter">{</span>
-      tb_poll_event<span class="Delimiter">(</span>&amp;event<span class="Delimiter">);</span>
-    <span class="Delimiter">}</span> while <span class="Delimiter">(</span>event<span class="Delimiter">.</span>type != TB_EVENT_KEY<span class="Delimiter">);</span>
-    long long int key = event<span class="Delimiter">.</span>key ? event<span class="Delimiter">.</span>key : event<span class="Delimiter">.</span>ch<span class="Delimiter">;</span>
-    if <span class="Delimiter">(</span>key == <span class="Constant">'q'</span> || key == <span class="Constant">'Q'</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span>
-    if <span class="Delimiter">(</span>key == <span class="Constant">'j'</span> || key == TB_KEY_ARROW_DOWN<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-      <span class="Comment">// move cursor one line down</span>
-      if <span class="Delimiter">(</span>Display_row &lt; Last_printed_row<span class="Delimiter">)</span> ++Display_row<span class="Delimiter">;</span>
-    <span class="Delimiter">}</span>
-    if <span class="Delimiter">(</span>key == <span class="Constant">'k'</span> || key == TB_KEY_ARROW_UP<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-      <span class="Comment">// move cursor one line up</span>
-      if <span class="Delimiter">(</span>Display_row &gt; <span class="Constant">0</span><span class="Delimiter">)</span> --Display_row<span class="Delimiter">;</span>
-    <span class="Delimiter">}</span>
-    if <span class="Delimiter">(</span>key == <span class="Constant">'H'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
-      <span class="Comment">// move cursor to top of screen</span>
-      Display_row = <span class="Constant">0</span><span class="Delimiter">;</span>
-    <span class="Delimiter">}</span>
-    if <span class="Delimiter">(</span>key == <span class="Constant">'M'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
-      <span class="Comment">// move cursor to center of screen</span>
-      Display_row = tb_height<span class="Delimiter">()</span>/<span class="Constant">2</span><span class="Delimiter">;</span>
-    <span class="Delimiter">}</span>
-    if <span class="Delimiter">(</span>key == <span class="Constant">'L'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
-      <span class="Comment">// move cursor to bottom of screen</span>
-      Display_row = tb_height<span class="Delimiter">()</span>-<span class="Constant">1</span><span class="Delimiter">;</span>
-    <span class="Delimiter">}</span>
-    if <span class="Delimiter">(</span>key == <span class="Constant">'J'</span> || key == TB_KEY_PGDN<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-      <span class="Comment">// page-down</span>
-      if <span class="Delimiter">(</span>Trace_index<span class="Delimiter">.</span>find<span class="Delimiter">(</span>tb_height<span class="Delimiter">()</span>-<span class="Constant">1</span><span class="Delimiter">)</span> != Trace_index<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span>
-        Top_of_screen = Trace_index[tb_height<span class="Delimiter">()</span>-<span class="Constant">1</span>]+<span class="Constant">1</span><span class="Delimiter">;</span>
-        refresh_screen_rows<span class="Delimiter">();</span>
-      <span class="Delimiter">}</span>
-    <span class="Delimiter">}</span>
-    if <span class="Delimiter">(</span>key == <span class="Constant">'K'</span> || key == TB_KEY_PGUP<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-      <span class="Comment">// page-up is more convoluted</span>
-<span class="CommentedCode">//?       tb_shutdown(); //? 1</span>
-<span class="CommentedCode">//?       cerr &lt;&lt; &quot;page-up: Top_of_screen is currently &quot; &lt;&lt; Top_of_screen &lt;&lt; '\n'; //? 1</span>
-      for <span class="Delimiter">(</span>int screen_row = tb_height<span class="Delimiter">();</span> screen_row &gt; <span class="Constant">0</span> &amp;&amp; Top_of_screen &gt; <span class="Constant">0</span><span class="Delimiter">;</span> --screen_row<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-        --Top_of_screen<span class="Delimiter">;</span>
-        if <span class="Delimiter">(</span>Top_of_screen &lt;= <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span>
-        while <span class="Delimiter">(</span>Top_of_screen &gt; <span class="Constant">0</span> &amp;&amp; Visible<span class="Delimiter">.</span>find<span class="Delimiter">(</span>Top_of_screen<span class="Delimiter">)</span> == Visible<span class="Delimiter">.</span>end<span class="Delimiter">())</span>
-          --Top_of_screen<span class="Delimiter">;</span>
-<span class="CommentedCode">//?         cerr &lt;&lt; &quot;now &quot; &lt;&lt; Top_of_screen &lt;&lt; '\n'; //? 1</span>
-      <span class="Delimiter">}</span>
-<span class="CommentedCode">//?       exit(0); //? 1</span>
-      if <span class="Delimiter">(</span>Top_of_screen &gt; <span class="Constant">0</span><span class="Delimiter">)</span>
-        refresh_screen_rows<span class="Delimiter">();</span>
-    <span class="Delimiter">}</span>
-    if <span class="Delimiter">(</span>key == <span class="Constant">'G'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
-      <span class="Comment">// go to bottom of screen; largely like page-up, interestingly</span>
-      Top_of_screen = SIZE<span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">)</span>-<span class="Constant">1</span><span class="Delimiter">;</span>
-      for <span class="Delimiter">(</span>int screen_row = tb_height<span class="Delimiter">();</span> screen_row &gt; <span class="Constant">0</span> &amp;&amp; Top_of_screen &gt; <span class="Constant">0</span><span class="Delimiter">;</span> --screen_row<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-        --Top_of_screen<span class="Delimiter">;</span>
-        if <span class="Delimiter">(</span>Top_of_screen &lt;= <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span>
-        while <span class="Delimiter">(</span>Top_of_screen &gt; <span class="Constant">0</span> &amp;&amp; Visible<span class="Delimiter">.</span>find<span class="Delimiter">(</span>Top_of_screen<span class="Delimiter">)</span> == Visible<span class="Delimiter">.</span>end<span class="Delimiter">())</span>
-          --Top_of_screen<span class="Delimiter">;</span>
-      <span class="Delimiter">}</span>
-      refresh_screen_rows<span class="Delimiter">();</span>
-      <span class="Comment">// move cursor to bottom</span>
-      Display_row = Last_printed_row<span class="Delimiter">;</span>
-      refresh_screen_rows<span class="Delimiter">();</span>
-    <span class="Delimiter">}</span>
-    if <span class="Delimiter">(</span>key == TB_KEY_CARRIAGE_RETURN<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-      <span class="Comment">// expand lines under current by one level</span>
-<span class="CommentedCode">//?       tb_shutdown();</span>
-      assert<span class="Delimiter">(</span>Trace_index<span class="Delimiter">.</span>find<span class="Delimiter">(</span>Display_row<span class="Delimiter">)</span> != Trace_index<span class="Delimiter">.</span>end<span class="Delimiter">());</span>
-      long long int start_index = Trace_index[Display_row]<span class="Delimiter">;</span>
-<span class="CommentedCode">//?       cerr &lt;&lt; &quot;start_index is &quot; &lt;&lt; start_index &lt;&lt; '\n';</span>
-      long long int index = <span class="Constant">0</span><span class="Delimiter">;</span>
-      <span class="Comment">// simultaneously compute end_index and min_depth</span>
-      int min_depth = <span class="Constant">9999</span><span class="Delimiter">;</span>
-      for <span class="Delimiter">(</span>index = start_index+<span class="Constant">1</span><span class="Delimiter">;</span> index &lt; SIZE<span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">);</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-        if <span class="Delimiter">(</span>Visible<span class="Delimiter">.</span>find<span class="Delimiter">(</span>index<span class="Delimiter">)</span> != Visible<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Identifier">break</span><span class="Delimiter">;</span>
-        trace_line&amp; curr_line = Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>index<span class="Delimiter">);</span>
-        if <span class="Delimiter">(</span>curr_line<span class="Delimiter">.</span>depth == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span>
-        assert<span class="Delimiter">(</span>curr_line<span class="Delimiter">.</span>depth &gt; Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>start_index<span class="Delimiter">).</span>depth<span class="Delimiter">);</span>
-        if <span class="Delimiter">(</span>curr_line<span class="Delimiter">.</span>depth &lt; min_depth<span class="Delimiter">)</span> min_depth = curr_line<span class="Delimiter">.</span>depth<span class="Delimiter">;</span>
-      <span class="Delimiter">}</span>
-<span class="CommentedCode">//?       cerr &lt;&lt; &quot;min_depth is &quot; &lt;&lt; min_depth &lt;&lt; '\n';</span>
-      long long int end_index = index<span class="Delimiter">;</span>
-<span class="CommentedCode">//?       cerr &lt;&lt; &quot;end_index is &quot; &lt;&lt; end_index &lt;&lt; '\n';</span>
-      <span class="Comment">// mark as visible all intervening indices at min_depth</span>
-      for <span class="Delimiter">(</span>index = start_index<span class="Delimiter">;</span> index &lt; end_index<span class="Delimiter">;</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-        trace_line&amp; curr_line = Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>index<span class="Delimiter">);</span>
-        if <span class="Delimiter">(</span>curr_line<span class="Delimiter">.</span>depth == min_depth<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-<span class="CommentedCode">//?           cerr &lt;&lt; &quot;adding &quot; &lt;&lt; index &lt;&lt; '\n';</span>
-          Visible<span class="Delimiter">.</span>insert<span class="Delimiter">(</span>index<span class="Delimiter">);</span>
-        <span class="Delimiter">}</span>
-      <span class="Delimiter">}</span>
-<span class="CommentedCode">//?       exit(0);</span>
-      refresh_screen_rows<span class="Delimiter">();</span>
-    <span class="Delimiter">}</span>
-    if <span class="Delimiter">(</span>key == TB_KEY_BACKSPACE || key == TB_KEY_BACKSPACE2<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-      <span class="Comment">// collapse all lines under current</span>
-      assert<span class="Delimiter">(</span>Trace_index<span class="Delimiter">.</span>find<span class="Delimiter">(</span>Display_row<span class="Delimiter">)</span> != Trace_index<span class="Delimiter">.</span>end<span class="Delimiter">());</span>
-      long long int start_index = Trace_index[Display_row]<span class="Delimiter">;</span>
-      long long int index = <span class="Constant">0</span><span class="Delimiter">;</span>
-      <span class="Comment">// end_index is the next line at a depth same as or lower than start_index</span>
-      int initial_depth = Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>start_index<span class="Delimiter">).</span>depth<span class="Delimiter">;</span>
-      for <span class="Delimiter">(</span>index = start_index+<span class="Constant">1</span><span class="Delimiter">;</span> index &lt; SIZE<span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">);</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-        if <span class="Delimiter">(</span>Visible<span class="Delimiter">.</span>find<span class="Delimiter">(</span>index<span class="Delimiter">)</span> == Visible<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Identifier">continue</span><span class="Delimiter">;</span>
-        trace_line&amp; curr_line = Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>index<span class="Delimiter">);</span>
-        if <span class="Delimiter">(</span>curr_line<span class="Delimiter">.</span>depth == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Identifier">continue</span><span class="Delimiter">;</span>
-        if <span class="Delimiter">(</span>curr_line<span class="Delimiter">.</span>depth &lt;= initial_depth<span class="Delimiter">)</span> <span class="Identifier">break</span><span class="Delimiter">;</span>
-      <span class="Delimiter">}</span>
-      long long int end_index = index<span class="Delimiter">;</span>
-      <span class="Comment">// mark as visible all intervening indices at min_depth</span>
-      for <span class="Delimiter">(</span>index = start_index+<span class="Constant">1</span><span class="Delimiter">;</span> index &lt; end_index<span class="Delimiter">;</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-        Visible<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>index<span class="Delimiter">);</span>
-      <span class="Delimiter">}</span>
-      refresh_screen_rows<span class="Delimiter">();</span>
-    <span class="Delimiter">}</span>
-  <span class="Delimiter">}</span>
-  tb_shutdown<span class="Delimiter">();</span>
-<span class="Delimiter">}</span>
-
-<span class="Comment">// update Trace_indices for each screen_row on the basis of Top_of_screen and Visible</span>
-void refresh_screen_rows<span class="Delimiter">()</span> <span class="Delimiter">{</span>
-  long long int screen_row = <span class="Constant">0</span><span class="Delimiter">,</span> index = <span class="Constant">0</span><span class="Delimiter">;</span>
-  Trace_index<span class="Delimiter">.</span>clear<span class="Delimiter">();</span>
-  for <span class="Delimiter">(</span>screen_row = <span class="Constant">0</span><span class="Delimiter">,</span> index = Top_of_screen<span class="Delimiter">;</span> screen_row &lt; tb_height<span class="Delimiter">()</span> &amp;&amp; index &lt; SIZE<span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">);</span> ++screen_row<span class="Delimiter">,</span> ++index<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    <span class="Comment">// skip lines without depth for now</span>
-    while <span class="Delimiter">(</span>Visible<span class="Delimiter">.</span>find<span class="Delimiter">(</span>index<span class="Delimiter">)</span> == Visible<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span>
-      ++index<span class="Delimiter">;</span>
-      if <span class="Delimiter">(</span>index &gt;= SIZE<span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">))</span> <span class="Identifier">goto</span> done<span class="Delimiter">;</span>
-    <span class="Delimiter">}</span>
-    assert<span class="Delimiter">(</span>index &lt; SIZE<span class="Delimiter">(</span>Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">));</span>
-    Trace_index[screen_row] = index<span class="Delimiter">;</span>
-  <span class="Delimiter">}</span>
-done:<span class="Delimiter">;</span>
-<span class="Delimiter">}</span>
-
-void render<span class="Delimiter">()</span> <span class="Delimiter">{</span>
-  long long int screen_row = <span class="Constant">0</span><span class="Delimiter">;</span>
-  for <span class="Delimiter">(</span>screen_row = <span class="Constant">0</span><span class="Delimiter">;</span> screen_row &lt; tb_height<span class="Delimiter">();</span> ++screen_row<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    if <span class="Delimiter">(</span>Trace_index<span class="Delimiter">.</span>find<span class="Delimiter">(</span>screen_row<span class="Delimiter">)</span> == Trace_index<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Identifier">break</span><span class="Delimiter">;</span>
-    trace_line&amp; curr_line = Trace_stream<span class="Delimiter">-&gt;</span>past_lines<span class="Delimiter">.</span>at<span class="Delimiter">(</span>Trace_index[screen_row]<span class="Delimiter">);</span>
-    ostringstream out<span class="Delimiter">;</span>
-    out &lt;&lt; std::setw<span class="Delimiter">(</span><span class="Constant">4</span><span class="Delimiter">)</span> &lt;&lt; curr_line<span class="Delimiter">.</span>depth &lt;&lt; <span class="Constant">' '</span> &lt;&lt; curr_line<span class="Delimiter">.</span>label &lt;&lt; <span class="Constant">&quot;: &quot;</span> &lt;&lt; curr_line<span class="Delimiter">.</span>contents<span class="Delimiter">;</span>
-    render_line<span class="Delimiter">(</span>screen_row<span class="Delimiter">,</span> out<span class="Delimiter">.</span>str<span class="Delimiter">());</span>
-  <span class="Delimiter">}</span>
-  <span class="Comment">// clear rest of screen</span>
-  Last_printed_row = screen_row-<span class="Constant">1</span><span class="Delimiter">;</span>
-  for <span class="Delimiter">(;</span> screen_row &lt; tb_height<span class="Delimiter">();</span> ++screen_row<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    render_line<span class="Delimiter">(</span>screen_row<span class="Delimiter">,</span> <span class="Constant">&quot;~&quot;</span><span class="Delimiter">);</span>
-  <span class="Delimiter">}</span>
-  <span class="Comment">// move cursor back to display row at the end</span>
-  tb_set_cursor<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">,</span> Display_row<span class="Delimiter">);</span>
-  tb_present<span class="Delimiter">();</span>
-<span class="Delimiter">}</span>
-
-void render_line<span class="Delimiter">(</span>int screen_row<span class="Delimiter">,</span> const string&amp; s<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-  long long int col = <span class="Constant">0</span><span class="Delimiter">;</span>
-  for <span class="Delimiter">(</span>col = <span class="Constant">0</span><span class="Delimiter">;</span> col &lt; tb_width<span class="Delimiter">()</span> &amp;&amp; col &lt; SIZE<span class="Delimiter">(</span>s<span class="Delimiter">);</span> ++col<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    char c = s<span class="Delimiter">.</span>at<span class="Delimiter">(</span>col<span class="Delimiter">);</span>
-    if <span class="Delimiter">(</span>c == <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> c = <span class="Constant">';'</span><span class="Delimiter">;</span>  <span class="Comment">// replace newlines with semi-colons</span>
-    tb_change_cell<span class="Delimiter">(</span>col<span class="Delimiter">,</span> screen_row<span class="Delimiter">,</span> c<span class="Delimiter">,</span> TB_WHITE<span class="Delimiter">,</span> TB_BLACK<span class="Delimiter">);</span>
-  <span class="Delimiter">}</span>
-  for <span class="Delimiter">(;</span> col &lt; tb_width<span class="Delimiter">();</span> ++col<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    tb_change_cell<span class="Delimiter">(</span>col<span class="Delimiter">,</span> screen_row<span class="Delimiter">,</span> <span class="Constant">' '</span><span class="Delimiter">,</span> TB_WHITE<span class="Delimiter">,</span> TB_BLACK<span class="Delimiter">);</span>
-  <span class="Delimiter">}</span>
-<span class="Delimiter">}</span>
-</pre>
-</body>
-</html>
-<!-- vim: set foldmethod=manual : -->
diff --git a/html/078run_interactive.cc.html b/html/078run_interactive.cc.html
deleted file mode 100644
index 834924c2..00000000
--- a/html/078run_interactive.cc.html
+++ /dev/null
@@ -1,159 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-<meta http-equiv="content-type" content="text/html; charset=UTF-8">
-<title>Mu - 078run_interactive.cc</title>
-<meta name="Generator" content="Vim/7.4">
-<meta name="plugin-version" content="vim7.4_v1">
-<meta name="syntax" content="cpp">
-<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
-<meta name="colorscheme" content="minimal">
-<style type="text/css">
-<!--
-pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
-body { font-family: monospace; color: #eeeeee; background-color: #080808; }
-* { font-size: 1.05em; }
-.cSpecial { color: #008000; }
-.Constant { color: #00a0a0; }
-.Comment { color: #9090ff; }
-.Delimiter { color: #a04060; }
-.SalientComment { color: #00ffff; }
-.Comment { color: #9090ff; }
-.Identifier { color: #008080; }
--->
-</style>
-
-<script type='text/javascript'>
-<!--
-
--->
-</script>
-</head>
-<body>
-<pre id='vimCodeElement'>
-<span class="Comment">//: Helper for the repl.</span>
-
-<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
-RUN_INTERACTIVE<span class="Delimiter">,</span>
-<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
-Recipe_number[<span class="Constant">&quot;run-interactive&quot;</span>] = RUN_INTERACTIVE<span class="Delimiter">;</span>
-<span class="CommentedCode">//? cerr &lt;&lt; &quot;run-interactive: &quot; &lt;&lt; RUN_INTERACTIVE &lt;&lt; '\n'; //? 1</span>
-<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
-case RUN_INTERACTIVE: <span class="Delimiter">{</span>
-  assert<span class="Delimiter">(</span>scalar<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">)));</span>
-<span class="CommentedCode">//?   cerr &lt;&lt; &quot;AAA 0\n&quot;; //? 1</span>
-  run_interactive<span class="Delimiter">(</span>ingredients<span class="Delimiter">.</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">).</span>at<span class="Delimiter">(</span><span class="Constant">0</span><span class="Delimiter">));</span>
-<span class="CommentedCode">//?   cerr &lt;&lt; &quot;ZZZ\n&quot;; //? 1</span>
-  <span class="Identifier">continue</span><span class="Delimiter">;</span>  <span class="Comment">// not done with caller; don't increment current_step_index()</span>
-<span class="Delimiter">}</span>
-
-<span class="Delimiter">:(code)</span>
-<span class="Comment">// manual tests:</span>
-<span class="Comment">//  empty string (excluding whitespace and comments) does nothing</span>
-<span class="Comment">//  ctrl-d</span>
-<span class="Comment">//  just an integer (excluding whitespace and comments) prints value of that location in memory</span>
-<span class="Comment">//  instruction executes</span>
-<span class="Comment">//  backspace at start begins new attempt</span>
-void run_interactive<span class="Delimiter">(</span>long long int address<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-<span class="CommentedCode">//?   tb_shutdown(); //? 1</span>
-  long long int size = Memory[address]<span class="Delimiter">;</span>
-  if <span class="Delimiter">(</span>size == <span class="Constant">0</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    ++current_step_index<span class="Delimiter">();</span>
-    <span class="Identifier">return</span><span class="Delimiter">;</span>
-  <span class="Delimiter">}</span>
-  ostringstream tmp<span class="Delimiter">;</span>
-  for <span class="Delimiter">(</span>long long int curr = address+<span class="Constant">1</span><span class="Delimiter">;</span> curr &lt; address+size<span class="Delimiter">;</span> ++curr<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    <span class="Comment">// todo: unicode</span>
-    tmp &lt;&lt; <span class="Delimiter">(</span>char<span class="Delimiter">)(</span>int<span class="Delimiter">)</span>Memory[curr]<span class="Delimiter">;</span>
-  <span class="Delimiter">}</span>
-<span class="CommentedCode">//?   cerr &lt;&lt; size &lt;&lt; ' ' &lt;&lt; Memory[address+size] &lt;&lt; '\n'; //? 1</span>
-  assert<span class="Delimiter">(</span>Memory[address+size] == <span class="Constant">10</span><span class="Delimiter">);</span>  <span class="Comment">// skip the newline</span>
-  if <span class="Delimiter">(</span>Recipe_number<span class="Delimiter">.</span>find<span class="Delimiter">(</span><span class="Constant">&quot;interactive&quot;</span><span class="Delimiter">)</span> == Recipe_number<span class="Delimiter">.</span>end<span class="Delimiter">())</span>
-    Recipe_number[<span class="Constant">&quot;interactive&quot;</span>] = Next_recipe_number++<span class="Delimiter">;</span>
-  string command = trim<span class="Delimiter">(</span>strip_comments<span class="Delimiter">(</span>tmp<span class="Delimiter">.</span>str<span class="Delimiter">()));</span>
-  if <span class="Delimiter">(</span>command<span class="Delimiter">.</span>empty<span class="Delimiter">())</span> <span class="Delimiter">{</span>
-    ++current_step_index<span class="Delimiter">();</span>
-    <span class="Identifier">return</span><span class="Delimiter">;</span>
-  <span class="Delimiter">}</span>
-  if <span class="Delimiter">(</span>is_integer<span class="Delimiter">(</span>command<span class="Delimiter">))</span> <span class="Delimiter">{</span>
-    print_value_of_location_as_response<span class="Delimiter">(</span>to_integer<span class="Delimiter">(</span>command<span class="Delimiter">));</span>
-    ++current_step_index<span class="Delimiter">();</span>
-    <span class="Identifier">return</span><span class="Delimiter">;</span>
-  <span class="Delimiter">}</span>
-<span class="CommentedCode">//?   exit(0); //? 1</span>
-  if <span class="Delimiter">(</span>Name[Recipe_number[<span class="Constant">&quot;interactive&quot;</span>]]<span class="Delimiter">.</span>find<span class="Delimiter">(</span>command<span class="Delimiter">)</span> != Name[Recipe_number[<span class="Constant">&quot;interactive&quot;</span>]]<span class="Delimiter">.</span>end<span class="Delimiter">())</span> <span class="Delimiter">{</span>
-    print_value_of_location_as_response<span class="Delimiter">(</span>Name[Recipe_number[<span class="Constant">&quot;interactive&quot;</span>]][command]<span class="Delimiter">);</span>
-    ++current_step_index<span class="Delimiter">();</span>
-    <span class="Identifier">return</span><span class="Delimiter">;</span>
-  <span class="Delimiter">}</span>
-<span class="CommentedCode">//?   tb_shutdown(); //? 1</span>
-<span class="CommentedCode">//?   cerr &lt;&lt; command; //? 1</span>
-<span class="CommentedCode">//?   exit(0); //? 1</span>
-<span class="CommentedCode">//?   cerr &lt;&lt; &quot;AAA 1\n&quot;; //? 1</span>
-  Recipe<span class="Delimiter">.</span>erase<span class="Delimiter">(</span>Recipe_number[<span class="Constant">&quot;interactive&quot;</span>]<span class="Delimiter">);</span>
-  <span class="Comment">// call run(string) but without the scheduling</span>
-<span class="CommentedCode">//?   cerr &lt;&lt; (&quot;recipe interactive [\n&quot;+command+&quot;\n]\n&quot;); //? 1</span>
-  load<span class="Delimiter">(</span><span class="Constant">&quot;recipe interactive [</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span>+command+<span class="Constant">&quot;</span><span class="cSpecial">\n</span><span class="Constant">]</span><span class="cSpecial">\n</span><span class="Constant">&quot;</span><span class="Delimiter">);</span>
-  transform_all<span class="Delimiter">();</span>
-<span class="CommentedCode">//?   cerr &lt;&lt; &quot;names: &quot; &lt;&lt; Name[Recipe_number[&quot;interactive&quot;]].size() &lt;&lt; &quot;; &quot;; //? 1</span>
-<span class="CommentedCode">//?   cerr &lt;&lt; &quot;steps: &quot; &lt;&lt; Recipe[Recipe_number[&quot;interactive&quot;]].steps.size() &lt;&lt; &quot;; &quot;; //? 1</span>
-<span class="CommentedCode">//?   cerr &lt;&lt; &quot;interactive transformed_until: &quot; &lt;&lt; Recipe[Recipe_number[&quot;interactive&quot;]].transformed_until &lt;&lt; '\n'; //? 1</span>
-  Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>push_front<span class="Delimiter">(</span>call<span class="Delimiter">(</span>Recipe_number[<span class="Constant">&quot;interactive&quot;</span>]<span class="Delimiter">));</span>
-<span class="Delimiter">}</span>
-
-string strip_comments<span class="Delimiter">(</span>string in<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-  ostringstream result<span class="Delimiter">;</span>
-<span class="CommentedCode">//?   cerr &lt;&lt; in; //? 1</span>
-  for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; SIZE<span class="Delimiter">(</span>in<span class="Delimiter">);</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    if <span class="Delimiter">(</span>in<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> != <span class="Constant">'#'</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
-      result &lt;&lt; in<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">);</span>
-    <span class="Delimiter">}</span>
-    else <span class="Delimiter">{</span>
-      while <span class="Delimiter">(</span>i &lt; SIZE<span class="Delimiter">(</span>in<span class="Delimiter">)</span> &amp;&amp; in<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> != <span class="cSpecial">'\n'</span><span class="Delimiter">)</span>
-        ++i<span class="Delimiter">;</span>
-      if <span class="Delimiter">(</span>i &lt; SIZE<span class="Delimiter">(</span>in<span class="Delimiter">)</span> &amp;&amp; in<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">)</span> == <span class="cSpecial">'\n'</span><span class="Delimiter">)</span> ++i<span class="Delimiter">;</span>
-    <span class="Delimiter">}</span>
-  <span class="Delimiter">}</span>
-<span class="CommentedCode">//?   cerr &lt;&lt; &quot;ZZZ&quot;; //? 1</span>
-  <span class="Identifier">return</span> result<span class="Delimiter">.</span>str<span class="Delimiter">();</span>
-<span class="Delimiter">}</span>
-
-void print_value_of_location_as_response<span class="Delimiter">(</span>long long int address<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-  <span class="Comment">// convert to string</span>
-  ostringstream out<span class="Delimiter">;</span>
-  out &lt;&lt; <span class="Constant">&quot;=&gt; &quot;</span> &lt;&lt; Memory[address]<span class="Delimiter">;</span>
-  string result = out<span class="Delimiter">.</span>str<span class="Delimiter">();</span>
-  <span class="Comment">// handle regular I/O</span>
-  if <span class="Delimiter">(</span>!tb_is_active<span class="Delimiter">())</span> <span class="Delimiter">{</span>
-    cerr &lt;&lt; result &lt;&lt; <span class="cSpecial">'\n'</span><span class="Delimiter">;</span>
-    <span class="Identifier">return</span><span class="Delimiter">;</span>
-  <span class="Delimiter">}</span>
-  <span class="Comment">// raw I/O; use termbox to print</span>
-  long long int bound = SIZE<span class="Delimiter">(</span>result<span class="Delimiter">);</span>
-  if <span class="Delimiter">(</span>bound &gt; tb_width<span class="Delimiter">())</span> bound = tb_width<span class="Delimiter">();</span>
-  for <span class="Delimiter">(</span>long long int i = <span class="Constant">0</span><span class="Delimiter">;</span> i &lt; bound<span class="Delimiter">;</span> ++i<span class="Delimiter">)</span> <span class="Delimiter">{</span>
-    tb_change_cell<span class="Delimiter">(</span>i<span class="Delimiter">,</span> Display_row<span class="Delimiter">,</span> result<span class="Delimiter">.</span>at<span class="Delimiter">(</span>i<span class="Delimiter">),</span> <span class="Comment">/*</span><span class="Comment">computer's color</span><span class="Comment">*/</span><span class="Constant">245</span><span class="Delimiter">,</span> TB_BLACK<span class="Delimiter">);</span>
-  <span class="Delimiter">}</span>
-  <span class="Comment">// newline</span>
-  if <span class="Delimiter">(</span>Display_row &lt; tb_height<span class="Delimiter">()</span>-<span class="Constant">1</span><span class="Delimiter">)</span>
-    ++Display_row<span class="Delimiter">;</span>
-  Display_column = <span class="Constant">0</span><span class="Delimiter">;</span>
-  tb_set_cursor<span class="Delimiter">(</span>Display_column<span class="Delimiter">,</span> Display_row<span class="Delimiter">);</span>
-  tb_present<span class="Delimiter">();</span>
-<span class="Delimiter">}</span>
-
-<span class="SalientComment">//:: debugging tool</span>
-
-<span class="Delimiter">:(before &quot;End Primitive Recipe Declarations&quot;)</span>
-_RUN_DEPTH<span class="Delimiter">,</span>
-<span class="Delimiter">:(before &quot;End Primitive Recipe Numbers&quot;)</span>
-Recipe_number[<span class="Constant">&quot;$run-depth&quot;</span>] = _RUN_DEPTH<span class="Delimiter">;</span>
-<span class="Delimiter">:(before &quot;End Primitive Recipe Implementations&quot;)</span>
-case _RUN_DEPTH: <span class="Delimiter">{</span>
-  cerr &lt;&lt; Current_routine<span class="Delimiter">-&gt;</span>calls<span class="Delimiter">.</span>size<span class="Delimiter">();</span>
-  <span class="Identifier">break</span><span class="Delimiter">;</span>
-<span class="Delimiter">}</span>
-</pre>
-</body>
-</html>
-<!-- vim: set foldmethod=manual : -->
diff --git a/html/edit.mu.html b/html/edit.mu.html
index 157998e3..8481c441 100644
--- a/html/edit.mu.html
+++ b/html/edit.mu.html
@@ -40,23 +40,34 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
   open-console
   width:number<span class="Special"> &lt;- </span>display-width
   height:number<span class="Special"> &lt;- </span>display-height
+  <span class="Comment"># draw a line</span>
   divider:number, _<span class="Special"> &lt;- </span>divide-with-remainder width:number, <span class="Constant">2:literal</span>
   draw-vertical <span class="Constant">0:literal/screen</span>, divider:number, <span class="Constant">0:literal/top</span>, height:number
-  in:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcdef</span>
-<span class="Constant">def</span>
-<span class="Constant">ghi</span>
-<span class="Constant">jkl</span>
-<span class="Constant">]</span>
-  editor:address:editor-data<span class="Special"> &lt;- </span>new-editor in:address:array:character, <span class="Constant">0:literal/screen</span>, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, divider:number/right
-  event-loop <span class="Constant">0:literal/screen</span>, <span class="Constant">0:literal/events</span>, editor:address:editor-data
+  <span class="Comment"># editor on the left</span>
+  left:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcde]</span>
+  left-editor:address:editor-data<span class="Special"> &lt;- </span>new-editor left:address:array:character, <span class="Constant">0:literal/screen</span>, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span> <span class="Comment">#divider:number/right</span>
+  <span class="Comment"># editor on the right</span>
+  right:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[def]</span>
+  new-left:number<span class="Special"> &lt;- </span>add divider:number/right, <span class="Constant">1:literal</span>
+  right-editor:address:editor-data<span class="Special"> &lt;- </span>new-editor right:address:array:character, <span class="Constant">0:literal/screen</span>, <span class="Constant">0:literal/top</span>, new-left:number, width:number
+  <span class="Comment"># chain</span>
+  x:address:address:editor-data<span class="Special"> &lt;- </span>get-address left-editor:address:editor-data/deref, next-editor:offset
+  x:address:address:editor-data/deref<span class="Special"> &lt;- </span>copy right-editor:address:editor-data
+  <span class="Comment"># initialize focus</span>
+  reset-focus left-editor:address:editor-data
+  cursor-row:number<span class="Special"> &lt;- </span>get left-editor:address:editor-data/deref, cursor-row:offset
+  cursor-column:number<span class="Special"> &lt;- </span>get left-editor:address:editor-data/deref, cursor-column:offset
+  move-cursor <span class="Constant">0:literal/screen</span>, cursor-row:number, cursor-column:number
+  <span class="Comment"># and we're off!</span>
+  event-loop <span class="Constant">0:literal/screen</span>, <span class="Constant">0:literal/events</span>, left-editor:address:editor-data
   close-console
 ]
 
 <span class="muScenario">scenario</span> editor-initially-prints-string-to-screen [
   assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
   run [
-    s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-    new-editor s:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span>
+    1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
   ]
   screen-should-contain [
    <span class="Constant"> .abc       .</span>
@@ -68,12 +79,12 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 <span class="SalientComment">## text to the screen.</span>
 
 container editor-data [
-  <span class="Comment"># doubly linked list of characters</span>
+  <span class="Comment"># doubly linked list of characters (head contains a special sentinel)</span>
   data:address:duplex-list
   <span class="Comment"># location of top-left of screen inside data (scrolling)</span>
   top-of-screen:address:duplex-list
-  <span class="Comment"># location of cursor inside data</span>
-  cursor:address:duplex-list
+  <span class="Comment"># location before cursor inside data</span>
+  before-cursor:address:duplex-list
 
   screen:address:screen
   <span class="Comment"># raw bounds of display area on screen</span>
@@ -84,6 +95,11 @@ container editor-data [
   <span class="Comment"># raw screen coordinates of cursor</span>
   cursor-row:number
   cursor-column:number
+
+  <span class="Comment"># pointer to another editor, responsible for a different area of screen.</span>
+  <span class="Comment"># helps organize editors in a 'chain'.</span>
+  next-editor:address:editor-data
+  in-focus?:boolean  <span class="Comment"># set for the one editor in this chain currently being edited</span>
 ]
 
 <span class="Comment"># editor:address, screen:address &lt;- new-editor s:address:array:character, screen:address, top:number, left:number, bottom:number</span>
@@ -109,31 +125,40 @@ container editor-data [
   x:address:number/deref<span class="Special"> &lt;- </span>copy left:number
   x:address:number<span class="Special"> &lt;- </span>get-address result:address:editor-data/deref, right:offset
   x:address:number/deref<span class="Special"> &lt;- </span>copy right:number
-  <span class="Comment"># initialize bottom to top for starters</span>
+  <span class="Comment"># bottom = top (in case of early exit)</span>
   x:address:number<span class="Special"> &lt;- </span>get-address result:address:editor-data/deref, bottom:offset
   x:address:number/deref<span class="Special"> &lt;- </span>copy top:number
   <span class="Comment"># initialize cursor</span>
   x:address:number<span class="Special"> &lt;- </span>get-address result:address:editor-data/deref, cursor-row:offset
   x:address:number/deref<span class="Special"> &lt;- </span>copy top:number
   x:address:number<span class="Special"> &lt;- </span>get-address result:address:editor-data/deref, cursor-column:offset
+<span class="CommentedCode">#?   $print left:number, [ </span>
+<span class="CommentedCode">#? ] #? 1</span>
   x:address:number/deref<span class="Special"> &lt;- </span>copy left:number
+  d:address:address:duplex-list<span class="Special"> &lt;- </span>get-address result:address:editor-data/deref, data:offset
+  d:address:address:duplex-list/deref<span class="Special"> &lt;- </span>push-duplex <span class="Constant">167:literal/§</span>, <span class="Constant">0:literal/tail</span>
+  y:address:address:duplex-list<span class="Special"> &lt;- </span>get-address result:address:editor-data/deref, before-cursor:offset
+  y:address:address:duplex-list/deref<span class="Special"> &lt;- </span>copy d:address:address:duplex-list/deref
+  init:address:address:duplex-list<span class="Special"> &lt;- </span>get-address result:address:editor-data/deref, top-of-screen:offset
+  init:address:address:duplex-list/deref<span class="Special"> &lt;- </span>copy d:address:address:duplex-list/deref
+  <span class="Comment"># set focus</span>
+  <span class="Comment"># if using multiple editors, must call reset-focus after chaining them all</span>
+  b:address:boolean<span class="Special"> &lt;- </span>get-address result:address:editor-data/deref, in-focus?:offset
+  b:address:boolean/deref<span class="Special"> &lt;- </span>copy <span class="Constant">1:literal/true</span>
+<span class="CommentedCode">#?   $print d:address:address:duplex-list/deref, [ </span>
+<span class="CommentedCode">#? ] #? 1</span>
   <span class="Comment"># early exit if s is empty</span>
   <span class="muControl">reply-unless</span> s:address:array:character, result:address:editor-data
   len:number<span class="Special"> &lt;- </span>length s:address:array:character/deref
   <span class="muControl">reply-unless</span> len:number, result:address:editor-data
   idx:number<span class="Special"> &lt;- </span>copy <span class="Constant">0:literal</span>
-  <span class="Comment"># s is guaranteed to have at least one character, so initialize result's</span>
-  <span class="Comment"># duplex-list</span>
-  init:address:address:duplex-list<span class="Special"> &lt;- </span>get-address result:address:editor-data/deref, top-of-screen:offset
-  init:address:address:duplex-list/deref<span class="Special"> &lt;- </span>copy <span class="Constant">0:literal</span>
-  c:character<span class="Special"> &lt;- </span>index s:address:array:character/deref, idx:number
-  idx:number<span class="Special"> &lt;- </span>add idx:number, <span class="Constant">1:literal</span>
-  init:address:address:duplex-list/deref<span class="Special"> &lt;- </span>push c:character, init:address:address:duplex-list/deref
-  curr:address:duplex-list<span class="Special"> &lt;- </span>copy init:address:address:duplex-list/deref
   <span class="Comment"># now we can start appending the rest, character by character</span>
+  curr:address:duplex-list<span class="Special"> &lt;- </span>copy init:address:address:duplex-list/deref
   <span class="Delimiter">{</span>
 <span class="CommentedCode">#?     $print idx:number, [ vs ], len:number, [ </span>
 <span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?     $print [append to ], curr:address:duplex-list, [ </span>
+<span class="CommentedCode">#? ] #? 1</span>
     done?:boolean<span class="Special"> &lt;- </span>greater-or-equal idx:number, len:number
     <span class="muControl">break-if</span> done?:boolean
     c:character<span class="Special"> &lt;- </span>index s:address:array:character/deref, idx:number
@@ -146,11 +171,11 @@ container editor-data [
     <span class="muControl">loop</span>
   <span class="Delimiter">}</span>
   <span class="Comment"># initialize cursor to top of screen</span>
-  y:address:address:duplex-list<span class="Special"> &lt;- </span>get-address result:address:editor-data/deref, cursor:offset
+  y:address:address:duplex-list<span class="Special"> &lt;- </span>get-address result:address:editor-data/deref, before-cursor:offset
   y:address:address:duplex-list/deref<span class="Special"> &lt;- </span>copy init:address:address:duplex-list/deref
   <span class="Comment"># perform initial rendering to screen</span>
   bottom:address:number<span class="Special"> &lt;- </span>get-address result:address:editor-data/deref, bottom:offset
-  bottom:address:number/deref, screen:address<span class="Special"> &lt;- </span>render result:address:editor-data, screen:address, top:number, left:number, right:number
+  result:address:editor-data<span class="Special"> &lt;- </span>render result:address:editor-data
   <span class="muControl">reply</span> result:address:editor-data
 ]
 
@@ -161,9 +186,9 @@ container editor-data [
     2:editor-data<span class="Special"> &lt;- </span>copy 1:address:editor-data/deref
   ]
   memory-should-contain [
-    2<span class="Special"> &lt;- </span>0  <span class="Comment"># data</span>
-    3<span class="Special"> &lt;- </span>0  <span class="Comment"># pointer into data to top of screen</span>
-    4<span class="Special"> &lt;- </span>0  <span class="Comment"># pointer into data to cursor</span>
+    <span class="Comment"># 2 &lt;- just the § sentinel</span>
+    <span class="Comment"># 3 (top of screen) &lt;- the § sentinel</span>
+    <span class="Comment"># 4 (before cursor) &lt;- the § sentinel</span>
     <span class="Comment"># 5 &lt;- screen</span>
     6<span class="Special"> &lt;- </span>1  <span class="Comment"># top</span>
     7<span class="Special"> &lt;- </span>2  <span class="Comment"># left</span>
@@ -180,19 +205,26 @@ container editor-data [
 ]
 
 <span class="muRecipe">recipe</span> render [
-  <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new location:type, <span class="Constant">30:literal</span>
+  <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new location:type, <span class="Constant">40:literal</span>
   editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  top:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  left:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+<span class="CommentedCode">#?   $print [=== render</span>
+<span class="CommentedCode">#? ] #? 2</span>
+  screen:address<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, screen:offset
+  top:number<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, top:offset
+  left:number<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, left:offset
   screen-height:number<span class="Special"> &lt;- </span>screen-height screen:address
-  right:number<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  cursor:address:duplex-list<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, cursor:offset
+  right:number<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, right:offset
+  hide-screen screen:address
   <span class="Comment"># traversing editor</span>
   curr:address:duplex-list<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, top-of-screen:offset
+  prev:address:duplex-list<span class="Special"> &lt;- </span>copy curr:address:duplex-list
+  curr:address:duplex-list<span class="Special"> &lt;- </span>next-duplex curr:address:duplex-list
   <span class="Comment"># traversing screen</span>
   row:number<span class="Special"> &lt;- </span>copy top:number
   column:number<span class="Special"> &lt;- </span>copy left:number
+  cursor-row:address:number<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, cursor-row:offset
+  cursor-column:address:number<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, cursor-column:offset
+  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, before-cursor:offset
   move-cursor screen:address, row:number, column:number
   <span class="Delimiter">{</span>
 <span class="Constant">    +next-character</span>
@@ -201,21 +233,56 @@ container editor-data [
     <span class="muControl">break-unless</span> curr:address:duplex-list
     off-screen?:boolean<span class="Special"> &lt;- </span>greater-or-equal row:number, screen-height:number
     <span class="muControl">break-if</span> off-screen?:boolean
+    <span class="Comment"># update editor-data.before-cursor</span>
+    <span class="Comment"># Doing so at the start of each iteration ensures it stays one step behind</span>
+    <span class="Comment"># the current character.</span>
     <span class="Delimiter">{</span>
-      at-cursor?:boolean<span class="Special"> &lt;- </span>equal curr:address:duplex-list, cursor:address:duplex-list
+      at-cursor-row?:boolean<span class="Special"> &lt;- </span>equal row:number, cursor-row:address:number/deref
+      <span class="muControl">break-unless</span> at-cursor-row?:boolean
+      at-cursor?:boolean<span class="Special"> &lt;- </span>equal column:number, cursor-column:address:number/deref
       <span class="muControl">break-unless</span> at-cursor?:boolean
-      cursor-row:number<span class="Special"> &lt;- </span>copy row:number
-      cursor-column:number<span class="Special"> &lt;- </span>copy column:number
+      before-cursor:address:address:duplex-list/deref<span class="Special"> &lt;- </span>prev-duplex curr:address:duplex-list
+<span class="CommentedCode">#?       new-prev:character &lt;- get before-cursor:address:address:duplex-list/deref/deref, value:offset #? 1</span>
+<span class="CommentedCode">#?       $print [render 0: cursor adjusted to after ], new-prev:character, [(], cursor-row:address:number/deref, [, ], cursor-column:address:number/deref, [)</span>
+<span class="CommentedCode">#? ] #? 1</span>
     <span class="Delimiter">}</span>
     c:character<span class="Special"> &lt;- </span>get curr:address:duplex-list/deref, value:offset
+<span class="CommentedCode">#?     $print [rendering ], c:character, [ </span>
+<span class="CommentedCode">#? ] #? 2</span>
     <span class="Delimiter">{</span>
       <span class="Comment"># newline? move to left rather than 0</span>
       newline?:boolean<span class="Special"> &lt;- </span>equal c:character, <span class="Constant">10:literal/newline</span>
       <span class="muControl">break-unless</span> newline?:boolean
+      <span class="Comment"># adjust cursor if necessary</span>
+      <span class="Delimiter">{</span>
+        at-cursor-row?:boolean<span class="Special"> &lt;- </span>equal row:number, cursor-row:address:number/deref
+        <span class="muControl">break-unless</span> at-cursor-row?:boolean
+        left-of-cursor?:boolean<span class="Special"> &lt;- </span>lesser-than column:number, cursor-column:address:number/deref
+        <span class="muControl">break-unless</span> left-of-cursor?:boolean
+        cursor-column:address:number/deref<span class="Special"> &lt;- </span>copy column:number
+        before-cursor:address:address:duplex-list/deref<span class="Special"> &lt;- </span>prev-duplex curr:address:duplex-list
+<span class="CommentedCode">#?         new-prev:character &lt;- get before-cursor:address:address:duplex-list/deref/deref, value:offset #? 1</span>
+<span class="CommentedCode">#?         $print [render 1: cursor adjusted to after ], new-prev:character, [(], cursor-row:address:number/deref, [, ], cursor-column:address:number/deref, [)</span>
+<span class="CommentedCode">#? ] #? 1</span>
+      <span class="Delimiter">}</span>
+      <span class="Comment"># clear rest of line in this window</span>
+<span class="CommentedCode">#?       $print row:number, [ ], column:number, [ ], right:number, [ </span>
+<span class="CommentedCode">#? ] #? 1</span>
+      <span class="Delimiter">{</span>
+        done?:boolean<span class="Special"> &lt;- </span>greater-than column:number, right:number
+        <span class="muControl">break-if</span> done?:boolean
+        print-character screen:address, <span class="Constant">32:literal/space</span>
+        column:number<span class="Special"> &lt;- </span>add column:number, <span class="Constant">1:literal</span>
+<span class="CommentedCode">#?         $print column:number, [ </span>
+<span class="CommentedCode">#? ] #? 1</span>
+        <span class="muControl">loop</span>
+      <span class="Delimiter">}</span>
+      <span class="Comment"># skip to next line</span>
       row:number<span class="Special"> &lt;- </span>add row:number, <span class="Constant">1:literal</span>
       column:number<span class="Special"> &lt;- </span>copy left:number
       move-cursor screen:address, row:number, column:number
       curr:address:duplex-list<span class="Special"> &lt;- </span>next-duplex curr:address:duplex-list
+      prev:address:duplex-list<span class="Special"> &lt;- </span>next-duplex prev:address:duplex-list
       <span class="muControl">loop</span> <span class="Constant">+next-character:label</span>
     <span class="Delimiter">}</span>
     <span class="Delimiter">{</span>
@@ -237,11 +304,82 @@ container editor-data [
     <span class="Delimiter">}</span>
     print-character screen:address, c:character
     curr:address:duplex-list<span class="Special"> &lt;- </span>next-duplex curr:address:duplex-list
+    prev:address:duplex-list<span class="Special"> &lt;- </span>next-duplex prev:address:duplex-list
     column:number<span class="Special"> &lt;- </span>add column:number, <span class="Constant">1:literal</span>
     <span class="muControl">loop</span>
   <span class="Delimiter">}</span>
-  move-cursor screen:address, cursor-row:number, cursor-column:number
-  <span class="muControl">reply</span> row:number, screen:address/same-as-ingredient:1
+  <span class="Comment"># bottom = row</span>
+  bottom:address:number<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, bottom:offset
+  bottom:address:number/deref<span class="Special"> &lt;- </span>copy row:number
+  <span class="Comment"># is cursor to the right of the last line? move to end</span>
+  <span class="Delimiter">{</span>
+    at-cursor-row?:boolean<span class="Special"> &lt;- </span>equal row:number, cursor-row:address:number/deref
+    cursor-outside-line?:boolean<span class="Special"> &lt;- </span>lesser-or-equal column:number, cursor-column:address:number/deref
+    before-cursor-on-same-line?:boolean<span class="Special"> &lt;- </span>and at-cursor-row?:boolean, cursor-outside-line?:boolean
+    above-cursor-row?:boolean<span class="Special"> &lt;- </span>lesser-than row:number, cursor-row:address:number/deref
+    before-cursor?:boolean<span class="Special"> &lt;- </span>or before-cursor-on-same-line?:boolean, above-cursor-row?:boolean
+    <span class="muControl">break-unless</span> before-cursor?:boolean
+<span class="CommentedCode">#?     $print [pointed after all text</span>
+<span class="CommentedCode">#? ] #? 1</span>
+    cursor-row:address:number/deref<span class="Special"> &lt;- </span>copy row:number
+    cursor-column:address:number/deref<span class="Special"> &lt;- </span>copy column:number
+<span class="CommentedCode">#?     $print [render: cursor moved to ], cursor-row:address:number/deref, [, ], cursor-column:address:number/deref, [ </span>
+<span class="CommentedCode">#? ] #? 1</span>
+    <span class="Comment"># line not wrapped but cursor outside bounds? wrap cursor</span>
+    <span class="Delimiter">{</span>
+      too-far-right?:boolean<span class="Special"> &lt;- </span>greater-than cursor-column:address:number/deref, right:number
+      <span class="muControl">break-unless</span> too-far-right?:boolean
+      cursor-column:address:number/deref<span class="Special"> &lt;- </span>copy left:number
+      cursor-row:address:number/deref<span class="Special"> &lt;- </span>add cursor-row:address:number/deref, <span class="Constant">1:literal</span>
+      above-screen-bottom?:boolean<span class="Special"> &lt;- </span>lesser-than cursor-row:address:number/deref, screen-height:number
+      assert above-screen-bottom?:boolean, <span class="Constant">[unimplemented: wrapping cursor past bottom of screen]</span>
+    <span class="Delimiter">}</span>
+<span class="CommentedCode">#?     $print [now ], cursor-row:address:number/deref, [, ], cursor-column:address:number/deref, [ </span>
+<span class="CommentedCode">#? ] #? 1</span>
+    before-cursor:address:address:duplex-list/deref<span class="Special"> &lt;- </span>copy prev:address:duplex-list
+<span class="CommentedCode">#?     new-prev:character &lt;- get before-cursor:address:address:duplex-list/deref/deref, value:offset #? 1</span>
+<span class="CommentedCode">#?     $print [render Ω: cursor adjusted to after ], new-prev:character, [(], cursor-row:address:number/deref, [, ], cursor-column:address:number/deref, [)</span>
+<span class="CommentedCode">#? ] #? 1</span>
+  <span class="Delimiter">}</span>
+<span class="CommentedCode">#?   $print [clearing ], row:number, [ ], column:number, [ ], right:number, [ </span>
+<span class="CommentedCode">#? ] #? 2</span>
+  <span class="Delimiter">{</span>
+    <span class="Comment"># clear rest of current line</span>
+    done?:boolean<span class="Special"> &lt;- </span>greater-or-equal row:number, screen-height:number
+    <span class="muControl">break-if</span> done?:boolean
+    <span class="Delimiter">{</span>
+      line-done?:boolean<span class="Special"> &lt;- </span>greater-than column:number, right:number
+      <span class="muControl">break-if</span> line-done?:boolean
+      print-character screen:address, <span class="Constant">32:literal/space</span>
+      column:number<span class="Special"> &lt;- </span>add column:number, <span class="Constant">1:literal</span>
+      <span class="muControl">loop</span>
+    <span class="Delimiter">}</span>
+    <span class="Comment"># clear one more line just in case we just backspaced out of it</span>
+    row:number<span class="Special"> &lt;- </span>add row:number, <span class="Constant">1:literal</span>
+    column:number<span class="Special"> &lt;- </span>copy left:number
+    done?:boolean<span class="Special"> &lt;- </span>greater-or-equal row:number, screen-height:number
+    <span class="muControl">break-if</span> done?:boolean
+    move-cursor screen:address, row:number, column:number
+    <span class="Delimiter">{</span>
+      line-done?:boolean<span class="Special"> &lt;- </span>greater-or-equal column:number, right:number
+      <span class="muControl">break-if</span> line-done?:boolean
+      print-character screen:address, <span class="Constant">32:literal/space</span>
+      column:number<span class="Special"> &lt;- </span>add column:number, <span class="Constant">1:literal</span>
+      <span class="muControl">loop</span>
+    <span class="Delimiter">}</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># update cursor</span>
+  <span class="Delimiter">{</span>
+    in-focus?:boolean<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, in-focus?:offset
+    <span class="muControl">break-unless</span> in-focus?:boolean
+    cursor-inside-right-margin?:boolean<span class="Special"> &lt;- </span>lesser-or-equal cursor-column:address:number/deref, right:number
+    assert cursor-inside-right-margin?:boolean, <span class="Constant">[cursor outside right margin]</span>
+    cursor-inside-left-margin?:boolean<span class="Special"> &lt;- </span>greater-or-equal cursor-column:address:number/deref, left:number
+    assert cursor-inside-left-margin?:boolean, <span class="Constant">[cursor outside left margin]</span>
+    move-cursor screen:address, cursor-row:address:number/deref, cursor-column:address:number/deref
+  <span class="Delimiter">}</span>
+  show-screen screen:address
+  <span class="muControl">reply</span> editor:address:editor-data/same-as-ingredient:0
 ]
 
 <span class="muScenario">scenario</span> editor-initially-prints-multiple-lines [
@@ -303,50 +441,364 @@ container editor-data [
   ]
 ]
 
-<span class="SalientComment">## handling events from the keyboard and mouse</span>
+<span class="muScenario">scenario</span> editor-initializes-empty-text [
+  assume-screen <span class="Constant">5:literal/width</span>, <span class="Constant">3:literal/height</span>
+  run [
+    1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+    2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span>
+    3:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  screen-should-contain [
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .     .</span>
+   <span class="Constant"> .     .</span>
+  ]
+  memory-should-contain [
+    3<span class="Special"> &lt;- </span>0  <span class="Comment"># cursor row</span>
+    4<span class="Special"> &lt;- </span>0  <span class="Comment"># cursor column</span>
+  ]
+]
+
+<span class="SalientComment">## handling events from the keyboard, mouse, touch screen, ...</span>
 
+<span class="Comment"># Takes a chain of editors (chained using editor-data.next-editor), sends each</span>
+<span class="Comment"># event from the console to each editor.</span>
 <span class="muRecipe">recipe</span> event-loop [
   <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new location:type, <span class="Constant">30:literal</span>
   screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
   <span class="Delimiter">{</span>
-<span class="Constant">    +next-event</span>
+    <span class="Comment"># send each event to each editor</span>
     e:event, console:address, found?:boolean, quit?:boolean<span class="Special"> &lt;- </span>read-event console:address
     <span class="muControl">loop-unless</span> found?:boolean
     <span class="muControl">break-if</span> quit?:boolean  <span class="Comment"># only in tests</span>
     trace <span class="Constant">[app]</span>, <span class="Constant">[next-event]</span>
+<span class="CommentedCode">#?     $print [--- new event</span>
+<span class="CommentedCode">#? ] #? 1</span>
+    curr:address:editor-data<span class="Special"> &lt;- </span>copy editor:address:editor-data
     <span class="Delimiter">{</span>
-      t:address:touch-event<span class="Special"> &lt;- </span>maybe-convert e:event, touch:variant
-      <span class="muControl">break-unless</span> t:address:touch-event
-      editor:address:editor-data<span class="Special"> &lt;- </span>move-cursor-in-editor editor:address:editor-data, t:address:touch-event
-      <span class="muControl">loop</span> <span class="Constant">+next-event:label</span>
+      <span class="muControl">break-unless</span> curr:address:editor-data
+      handle-event screen:address, console:address, curr:address:editor-data, e:event
+      curr:address:editor-data<span class="Special"> &lt;- </span>get curr:address:editor-data/deref, next-editor:offset
+      <span class="muControl">loop</span>
+    <span class="Delimiter">}</span>
+    <span class="Comment"># after each non-trivial event, render all editors</span>
+    curr:address:editor-data<span class="Special"> &lt;- </span>copy editor:address:editor-data
+    <span class="Delimiter">{</span>
+      <span class="muControl">break-unless</span> curr:address:editor-data
+      render curr:address:editor-data
+      curr:address:editor-data<span class="Special"> &lt;- </span>get curr:address:editor-data/deref, next-editor:offset
+      <span class="muControl">loop</span>
+    <span class="Delimiter">}</span>
+    <span class="Comment"># ..and position the cursor</span>
+    curr:address:editor-data<span class="Special"> &lt;- </span>copy editor:address:editor-data
+    <span class="Delimiter">{</span>
+      <span class="muControl">break-unless</span> curr:address:editor-data
+      <span class="Delimiter">{</span>
+        in-focus?:boolean<span class="Special"> &lt;- </span>get curr:address:editor-data/deref, in-focus?:offset
+        <span class="muControl">break-unless</span> in-focus?:boolean
+        cursor-row:number<span class="Special"> &lt;- </span>get curr:address:editor-data/deref, cursor-row:offset
+        cursor-column:number<span class="Special"> &lt;- </span>get curr:address:editor-data/deref, cursor-column:offset
+        move-cursor screen:address, cursor-row:number, cursor-column:number
+      <span class="Delimiter">}</span>
+      curr:address:editor-data<span class="Special"> &lt;- </span>get curr:address:editor-data/deref, next-editor:offset
+      <span class="muControl">loop</span>
     <span class="Delimiter">}</span>
-    c:address:character<span class="Special"> &lt;- </span>maybe-convert e:event, text:variant
-    assert c:address:character, <span class="Constant">[event was of unknown type; neither keyboard nor mouse]</span>
     <span class="muControl">loop</span>
   <span class="Delimiter">}</span>
 ]
 
+<span class="muRecipe">recipe</span> handle-event [
+  <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new location:type, <span class="Constant">50:literal</span>
+  screen:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  console:address<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  e:event<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Comment"># 'touch' event</span>
+  <span class="Delimiter">{</span>
+    t:address:touch-event<span class="Special"> &lt;- </span>maybe-convert e:event, touch:variant
+    <span class="muControl">break-unless</span> t:address:touch-event
+    move-cursor-in-editor editor:address:editor-data, t:address:touch-event/deref
+    <span class="muControl">reply</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># other events trigger only if this editor is in focus</span>
+<span class="CommentedCode">#?   $print [checking ], editor:address:editor-data, [ </span>
+<span class="CommentedCode">#? ] #? 1</span>
+<span class="CommentedCode">#?   x:address:boolean &lt;- get-address editor:address:editor-data/deref, in-focus?:offset #? 1</span>
+<span class="CommentedCode">#?   $print [address of focus: ], x:address:boolean, [ </span>
+<span class="CommentedCode">#? ] #? 1</span>
+  in-focus?:address:boolean<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, in-focus?:offset
+<span class="CommentedCode">#?   $print [ at ], in-focus?:address:boolean, [ </span>
+<span class="CommentedCode">#? ] #? 1</span>
+  <span class="muControl">reply-unless</span> in-focus?:address:boolean/deref
+<span class="CommentedCode">#?   $print [in focus: ], editor:address:editor-data, [ </span>
+<span class="CommentedCode">#? ] #? 1</span>
+  <span class="Comment"># typing a character</span>
+  <span class="Delimiter">{</span>
+    c:address:character<span class="Special"> &lt;- </span>maybe-convert e:event, text:variant
+    <span class="muControl">break-unless</span> c:address:character
+    <span class="Comment"># unless it's a backspace</span>
+    <span class="Delimiter">{</span>
+      backspace?:boolean<span class="Special"> &lt;- </span>equal c:address:character/deref, <span class="Constant">8:literal/backspace</span>
+      <span class="muControl">break-unless</span> backspace?:boolean
+      delete-before-cursor editor:address:editor-data
+      <span class="muControl">reply</span>
+    <span class="Delimiter">}</span>
+    insert-at-cursor editor:address:editor-data, c:address:character/deref
+    <span class="muControl">reply</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># otherwise it's a special key to control the editor</span>
+  k:address:number<span class="Special"> &lt;- </span>maybe-convert e:event, keycode:variant
+  assert k:address:number, <span class="Constant">[event was of unknown type; neither keyboard nor mouse]</span>
+  d:address:duplex-list<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, data:offset
+  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, before-cursor:offset
+  cursor-row:address:number<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, cursor-row:offset
+  cursor-column:address:number<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, cursor-column:offset
+  screen-height:number<span class="Special"> &lt;- </span>screen-height screen:address
+  top:number<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, top:offset
+  <span class="Comment"># arrows; update cursor-row and cursor-column, leave before-cursor to 'render'.</span>
+  <span class="Comment"># right arrow</span>
+  <span class="Delimiter">{</span>
+    move-to-next-character?:boolean<span class="Special"> &lt;- </span>equal k:address:number/deref, <span class="Constant">65514:literal/right-arrow</span>
+    <span class="muControl">break-unless</span> move-to-next-character?:boolean
+    <span class="Comment"># if not at end of text</span>
+    old-cursor:address:duplex-list<span class="Special"> &lt;- </span>next-duplex before-cursor:address:address:duplex-list/deref
+    <span class="muControl">break-unless</span> old-cursor:address:duplex-list
+    <span class="Comment"># scan to next character</span>
+    before-cursor:address:address:duplex-list/deref<span class="Special"> &lt;- </span>copy old-cursor:address:duplex-list
+    <span class="Comment"># if crossed a newline, move cursor to start of next row</span>
+    <span class="Delimiter">{</span>
+      old-cursor-character:character<span class="Special"> &lt;- </span>get before-cursor:address:address:duplex-list/deref/deref, value:offset
+      was-at-newline?:boolean<span class="Special"> &lt;- </span>equal old-cursor-character:character, <span class="Constant">10:literal/newline</span>
+      <span class="muControl">break-unless</span> was-at-newline?:boolean
+      cursor-row:address:number/deref<span class="Special"> &lt;- </span>add cursor-row:address:number/deref, <span class="Constant">1:literal</span>
+      cursor-column:address:number/deref<span class="Special"> &lt;- </span>copy <span class="Constant">0:literal</span>
+      <span class="Comment"># todo: what happens when cursor is too far down?</span>
+      screen-height:number<span class="Special"> &lt;- </span>screen-height screen:address
+      above-screen-bottom?:boolean<span class="Special"> &lt;- </span>lesser-than cursor-row:address:number/deref, screen-height:number
+      assert above-screen-bottom?:boolean, <span class="Constant">[unimplemented: moving past bottom of screen]</span>
+      <span class="muControl">reply</span>
+    <span class="Delimiter">}</span>
+    <span class="Comment"># if the line wraps, move cursor to start of next row</span>
+    <span class="Delimiter">{</span>
+      <span class="Comment"># if we're at the column just before the wrap indicator</span>
+      right:number<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, right:offset
+      wrap-column:number<span class="Special"> &lt;- </span>subtract right:number, <span class="Constant">1:literal</span>
+      at-wrap?:boolean<span class="Special"> &lt;- </span>equal cursor-column:address:number/deref, wrap-column:number
+      <span class="muControl">break-unless</span> at-wrap?:boolean
+      <span class="Comment"># and if character after next isn't newline</span>
+<span class="CommentedCode">#?       $print [aaa] #? 1</span>
+      new-cursor:address:duplex-list<span class="Special"> &lt;- </span>next-duplex old-cursor:address:duplex-list
+      <span class="muControl">break-unless</span> new-cursor:address:duplex-list
+      next:address:duplex-list<span class="Special"> &lt;- </span>next-duplex new-cursor:address:duplex-list
+      <span class="muControl">break-unless</span> next:address:duplex-list
+      next-character:character<span class="Special"> &lt;- </span>get next:address:duplex-list/deref, value:offset
+      newline?:boolean<span class="Special"> &lt;- </span>equal next-character:character, <span class="Constant">10:literal/newline</span>
+      <span class="muControl">break-if</span> newline?:boolean
+      cursor-row:address:number/deref<span class="Special"> &lt;- </span>add cursor-row:address:number/deref, <span class="Constant">1:literal</span>
+      cursor-column:address:number/deref<span class="Special"> &lt;- </span>copy <span class="Constant">0:literal</span>
+      <span class="Comment"># todo: what happens when cursor is too far down?</span>
+      above-screen-bottom?:boolean<span class="Special"> &lt;- </span>lesser-than cursor-row:address:number/deref, screen-height:number
+      assert above-screen-bottom?:boolean, <span class="Constant">[unimplemented: moving past bottom of screen]</span>
+      <span class="muControl">reply</span>
+    <span class="Delimiter">}</span>
+    <span class="Comment"># otherwise move cursor one character right</span>
+    cursor-column:address:number/deref<span class="Special"> &lt;- </span>add cursor-column:address:number/deref, <span class="Constant">1:literal</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># left arrow</span>
+  <span class="Delimiter">{</span>
+    move-to-previous-character?:boolean<span class="Special"> &lt;- </span>equal k:address:number/deref, <span class="Constant">65515:literal/left-arrow</span>
+    <span class="muControl">break-unless</span> move-to-previous-character?:boolean
+    <span class="Comment"># if not at start of text (before-cursor at § sentinel)</span>
+    prev:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex before-cursor:address:address:duplex-list/deref
+    <span class="muControl">break-unless</span> prev:address:duplex-list
+    <span class="Comment"># if cursor not at left margin, move one character left</span>
+    <span class="Delimiter">{</span>
+      at-left-margin?:boolean<span class="Special"> &lt;- </span>equal cursor-column:address:number/deref, <span class="Constant">0:literal</span>
+      <span class="muControl">break-if</span> at-left-margin?:boolean
+      cursor-column:address:number/deref<span class="Special"> &lt;- </span>subtract cursor-column:address:number/deref, <span class="Constant">1:literal</span>
+      <span class="muControl">reply</span>
+    <span class="Delimiter">}</span>
+    <span class="Comment"># if at left margin, there's guaranteed to be a previous line, since we're</span>
+    <span class="Comment"># not at start of text</span>
+    <span class="Delimiter">{</span>
+      <span class="Comment"># if before-cursor is at newline, figure out how long the previous line is</span>
+      prevc:character<span class="Special"> &lt;- </span>get before-cursor:address:address:duplex-list/deref/deref, value:offset
+      previous-character-is-newline?:boolean<span class="Special"> &lt;- </span>equal prevc:character, <span class="Constant">10:literal/newline</span>
+      <span class="muControl">break-unless</span> previous-character-is-newline?:boolean
+      <span class="Comment"># compute length of previous line</span>
+      end-of-line:number<span class="Special"> &lt;- </span>previous-line-length before-cursor:address:address:duplex-list/deref, d:address:duplex-list
+      cursor-row:address:number/deref<span class="Special"> &lt;- </span>subtract cursor-row:address:number/deref, <span class="Constant">1:literal</span>
+      cursor-column:address:number/deref<span class="Special"> &lt;- </span>copy end-of-line:number
+      <span class="muControl">reply</span>
+    <span class="Delimiter">}</span>
+    <span class="Comment"># if before-cursor is not at newline, we're just at a wrapped line</span>
+    assert cursor-row:address:number/deref, <span class="Constant">[unimplemented: moving cursor above top of screen]</span>
+    cursor-row:address:number/deref<span class="Special"> &lt;- </span>subtract cursor-row:address:number/deref, <span class="Constant">1:literal</span>
+    right:number<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, right:offset
+    cursor-column:address:number/deref<span class="Special"> &lt;- </span>subtract right:number, <span class="Constant">1:literal</span>  <span class="Comment"># leave room for wrap icon</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># down arrow</span>
+  <span class="Delimiter">{</span>
+    move-to-next-line?:boolean<span class="Special"> &lt;- </span>equal k:address:number/deref, <span class="Constant">65516:literal/down-arrow</span>
+    <span class="muControl">break-unless</span> move-to-next-line?:boolean
+    <span class="Comment"># todo: support scrolling</span>
+    already-at-bottom?:boolean<span class="Special"> &lt;- </span>greater-or-equal cursor-row:address:number/deref, screen-height:number
+    <span class="muControl">break-if</span> already-at-bottom?:boolean
+<span class="CommentedCode">#?     $print [moving down</span>
+<span class="CommentedCode">#? ] #? 1</span>
+    cursor-row:address:number/deref<span class="Special"> &lt;- </span>add cursor-row:address:number/deref, <span class="Constant">1:literal</span>
+    <span class="Comment"># that's it; render will adjust cursor-column as necessary</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># up arrow</span>
+  <span class="Delimiter">{</span>
+    move-to-previous-line?:boolean<span class="Special"> &lt;- </span>equal k:address:number/deref, <span class="Constant">65517:literal/up-arrow</span>
+    <span class="muControl">break-unless</span> move-to-previous-line?:boolean
+    <span class="Comment"># todo: support scrolling</span>
+    already-at-top?:boolean<span class="Special"> &lt;- </span>lesser-or-equal cursor-row:address:number/deref, top:number
+    <span class="muControl">break-if</span> already-at-top?:boolean
+<span class="CommentedCode">#?     $print [moving up</span>
+<span class="CommentedCode">#? ] #? 1</span>
+    cursor-row:address:number/deref<span class="Special"> &lt;- </span>subtract cursor-row:address:number/deref, <span class="Constant">1:literal</span>
+    <span class="Comment"># that's it; render will adjust cursor-column as necessary</span>
+  <span class="Delimiter">}</span>
+]
+
 <span class="muRecipe">recipe</span> move-cursor-in-editor [
   <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new location:type, <span class="Constant">30:literal</span>
   editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  t:address:touch-event<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
-  row:address:number<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, cursor-row:offset
-  row:address:number/deref<span class="Special"> &lt;- </span>get t:address:touch-event/deref, row:offset
-  column:address:number<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, cursor-column:offset
-  column:address:number/deref<span class="Special"> &lt;- </span>get t:address:touch-event/deref, column:offset
-  <span class="Comment"># todo: adjust 'cursor' pointer into editor data</span>
+  t:touch-event<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  <span class="Comment"># always reset focus to start</span>
+  in-focus?:address:boolean<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, in-focus?:offset
+  in-focus?:address:boolean/deref<span class="Special"> &lt;- </span>copy <span class="Constant">0:literal/true</span>
+  click-column:number<span class="Special"> &lt;- </span>get t:touch-event, column:offset
+  left:number<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, left:offset
+  too-far-left?:boolean<span class="Special"> &lt;- </span>lesser-than click-column:number, left:number
+  <span class="muControl">reply-if</span> too-far-left?:boolean
+  right:number<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, right:offset
+  too-far-right?:boolean<span class="Special"> &lt;- </span>greater-than click-column:number, right:number
+  <span class="muControl">reply-if</span> too-far-right?:boolean
+<span class="CommentedCode">#?   $print [focus now at ], editor:address:editor-data, [ </span>
+<span class="CommentedCode">#? ] #? 2</span>
+  <span class="Comment"># click on this window; gain focus</span>
+  in-focus?:address:boolean/deref<span class="Special"> &lt;- </span>copy <span class="Constant">1:literal/true</span>
+  <span class="Comment"># update cursor</span>
+  cursor-row:address:number<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, cursor-row:offset
+  cursor-row:address:number/deref<span class="Special"> &lt;- </span>get t:touch-event, row:offset
+  cursor-column:address:number<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, cursor-column:offset
+  cursor-column:address:number/deref<span class="Special"> &lt;- </span>get t:touch-event, column:offset
+<span class="CommentedCode">#?   $print [column is at: ], cursor-column:address:number, [ </span>
+<span class="CommentedCode">#? ] #? 1</span>
+]
+
+<span class="muRecipe">recipe</span> insert-at-cursor [
+  <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new location:type, <span class="Constant">30:literal</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  c:character<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+<span class="CommentedCode">#?   $print [insert ], c:character, [ </span>
+<span class="CommentedCode">#? ] #? 1</span>
+  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, before-cursor:offset
+  d:address:duplex-list<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, data:offset
+  insert-duplex c:character, before-cursor:address:address:duplex-list/deref
+  screen:address<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, screen:offset
+  cursor-row:address:number<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, cursor-row:offset
+  cursor-column:address:number<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, cursor-column:offset
+  <span class="Comment"># update cursor: if newline, move cursor to start of next line</span>
+  <span class="Comment"># todo: bottom of screen</span>
+  <span class="Delimiter">{</span>
+    newline?:boolean<span class="Special"> &lt;- </span>equal c:character, <span class="Constant">10:literal/newline</span>
+    <span class="muControl">break-unless</span> newline?:boolean
+    cursor-row:address:number/deref<span class="Special"> &lt;- </span>add cursor-row:address:number/deref, <span class="Constant">1:literal</span>
+    cursor-column:address:number/deref<span class="Special"> &lt;- </span>copy <span class="Constant">0:literal</span>
+    <span class="muControl">reply</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># if the line wraps at the cursor, move cursor to start of next row</span>
+  <span class="Delimiter">{</span>
+    <span class="Comment"># if we're at the column just before the wrap indicator</span>
+    right:number<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, right:offset
+    wrap-column:number<span class="Special"> &lt;- </span>subtract right:number, <span class="Constant">1:literal</span>
+<span class="CommentedCode">#?     $print [wrap? ], cursor-column:address:number/deref, [ vs ], wrap-column:number, [ </span>
+<span class="CommentedCode">#? ] #? 1</span>
+    at-wrap?:boolean<span class="Special"> &lt;- </span>greater-or-equal cursor-column:address:number/deref, wrap-column:number
+    <span class="muControl">break-unless</span> at-wrap?:boolean
+<span class="CommentedCode">#?     $print [wrap!</span>
+<span class="CommentedCode">#? ] #? 1</span>
+    cursor-column:address:number/deref<span class="Special"> &lt;- </span>subtract cursor-column:address:number/deref, wrap-column:number
+    cursor-row:address:number/deref<span class="Special"> &lt;- </span>add cursor-row:address:number/deref, <span class="Constant">1:literal</span>
+    <span class="Comment"># todo: what happens when cursor is too far down?</span>
+    screen-height:number<span class="Special"> &lt;- </span>screen-height screen:address
+    above-screen-bottom?:boolean<span class="Special"> &lt;- </span>lesser-than cursor-row:address:number/deref, screen-height:number
+    assert above-screen-bottom?:boolean, <span class="Constant">[unimplemented: typing past bottom of screen]</span>
+<span class="CommentedCode">#?     $print [return</span>
+<span class="CommentedCode">#? ] #? 1</span>
+    <span class="muControl">reply</span>
+  <span class="Delimiter">}</span>
+  <span class="Comment"># otherwise move cursor right</span>
+  cursor-column:address:number/deref<span class="Special"> &lt;- </span>add cursor-column:address:number/deref, <span class="Constant">1:literal</span>
+]
+
+<span class="muRecipe">recipe</span> delete-before-cursor [
+  <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new location:type, <span class="Constant">30:literal</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  before-cursor:address:address:duplex-list<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, before-cursor:offset
+  d:address:duplex-list<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, data:offset
+  <span class="Comment"># unless already at start</span>
+  at-start?:boolean<span class="Special"> &lt;- </span>equal before-cursor:address:address:duplex-list/deref, d:address:duplex-list
+  <span class="muControl">reply-if</span> at-start?:boolean
+  <span class="Comment"># delete character</span>
+  prev:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex before-cursor:address:address:duplex-list/deref
+  remove-duplex before-cursor:address:address:duplex-list/deref
+  <span class="Comment"># update cursor</span>
+  before-cursor:address:address:duplex-list/deref<span class="Special"> &lt;- </span>copy prev:address:duplex-list
+  cursor-column:address:number<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, cursor-column:offset
+  cursor-column:address:number/deref<span class="Special"> &lt;- </span>subtract cursor-column:address:number/deref, <span class="Constant">1:literal</span>
+<span class="CommentedCode">#?   $print [delete-before-cursor: ], cursor-column:address:number/deref, [ </span>
+<span class="CommentedCode">#? ] #? 1</span>
+]
+
+<span class="Comment"># takes a pointer 'curr' into the doubly-linked list and its sentinel, counts</span>
+<span class="Comment"># the length of the previous line before the 'curr' pointer.</span>
+<span class="muRecipe">recipe</span> previous-line-length [
+  <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new location:type, <span class="Constant">30:literal</span>
+  curr:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  start:address:duplex-list<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  result:number<span class="Special"> &lt;- </span>copy <span class="Constant">0:literal</span>
+  <span class="muControl">reply-unless</span> curr:address:duplex-list, result:number
+  at-start?:boolean<span class="Special"> &lt;- </span>equal curr:address:duplex-list, start:address:duplex-list
+  <span class="muControl">reply-if</span> at-start?:boolean, result:number
+  <span class="Delimiter">{</span>
+    curr:address:duplex-list<span class="Special"> &lt;- </span>prev-duplex curr:address:duplex-list
+    <span class="muControl">break-unless</span> curr:address:duplex-list
+    at-start?:boolean<span class="Special"> &lt;- </span>equal curr:address:duplex-list, start:address:duplex-list
+    <span class="muControl">break-if</span> at-start?:boolean
+    c:character<span class="Special"> &lt;- </span>get curr:address:duplex-list/deref, value:offset
+    at-newline?:boolean<span class="Special"> &lt;- </span>equal c:character <span class="Constant">10:literal/newline</span>
+    <span class="muControl">break-if</span> at-newline?:boolean
+    result:number<span class="Special"> &lt;- </span>add result:number, <span class="Constant">1:literal</span>
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+  <span class="muControl">reply</span> result:number
 ]
 
 <span class="muScenario">scenario</span> editor-handles-empty-event-queue [
   assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+<span class="CommentedCode">#?   3:number &lt;- get screen:address/deref, num-rows:offset #? 1</span>
+<span class="CommentedCode">#?   $print [0: ], screen:address, [: ], 3:number, [ </span>
+<span class="CommentedCode">#? ] #? 1</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+<span class="CommentedCode">#?   $print [1: ], screen:address, [ </span>
+<span class="CommentedCode">#? ] #? 1</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
   assume-console <span class="Constant">[]</span>
+<span class="CommentedCode">#?   $print [8: ], screen:address, [ </span>
+<span class="CommentedCode">#? ] #? 1</span>
   run [
-    s:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-    editor:address:editor-data<span class="Special"> &lt;- </span>new-editor s:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span>
-    event-loop screen:address, console:address, editor:address:editor-data
+    event-loop screen:address, console:address, 2:address:editor-data
   ]
+<span class="CommentedCode">#?   $print [9: ], screen:address, [ </span>
+<span class="CommentedCode">#? ] #? 1</span>
   screen-should-contain [
    <span class="Constant"> .abc       .</span>
    <span class="Constant"> .          .</span>
@@ -355,12 +807,12 @@ container editor-data [
 
 <span class="muScenario">scenario</span> editor-handles-mouse-clicks [
   assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
   assume-console [
-    left-click 0, 1
+    left-click 0, 1  <span class="Comment"># on the 'b'</span>
   ]
   run [
-    1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
-    2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span>
     event-loop screen:address, console:address, 2:address:editor-data
     3:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
     4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
@@ -375,6 +827,927 @@ container editor-data [
   ]
 ]
 
+<span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-text [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  assume-console [
+    left-click 0, 7  <span class="Comment"># last line, to the right of text</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    3:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  memory-should-contain [
+    3<span class="Special"> &lt;- </span>0  <span class="Comment"># cursor row</span>
+    4<span class="Special"> &lt;- </span>3  <span class="Comment"># cursor column</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-text-2 [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  assume-console [
+    left-click 0, 7  <span class="Comment"># interior line, to the right of text</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    3:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  memory-should-contain [
+    3<span class="Special"> &lt;- </span>0  <span class="Comment"># cursor row</span>
+    4<span class="Special"> &lt;- </span>3  <span class="Comment"># cursor column</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-text-3 [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  assume-console [
+    left-click 2, 7  <span class="Comment"># below text</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    3:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  memory-should-contain [
+    3<span class="Special"> &lt;- </span>1  <span class="Comment"># cursor row</span>
+    4<span class="Special"> &lt;- </span>3  <span class="Comment"># cursor column</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-handles-mouse-clicks-outside-column [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  <span class="Comment"># editor occupies only left half of screen</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span>
+  assume-console [
+    <span class="Comment"># click on right half of screen</span>
+    left-click 3, 8
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    3:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  screen-should-contain [
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .          .</span>
+  ]
+  memory-should-contain [
+    3<span class="Special"> &lt;- </span>0  <span class="Comment"># no change to cursor row</span>
+    4<span class="Special"> &lt;- </span>0  <span class="Comment"># ..or column</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-inserts-characters-into-empty-editor [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span>
+  assume-console [
+    type <span class="Constant">[abc]</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  assume-console [
+    type <span class="Constant">[0]</span>
+    left-click 0, 2
+    type <span class="Constant">[d]</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .0adbc     .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-2 [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  assume-console [
+    left-click 0, 5  <span class="Comment"># right of last line</span>
+    type <span class="Constant">[d]</span>  <span class="Comment"># should append</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .abcd      .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-3 [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  assume-console [
+    left-click 3, 5  <span class="Comment"># below all text</span>
+    type <span class="Constant">[d]</span>  <span class="Comment"># should append</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .abcd      .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-4 [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">d]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  assume-console [
+    left-click 3, 5  <span class="Comment"># below all text</span>
+    type <span class="Constant">[e]</span>  <span class="Comment"># should append</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .de        .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-5 [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">d]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  assume-console [
+    left-click 3, 5  <span class="Comment"># below all text</span>
+    type <span class="Constant">[ef]</span>  <span class="Comment"># should append multiple characters in order</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .def       .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-inserts-characters-at-cursor-6 [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  <span class="Comment"># text fills line</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcde]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span>
+  <span class="Comment"># position cursor at end</span>
+  assume-console [
+    left-click 3, 0
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    3:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  <span class="Comment"># text shouldn't wrap</span>
+  screen-should-contain [
+   <span class="Constant"> .abcde     .</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># cursor should wrap</span>
+  memory-should-contain [
+    3<span class="Special"> &lt;- </span>1
+    4<span class="Special"> &lt;- </span>0
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-wraps-line-on-insert [
+  assume-screen <span class="Constant">5:literal/width</span>, <span class="Constant">3:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcd]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span>
+  <span class="Comment"># type a letter</span>
+  assume-console [
+    type <span class="Constant">[e]</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  <span class="Comment"># no wrap yet</span>
+  screen-should-contain [
+<span class="Constant">    .eabcd.</span>
+   <span class="Constant"> .     .</span>
+  ]
+  <span class="Comment"># type a second letter</span>
+  assume-console [
+    type <span class="Constant">[f]</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  <span class="Comment"># now wrap</span>
+  screen-should-contain [
+<span class="Constant">    .efab↩.</span>
+   <span class="Constant"> .cd   .</span>
+   <span class="Constant"> .     .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-after-inserting-characters [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span>
+  assume-console [
+    type <span class="Constant">[01]</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .01abc     .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-wraps-cursor-after-inserting-characters [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcde]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span>
+  assume-console [
+    left-click 0, 4  <span class="Comment"># line is full; no wrap icon yet</span>
+    type <span class="Constant">[f]</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    3:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  screen-should-contain [
+   <span class="Constant"> .abcd↩     .</span>
+   <span class="Constant"> .fe        .</span>
+   <span class="Constant"> .          .</span>
+  ]
+  memory-should-contain [
+    3<span class="Special"> &lt;- </span>1  <span class="Comment"># cursor row</span>
+    4<span class="Special"> &lt;- </span>1  <span class="Comment"># cursor column</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-wraps-cursor-after-inserting-characters-2 [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcde]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span>
+  assume-console [
+    left-click 0, 3  <span class="Comment"># right before the wrap icon</span>
+    type <span class="Constant">[f]</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    3:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  screen-should-contain [
+   <span class="Constant"> .abcf↩     .</span>
+   <span class="Constant"> .de        .</span>
+   <span class="Constant"> .          .</span>
+  ]
+  memory-should-contain [
+    3<span class="Special"> &lt;- </span>1  <span class="Comment"># cursor row</span>
+    4<span class="Special"> &lt;- </span>0  <span class="Comment"># cursor column</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-down-after-inserting-newline [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  assume-console [
+    type <span class="Constant">[0</span>
+<span class="Constant">1]</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .0         .</span>
+   <span class="Constant"> .1abc      .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-clears-previous-line-completely-after-inserting-newline [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcde]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span>
+  <span class="Comment"># press just a 'newline'</span>
+  assume-console [
+    type [
+]
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  <span class="Comment"># line should be fully cleared</span>
+  screen-should-contain [
+   <span class="Constant"> .          .</span>
+   <span class="Constant"> .abcde     .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-handles-backspace-key [
+<span class="CommentedCode">#?   $print [=== new test</span>
+<span class="CommentedCode">#? ] #? 1</span>
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+<span class="CommentedCode">#?   $print [editor: ], 2:address:editor-data, [ </span>
+<span class="CommentedCode">#? ] #? 1</span>
+  assume-console [
+    left-click 0, 1
+    type <span class="Constant">[«]</span>
+  ]
+  3:event/backspace<span class="Special"> &lt;- </span>merge <span class="Constant">0:literal/text</span>, <span class="Constant">8:literal/backspace</span>, <span class="Constant">0:literal/dummy</span>, <span class="Constant">0:literal/dummy</span>
+  replace-in-console <span class="Constant">171:literal/«</span>, 3:event/backspace
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    5:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  screen-should-contain [
+   <span class="Constant"> .bc        .</span>
+   <span class="Constant"> .          .</span>
+  ]
+  memory-should-contain [
+    4<span class="Special"> &lt;- </span>0
+    5<span class="Special"> &lt;- </span>0
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-clears-last-line-on-backspace [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  <span class="Comment"># just one character in final line</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">d]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span>
+  assume-console [
+    left-click 1, 0  <span class="Comment"># cursor at only character in final line</span>
+    type <span class="Constant">[«]</span>
+  ]
+  3:event/backspace<span class="Special"> &lt;- </span>merge <span class="Constant">0:literal/text</span>, <span class="Constant">8:literal/backspace</span>, <span class="Constant">0:literal/dummy</span>, <span class="Constant">0:literal/dummy</span>
+  replace-in-console <span class="Constant">171:literal/«</span>, 3:event/backspace
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .abcd      .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-handles-backspace-key-at-right-margin [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  <span class="Comment"># fill a line with text</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcde]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span>
+  <span class="Comment"># position cursor at end</span>
+  assume-console [
+    left-click 1, 3  <span class="Comment"># at end of text</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    3:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  <span class="Comment"># check that cursor wraps to next line</span>
+  memory-should-contain [
+    3<span class="Special"> &lt;- </span>1
+    4<span class="Special"> &lt;- </span>0
+  ]
+  <span class="Comment"># now hit a backspace key</span>
+  assume-console [
+    type <span class="Constant">[«]</span>
+  ]
+  5:event/backspace<span class="Special"> &lt;- </span>merge <span class="Constant">0:literal/text</span>, <span class="Constant">8:literal/backspace</span>, <span class="Constant">0:literal/dummy</span>, <span class="Constant">0:literal/dummy</span>
+  replace-in-console <span class="Constant">171:literal/«</span>, 5:event/backspace
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    3:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  <span class="Comment"># cursor unwraps</span>
+  memory-should-contain [
+    3<span class="Special"> &lt;- </span>0
+    4<span class="Special"> &lt;- </span>4
+  ]
+  screen-should-contain [
+   <span class="Constant"> .abcd      .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-right-with-key [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  assume-console [
+    press 65514  <span class="Comment"># right arrow</span>
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .a0bc      .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-to-next-line-with-right-arrow [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">d]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  assume-console [
+    press 65514  <span class="Comment"># right arrow</span>
+    press 65514  <span class="Comment"># right arrow</span>
+    press 65514  <span class="Comment"># right arrow</span>
+    press 65514  <span class="Comment"># right arrow - next line</span>
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .0d        .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-to-next-wrapped-line-with-right-arrow [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcdef]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span>
+  assume-console [
+    left-click 0, 3
+    press 65514  <span class="Comment"># right arrow</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    3:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  screen-should-contain [
+   <span class="Constant"> .abcd↩     .</span>
+   <span class="Constant"> .ef        .</span>
+   <span class="Constant"> .          .</span>
+  ]
+  memory-should-contain [
+    3<span class="Special"> &lt;- </span>1
+    4<span class="Special"> &lt;- </span>0
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-does-not-wrap-cursor-when-line-does-not-wrap [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcde]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span>
+  assume-console [
+    left-click 0, 3  <span class="Comment"># one before right, in the last line</span>
+    press 65514  <span class="Comment"># right arrow</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    3:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  memory-should-contain [
+    3<span class="Special"> &lt;- </span>0
+    4<span class="Special"> &lt;- </span>4
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-does-not-wrap-cursor-when-line-does-not-wrap-2 [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcde</span>
+<span class="Constant">f]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span>
+  assume-console [
+    left-click 0, 3  <span class="Comment"># one before right, not the last line</span>
+    press 65514  <span class="Comment"># right arrow</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    3:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  memory-should-contain [
+    3<span class="Special"> &lt;- </span>0
+    4<span class="Special"> &lt;- </span>4
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-to-next-line-with-right-arrow-at-end-of-line [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">d]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  assume-console [
+    left-click 0, 3
+    press 65514  <span class="Comment"># right arrow - next line</span>
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .0d        .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-left-with-key [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  assume-console [
+    left-click 0, 2
+    press 65515  <span class="Comment"># left arrow</span>
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .a0bc      .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  <span class="Comment"># initialize editor with two lines</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">d]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># position cursor at start of second line (so there's no previous newline)</span>
+  assume-console [
+    left-click 1, 0
+    press 65515  <span class="Comment"># left arrow</span>
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .abc0      .</span>
+   <span class="Constant"> .d         .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line-2 [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  <span class="Comment"># initialize editor with three lines</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def</span>
+<span class="Constant">g]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># position cursor further down (so there's a newline before the character at</span>
+  <span class="Comment"># the cursor)</span>
+  assume-console [
+    left-click 2, 0
+    press 65515  <span class="Comment"># left arrow</span>
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .def0      .</span>
+   <span class="Constant"> .g         .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line-3 [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def</span>
+<span class="Constant">g]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># position cursor at start of text</span>
+  assume-console [
+    left-click 0, 0
+    press 65515  <span class="Comment"># left arrow should have no effect</span>
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .0abc      .</span>
+   <span class="Constant"> .def       .</span>
+   <span class="Constant"> .g         .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-moves-cursor-to-previous-line-with-left-arrow-at-start-of-line-4 [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  <span class="Comment"># initialize editor with text containing an empty line</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+
+d]
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># position cursor right after empty line</span>
+  assume-console [
+    left-click 2, 0
+    press 65515  <span class="Comment"># left arrow</span>
+    type <span class="Constant">[0]</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  screen-should-contain [
+   <span class="Constant"> .abc       .</span>
+   <span class="Constant"> .0         .</span>
+   <span class="Constant"> .d         .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-moves-across-screen-lines-across-wrap-with-left-arrow [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  <span class="Comment"># initialize editor with text containing an empty line</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abcdef]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span>
+  screen-should-contain [
+   <span class="Constant"> .abcd↩     .</span>
+   <span class="Constant"> .ef        .</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># position cursor right after empty line</span>
+  assume-console [
+    left-click 1, 0
+    press 65515  <span class="Comment"># left arrow</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    3:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  memory-should-contain [
+    3<span class="Special"> &lt;- </span>0  <span class="Comment"># previous row</span>
+    4<span class="Special"> &lt;- </span>3  <span class="Comment"># end of wrapped line</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-moves-to-previous-line-with-up-arrow [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  assume-console [
+    left-click 1, 1
+    press 65517  <span class="Comment"># up arrow</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    3:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  memory-should-contain [
+    3<span class="Special"> &lt;- </span>0
+    4<span class="Special"> &lt;- </span>1
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-moves-to-next-line-with-down-arrow [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">def]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># cursor starts out at (0, 0)</span>
+  assume-console [
+    press 65516  <span class="Comment"># down arrow</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    3:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  <span class="Comment"># ..and ends at (1, 0)</span>
+  memory-should-contain [
+    3<span class="Special"> &lt;- </span>1
+    4<span class="Special"> &lt;- </span>0
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-adjusts-column-at-previous-line [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[ab</span>
+<span class="Constant">def]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  assume-console [
+    left-click 1, 3
+    press 65517  <span class="Comment"># up arrow</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    3:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  memory-should-contain [
+    3<span class="Special"> &lt;- </span>0
+    4<span class="Special"> &lt;- </span>2
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-adjusts-column-at-next-line [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc</span>
+<span class="Constant">de]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">10:literal/right</span>
+  assume-console [
+    left-click 0, 3
+    press 65516  <span class="Comment"># down arrow</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    3:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    4:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+  ]
+  memory-should-contain [
+    3<span class="Special"> &lt;- </span>1
+    4<span class="Special"> &lt;- </span>2
+  ]
+]
+
+<span class="muScenario">scenario</span> point-at-multiple-editors [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  <span class="Comment"># initialize an editor covering left half of screen</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span>
+  3:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[def]</span>
+  <span class="Comment"># chain new editor to it, covering the right half of the screen</span>
+  4:address:address:editor-data<span class="Special"> &lt;- </span>get-address 2:address:editor-data/deref, next-editor:offset
+  4:address:address:editor-data/deref<span class="Special"> &lt;- </span>new-editor 3:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">5:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># type one letter in each of them</span>
+  assume-console [
+    left-click 0, 1
+    left-click 0, 8
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    5:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+    6:number<span class="Special"> &lt;- </span>get 4:address:address:editor-data/deref/deref, cursor-column:offset
+  ]
+  memory-should-contain [
+    5<span class="Special"> &lt;- </span>1
+    6<span class="Special"> &lt;- </span>8
+  ]
+]
+
+<span class="muScenario">scenario</span> editors-chain-to-cover-multiple-columns [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  <span class="Comment"># initialize an editor covering left half of screen</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span>
+  3:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[def]</span>
+  <span class="Comment"># chain new editor to it, covering the right half of the screen</span>
+  4:address:address:editor-data<span class="Special"> &lt;- </span>get-address 2:address:editor-data/deref, next-editor:offset
+  4:address:address:editor-data/deref<span class="Special"> &lt;- </span>new-editor 3:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">5:literal/left</span>, <span class="Constant">10:literal/right</span>
+  reset-focus 2:address:editor-data
+  <span class="Comment"># type one letter in each of them</span>
+  assume-console [
+    left-click 0, 1
+    type <span class="Constant">[0]</span>
+    left-click 0, 6
+    type <span class="Constant">[1]</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    5:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+    6:number<span class="Special"> &lt;- </span>get 4:address:address:editor-data/deref/deref, cursor-column:offset
+  ]
+  screen-should-contain [
+   <span class="Constant"> .a0bc d1ef .</span>
+   <span class="Constant"> .          .</span>
+  ]
+  memory-should-contain [
+    5<span class="Special"> &lt;- </span>2
+    6<span class="Special"> &lt;- </span>7
+  ]
+  <span class="Comment"># show the cursor at the right window</span>
+  run [
+    screen:address<span class="Special"> &lt;- </span>print-character screen:address, <span class="Constant">9251:literal/␣</span>
+  ]
+  screen-should-contain [
+   <span class="Constant"> .a0bc d1␣f .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> multiple-editors-cover-only-their-own-areas [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  run [
+    <span class="Comment"># draw a divider</span>
+    draw-vertical screen:address, <span class="Constant">5:literal/divider</span>, <span class="Constant">0:literal/top</span>, <span class="Constant">5:literal/height</span>
+    <span class="Comment"># initialize editors on both sides of it and chain the two</span>
+    1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+    2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span>
+    3:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[def]</span>
+    4:address:address:editor-data<span class="Special"> &lt;- </span>get-address 2:address:editor-data/deref, next-editor:offset
+    4:address:address:editor-data/deref<span class="Special"> &lt;- </span>new-editor 3:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">6:literal/left</span>, <span class="Constant">10:literal/right</span>
+  ]
+  <span class="Comment"># divider isn't messed up</span>
+  screen-should-contain [
+   <span class="Constant"> .abc  │def .</span>
+   <span class="Constant"> .     │    .</span>
+   <span class="Constant"> .     │    .</span>
+   <span class="Constant"> .     │    .</span>
+   <span class="Constant"> .     │    .</span>
+  ]
+]
+
+<span class="muScenario">scenario</span> editor-in-focus-keeps-cursor [
+  assume-screen <span class="Constant">10:literal/width</span>, <span class="Constant">5:literal/height</span>
+  <span class="Comment"># initialize an editor covering left half of screen</span>
+  1:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[abc]</span>
+  2:address:editor-data<span class="Special"> &lt;- </span>new-editor 1:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">0:literal/left</span>, <span class="Constant">5:literal/right</span>
+  3:address:array:character<span class="Special"> &lt;- </span>new <span class="Constant">[def]</span>
+  <span class="Comment"># chain new editor to it, covering the right half of the screen</span>
+  4:address:address:editor-data<span class="Special"> &lt;- </span>get-address 2:address:editor-data/deref, next-editor:offset
+  4:address:address:editor-data/deref<span class="Special"> &lt;- </span>new-editor 3:address:array:character, screen:address, <span class="Constant">0:literal/top</span>, <span class="Constant">5:literal/left</span>, <span class="Constant">10:literal/right</span>
+  <span class="Comment"># initialize cursor</span>
+  run [
+    reset-focus 2:address:editor-data
+    5:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-row:offset
+    6:number<span class="Special"> &lt;- </span>get 2:address:editor-data/deref, cursor-column:offset
+    move-cursor screen:address, 5:number, 6:number
+    screen:address<span class="Special"> &lt;- </span>print-character screen:address, <span class="Constant">9251:literal/␣</span>
+  ]
+  <span class="Comment"># is it at the right place?</span>
+  screen-should-contain [
+   <span class="Constant"> .␣bc  def  .</span>
+   <span class="Constant"> .          .</span>
+  ]
+  <span class="Comment"># now try typing a letter</span>
+  assume-console [
+    type <span class="Constant">[z]</span>
+  ]
+  run [
+    event-loop screen:address, console:address, 2:address:editor-data
+    screen:address<span class="Special"> &lt;- </span>print-character screen:address, <span class="Constant">9251:literal/␣</span>
+  ]
+  <span class="Comment"># cursor should still be right</span>
+  screen-should-contain [
+   <span class="Constant"> .z␣bc def  .</span>
+   <span class="Constant"> .          .</span>
+  ]
+]
+
+<span class="Comment"># set focus to first editor, reset it in later ones</span>
+<span class="muRecipe">recipe</span> reset-focus [
+  <span class="Constant">default-space</span>:address:array:location<span class="Special"> &lt;- </span>new location:type, <span class="Constant">30:literal</span>
+  editor:address:editor-data<span class="Special"> &lt;- </span><span class="Constant">next-ingredient</span>
+  in-focus:address:boolean<span class="Special"> &lt;- </span>get-address editor:address:editor-data/deref, in-focus?:offset
+  in-focus:address:boolean/deref<span class="Special"> &lt;- </span>copy <span class="Constant">1:literal/true</span>
+  e:address:editor-data<span class="Special"> &lt;- </span>get editor:address:editor-data/deref, next-editor:offset
+  <span class="Delimiter">{</span>
+    <span class="muControl">break-unless</span> e:address:editor-data
+<span class="CommentedCode">#?     $print [resetting focus in ], e:address:editor-data, [ </span>
+<span class="CommentedCode">#? ] #? 1</span>
+    x:address:boolean<span class="Special"> &lt;- </span>get-address e:address:editor-data/deref, in-focus?:offset
+<span class="CommentedCode">#?     $print [ at ], x:address:boolean, [ </span>
+<span class="CommentedCode">#? ] #? 1</span>
+    x:address:boolean/deref<span class="Special"> &lt;- </span>copy <span class="Constant">0:literal/false</span>
+    e:address:editor-data<span class="Special"> &lt;- </span>get e:address:editor-data/deref, next-editor:offset
+    <span class="muControl">loop</span>
+  <span class="Delimiter">}</span>
+]
+
 <span class="SalientComment">## helpers for drawing editor borders</span>
 
 <span class="muRecipe">recipe</span> draw-box [
diff --git a/html/factorial.mu.html b/html/factorial.mu.html
index 13e4a6c0..b180a35b 100644
--- a/html/factorial.mu.html
+++ b/html/factorial.mu.html
@@ -49,7 +49,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
     <span class="muControl">break-unless</span> zero?:boolean
     <span class="muControl">reply</span> <span class="Constant">1:literal</span>
   <span class="Delimiter">}</span>
-  <span class="Comment"># return n * factorial(n - 1)</span>
+  <span class="Comment"># return n * factorial(n-1)</span>
   x:number<span class="Special"> &lt;- </span>subtract n:number, <span class="Constant">1:literal</span>
   subresult:number<span class="Special"> &lt;- </span>factorial x:number
   result:number<span class="Special"> &lt;- </span>multiply subresult:number, n:number
diff --git a/html/keyboard.mu.html b/html/keyboard.mu.html
deleted file mode 100644
index 883ead79..00000000
--- a/html/keyboard.mu.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-<meta http-equiv="content-type" content="text/html; charset=UTF-8">
-<title>Mu - keyboard.mu</title>
-<meta name="Generator" content="Vim/7.4">
-<meta name="plugin-version" content="vim7.4_v1">
-<meta name="syntax" content="none">
-<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
-<meta name="colorscheme" content="minimal">
-<style type="text/css">
-<!--
-pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
-body { font-family: monospace; color: #eeeeee; background-color: #080808; }
-* { font-size: 1.05em; }
-.Constant { color: #00a0a0; }
-.Comment { color: #9090ff; }
-.Delimiter { color: #a04060; }
-.Special { color: #ff6060; }
-.muControl { color: #c0a020; }
-.muRecipe { color: #ff8700; }
--->
-</style>
-
-<script type='text/javascript'>
-<!--
-
--->
-</script>
-</head>
-<body>
-<pre id='vimCodeElement'>
-<span class="Comment"># example program: reading keys from keyboard</span>
-<span class="Comment">#</span>
-<span class="Comment"># Keeps printing 'a' until you press a key. Then prints the key you pressed</span>
-<span class="Comment"># and exits.</span>
-
-<span class="muRecipe">recipe</span> main [
-  switch-to-display
-  <span class="Delimiter">{</span>
-    c:character, found?:boolean<span class="Special"> &lt;- </span>read-key-from-keyboard
-    <span class="muControl">break-if</span> found?:boolean
-    print-character-to-display <span class="Constant">97:literal</span>
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  return-to-console
-]
-</pre>
-</body>
-</html>
-<!-- vim: set foldmethod=manual : -->
diff --git a/html/mouse.mu.html b/html/mouse.mu.html
deleted file mode 100644
index 8987fca6..00000000
--- a/html/mouse.mu.html
+++ /dev/null
@@ -1,46 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-<meta http-equiv="content-type" content="text/html; charset=UTF-8">
-<title>Mu - mouse.mu</title>
-<meta name="Generator" content="Vim/7.4">
-<meta name="plugin-version" content="vim7.4_v1">
-<meta name="syntax" content="none">
-<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
-<meta name="colorscheme" content="minimal">
-<style type="text/css">
-<!--
-pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
-body { font-family: monospace; color: #eeeeee; background-color: #080808; }
-* { font-size: 1.05em; }
-.Comment { color: #9090ff; }
-.Delimiter { color: #a04060; }
-.Special { color: #ff6060; }
-.muControl { color: #c0a020; }
-.muRecipe { color: #ff8700; }
--->
-</style>
-
-<script type='text/javascript'>
-<!--
-
--->
-</script>
-</head>
-<body>
-<pre id='vimCodeElement'>
-<span class="Comment"># example program: managing the display</span>
-
-<span class="muRecipe">recipe</span> main [
-  switch-to-display
-  <span class="Delimiter">{</span>
-    _, found?:boolean<span class="Special"> &lt;- </span>read-keyboard-or-mouse-event
-    <span class="muControl">break-if</span> found?:boolean
-    <span class="muControl">loop</span>
-  <span class="Delimiter">}</span>
-  return-to-console
-]
-</pre>
-</body>
-</html>
-<!-- vim: set foldmethod=manual : -->