about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2022-07-12 14:18:50 -0700
committerKartik K. Agaram <vc@akkartik.com>2022-07-12 15:24:56 -0700
commit8bbc1ffe349a78ed2130e24e0356276ddbb22955 (patch)
tree8e3f748433d5147e258fd1008e75cf2c41700e28
parenta5f725ab3b860b22199036f7ab0d0a0193a5a6ac (diff)
downloadtext.love-8bbc1ffe349a78ed2130e24e0356276ddbb22955.tar.gz
group all editor globals
We're still accessing them through a global. But we'll change that next.
-rw-r--r--drawing.lua188
-rw-r--r--drawing_tests.lua496
-rw-r--r--edit.lua386
-rw-r--r--help.lua214
-rw-r--r--main.lua64
-rw-r--r--main_tests.lua22
-rw-r--r--search.lua82
-rw-r--r--select.lua94
-rw-r--r--text.lua598
-rw-r--r--text_tests.lua1754
-rw-r--r--undo.lua40
11 files changed, 1974 insertions, 1964 deletions
diff --git a/drawing.lua b/drawing.lua
index 53f2c78..33bfd26 100644
--- a/drawing.lua
+++ b/drawing.lua
@@ -6,13 +6,13 @@ require 'drawing_tests'
 -- into 256 parts.
 function Drawing.draw(line)
   local pmx,pmy = App.mouse_x(), App.mouse_y()
-  if pmx < App.screen.width-Margin_right and pmy > line.y and pmy < line.y+Drawing.pixels(line.h) then
+  if pmx < App.screen.width-Editor_state.margin_right and pmy > line.y and pmy < line.y+Drawing.pixels(line.h) then
     App.color(Icon_color)
-    love.graphics.rectangle('line', Margin_left,line.y, App.screen.width-Margin_width,Drawing.pixels(line.h))
-    if icon[Current_drawing_mode] then
-      icon[Current_drawing_mode](App.screen.width-Margin_right-22, line.y+4)
+    love.graphics.rectangle('line', Editor_state.margin_left,line.y, App.screen.width-Editor_state.margin_width,Drawing.pixels(line.h))
+    if icon[Editor_state.current_drawing_mode] then
+      icon[Editor_state.current_drawing_mode](App.screen.width-Editor_state.margin_right-22, line.y+4)
     else
-      icon[Previous_drawing_mode](App.screen.width-Margin_right-22, line.y+4)
+      icon[Editor_state.previous_drawing_mode](App.screen.width-Editor_state.margin_right-22, line.y+4)
     end
 
     if App.mouse_down(1) and love.keyboard.isDown('h') then
@@ -26,7 +26,7 @@ function Drawing.draw(line)
     return
   end
 
-  local mx,my = Drawing.coord(pmx-Margin_left), Drawing.coord(pmy-line.y)
+  local mx,my = Drawing.coord(pmx-Editor_state.margin_left), Drawing.coord(pmy-line.y)
 
   for _,shape in ipairs(line.shapes) do
     assert(shape)
@@ -35,38 +35,38 @@ function Drawing.draw(line)
     else
       App.color(Stroke_color)
     end
-    Drawing.draw_shape(Margin_left,line.y, line, shape)
+    Drawing.draw_shape(Editor_state.margin_left,line.y, line, shape)
   end
   for i,p in ipairs(line.points) do
     if p.deleted == nil then
       if Drawing.near(p, mx,my) then
         App.color(Focus_stroke_color)
-        love.graphics.circle('line', Drawing.pixels(p.x)+Margin_left,Drawing.pixels(p.y)+line.y, 4)
+        love.graphics.circle('line', Drawing.pixels(p.x)+Editor_state.margin_left,Drawing.pixels(p.y)+line.y, 4)
       else
         App.color(Stroke_color)
-        love.graphics.circle('fill', Drawing.pixels(p.x)+Margin_left,Drawing.pixels(p.y)+line.y, 2)
+        love.graphics.circle('fill', Drawing.pixels(p.x)+Editor_state.margin_left,Drawing.pixels(p.y)+line.y, 2)
       end
       if p.name then
         -- TODO: clip
-        local x,y = Drawing.pixels(p.x)+Margin_left+5, Drawing.pixels(p.y)+line.y+5
+        local x,y = Drawing.pixels(p.x)+Editor_state.margin_left+5, Drawing.pixels(p.y)+line.y+5
         love.graphics.print(p.name, x,y)
-        if Current_drawing_mode == 'name' and i == line.pending.target_point then
+        if Editor_state.current_drawing_mode == 'name' and i == line.pending.target_point then
           -- create a faint red box for the name
           App.color(Current_name_background_color)
           local name_text
           -- TODO: avoid computing name width on every repaint
           if p.name == '' then
-            name_text = Em
+            name_text = Editor_state.em
           else
             name_text = App.newText(love.graphics.getFont(), p.name)
           end
-          love.graphics.rectangle('fill', x,y, App.width(name_text), Line_height)
+          love.graphics.rectangle('fill', x,y, App.width(name_text), Editor_state.line_height)
         end
       end
     end
   end
   App.color(Current_stroke_color)
-  Drawing.draw_pending_shape(Margin_left,line.y, line)
+  Drawing.draw_pending_shape(Editor_state.margin_left,line.y, line)
 end
 
 function Drawing.draw_shape(left,top, drawing, shape)
@@ -204,51 +204,51 @@ end
 
 function Drawing.in_drawing(drawing, x,y)
   if drawing.y == nil then return false end  -- outside current page
-  return y >= drawing.y and y < drawing.y + Drawing.pixels(drawing.h) and x >= Margin_left and x < App.screen.width-Margin_right
+  return y >= drawing.y and y < drawing.y + Drawing.pixels(drawing.h) and x >= Editor_state.margin_left and x < App.screen.width-Editor_state.margin_right
 end
 
 function Drawing.mouse_pressed(drawing, x,y, button)
-  if Current_drawing_mode == 'freehand' then
-    drawing.pending = {mode=Current_drawing_mode, points={{x=Drawing.coord(x-Margin_left), y=Drawing.coord(y-drawing.y)}}}
-  elseif Current_drawing_mode == 'line' or Current_drawing_mode == 'manhattan' then
-    local j = Drawing.insert_point(drawing.points, Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y))
-    drawing.pending = {mode=Current_drawing_mode, p1=j}
-  elseif Current_drawing_mode == 'polygon' or Current_drawing_mode == 'rectangle' or Current_drawing_mode == 'square' then
-    local j = Drawing.insert_point(drawing.points, Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y))
-    drawing.pending = {mode=Current_drawing_mode, vertices={j}}
-  elseif Current_drawing_mode == 'circle' then
-    local j = Drawing.insert_point(drawing.points, Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y))
-    drawing.pending = {mode=Current_drawing_mode, center=j}
-  elseif Current_drawing_mode == 'move' then
+  if Editor_state.current_drawing_mode == 'freehand' then
+    drawing.pending = {mode=Editor_state.current_drawing_mode, points={{x=Drawing.coord(x-Editor_state.margin_left), y=Drawing.coord(y-drawing.y)}}}
+  elseif Editor_state.current_drawing_mode == 'line' or Editor_state.current_drawing_mode == 'manhattan' then
+    local j = Drawing.insert_point(drawing.points, Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y))
+    drawing.pending = {mode=Editor_state.current_drawing_mode, p1=j}
+  elseif Editor_state.current_drawing_mode == 'polygon' or Editor_state.current_drawing_mode == 'rectangle' or Editor_state.current_drawing_mode == 'square' then
+    local j = Drawing.insert_point(drawing.points, Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y))
+    drawing.pending = {mode=Editor_state.current_drawing_mode, vertices={j}}
+  elseif Editor_state.current_drawing_mode == 'circle' then
+    local j = Drawing.insert_point(drawing.points, Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y))
+    drawing.pending = {mode=Editor_state.current_drawing_mode, center=j}
+  elseif Editor_state.current_drawing_mode == 'move' then
     -- all the action is in mouse_released
-  elseif Current_drawing_mode == 'name' then
+  elseif Editor_state.current_drawing_mode == 'name' then
     -- nothing
   else
-    print(Current_drawing_mode)
+    print(Editor_state.current_drawing_mode)
     assert(false)
   end
 end
 
 -- a couple of operations on drawings need to constantly check the state of the mouse
 function Drawing.update()
-  if Lines.current_drawing == nil then return end
-  local drawing = Lines.current_drawing
+  if Editor_state.lines.current_drawing == nil then return end
+  local drawing = Editor_state.lines.current_drawing
   assert(drawing.mode == 'drawing')
   local x, y = App.mouse_x(), App.mouse_y()
   if App.mouse_down(1) then
     if Drawing.in_drawing(drawing, x,y) then
       if drawing.pending.mode == 'freehand' then
-        table.insert(drawing.pending.points, {x=Drawing.coord(App.mouse_x()-Margin_left), y=Drawing.coord(App.mouse_y()-drawing.y)})
+        table.insert(drawing.pending.points, {x=Drawing.coord(App.mouse_x()-Editor_state.margin_left), y=Drawing.coord(App.mouse_y()-drawing.y)})
       elseif drawing.pending.mode == 'move' then
-        local mx,my = Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y)
+        local mx,my = Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y)
         drawing.pending.target_point.x = mx
         drawing.pending.target_point.y = my
         Drawing.relax_constraints(drawing, drawing.pending.target_point_index)
       end
     end
-  elseif Current_drawing_mode == 'move' then
+  elseif Editor_state.current_drawing_mode == 'move' then
     if Drawing.in_drawing(drawing, x, y) then
-      local mx,my = Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y)
+      local mx,my = Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y)
       drawing.pending.target_point.x = mx
       drawing.pending.target_point.y = my
       Drawing.relax_constraints(drawing, drawing.pending.target_point_index)
@@ -277,15 +277,15 @@ function Drawing.relax_constraints(drawing, p)
 end
 
 function Drawing.mouse_released(x,y, button)
-  if Current_drawing_mode == 'move' then
-    Current_drawing_mode = Previous_drawing_mode
-    Previous_drawing_mode = nil
-    if Lines.current_drawing then
-      Lines.current_drawing.pending = {}
-      Lines.current_drawing = nil
-    end
-  elseif Lines.current_drawing then
-    local drawing = Lines.current_drawing
+  if Editor_state.current_drawing_mode == 'move' then
+    Editor_state.current_drawing_mode = Editor_state.previous_drawing_mode
+    Editor_state.previous_drawing_mode = nil
+    if Editor_state.lines.current_drawing then
+      Editor_state.lines.current_drawing.pending = {}
+      Editor_state.lines.current_drawing = nil
+    end
+  elseif Editor_state.lines.current_drawing then
+    local drawing = Editor_state.lines.current_drawing
     if drawing.pending then
       if drawing.pending.mode == nil then
         -- nothing pending
@@ -294,14 +294,14 @@ function Drawing.mouse_released(x,y, button)
         Drawing.smoothen(drawing.pending)
         table.insert(drawing.shapes, drawing.pending)
       elseif drawing.pending.mode == 'line' then
-        local mx,my = Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y)
+        local mx,my = Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y)
         if mx >= 0 and mx < 256 and my >= 0 and my < drawing.h then
           drawing.pending.p2 = Drawing.insert_point(drawing.points, mx,my)
           table.insert(drawing.shapes, drawing.pending)
         end
       elseif drawing.pending.mode == 'manhattan' then
         local p1 = drawing.points[drawing.pending.p1]
-        local mx,my = Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y)
+        local mx,my = Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y)
         if mx >= 0 and mx < 256 and my >= 0 and my < drawing.h then
           if math.abs(mx-p1.x) > math.abs(my-p1.y) then
             drawing.pending.p2 = Drawing.insert_point(drawing.points, mx, p1.y)
@@ -309,11 +309,11 @@ function Drawing.mouse_released(x,y, button)
             drawing.pending.p2 = Drawing.insert_point(drawing.points, p1.x, my)
           end
           local p2 = drawing.points[drawing.pending.p2]
-          App.mouse_move(Margin_left+Drawing.pixels(p2.x), drawing.y+Drawing.pixels(p2.y))
+          App.mouse_move(Editor_state.margin_left+Drawing.pixels(p2.x), drawing.y+Drawing.pixels(p2.y))
           table.insert(drawing.shapes, drawing.pending)
         end
       elseif drawing.pending.mode == 'polygon' then
-        local mx,my = Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y)
+        local mx,my = Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y)
         if mx >= 0 and mx < 256 and my >= 0 and my < drawing.h then
           table.insert(drawing.pending.vertices, Drawing.insert_point(drawing.points, mx,my))
           table.insert(drawing.shapes, drawing.pending)
@@ -321,7 +321,7 @@ function Drawing.mouse_released(x,y, button)
       elseif drawing.pending.mode == 'rectangle' then
         assert(#drawing.pending.vertices <= 2)
         if #drawing.pending.vertices == 2 then
-          local mx,my = Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y)
+          local mx,my = Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y)
           if mx >= 0 and mx < 256 and my >= 0 and my < drawing.h then
             local first = drawing.points[drawing.pending.vertices[1]]
             local second = drawing.points[drawing.pending.vertices[2]]
@@ -336,7 +336,7 @@ function Drawing.mouse_released(x,y, button)
       elseif drawing.pending.mode == 'square' then
         assert(#drawing.pending.vertices <= 2)
         if #drawing.pending.vertices == 2 then
-          local mx,my = Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y)
+          local mx,my = Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y)
           if mx >= 0 and mx < 256 and my >= 0 and my < drawing.h then
             local first = drawing.points[drawing.pending.vertices[1]]
             local second = drawing.points[drawing.pending.vertices[2]]
@@ -347,14 +347,14 @@ function Drawing.mouse_released(x,y, button)
           end
         end
       elseif drawing.pending.mode == 'circle' then
-        local mx,my = Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y)
+        local mx,my = Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y)
         if mx >= 0 and mx < 256 and my >= 0 and my < drawing.h then
           local center = drawing.points[drawing.pending.center]
           drawing.pending.radius = geom.dist(center.x,center.y, mx,my)
           table.insert(drawing.shapes, drawing.pending)
         end
       elseif drawing.pending.mode == 'arc' then
-        local mx,my = Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y)
+        local mx,my = Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y)
         if mx >= 0 and mx < 256 and my >= 0 and my < drawing.h then
           local center = drawing.points[drawing.pending.center]
           drawing.pending.end_angle = geom.angle_with_hint(center.x,center.y, mx,my, drawing.pending.end_angle)
@@ -366,17 +366,17 @@ function Drawing.mouse_released(x,y, button)
         print(drawing.pending.mode)
         assert(false)
       end
-      Lines.current_drawing.pending = {}
-      Lines.current_drawing = nil
+      Editor_state.lines.current_drawing.pending = {}
+      Editor_state.lines.current_drawing = nil
     end
   end
 end
 
 function Drawing.keychord_pressed(chord)
   if chord == 'C-p' and not App.mouse_down(1) then
-    Current_drawing_mode = 'freehand'
+    Editor_state.current_drawing_mode = 'freehand'
   elseif App.mouse_down(1) and chord == 'l' then
-    Current_drawing_mode = 'line'
+    Editor_state.current_drawing_mode = 'line'
     local _,drawing = Drawing.current_drawing()
     if drawing.pending.mode == 'freehand' then
       drawing.pending.p1 = Drawing.insert_point(drawing.points, drawing.pending.points[1].x, drawing.pending.points[1].y)
@@ -387,9 +387,9 @@ function Drawing.keychord_pressed(chord)
     end
     drawing.pending.mode = 'line'
   elseif chord == 'C-l' and not App.mouse_down(1) then
-    Current_drawing_mode = 'line'
+    Editor_state.current_drawing_mode = 'line'
   elseif App.mouse_down(1) and chord == 'm' then
-    Current_drawing_mode = 'manhattan'
+    Editor_state.current_drawing_mode = 'manhattan'
     local drawing = Drawing.select_drawing_at_mouse()
     if drawing.pending.mode == 'freehand' then
       drawing.pending.p1 = Drawing.insert_point(drawing.points, drawing.pending.points[1].x, drawing.pending.points[1].y)
@@ -402,11 +402,11 @@ function Drawing.keychord_pressed(chord)
     end
     drawing.pending.mode = 'manhattan'
   elseif chord == 'C-m' and not App.mouse_down(1) then
-    Current_drawing_mode = 'manhattan'
+    Editor_state.current_drawing_mode = 'manhattan'
   elseif chord == 'C-g' and not App.mouse_down(1) then
-    Current_drawing_mode = 'polygon'
+    Editor_state.current_drawing_mode = 'polygon'
   elseif App.mouse_down(1) and chord == 'g' then
-    Current_drawing_mode = 'polygon'
+    Editor_state.current_drawing_mode = 'polygon'
     local _,drawing = Drawing.current_drawing()
     if drawing.pending.mode == 'freehand' then
       drawing.pending.vertices = {Drawing.insert_point(drawing.points, drawing.pending.points[1].x, drawing.pending.points[1].y)}
@@ -421,9 +421,9 @@ function Drawing.keychord_pressed(chord)
     end
     drawing.pending.mode = 'polygon'
   elseif chord == 'C-r' and not App.mouse_down(1) then
-    Current_drawing_mode = 'rectangle'
+    Editor_state.current_drawing_mode = 'rectangle'
   elseif App.mouse_down(1) and chord == 'r' then
-    Current_drawing_mode = 'rectangle'
+    Editor_state.current_drawing_mode = 'rectangle'
     local _,drawing = Drawing.current_drawing()
     if drawing.pending.mode == 'freehand' then
       drawing.pending.vertices = {Drawing.insert_point(drawing.points, drawing.pending.points[1].x, drawing.pending.points[1].y)}
@@ -438,9 +438,9 @@ function Drawing.keychord_pressed(chord)
     end
     drawing.pending.mode = 'rectangle'
   elseif chord == 'C-s' and not App.mouse_down(1) then
-    Current_drawing_mode = 'square'
+    Editor_state.current_drawing_mode = 'square'
   elseif App.mouse_down(1) and chord == 's' then
-    Current_drawing_mode = 'square'
+    Editor_state.current_drawing_mode = 'square'
     local _,drawing = Drawing.current_drawing()
     if drawing.pending.mode == 'freehand' then
       drawing.pending.vertices = {Drawing.insert_point(drawing.points, drawing.pending.points[1].x, drawing.pending.points[1].y)}
@@ -458,30 +458,30 @@ function Drawing.keychord_pressed(chord)
       drawing.pending.vertices = {drawing.pending.center}
     end
     drawing.pending.mode = 'square'
-  elseif App.mouse_down(1) and chord == 'p' and Current_drawing_mode == 'polygon' then
+  elseif App.mouse_down(1) and chord == 'p' and Editor_state.current_drawing_mode == 'polygon' then
     local _,drawing = Drawing.current_drawing()
-    local mx,my = Drawing.coord(App.mouse_x()-Margin_left), Drawing.coord(App.mouse_y()-drawing.y)
+    local mx,my = Drawing.coord(App.mouse_x()-Editor_state.margin_left), Drawing.coord(App.mouse_y()-drawing.y)
     local j = Drawing.insert_point(drawing.points, mx,my)
     table.insert(drawing.pending.vertices, j)
-  elseif App.mouse_down(1) and chord == 'p' and (Current_drawing_mode == 'rectangle' or Current_drawing_mode == 'square') then
+  elseif App.mouse_down(1) and chord == 'p' and (Editor_state.current_drawing_mode == 'rectangle' or Editor_state.current_drawing_mode == 'square') then
     local _,drawing = Drawing.current_drawing()
-    local mx,my = Drawing.coord(App.mouse_x()-Margin_left), Drawing.coord(App.mouse_y()-drawing.y)
+    local mx,my = Drawing.coord(App.mouse_x()-Editor_state.margin_left), Drawing.coord(App.mouse_y()-drawing.y)
     local j = Drawing.insert_point(drawing.points, mx,my)
     while #drawing.pending.vertices >= 2 do
       table.remove(drawing.pending.vertices)
     end
     table.insert(drawing.pending.vertices, j)
   elseif chord == 'C-o' and not App.mouse_down(1) then
-    Current_drawing_mode = 'circle'
-  elseif App.mouse_down(1) and chord == 'a' and Current_drawing_mode == 'circle' then
+    Editor_state.current_drawing_mode = 'circle'
+  elseif App.mouse_down(1) and chord == 'a' and Editor_state.current_drawing_mode == 'circle' then
     local _,drawing = Drawing.current_drawing()
     drawing.pending.mode = 'arc'
-    local mx,my = Drawing.coord(App.mouse_x()-Margin_left), Drawing.coord(App.mouse_y()-drawing.y)
+    local mx,my = Drawing.coord(App.mouse_x()-Editor_state.margin_left), Drawing.coord(App.mouse_y()-drawing.y)
     local center = drawing.points[drawing.pending.center]
     drawing.pending.radius = geom.dist(center.x,center.y, mx,my)
     drawing.pending.start_angle = geom.angle(center.x,center.y, mx,my)
   elseif App.mouse_down(1) and chord == 'o' then
-    Current_drawing_mode = 'circle'
+    Editor_state.current_drawing_mode = 'circle'
     local _,drawing = Drawing.current_drawing()
     if drawing.pending.mode == 'freehand' then
       drawing.pending.center = Drawing.insert_point(drawing.points, drawing.pending.points[1].x, drawing.pending.points[1].y)
@@ -494,26 +494,26 @@ function Drawing.keychord_pressed(chord)
   elseif chord == 'C-u' and not App.mouse_down(1) then
     local drawing_index,drawing,i,p = Drawing.select_point_at_mouse()
     if drawing then
-      if Previous_drawing_mode == nil then
-        Previous_drawing_mode = Current_drawing_mode
+      if Editor_state.previous_drawing_mode == nil then
+        Editor_state.previous_drawing_mode = Editor_state.current_drawing_mode
       end
-      Current_drawing_mode = 'move'
-      drawing.pending = {mode=Current_drawing_mode, target_point=p, target_point_index=i}
-      Lines.current_drawing_index = drawing_index
-      Lines.current_drawing = drawing
+      Editor_state.current_drawing_mode = 'move'
+      drawing.pending = {mode=Editor_state.current_drawing_mode, target_point=p, target_point_index=i}
+      Editor_state.lines.current_drawing_index = drawing_index
+      Editor_state.lines.current_drawing = drawing
     end
   elseif chord == 'C-n' and not App.mouse_down(1) then
     local drawing_index,drawing,point_index,p = Drawing.select_point_at_mouse()
     if drawing then
-      if Previous_drawing_mode == nil then
+      if Editor_state.previous_drawing_mode == nil then
         -- don't clobber
-        Previous_drawing_mode = Current_drawing_mode
+        Editor_state.previous_drawing_mode = Editor_state.current_drawing_mode
       end
-      Current_drawing_mode = 'name'
+      Editor_state.current_drawing_mode = 'name'
       p.name = ''
-      drawing.pending = {mode=Current_drawing_mode, target_point=point_index}
-      Lines.current_drawing_index = drawing_index
-      Lines.current_drawing = drawing
+      drawing.pending = {mode=Editor_state.current_drawing_mode, target_point=point_index}
+      Editor_state.lines.current_drawing_index = drawing_index
+      Editor_state.lines.current_drawing = drawing
     end
   elseif chord == 'C-d' and not App.mouse_down(1) then
     local _,drawing,i,p = Drawing.select_point_at_mouse()
@@ -599,7 +599,7 @@ end
 
 function Drawing.current_drawing()
   local x, y = App.mouse_x(), App.mouse_y()
-  for drawing_index,drawing in ipairs(Lines) do
+  for drawing_index,drawing in ipairs(Editor_state.lines) do
     if drawing.mode == 'drawing' then
       if Drawing.in_drawing(drawing, x,y) then
         return drawing_index,drawing
@@ -610,11 +610,11 @@ function Drawing.current_drawing()
 end
 
 function Drawing.select_shape_at_mouse()
-  for _,drawing in ipairs(Lines) do
+  for _,drawing in ipairs(Editor_state.lines) do
     if drawing.mode == 'drawing' then
       local x, y = App.mouse_x(), App.mouse_y()
       if Drawing.in_drawing(drawing, x,y) then
-        local mx,my = Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y)
+        local mx,my = Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y)
         for i,shape in ipairs(drawing.shapes) do
           assert(shape)
           if geom.on_shape(mx,my, drawing, shape) then
@@ -627,11 +627,11 @@ function Drawing.select_shape_at_mouse()
 end
 
 function Drawing.select_point_at_mouse()
-  for drawing_index,drawing in ipairs(Lines) do
+  for drawing_index,drawing in ipairs(Editor_state.lines) do
     if drawing.mode == 'drawing' then
       local x, y = App.mouse_x(), App.mouse_y()
       if Drawing.in_drawing(drawing, x,y) then
-        local mx,my = Drawing.coord(x-Margin_left), Drawing.coord(y-drawing.y)
+        local mx,my = Drawing.coord(x-Editor_state.margin_left), Drawing.coord(y-drawing.y)
         for i,point in ipairs(drawing.points) do
           assert(point)
           if Drawing.near(point, mx,my) then
@@ -644,7 +644,7 @@ function Drawing.select_point_at_mouse()
 end
 
 function Drawing.select_drawing_at_mouse()
-  for _,drawing in ipairs(Lines) do
+  for _,drawing in ipairs(Editor_state.lines) do
     if drawing.mode == 'drawing' then
       local x, y = App.mouse_x(), App.mouse_y()
       if Drawing.in_drawing(drawing, x,y) then
@@ -700,14 +700,14 @@ end
 function Drawing.near(point, x,y)
   local px,py = Drawing.pixels(x),Drawing.pixels(y)
   local cx,cy = Drawing.pixels(point.x), Drawing.pixels(point.y)
-  return (cx-px)*(cx-px) + (cy-py)*(cy-py) < Margin_left
+  return (cx-px)*(cx-px) + (cy-py)*(cy-py) < Editor_state.margin_left
 end
 
 function Drawing.pixels(n)  -- parts to pixels
-  return math.floor(n*(App.screen.width-Margin_width)/256)
+  return math.floor(n*(App.screen.width-Editor_state.margin_width)/256)
 end
 function Drawing.coord(n)  -- pixels to parts
-  return math.floor(n*256/(App.screen.width-Margin_width))
+  return math.floor(n*256/(App.screen.width-Editor_state.margin_width))
 end
 
 function table.find(h, x)
diff --git a/drawing_tests.lua b/drawing_tests.lua
index c170caa..bc3b654 100644
--- a/drawing_tests.lua
+++ b/drawing_tests.lua
@@ -5,11 +5,11 @@
 function test_creating_drawing_saves()
   io.write('\ntest_creating_drawing_saves')
   App.screen.init{width=120, height=60}
-  Filename = 'foo'
-  Lines = load_array{}
+  Editor_state.filename = 'foo'
+  Editor_state.lines = load_array{}
   edit.draw()
   -- click on button to create drawing
-  App.run_after_mouse_click(8,Margin_top+8, 1)
+  App.run_after_mouse_click(8,Editor_state.margin_top+8, 1)
   -- file not immediately saved
   App.update(0.01)
   check_nil(App.filesystem['foo'], 'F - test_creating_drawing_saves/early')
@@ -23,20 +23,20 @@ end
 function test_draw_line()
   io.write('\ntest_draw_line')
   -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)
-  Filename = 'foo'
-  App.screen.init{width=Margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
-  Lines = load_array{'```lines', '```', ''}
-  Current_drawing_mode = 'line'
+  Editor_state.filename = 'foo'
+  App.screen.init{width=Editor_state.margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
+  Editor_state.lines = load_array{'```lines', '```', ''}
+  Editor_state.current_drawing_mode = 'line'
   edit.draw()
-  check_eq(#Lines, 2, 'F - test_draw_line/baseline/#lines')
-  check_eq(Lines[1].mode, 'drawing', 'F - test_draw_line/baseline/mode')
-  check_eq(Lines[1].y, Margin_top+Drawing_padding_top, 'F - test_draw_line/baseline/y')
-  check_eq(Lines[1].h, 128, 'F - test_draw_line/baseline/y')
-  check_eq(#Lines[1].shapes, 0, 'F - test_draw_line/baseline/#shapes')
+  check_eq(#Editor_state.lines, 2, 'F - test_draw_line/baseline/#lines')
+  check_eq(Editor_state.lines[1].mode, 'drawing', 'F - test_draw_line/baseline/mode')
+  check_eq(Editor_state.lines[1].y, Editor_state.margin_top+Editor_state.drawing_padding_top, 'F - test_draw_line/baseline/y')
+  check_eq(Editor_state.lines[1].h, 128, 'F - test_draw_line/baseline/y')
+  check_eq(#Editor_state.lines[1].shapes, 0, 'F - test_draw_line/baseline/#shapes')
   -- draw a line
-  App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1)
-  App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+36, 1)
-  local drawing = Lines[1]
+  App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1)
+  App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1)
+  local drawing = Editor_state.lines[1]
   check_eq(#drawing.shapes, 1, 'F - test_draw_line/#shapes')
   check_eq(#drawing.points, 2, 'F - test_draw_line/#points')
   check_eq(drawing.shapes[1].mode, 'line', 'F - test_draw_line/shape:1')
@@ -51,8 +51,8 @@ function test_draw_line()
   App.update(0)
   -- The format on disk isn't perfectly stable. Table fields can be reordered.
   -- So just reload from disk to verify.
-  Lines = load_from_disk(Filename)
-  local drawing = Lines[1]
+  Editor_state.lines = load_from_disk(Editor_state.filename)
+  local drawing = Editor_state.lines[1]
   check_eq(#drawing.shapes, 1, 'F - test_draw_line/save/#shapes')
   check_eq(#drawing.points, 2, 'F - test_draw_line/save/#points')
   check_eq(drawing.shapes[1].mode, 'line', 'F - test_draw_line/save/shape:1')
@@ -67,19 +67,19 @@ end
 function test_draw_horizontal_line()
   io.write('\ntest_draw_horizontal_line')
   -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)
-  App.screen.init{width=Margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
-  Lines = load_array{'```lines', '```', ''}
-  Current_drawing_mode = 'manhattan'
+  App.screen.init{width=Editor_state.margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
+  Editor_state.lines = load_array{'```lines', '```', ''}
+  Editor_state.current_drawing_mode = 'manhattan'
   edit.draw()
-  check_eq(#Lines, 2, 'F - test_draw_horizontal_line/baseline/#lines')
-  check_eq(Lines[1].mode, 'drawing', 'F - test_draw_horizontal_line/baseline/mode')
-  check_eq(Lines[1].y, Margin_top+Drawing_padding_top, 'F - test_draw_horizontal_line/baseline/y')
-  check_eq(Lines[1].h, 128, 'F - test_draw_horizontal_line/baseline/y')
-  check_eq(#Lines[1].shapes, 0, 'F - test_draw_horizontal_line/baseline/#shapes')
+  check_eq(#Editor_state.lines, 2, 'F - test_draw_horizontal_line/baseline/#lines')
+  check_eq(Editor_state.lines[1].mode, 'drawing', 'F - test_draw_horizontal_line/baseline/mode')
+  check_eq(Editor_state.lines[1].y, Editor_state.margin_top+Editor_state.drawing_padding_top, 'F - test_draw_horizontal_line/baseline/y')
+  check_eq(Editor_state.lines[1].h, 128, 'F - test_draw_horizontal_line/baseline/y')
+  check_eq(#Editor_state.lines[1].shapes, 0, 'F - test_draw_horizontal_line/baseline/#shapes')
   -- draw a line that is more horizontal than vertical
-  App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1)
-  App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+26, 1)
-  local drawing = Lines[1]
+  App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1)
+  App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+26, 1)
+  local drawing = Editor_state.lines[1]
   check_eq(#drawing.shapes, 1, 'F - test_draw_horizontal_line/#shapes')
   check_eq(#drawing.points, 2, 'F - test_draw_horizontal_line/#points')
   check_eq(drawing.shapes[1].mode, 'manhattan', 'F - test_draw_horizontal_line/shape_mode')
@@ -94,21 +94,21 @@ end
 function test_draw_circle()
   io.write('\ntest_draw_circle')
   -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)
-  App.screen.init{width=Margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
-  Lines = load_array{'```lines', '```', ''}
-  Current_drawing_mode = 'line'
+  App.screen.init{width=Editor_state.margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
+  Editor_state.lines = load_array{'```lines', '```', ''}
+  Editor_state.current_drawing_mode = 'line'
   edit.draw()
-  check_eq(#Lines, 2, 'F - test_draw_circle/baseline/#lines')
-  check_eq(Lines[1].mode, 'drawing', 'F - test_draw_circle/baseline/mode')
-  check_eq(Lines[1].y, Margin_top+Drawing_padding_top, 'F - test_draw_circle/baseline/y')
-  check_eq(Lines[1].h, 128, 'F - test_draw_circle/baseline/y')
-  check_eq(#Lines[1].shapes, 0, 'F - test_draw_circle/baseline/#shapes')
+  check_eq(#Editor_state.lines, 2, 'F - test_draw_circle/baseline/#lines')
+  check_eq(Editor_state.lines[1].mode, 'drawing', 'F - test_draw_circle/baseline/mode')
+  check_eq(Editor_state.lines[1].y, Editor_state.margin_top+Editor_state.drawing_padding_top, 'F - test_draw_circle/baseline/y')
+  check_eq(Editor_state.lines[1].h, 128, 'F - test_draw_circle/baseline/y')
+  check_eq(#Editor_state.lines[1].shapes, 0, 'F - test_draw_circle/baseline/#shapes')
   -- draw a circle
-  App.mouse_move(Margin_left+4, Margin_top+Drawing_padding_top+4)  -- hover on drawing
+  App.mouse_move(Editor_state.margin_left+4, Editor_state.margin_top+Editor_state.drawing_padding_top+4)  -- hover on drawing
   App.run_after_keychord('C-o')
-  App.run_after_mouse_press(Margin_left+35, Margin_top+Drawing_padding_top+36, 1)
-  App.run_after_mouse_release(Margin_left+35+30, Margin_top+Drawing_padding_top+36, 1)
-  local drawing = Lines[1]
+  App.run_after_mouse_press(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1)
+  App.run_after_mouse_release(Editor_state.margin_left+35+30, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1)
+  local drawing = Editor_state.lines[1]
   check_eq(#drawing.shapes, 1, 'F - test_draw_circle/#shapes')
   check_eq(#drawing.points, 1, 'F - test_draw_circle/#points')
   check_eq(drawing.shapes[1].mode, 'circle', 'F - test_draw_horizontal_line/shape_mode')
@@ -121,58 +121,58 @@ end
 function test_cancel_stroke()
   io.write('\ntest_cancel_stroke')
   -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)
-  Filename = 'foo'
-  App.screen.init{width=Margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
-  Lines = load_array{'```lines', '```', ''}
-  Current_drawing_mode = 'line'
+  Editor_state.filename = 'foo'
+  App.screen.init{width=Editor_state.margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
+  Editor_state.lines = load_array{'```lines', '```', ''}
+  Editor_state.current_drawing_mode = 'line'
   edit.draw()
-  check_eq(#Lines, 2, 'F - test_cancel_stroke/baseline/#lines')
-  check_eq(Lines[1].mode, 'drawing', 'F - test_cancel_stroke/baseline/mode')
-  check_eq(Lines[1].y, Margin_top+Drawing_padding_top, 'F - test_cancel_stroke/baseline/y')
-  check_eq(Lines[1].h, 128, 'F - test_cancel_stroke/baseline/y')
-  check_eq(#Lines[1].shapes, 0, 'F - test_cancel_stroke/baseline/#shapes')
+  check_eq(#Editor_state.lines, 2, 'F - test_cancel_stroke/baseline/#lines')
+  check_eq(Editor_state.lines[1].mode, 'drawing', 'F - test_cancel_stroke/baseline/mode')
+  check_eq(Editor_state.lines[1].y, Editor_state.margin_top+Editor_state.drawing_padding_top, 'F - test_cancel_stroke/baseline/y')
+  check_eq(Editor_state.lines[1].h, 128, 'F - test_cancel_stroke/baseline/y')
+  check_eq(#Editor_state.lines[1].shapes, 0, 'F - test_cancel_stroke/baseline/#shapes')
   -- start drawing a line
-  App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1)
+  App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1)
   -- cancel
   App.run_after_keychord('escape')
-  App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+36, 1)
-  local drawing = Lines[1]
+  App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1)
+  local drawing = Editor_state.lines[1]
   check_eq(#drawing.shapes, 0, 'F - test_cancel_stroke/#shapes')
 end
 
 function test_keys_do_not_affect_shape_when_mouse_up()
   io.write('\ntest_keys_do_not_affect_shape_when_mouse_up')
   -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)
-  App.screen.init{width=Margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
-  Lines = load_array{'```lines', '```', ''}
-  Current_drawing_mode = 'line'
+  App.screen.init{width=Editor_state.margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
+  Editor_state.lines = load_array{'```lines', '```', ''}
+  Editor_state.current_drawing_mode = 'line'
   edit.draw()
   -- hover over drawing and press 'o' without holding mouse
-  App.mouse_move(Margin_left+4, Margin_top+Drawing_padding_top+4)  -- hover on drawing
+  App.mouse_move(Editor_state.margin_left+4, Editor_state.margin_top+Editor_state.drawing_padding_top+4)  -- hover on drawing
   App.run_after_keychord('o')
   -- no change to drawing mode
-  check_eq(Current_drawing_mode, 'line', 'F - test_keys_do_not_affect_shape_when_mouse_up/drawing_mode')
+  check_eq(Editor_state.current_drawing_mode, 'line', 'F - test_keys_do_not_affect_shape_when_mouse_up/drawing_mode')
   -- no change to text either because we didn't run the textinput event
 end
 
 function test_draw_circle_mid_stroke()
   io.write('\ntest_draw_circle_mid_stroke')
   -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)
-  App.screen.init{width=Margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
-  Lines = load_array{'```lines', '```', ''}
-  Current_drawing_mode = 'line'
+  App.screen.init{width=Editor_state.margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
+  Editor_state.lines = load_array{'```lines', '```', ''}
+  Editor_state.current_drawing_mode = 'line'
   edit.draw()
-  check_eq(#Lines, 2, 'F - test_draw_circle_mid_stroke/baseline/#lines')
-  check_eq(Lines[1].mode, 'drawing', 'F - test_draw_circle_mid_stroke/baseline/mode')
-  check_eq(Lines[1].y, Margin_top+Drawing_padding_top, 'F - test_draw_circle_mid_stroke/baseline/y')
-  check_eq(Lines[1].h, 128, 'F - test_draw_circle_mid_stroke/baseline/y')
-  check_eq(#Lines[1].shapes, 0, 'F - test_draw_circle_mid_stroke/baseline/#shapes')
+  check_eq(#Editor_state.lines, 2, 'F - test_draw_circle_mid_stroke/baseline/#lines')
+  check_eq(Editor_state.lines[1].mode, 'drawing', 'F - test_draw_circle_mid_stroke/baseline/mode')
+  check_eq(Editor_state.lines[1].y, Editor_state.margin_top+Editor_state.drawing_padding_top, 'F - test_draw_circle_mid_stroke/baseline/y')
+  check_eq(Editor_state.lines[1].h, 128, 'F - test_draw_circle_mid_stroke/baseline/y')
+  check_eq(#Editor_state.lines[1].shapes, 0, 'F - test_draw_circle_mid_stroke/baseline/#shapes')
   -- draw a circle
-  App.mouse_move(Margin_left+4, Margin_top+Drawing_padding_top+4)  -- hover on drawing
-  App.run_after_mouse_press(Margin_left+35, Margin_top+Drawing_padding_top+36, 1)
+  App.mouse_move(Editor_state.margin_left+4, Editor_state.margin_top+Editor_state.drawing_padding_top+4)  -- hover on drawing
+  App.run_after_mouse_press(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1)
   App.run_after_keychord('o')
-  App.run_after_mouse_release(Margin_left+35+30, Margin_top+Drawing_padding_top+36, 1)
-  local drawing = Lines[1]
+  App.run_after_mouse_release(Editor_state.margin_left+35+30, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1)
+  local drawing = Editor_state.lines[1]
   check_eq(#drawing.shapes, 1, 'F - test_draw_circle_mid_stroke/#shapes')
   check_eq(#drawing.points, 1, 'F - test_draw_circle_mid_stroke/#points')
   check_eq(drawing.shapes[1].mode, 'circle', 'F - test_draw_horizontal_line/shape_mode')
@@ -185,21 +185,21 @@ end
 function test_draw_arc()
   io.write('\ntest_draw_arc')
   -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)
-  App.screen.init{width=Margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
-  Lines = load_array{'```lines', '```', ''}
-  Current_drawing_mode = 'circle'
+  App.screen.init{width=Editor_state.margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
+  Editor_state.lines = load_array{'```lines', '```', ''}
+  Editor_state.current_drawing_mode = 'circle'
   edit.draw()
-  check_eq(#Lines, 2, 'F - test_draw_arc/baseline/#lines')
-  check_eq(Lines[1].mode, 'drawing', 'F - test_draw_arc/baseline/mode')
-  check_eq(Lines[1].y, Margin_top+Drawing_padding_top, 'F - test_draw_arc/baseline/y')
-  check_eq(Lines[1].h, 128, 'F - test_draw_arc/baseline/y')
-  check_eq(#Lines[1].shapes, 0, 'F - test_draw_arc/baseline/#shapes')
+  check_eq(#Editor_state.lines, 2, 'F - test_draw_arc/baseline/#lines')
+  check_eq(Editor_state.lines[1].mode, 'drawing', 'F - test_draw_arc/baseline/mode')
+  check_eq(Editor_state.lines[1].y, Editor_state.margin_top+Editor_state.drawing_padding_top, 'F - test_draw_arc/baseline/y')
+  check_eq(Editor_state.lines[1].h, 128, 'F - test_draw_arc/baseline/y')
+  check_eq(#Editor_state.lines[1].shapes, 0, 'F - test_draw_arc/baseline/#shapes')
   -- draw an arc
-  App.run_after_mouse_press(Margin_left+35, Margin_top+Drawing_padding_top+36, 1)
-  App.mouse_move(Margin_left+35+30, Margin_top+Drawing_padding_top+36)
+  App.run_after_mouse_press(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1)
+  App.mouse_move(Editor_state.margin_left+35+30, Editor_state.margin_top+Editor_state.drawing_padding_top+36)
   App.run_after_keychord('a')  -- arc mode
-  App.run_after_mouse_release(Margin_left+35+50, Margin_top+Drawing_padding_top+36+50, 1)  -- 45°
-  local drawing = Lines[1]
+  App.run_after_mouse_release(Editor_state.margin_left+35+50, Editor_state.margin_top+Editor_state.drawing_padding_top+36+50, 1)  -- 45°
+  local drawing = Editor_state.lines[1]
   check_eq(#drawing.shapes, 1, 'F - test_draw_arc/#shapes')
   check_eq(#drawing.points, 1, 'F - test_draw_arc/#points')
   check_eq(drawing.shapes[1].mode, 'arc', 'F - test_draw_horizontal_line/shape_mode')
@@ -215,24 +215,24 @@ end
 function test_draw_polygon()
   io.write('\ntest_draw_polygon')
   -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)
-  App.screen.init{width=Margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
-  Lines = load_array{'```lines', '```', ''}
+  App.screen.init{width=Editor_state.margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
+  Editor_state.lines = load_array{'```lines', '```', ''}
   edit.draw()
-  check_eq(Current_drawing_mode, 'line', 'F - test_draw_polygon/baseline/drawing_mode')
-  check_eq(#Lines, 2, 'F - test_draw_polygon/baseline/#lines')
-  check_eq(Lines[1].mode, 'drawing', 'F - test_draw_polygon/baseline/mode')
-  check_eq(Lines[1].y, Margin_top+Drawing_padding_top, 'F - test_draw_polygon/baseline/y')
-  check_eq(Lines[1].h, 128, 'F - test_draw_polygon/baseline/y')
-  check_eq(#Lines[1].shapes, 0, 'F - test_draw_polygon/baseline/#shapes')
+  check_eq(Editor_state.current_drawing_mode, 'line', 'F - test_draw_polygon/baseline/drawing_mode')
+  check_eq(#Editor_state.lines, 2, 'F - test_draw_polygon/baseline/#lines')
+  check_eq(Editor_state.lines[1].mode, 'drawing', 'F - test_draw_polygon/baseline/mode')
+  check_eq(Editor_state.lines[1].y, Editor_state.margin_top+Editor_state.drawing_padding_top, 'F - test_draw_polygon/baseline/y')
+  check_eq(Editor_state.lines[1].h, 128, 'F - test_draw_polygon/baseline/y')
+  check_eq(#Editor_state.lines[1].shapes, 0, 'F - test_draw_polygon/baseline/#shapes')
   -- first point
-  App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1)
+  App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1)
   App.run_after_keychord('g')  -- polygon mode
   -- second point
-  App.mouse_move(Margin_left+65, Margin_top+Drawing_padding_top+36)
+  App.mouse_move(Editor_state.margin_left+65, Editor_state.margin_top+Editor_state.drawing_padding_top+36)
   App.run_after_keychord('p')  -- add point
   -- final point
-  App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+26, 1)
-  local drawing = Lines[1]
+  App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+26, 1)
+  local drawing = Editor_state.lines[1]
   check_eq(#drawing.shapes, 1, 'F - test_draw_polygon/#shapes')
   check_eq(#drawing.points, 3, 'F - test_draw_polygon/vertices')
   local shape = drawing.shapes[1]
@@ -252,27 +252,27 @@ end
 function test_draw_rectangle()
   io.write('\ntest_draw_rectangle')
   -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)
-  App.screen.init{width=Margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
-  Lines = load_array{'```lines', '```', ''}
+  App.screen.init{width=Editor_state.margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
+  Editor_state.lines = load_array{'```lines', '```', ''}
   edit.draw()
-  check_eq(Current_drawing_mode, 'line', 'F - test_draw_rectangle/baseline/drawing_mode')
-  check_eq(#Lines, 2, 'F - test_draw_rectangle/baseline/#lines')
-  check_eq(Lines[1].mode, 'drawing', 'F - test_draw_rectangle/baseline/mode')
-  check_eq(Lines[1].y, Margin_top+Drawing_padding_top, 'F - test_draw_rectangle/baseline/y')
-  check_eq(Lines[1].h, 128, 'F - test_draw_rectangle/baseline/y')
-  check_eq(#Lines[1].shapes, 0, 'F - test_draw_rectangle/baseline/#shapes')
+  check_eq(Editor_state.current_drawing_mode, 'line', 'F - test_draw_rectangle/baseline/drawing_mode')
+  check_eq(#Editor_state.lines, 2, 'F - test_draw_rectangle/baseline/#lines')
+  check_eq(Editor_state.lines[1].mode, 'drawing', 'F - test_draw_rectangle/baseline/mode')
+  check_eq(Editor_state.lines[1].y, Editor_state.margin_top+Editor_state.drawing_padding_top, 'F - test_draw_rectangle/baseline/y')
+  check_eq(Editor_state.lines[1].h, 128, 'F - test_draw_rectangle/baseline/y')
+  check_eq(#Editor_state.lines[1].shapes, 0, 'F - test_draw_rectangle/baseline/#shapes')
   -- first point
-  App.run_after_mouse_press(Margin_left+35, Margin_top+Drawing_padding_top+36, 1)
+  App.run_after_mouse_press(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1)
   App.run_after_keychord('r')  -- rectangle mode
   -- second point/first edge
-  App.mouse_move(Margin_left+42, Margin_top+Drawing_padding_top+45)
+  App.mouse_move(Editor_state.margin_left+42, Editor_state.margin_top+Editor_state.drawing_padding_top+45)
   App.run_after_keychord('p')
   -- override second point/first edge
-  App.mouse_move(Margin_left+75, Margin_top+Drawing_padding_top+76)
+  App.mouse_move(Editor_state.margin_left+75, Editor_state.margin_top+Editor_state.drawing_padding_top+76)
   App.run_after_keychord('p')
   -- release (decides 'thickness' of rectangle perpendicular to first edge)
-  App.run_after_mouse_release(Margin_left+15, Margin_top+Drawing_padding_top+26, 1)
-  local drawing = Lines[1]
+  App.run_after_mouse_release(Editor_state.margin_left+15, Editor_state.margin_top+Editor_state.drawing_padding_top+26, 1)
+  local drawing = Editor_state.lines[1]
   check_eq(#drawing.shapes, 1, 'F - test_draw_rectangle/#shapes')
   check_eq(#drawing.points, 5, 'F - test_draw_rectangle/#points')  -- currently includes every point added
   local shape = drawing.shapes[1]
@@ -295,25 +295,25 @@ end
 function test_draw_rectangle_intermediate()
   io.write('\ntest_draw_rectangle_intermediate')
   -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)
-  App.screen.init{width=Margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
-  Lines = load_array{'```lines', '```', ''}
+  App.screen.init{width=Editor_state.margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
+  Editor_state.lines = load_array{'```lines', '```', ''}
   edit.draw()
-  check_eq(Current_drawing_mode, 'line', 'F - test_draw_rectangle_intermediate/baseline/drawing_mode')
-  check_eq(#Lines, 2, 'F - test_draw_rectangle_intermediate/baseline/#lines')
-  check_eq(Lines[1].mode, 'drawing', 'F - test_draw_rectangle_intermediate/baseline/mode')
-  check_eq(Lines[1].y, Margin_top+Drawing_padding_top, 'F - test_draw_rectangle_intermediate/baseline/y')
-  check_eq(Lines[1].h, 128, 'F - test_draw_rectangle_intermediate/baseline/y')
-  check_eq(#Lines[1].shapes, 0, 'F - test_draw_rectangle_intermediate/baseline/#shapes')
+  check_eq(Editor_state.current_drawing_mode, 'line', 'F - test_draw_rectangle_intermediate/baseline/drawing_mode')
+  check_eq(#Editor_state.lines, 2, 'F - test_draw_rectangle_intermediate/baseline/#lines')
+  check_eq(Editor_state.lines[1].mode, 'drawing', 'F - test_draw_rectangle_intermediate/baseline/mode')
+  check_eq(Editor_state.lines[1].y, Editor_state.margin_top+Editor_state.drawing_padding_top, 'F - test_draw_rectangle_intermediate/baseline/y')
+  check_eq(Editor_state.lines[1].h, 128, 'F - test_draw_rectangle_intermediate/baseline/y')
+  check_eq(#Editor_state.lines[1].shapes, 0, 'F - test_draw_rectangle_intermediate/baseline/#shapes')
   -- first point
-  App.run_after_mouse_press(Margin_left+35, Margin_top+Drawing_padding_top+36, 1)
+  App.run_after_mouse_press(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1)
   App.run_after_keychord('r')  -- rectangle mode
   -- second point/first edge
-  App.mouse_move(Margin_left+42, Margin_top+Drawing_padding_top+45)
+  App.mouse_move(Editor_state.margin_left+42, Editor_state.margin_top+Editor_state.drawing_padding_top+45)
   App.run_after_keychord('p')
   -- override second point/first edge
-  App.mouse_move(Margin_left+75, Margin_top+Drawing_padding_top+76)
+  App.mouse_move(Editor_state.margin_left+75, Editor_state.margin_top+Editor_state.drawing_padding_top+76)
   App.run_after_keychord('p')
-  local drawing = Lines[1]
+  local drawing = Editor_state.lines[1]
   check_eq(#drawing.points, 3, 'F - test_draw_rectangle_intermediate/#points')  -- currently includes every point added
   local pending = drawing.pending
   check_eq(pending.mode, 'rectangle', 'F - test_draw_rectangle_intermediate/shape_mode')
@@ -330,27 +330,27 @@ end
 function test_draw_square()
   io.write('\ntest_draw_square')
   -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)
-  App.screen.init{width=Margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
-  Lines = load_array{'```lines', '```', ''}
+  App.screen.init{width=Editor_state.margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
+  Editor_state.lines = load_array{'```lines', '```', ''}
   edit.draw()
-  check_eq(Current_drawing_mode, 'line', 'F - test_draw_square/baseline/drawing_mode')
-  check_eq(#Lines, 2, 'F - test_draw_square/baseline/#lines')
-  check_eq(Lines[1].mode, 'drawing', 'F - test_draw_square/baseline/mode')
-  check_eq(Lines[1].y, Margin_top+Drawing_padding_top, 'F - test_draw_square/baseline/y')
-  check_eq(Lines[1].h, 128, 'F - test_draw_square/baseline/y')
-  check_eq(#Lines[1].shapes, 0, 'F - test_draw_square/baseline/#shapes')
+  check_eq(Editor_state.current_drawing_mode, 'line', 'F - test_draw_square/baseline/drawing_mode')
+  check_eq(#Editor_state.lines, 2, 'F - test_draw_square/baseline/#lines')
+  check_eq(Editor_state.lines[1].mode, 'drawing', 'F - test_draw_square/baseline/mode')
+  check_eq(Editor_state.lines[1].y, Editor_state.margin_top+Editor_state.drawing_padding_top, 'F - test_draw_square/baseline/y')
+  check_eq(Editor_state.lines[1].h, 128, 'F - test_draw_square/baseline/y')
+  check_eq(#Editor_state.lines[1].shapes, 0, 'F - test_draw_square/baseline/#shapes')
   -- first point
-  App.run_after_mouse_press(Margin_left+35, Margin_top+Drawing_padding_top+36, 1)
+  App.run_after_mouse_press(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1)
   App.run_after_keychord('s')  -- square mode
   -- second point/first edge
-  App.mouse_move(Margin_left+42, Margin_top+Drawing_padding_top+45)
+  App.mouse_move(Editor_state.margin_left+42, Editor_state.margin_top+Editor_state.drawing_padding_top+45)
   App.run_after_keychord('p')
   -- override second point/first edge
-  App.mouse_move(Margin_left+65, Margin_top+Drawing_padding_top+66)
+  App.mouse_move(Editor_state.margin_left+65, Editor_state.margin_top+Editor_state.drawing_padding_top+66)
   App.run_after_keychord('p')
   -- release (decides which side of first edge to draw square on)
-  App.run_after_mouse_release(Margin_left+15, Margin_top+Drawing_padding_top+26, 1)
-  local drawing = Lines[1]
+  App.run_after_mouse_release(Editor_state.margin_left+15, Editor_state.margin_top+Editor_state.drawing_padding_top+26, 1)
+  local drawing = Editor_state.lines[1]
   check_eq(#drawing.shapes, 1, 'F - test_draw_square/#shapes')
   check_eq(#drawing.points, 5, 'F - test_draw_square/#points')  -- currently includes every point added
   check_eq(drawing.shapes[1].mode, 'square', 'F - test_draw_square/shape_mode')
@@ -372,15 +372,15 @@ end
 function test_name_point()
   io.write('\ntest_name_point')
   -- create a drawing with a line
-  Filename = 'foo'
-  App.screen.init{width=Margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
-  Lines = load_array{'```lines', '```', ''}
-  Current_drawing_mode = 'line'
+  Editor_state.filename = 'foo'
+  App.screen.init{width=Editor_state.margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
+  Editor_state.lines = load_array{'```lines', '```', ''}
+  Editor_state.current_drawing_mode = 'line'
   edit.draw()
   -- draw a line
-  App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1)
-  App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+36, 1)
-  local drawing = Lines[1]
+  App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1)
+  App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1)
+  local drawing = Editor_state.lines[1]
   check_eq(#drawing.shapes, 1, 'F - test_name_point/baseline/#shapes')
   check_eq(#drawing.points, 2, 'F - test_name_point/baseline/#points')
   check_eq(drawing.shapes[1].mode, 'line', 'F - test_name_point/baseline/shape:1')
@@ -393,35 +393,35 @@ function test_name_point()
   check_nil(p2.name, 'F - test_name_point/baseline/p2:name')
   -- enter 'name' mode without moving the mouse
   App.run_after_keychord('C-n')
-  check_eq(Current_drawing_mode, 'name', 'F - test_name_point/mode:1')
+  check_eq(Editor_state.current_drawing_mode, 'name', 'F - test_name_point/mode:1')
   App.run_after_textinput('A')
   check_eq(p2.name, 'A', 'F - test_name_point')
   -- still in 'name' mode
-  check_eq(Current_drawing_mode, 'name', 'F - test_name_point/mode:2')
+  check_eq(Editor_state.current_drawing_mode, 'name', 'F - test_name_point/mode:2')
   -- exit 'name' mode
   App.run_after_keychord('return')
-  check_eq(Current_drawing_mode, 'line', 'F - test_name_point/mode:3')
+  check_eq(Editor_state.current_drawing_mode, 'line', 'F - test_name_point/mode:3')
   check_eq(p2.name, 'A', 'F - test_name_point')
   -- wait until save
   App.wait_fake_time(3.1)
   App.update(0)
   -- change is saved
-  Lines = load_from_disk(Filename)
-  local p2 = Lines[1].points[drawing.shapes[1].p2]
+  Editor_state.lines = load_from_disk(Editor_state.filename)
+  local p2 = Editor_state.lines[1].points[drawing.shapes[1].p2]
   check_eq(p2.name, 'A', 'F - test_name_point/save')
 end
 
 function test_move_point()
   io.write('\ntest_move_point')
   -- create a drawing with a line
-  Filename = 'foo'
-  App.screen.init{width=Margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
-  Lines = load_array{'```lines', '```', ''}
-  Current_drawing_mode = 'line'
+  Editor_state.filename = 'foo'
+  App.screen.init{width=Editor_state.margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
+  Editor_state.lines = load_array{'```lines', '```', ''}
+  Editor_state.current_drawing_mode = 'line'
   edit.draw()
-  App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1)
-  App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+36, 1)
-  local drawing = Lines[1]
+  App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1)
+  App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1)
+  local drawing = Editor_state.lines[1]
   check_eq(#drawing.shapes, 1, 'F - test_move_point/baseline/#shapes')
   check_eq(#drawing.points, 2, 'F - test_move_point/baseline/#points')
   check_eq(drawing.shapes[1].mode, 'line', 'F - test_move_point/baseline/shape:1')
@@ -435,34 +435,34 @@ function test_move_point()
   App.wait_fake_time(3.1)
   App.update(0)
   -- line is saved to disk
-  Lines = load_from_disk(Filename)
-  local drawing = Lines[1]
-  local p2 = Lines[1].points[drawing.shapes[1].p2]
+  Editor_state.lines = load_from_disk(Editor_state.filename)
+  local drawing = Editor_state.lines[1]
+  local p2 = Editor_state.lines[1].points[drawing.shapes[1].p2]
   check_eq(p2.x, 35, 'F - test_move_point/save/x')
   check_eq(p2.y, 36, 'F - test_move_point/save/y')
   edit.draw()
   -- enter 'move' mode without moving the mouse
   App.run_after_keychord('C-u')
-  check_eq(Current_drawing_mode, 'move', 'F - test_move_point/mode:1')
+  check_eq(Editor_state.current_drawing_mode, 'move', 'F - test_move_point/mode:1')
   -- point is lifted
   check_eq(drawing.pending.mode, 'move', 'F - test_move_point/mode:2')
   check_eq(drawing.pending.target_point, p2, 'F - test_move_point/target')
   -- move point
-  App.mouse_move(Margin_left+26, Margin_top+Drawing_padding_top+44)
+  App.mouse_move(Editor_state.margin_left+26, Editor_state.margin_top+Editor_state.drawing_padding_top+44)
   App.update(0.05)
   local p2 = drawing.points[drawing.shapes[1].p2]
   check_eq(p2.x, 26, 'F - test_move_point/x')
   check_eq(p2.y, 44, 'F - test_move_point/y')
   -- exit 'move' mode
-  App.run_after_mouse_click(Margin_left+26, Margin_top+Drawing_padding_top+44, 1)
-  check_eq(Current_drawing_mode, 'line', 'F - test_move_point/mode:3')
+  App.run_after_mouse_click(Editor_state.margin_left+26, Editor_state.margin_top+Editor_state.drawing_padding_top+44, 1)
+  check_eq(Editor_state.current_drawing_mode, 'line', 'F - test_move_point/mode:3')
   check_eq(drawing.pending, {}, 'F - test_move_point/pending')
   -- wait until save
   App.wait_fake_time(3.1)
   App.update(0)
   -- change is saved
-  Lines = load_from_disk(Filename)
-  local p2 = Lines[1].points[drawing.shapes[1].p2]
+  Editor_state.lines = load_from_disk(Editor_state.filename)
+  local p2 = Editor_state.lines[1].points[drawing.shapes[1].p2]
   check_eq(p2.x, 26, 'F - test_move_point/save/x')
   check_eq(p2.y, 44, 'F - test_move_point/save/y')
 end
@@ -470,23 +470,23 @@ end
 function test_move_point_on_manhattan_line()
   io.write('\ntest_move_point_on_manhattan_line')
   -- create a drawing with a manhattan line
-  Filename = 'foo'
-  App.screen.init{width=Margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
-  Lines = load_array{'```lines', '```', ''}
-  Current_drawing_mode = 'manhattan'
+  Editor_state.filename = 'foo'
+  App.screen.init{width=Editor_state.margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
+  Editor_state.lines = load_array{'```lines', '```', ''}
+  Editor_state.current_drawing_mode = 'manhattan'
   edit.draw()
-  App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1)
-  App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+46, 1)
-  local drawing = Lines[1]
+  App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1)
+  App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+46, 1)
+  local drawing = Editor_state.lines[1]
   check_eq(#drawing.shapes, 1, 'F - test_move_point_on_manhattan_line/baseline/#shapes')
   check_eq(#drawing.points, 2, 'F - test_move_point_on_manhattan_line/baseline/#points')
   check_eq(drawing.shapes[1].mode, 'manhattan', 'F - test_move_point_on_manhattan_line/baseline/shape:1')
   edit.draw()
   -- enter 'move' mode
   App.run_after_keychord('C-u')
-  check_eq(Current_drawing_mode, 'move', 'F - test_move_point_on_manhattan_line/mode:1')
+  check_eq(Editor_state.current_drawing_mode, 'move', 'F - test_move_point_on_manhattan_line/mode:1')
   -- move point
-  App.mouse_move(Margin_left+26, Margin_top+Drawing_padding_top+44)
+  App.mouse_move(Editor_state.margin_left+26, Editor_state.margin_top+Editor_state.drawing_padding_top+44)
   App.update(0.05)
   -- line is no longer manhattan
   check_eq(drawing.shapes[1].mode, 'line', 'F - test_move_point_on_manhattan_line/baseline/shape:1')
@@ -495,21 +495,21 @@ end
 function test_delete_lines_at_point()
   io.write('\ntest_delete_lines_at_point')
   -- create a drawing with two lines connected at a point
-  Filename = 'foo'
-  App.screen.init{width=Margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
-  Lines = load_array{'```lines', '```', ''}
-  Current_drawing_mode = 'line'
+  Editor_state.filename = 'foo'
+  App.screen.init{width=Editor_state.margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
+  Editor_state.lines = load_array{'```lines', '```', ''}
+  Editor_state.current_drawing_mode = 'line'
   edit.draw()
-  App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1)
-  App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+36, 1)
-  App.run_after_mouse_press(Margin_left+35, Margin_top+Drawing_padding_top+36, 1)
-  App.run_after_mouse_release(Margin_left+55, Margin_top+Drawing_padding_top+26, 1)
-  local drawing = Lines[1]
+  App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1)
+  App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1)
+  App.run_after_mouse_press(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1)
+  App.run_after_mouse_release(Editor_state.margin_left+55, Editor_state.margin_top+Editor_state.drawing_padding_top+26, 1)
+  local drawing = Editor_state.lines[1]
   check_eq(#drawing.shapes, 2, 'F - test_delete_lines_at_point/baseline/#shapes')
   check_eq(drawing.shapes[1].mode, 'line', 'F - test_delete_lines_at_point/baseline/shape:1')
   check_eq(drawing.shapes[2].mode, 'line', 'F - test_delete_lines_at_point/baseline/shape:2')
   -- hover on the common point and delete
-  App.mouse_move(Margin_left+35, Margin_top+Drawing_padding_top+36)
+  App.mouse_move(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36)
   App.run_after_keychord('C-d')
   check_eq(drawing.shapes[1].mode, 'deleted', 'F - test_delete_lines_at_point/shape:1')
   check_eq(drawing.shapes[2].mode, 'deleted', 'F - test_delete_lines_at_point/shape:2')
@@ -517,27 +517,27 @@ function test_delete_lines_at_point()
   App.wait_fake_time(3.1)
   App.update(0)
   -- deleted points disappear after file is reloaded
-  Lines = load_from_disk(Filename)
-  check_eq(#Lines[1].shapes, 0, 'F - test_delete_lines_at_point/save')
+  Editor_state.lines = load_from_disk(Editor_state.filename)
+  check_eq(#Editor_state.lines[1].shapes, 0, 'F - test_delete_lines_at_point/save')
 end
 
 function test_delete_line_under_mouse_pointer()
   io.write('\ntest_delete_line_under_mouse_pointer')
   -- create a drawing with two lines connected at a point
-  App.screen.init{width=Margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
-  Lines = load_array{'```lines', '```', ''}
-  Current_drawing_mode = 'line'
+  App.screen.init{width=Editor_state.margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
+  Editor_state.lines = load_array{'```lines', '```', ''}
+  Editor_state.current_drawing_mode = 'line'
   edit.draw()
-  App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1)
-  App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+36, 1)
-  App.run_after_mouse_press(Margin_left+35, Margin_top+Drawing_padding_top+36, 1)
-  App.run_after_mouse_release(Margin_left+55, Margin_top+Drawing_padding_top+26, 1)
-  local drawing = Lines[1]
+  App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1)
+  App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1)
+  App.run_after_mouse_press(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1)
+  App.run_after_mouse_release(Editor_state.margin_left+55, Editor_state.margin_top+Editor_state.drawing_padding_top+26, 1)
+  local drawing = Editor_state.lines[1]
   check_eq(#drawing.shapes, 2, 'F - test_delete_line_under_mouse_pointer/baseline/#shapes')
   check_eq(drawing.shapes[1].mode, 'line', 'F - test_delete_line_under_mouse_pointer/baseline/shape:1')
   check_eq(drawing.shapes[2].mode, 'line', 'F - test_delete_line_under_mouse_pointer/baseline/shape:2')
   -- hover on one of the lines and delete
-  App.mouse_move(Margin_left+25, Margin_top+Drawing_padding_top+26)
+  App.mouse_move(Editor_state.margin_left+25, Editor_state.margin_top+Editor_state.drawing_padding_top+26)
   App.run_after_keychord('C-d')
   -- only that line is deleted
   check_eq(drawing.shapes[1].mode, 'deleted', 'F - test_delete_line_under_mouse_pointer/shape:1')
@@ -547,27 +547,27 @@ end
 function test_delete_point_from_polygon()
   io.write('\ntest_delete_point_from_polygon')
   -- create a drawing with two lines connected at a point
-  App.screen.init{width=Margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
-  Lines = load_array{'```lines', '```', ''}
-  Current_drawing_mode = 'line'
+  App.screen.init{width=Editor_state.margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
+  Editor_state.lines = load_array{'```lines', '```', ''}
+  Editor_state.current_drawing_mode = 'line'
   edit.draw()
   -- first point
-  App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1)
+  App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1)
   App.run_after_keychord('g')  -- polygon mode
   -- second point
-  App.mouse_move(Margin_left+65, Margin_top+Drawing_padding_top+36)
+  App.mouse_move(Editor_state.margin_left+65, Editor_state.margin_top+Editor_state.drawing_padding_top+36)
   App.run_after_keychord('p')  -- add point
   -- third point
-  App.mouse_move(Margin_left+35, Margin_top+Drawing_padding_top+26)
+  App.mouse_move(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+26)
   App.run_after_keychord('p')  -- add point
   -- fourth point
-  App.run_after_mouse_release(Margin_left+14, Margin_top+Drawing_padding_top+16, 1)
-  local drawing = Lines[1]
+  App.run_after_mouse_release(Editor_state.margin_left+14, Editor_state.margin_top+Editor_state.drawing_padding_top+16, 1)
+  local drawing = Editor_state.lines[1]
   check_eq(#drawing.shapes, 1, 'F - test_delete_point_from_polygon/baseline/#shapes')
   check_eq(drawing.shapes[1].mode, 'polygon', 'F - test_delete_point_from_polygon/baseline/mode')
   check_eq(#drawing.shapes[1].vertices, 4, 'F - test_delete_point_from_polygon/baseline/vertices')
   -- hover on a point and delete
-  App.mouse_move(Margin_left+35, Margin_top+Drawing_padding_top+26)
+  App.mouse_move(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+26)
   App.run_after_keychord('C-d')
   -- just the one point is deleted
   check_eq(drawing.shapes[1].mode, 'polygon', 'F - test_delete_point_from_polygon/shape')
@@ -577,24 +577,24 @@ end
 function test_delete_point_from_polygon()
   io.write('\ntest_delete_point_from_polygon')
   -- create a drawing with two lines connected at a point
-  App.screen.init{width=Margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
-  Lines = load_array{'```lines', '```', ''}
-  Current_drawing_mode = 'line'
+  App.screen.init{width=Editor_state.margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
+  Editor_state.lines = load_array{'```lines', '```', ''}
+  Editor_state.current_drawing_mode = 'line'
   edit.draw()
   -- first point
-  App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1)
+  App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1)
   App.run_after_keychord('g')  -- polygon mode
   -- second point
-  App.mouse_move(Margin_left+65, Margin_top+Drawing_padding_top+36)
+  App.mouse_move(Editor_state.margin_left+65, Editor_state.margin_top+Editor_state.drawing_padding_top+36)
   App.run_after_keychord('p')  -- add point
   -- third point
-  App.run_after_mouse_release(Margin_left+14, Margin_top+Drawing_padding_top+16, 1)
-  local drawing = Lines[1]
+  App.run_after_mouse_release(Editor_state.margin_left+14, Editor_state.margin_top+Editor_state.drawing_padding_top+16, 1)
+  local drawing = Editor_state.lines[1]
   check_eq(#drawing.shapes, 1, 'F - test_delete_point_from_polygon/baseline/#shapes')
   check_eq(drawing.shapes[1].mode, 'polygon', 'F - test_delete_point_from_polygon/baseline/mode')
   check_eq(#drawing.shapes[1].vertices, 3, 'F - test_delete_point_from_polygon/baseline/vertices')
   -- hover on a point and delete
-  App.mouse_move(Margin_left+65, Margin_top+Drawing_padding_top+36)
+  App.mouse_move(Editor_state.margin_left+65, Editor_state.margin_top+Editor_state.drawing_padding_top+36)
   App.run_after_keychord('C-d')
   -- there's < 3 points left, so the whole polygon is deleted
   check_eq(drawing.shapes[1].mode, 'deleted', 'F - test_delete_point_from_polygon')
@@ -603,15 +603,15 @@ end
 function test_undo_name_point()
   io.write('\ntest_undo_name_point')
   -- create a drawing with a line
-  Filename = 'foo'
-  App.screen.init{width=Margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
-  Lines = load_array{'```lines', '```', ''}
-  Current_drawing_mode = 'line'
+  Editor_state.filename = 'foo'
+  App.screen.init{width=Editor_state.margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
+  Editor_state.lines = load_array{'```lines', '```', ''}
+  Editor_state.current_drawing_mode = 'line'
   edit.draw()
   -- draw a line
-  App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1)
-  App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+36, 1)
-  local drawing = Lines[1]
+  App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1)
+  App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1)
+  local drawing = Editor_state.lines[1]
   check_eq(#drawing.shapes, 1, 'F - test_undo_name_point/baseline/#shapes')
   check_eq(#drawing.points, 2, 'F - test_undo_name_point/baseline/#points')
   check_eq(drawing.shapes[1].mode, 'line', 'F - test_undo_name_point/baseline/shape:1')
@@ -622,40 +622,40 @@ function test_undo_name_point()
   check_eq(p2.x, 35, 'F - test_undo_name_point/baseline/p2:x')
   check_eq(p2.y, 36, 'F - test_undo_name_point/baseline/p2:y')
   check_nil(p2.name, 'F - test_undo_name_point/baseline/p2:name')
-  check_eq(#History, 1, 'F - test_undo_name_point/baseline/history:1')
+  check_eq(#Editor_state.history, 1, 'F - test_undo_name_point/baseline/history:1')
   -- enter 'name' mode without moving the mouse
   App.run_after_keychord('C-n')
   App.run_after_textinput('A')
   App.run_after_keychord('return')
   check_eq(p2.name, 'A', 'F - test_undo_name_point/baseline')
-  check_eq(#History, 3, 'F - test_undo_name_point/baseline/history:2')
-  check_eq(Next_history, 4, 'F - test_undo_name_point/baseline/next_history')
+  check_eq(#Editor_state.history, 3, 'F - test_undo_name_point/baseline/history:2')
+  check_eq(Editor_state.next_history, 4, 'F - test_undo_name_point/baseline/next_history')
   -- undo
   App.run_after_keychord('C-z')
-  local drawing = Lines[1]
+  local drawing = Editor_state.lines[1]
   local p2 = drawing.points[drawing.shapes[1].p2]
-  check_eq(Next_history, 3, 'F - test_undo_name_point/next_history')
+  check_eq(Editor_state.next_history, 3, 'F - test_undo_name_point/next_history')
   check_eq(p2.name, '', 'F - test_undo_name_point')  -- not quite what it was before, but close enough
   -- wait until save
   App.wait_fake_time(3.1)
   App.update(0)
   -- undo is saved
-  Lines = load_from_disk(Filename)
-  local p2 = Lines[1].points[drawing.shapes[1].p2]
+  Editor_state.lines = load_from_disk(Editor_state.filename)
+  local p2 = Editor_state.lines[1].points[drawing.shapes[1].p2]
   check_eq(p2.name, '', 'F - test_undo_name_point/save')
 end
 
 function test_undo_move_point()
   io.write('\ntest_undo_move_point')
   -- create a drawing with a line
-  Filename = 'foo'
-  App.screen.init{width=Margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
-  Lines = load_array{'```lines', '```', ''}
-  Current_drawing_mode = 'line'
+  Editor_state.filename = 'foo'
+  App.screen.init{width=Editor_state.margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
+  Editor_state.lines = load_array{'```lines', '```', ''}
+  Editor_state.current_drawing_mode = 'line'
   edit.draw()
-  App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1)
-  App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+36, 1)
-  local drawing = Lines[1]
+  App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1)
+  App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1)
+  local drawing = Editor_state.lines[1]
   check_eq(#drawing.shapes, 1, 'F - test_undo_move_point/baseline/#shapes')
   check_eq(#drawing.points, 2, 'F - test_undo_move_point/baseline/#points')
   check_eq(drawing.shapes[1].mode, 'line', 'F - test_undo_move_point/baseline/shape:1')
@@ -668,28 +668,28 @@ function test_undo_move_point()
   check_nil(p2.name, 'F - test_undo_move_point/baseline/p2:name')
   -- move p2
   App.run_after_keychord('C-u')
-  App.mouse_move(Margin_left+26, Margin_top+Drawing_padding_top+44)
+  App.mouse_move(Editor_state.margin_left+26, Editor_state.margin_top+Editor_state.drawing_padding_top+44)
   App.update(0.05)
   local p2 = drawing.points[drawing.shapes[1].p2]
   check_eq(p2.x, 26, 'F - test_undo_move_point/x')
   check_eq(p2.y, 44, 'F - test_undo_move_point/y')
   -- exit 'move' mode
-  App.run_after_mouse_click(Margin_left+26, Margin_top+Drawing_padding_top+44, 1)
-  check_eq(Next_history, 4, 'F - test_undo_move_point/next_history')
+  App.run_after_mouse_click(Editor_state.margin_left+26, Editor_state.margin_top+Editor_state.drawing_padding_top+44, 1)
+  check_eq(Editor_state.next_history, 4, 'F - test_undo_move_point/next_history')
   -- undo
   App.run_after_keychord('C-z')
   App.run_after_keychord('C-z')  -- bug: need to undo twice
-  local drawing = Lines[1]
+  local drawing = Editor_state.lines[1]
   local p2 = drawing.points[drawing.shapes[1].p2]
-  check_eq(Next_history, 2, 'F - test_undo_move_point/next_history')
+  check_eq(Editor_state.next_history, 2, 'F - test_undo_move_point/next_history')
   check_eq(p2.x, 35, 'F - test_undo_move_point/x')
   check_eq(p2.y, 36, 'F - test_undo_move_point/y')
   -- wait until save
   App.wait_fake_time(3.1)
   App.update(0)
   -- undo is saved
-  Lines = load_from_disk(Filename)
-  local p2 = Lines[1].points[drawing.shapes[1].p2]
+  Editor_state.lines = load_from_disk(Editor_state.filename)
+  local p2 = Editor_state.lines[1].points[drawing.shapes[1].p2]
   check_eq(p2.x, 35, 'F - test_undo_move_point/save/x')
   check_eq(p2.y, 36, 'F - test_undo_move_point/save/y')
 end
@@ -697,35 +697,35 @@ end
 function test_undo_delete_point()
   io.write('\ntest_undo_delete_point')
   -- create a drawing with two lines connected at a point
-  Filename = 'foo'
-  App.screen.init{width=Margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
-  Lines = load_array{'```lines', '```', ''}
-  Current_drawing_mode = 'line'
+  Editor_state.filename = 'foo'
+  App.screen.init{width=Editor_state.margin_width+256, height=300}  -- drawing coordinates 1:1 with pixels
+  Editor_state.lines = load_array{'```lines', '```', ''}
+  Editor_state.current_drawing_mode = 'line'
   edit.draw()
-  App.run_after_mouse_press(Margin_left+5, Margin_top+Drawing_padding_top+6, 1)
-  App.run_after_mouse_release(Margin_left+35, Margin_top+Drawing_padding_top+36, 1)
-  App.run_after_mouse_press(Margin_left+35, Margin_top+Drawing_padding_top+36, 1)
-  App.run_after_mouse_release(Margin_left+55, Margin_top+Drawing_padding_top+26, 1)
-  local drawing = Lines[1]
+  App.run_after_mouse_press(Editor_state.margin_left+5, Editor_state.margin_top+Editor_state.drawing_padding_top+6, 1)
+  App.run_after_mouse_release(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1)
+  App.run_after_mouse_press(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36, 1)
+  App.run_after_mouse_release(Editor_state.margin_left+55, Editor_state.margin_top+Editor_state.drawing_padding_top+26, 1)
+  local drawing = Editor_state.lines[1]
   check_eq(#drawing.shapes, 2, 'F - test_undo_delete_point/baseline/#shapes')
   check_eq(drawing.shapes[1].mode, 'line', 'F - test_undo_delete_point/baseline/shape:1')
   check_eq(drawing.shapes[2].mode, 'line', 'F - test_undo_delete_point/baseline/shape:2')
   -- hover on the common point and delete
-  App.mouse_move(Margin_left+35, Margin_top+Drawing_padding_top+36)
+  App.mouse_move(Editor_state.margin_left+35, Editor_state.margin_top+Editor_state.drawing_padding_top+36)
   App.run_after_keychord('C-d')
   check_eq(drawing.shapes[1].mode, 'deleted', 'F - test_undo_delete_point/shape:1')
   check_eq(drawing.shapes[2].mode, 'deleted', 'F - test_undo_delete_point/shape:2')
   -- undo
   App.run_after_keychord('C-z')
-  local drawing = Lines[1]
+  local drawing = Editor_state.lines[1]
   local p2 = drawing.points[drawing.shapes[1].p2]
-  check_eq(Next_history, 3, 'F - test_undo_move_point/next_history')
+  check_eq(Editor_state.next_history, 3, 'F - test_undo_move_point/next_history')
   check_eq(drawing.shapes[1].mode, 'line', 'F - test_undo_delete_point/shape:1')
   check_eq(drawing.shapes[2].mode, 'line', 'F - test_undo_delete_point/shape:2')
   -- wait until save
   App.wait_fake_time(3.1)
   App.update(0)
   -- undo is saved
-  Lines = load_from_disk(Filename)
-  check_eq(#Lines[1].shapes, 2, 'F - test_undo_delete_point/save')
+  Editor_state.lines = load_from_disk(Editor_state.filename)
+  check_eq(#Editor_state.lines[1].shapes, 2, 'F - test_undo_delete_point/save')
 end
diff --git a/edit.lua b/edit.lua
index a114607..d136c5d 100644
--- a/edit.lua
+++ b/edit.lua
@@ -22,100 +22,110 @@ require 'icons'
 edit = {}
 
 -- run in both tests and a real run
-function edit.initialize_globals()
--- a line is either text or a drawing
--- a text is a table with:
---    mode = 'text',
---    string data,
---    startpos, the index of data the line starts rendering from (if currently on screen), can only be >1 for topmost line on screen
---    starty, the y coord in pixels
---    some cached data that's blown away and recomputed when data changes:
---      fragments: snippets of rendered love.graphics.Text, guaranteed to not wrap
---      screen_line_starting_pos: optional array of grapheme indices if it wraps over more than one screen line
--- a drawing is a table with:
---    mode = 'drawing'
---    a (y) coord in pixels (updated while painting screen),
---    a (h)eight,
---    an array of points, and
---    an array of shapes
--- a shape is a table containing:
---    a mode
---    an array points for mode 'freehand' (raw x,y coords; freehand drawings don't pollute the points array of a drawing)
---    an array vertices for mode 'polygon', 'rectangle', 'square'
---    p1, p2 for mode 'line'
---    center, radius for mode 'circle'
---    center, radius, start_angle, end_angle for mode 'arc'
--- Unless otherwise specified, coord fields are normalized; a drawing is always 256 units wide
--- The field names are carefully chosen so that switching modes in midstream
--- remembers previously entered points where that makes sense.
-Lines = {{mode='text', data=''}}
+function edit.initialize_state()
+  local result = {
+    -- a line is either text or a drawing
+    -- a text is a table with:
+    --    mode = 'text',
+    --    string data,
+    --    startpos, the index of data the line starts rendering from (if currently on screen), can only be >1 for topmost line on screen
+    --    starty, the y coord in pixels
+    --    some cached data that's blown away and recomputed when data changes:
+    --      fragments: snippets of rendered love.graphics.Text, guaranteed to not wrap
+    --      screen_line_starting_pos: optional array of grapheme indices if it wraps over more than one screen line
+    -- a drawing is a table with:
+    --    mode = 'drawing'
+    --    a (y) coord in pixels (updated while painting screen),
+    --    a (h)eight,
+    --    an array of points, and
+    --    an array of shapes
+    -- a shape is a table containing:
+    --    a mode
+    --    an array points for mode 'freehand' (raw x,y coords; freehand drawings don't pollute the points array of a drawing)
+    --    an array vertices for mode 'polygon', 'rectangle', 'square'
+    --    p1, p2 for mode 'line'
+    --    center, radius for mode 'circle'
+    --    center, radius, start_angle, end_angle for mode 'arc'
+    -- Unless otherwise specified, coord fields are normalized; a drawing is always 256 units wide
+    -- The field names are carefully chosen so that switching modes in midstream
+    -- remembers previously entered points where that makes sense.
+    lines = {{mode='text', data=''}},
 
--- Lines can be too long to fit on screen, in which case they _wrap_ into
--- multiple _screen lines_.
---
--- Therefore, any potential location for the cursor can be described in two ways:
--- * schema 1: As a combination of line index and position within a line (in utf8 codepoint units)
--- * schema 2: As a combination of line index, screen line index within the line, and a position within the screen line.
---
--- Most of the time we'll only persist positions in schema 1, translating to
--- schema 2 when that's convenient.
---
--- Make sure these coordinates are never aliased, so that changing one causes
--- action at a distance.
-Screen_top1 = {line=1, pos=1}  -- position of start of screen line at top of screen
-Cursor1 = {line=1, pos=1}  -- position of cursor
-Screen_bottom1 = {line=1, pos=1}  -- position of start of screen line at bottom of screen
+    -- Lines can be too long to fit on screen, in which case they _wrap_ into
+    -- multiple _screen lines_.
+    --
+    -- Therefore, any potential location for the cursor can be described in two ways:
+    -- * schema 1: As a combination of line index and position within a line (in utf8 codepoint units)
+    -- * schema 2: As a combination of line index, screen line index within the line, and a position within the screen line.
+    --
+    -- Most of the time we'll only persist positions in schema 1, translating to
+    -- schema 2 when that's convenient.
+    --
+    -- Make sure these coordinates are never aliased, so that changing one causes
+    -- action at a distance.
+    screen_top1 = {line=1, pos=1},  -- position of start of screen line at top of screen
+    cursor1 = {line=1, pos=1},  -- position of cursor
+    screen_bottom1 = {line=1, pos=1},  -- position of start of screen line at bottom of screen
 
-Selection1 = {}
-Old_cursor1, Old_selection1, Mousepress_shift = nil  -- some extra state to compute selection between mouse press and release
-Recent_mouse = {}  -- when selecting text, avoid recomputing some state on every single frame
+    selection1 = {},
+    -- some extra state to compute selection between mouse press and release
+    old_cursor1 = nil,
+    old_selection1 = nil,
+    mousepress_shift = nil,
+    -- when selecting text, avoid recomputing some state on every single frame
+    recent_mouse = {},
 
-Cursor_x, Cursor_y = 0, 0  -- in pixels
+    -- cursor coordinates in pixels
+    cursor_x = 0,
+    cursor_y = 0,
 
-Current_drawing_mode = 'line'
-Previous_drawing_mode = nil
+    current_drawing_mode = 'line',
+    previous_drawing_mode = nil,  -- extra state for some ephemeral modes like moving/deleting/naming points
 
--- values for tests
-Font_height = 14
-Line_height = 15
--- widest possible character width
-Em = App.newText(love.graphics.getFont(), 'm')
+    -- these default values are important for tests
+    font_height = 14,
+    line_height = 15,
+    -- widest possible character width
+    em = App.newText(love.graphics.getFont(), 'm'),
 
-Margin_top = 15
-Margin_left = 25
-Margin_right = 25
-Margin_width = Margin_left + Margin_right
+    margin_top = 15,
+    margin_left = 25,
+    margin_right = 25,
+    margin_width = nil,
 
-Drawing_padding_top = 10
-Drawing_padding_bottom = 10
-Drawing_padding_height = Drawing_padding_top + Drawing_padding_bottom
+    drawing_padding_top = 10,
+    drawing_padding_bottom = 10,
+    drawing_padding_height = nil,
 
-Filename = love.filesystem.getUserDirectory()..'/lines.txt'
-Next_save = nil
+    filename = love.filesystem.getUserDirectory()..'/lines.txt',
+    next_save = nil,
 
--- undo
-History = {}
-Next_history = 1
+    -- undo
+    history = {},
+    next_history = 1,
 
--- search
-Search_term = nil
-Search_text = nil
-Search_backup = nil  -- stuff to restore when cancelling search
-
-end  -- App.initialize_globals
+    -- search
+    search_term = nil,
+    search_text = nil,
+    search_backup = nil,  -- stuff to restore when cancelling search
+  }
+  result.margin_width = result.margin_left + result.margin_right
+  result.drawing_padding_height = result.drawing_padding_top + result.drawing_padding_bottom
+  return result
+end  -- App.initialize_state
 
 function edit.draw()
   App.color(Text_color)
---?   print(Screen_top1.line, Screen_top1.pos, Cursor1.line, Cursor1.pos)
-  assert(Text.le1(Screen_top1, Cursor1))
-  Cursor_y = -1
-  local y = Margin_top
+--?   print(Editor_state.screen_top1.line, Editor_state.screen_top1.pos, Editor_state.cursor1.line, Editor_state.cursor1.pos)
+  assert(Text.le1(Editor_state.screen_top1, Editor_state.cursor1))
+  Editor_state.cursor_y = -1
+  local y = Editor_state.margin_top
 --?   print('== draw')
-  for line_index = Screen_top1.line,#Lines do
-    local line = Lines[line_index]
+  for line_index = Editor_state.screen_top1.line,#Editor_state.lines do
+    local line = Editor_state.lines[line_index]
 --?     print('draw:', y, line_index, line)
-    if y + Line_height > App.screen.height then break end
-    Screen_bottom1.line = line_index
+    if y + Editor_state.line_height > App.screen.height then break end
+    Editor_state.screen_bottom1.line = line_index
     if line.mode == 'text' and line.data == '' then
       line.starty = y
       line.startpos = 1
@@ -124,76 +134,76 @@ function edit.draw()
         icon = icon.insert_drawing,
         onpress1 = function()
                      Drawing.before = snapshot(line_index-1, line_index)
-                     table.insert(Lines, line_index, {mode='drawing', y=y, h=256/2, points={}, shapes={}, pending={}})
-                     if Cursor1.line >= line_index then
-                       Cursor1.line = Cursor1.line+1
+                     table.insert(Editor_state.lines, line_index, {mode='drawing', y=y, h=256/2, points={}, shapes={}, pending={}})
+                     if Editor_state.cursor1.line >= line_index then
+                       Editor_state.cursor1.line = Editor_state.cursor1.line+1
                      end
                      schedule_save()
                      record_undo_event({before=Drawing.before, after=snapshot(line_index-1, line_index+1)})
                    end
       })
-      if Search_term == nil then
-        if line_index == Cursor1.line then
-          Text.draw_cursor(Margin_left, y)
+      if Editor_state.search_term == nil then
+        if line_index == Editor_state.cursor1.line then
+          Text.draw_cursor(Editor_state.margin_left, y)
         end
       end
-      Screen_bottom1.pos = Screen_top1.pos
-      y = y + Line_height
+      Editor_state.screen_bottom1.pos = Editor_state.screen_top1.pos
+      y = y + Editor_state.line_height
     elseif line.mode == 'drawing' then
-      y = y+Drawing_padding_top
+      y = y+Editor_state.drawing_padding_top
       line.y = y
       Drawing.draw(line)
-      y = y + Drawing.pixels(line.h) + Drawing_padding_bottom
+      y = y + Drawing.pixels(line.h) + Editor_state.drawing_padding_bottom
     else
       line.starty = y
       line.startpos = 1
-      if line_index == Screen_top1.line then
-        line.startpos = Screen_top1.pos
+      if line_index == Editor_state.screen_top1.line then
+        line.startpos = Editor_state.screen_top1.pos
       end
 --?       print('text.draw', y, line_index)
-      y, Screen_bottom1.pos = Text.draw(line, line_index, line.starty, Margin_left, App.screen.width-Margin_right)
-      y = y + Line_height
+      y, Editor_state.screen_bottom1.pos = Text.draw(line, line_index, line.starty, Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
+      y = y + Editor_state.line_height
 --?       print('=> y', y)
     end
   end
-  if Cursor_y == -1 then
-    Cursor_y = App.screen.height
+  if Editor_state.cursor_y == -1 then
+    Editor_state.cursor_y = App.screen.height
   end
---?   print('screen bottom: '..tostring(Screen_bottom1.pos)..' in '..tostring(Lines[Screen_bottom1.line].data))
-  if Search_term then
+--?   print('screen bottom: '..tostring(Editor_state.screen_bottom1.pos)..' in '..tostring(Editor_state.lines[Editor_state.screen_bottom1.line].data))
+  if Editor_state.search_term then
     Text.draw_search_bar()
   end
 end
 
 function edit.update(dt)
   Drawing.update(dt)
-  if Next_save and Next_save < App.getTime() then
-    save_to_disk(Lines, Filename)
-    Next_save = nil
+  if Editor_state.next_save and Editor_state.next_save < App.getTime() then
+    save_to_disk(Editor_state.lines, Editor_state.filename)
+    Editor_state.next_save = nil
   end
 end
 
 function schedule_save()
-  if Next_save == nil then
-    Next_save = App.getTime() + 3  -- short enough that you're likely to still remember what you did
+  if Editor_state.next_save == nil then
+    Editor_state.next_save = App.getTime() + 3  -- short enough that you're likely to still remember what you did
   end
 end
 
 function edit.quit()
   -- make sure to save before quitting
-  if Next_save then
-    save_to_disk(Lines, Filename)
+  if Editor_state.next_save then
+    save_to_disk(Editor_state.lines, Editor_state.filename)
   end
 end
 
 function edit.mouse_pressed(x,y, mouse_button)
-  if Search_term then return end
---?   print('press', Selection1.line, Selection1.pos)
+  if Editor_state.search_term then return end
+--?   print('press', Editor_state.selection1.line, Editor_state.selection1.pos)
   propagate_to_button_handlers(x,y, mouse_button)
 
-  for line_index,line in ipairs(Lines) do
+  for line_index,line in ipairs(Editor_state.lines) do
     if line.mode == 'text' then
-      if Text.in_line(line, x,y, Margin_left, App.screen.width-Margin_right) then
+      if Text.in_line(line, x,y, Editor_state.margin_left, App.screen.width-Editor_state.margin_right) then
         -- delicate dance between cursor, selection and old cursor/selection
         -- scenarios:
         --  regular press+release: sets cursor, clears selection
@@ -203,20 +213,20 @@ function edit.mouse_pressed(x,y, mouse_button)
         --  press and hold to start a selection: sets selection on press, cursor on release
         --  press and hold, then press shift: ignore shift
         --    i.e. mousereleased should never look at shift state
-        Old_cursor1 = Cursor1
-        Old_selection1 = Selection1
-        Mousepress_shift = App.shift_down()
-        Selection1 = {
+        Editor_state.old_cursor1 = Editor_state.cursor1
+        Editor_state.old_selection1 = Editor_state.selection1
+        Editor_state.mousepress_shift = App.shift_down()
+        Editor_state.selection1 = {
             line=line_index,
-            pos=Text.to_pos_on_line(line, x, y, Margin_left, App.screen.width-Margin_right),
+            pos=Text.to_pos_on_line(line, x, y, Editor_state.margin_left, App.screen.width-Editor_state.margin_right),
         }
---?         print('selection', Selection1.line, Selection1.pos)
+--?         print('selection', Editor_state.selection1.line, Editor_state.selection1.pos)
         break
       end
     elseif line.mode == 'drawing' then
       if Drawing.in_drawing(line, x, y) then
-        Lines.current_drawing_index = line_index
-        Lines.current_drawing = line
+        Editor_state.lines.current_drawing_index = line_index
+        Editor_state.lines.current_drawing = line
         Drawing.before = snapshot(line_index)
         Drawing.mouse_pressed(line, x,y, mouse_button)
         break
@@ -226,56 +236,56 @@ function edit.mouse_pressed(x,y, mouse_button)
 end
 
 function edit.mouse_released(x,y, mouse_button)
-  if Search_term then return end
+  if Editor_state.search_term then return end
 --?   print('release')
-  if Lines.current_drawing then
+  if Editor_state.lines.current_drawing then
     Drawing.mouse_released(x,y, mouse_button)
     schedule_save()
     if Drawing.before then
-      record_undo_event({before=Drawing.before, after=snapshot(Lines.current_drawing_index)})
+      record_undo_event({before=Drawing.before, after=snapshot(Editor_state.lines.current_drawing_index)})
       Drawing.before = nil
     end
   else
-    for line_index,line in ipairs(Lines) do
+    for line_index,line in ipairs(Editor_state.lines) do
       if line.mode == 'text' then
-        if Text.in_line(line, x,y, Margin_left, App.screen.width-Margin_right) then
+        if Text.in_line(line, x,y, Editor_state.margin_left, App.screen.width-Editor_state.margin_right) then
 --?           print('reset selection')
-          Cursor1 = {
+          Editor_state.cursor1 = {
               line=line_index,
-              pos=Text.to_pos_on_line(line, x, y, Margin_left, App.screen.width-Margin_right),
+              pos=Text.to_pos_on_line(line, x, y, Editor_state.margin_left, App.screen.width-Editor_state.margin_right),
           }
---?           print('cursor', Cursor1.line, Cursor1.pos)
-          if Mousepress_shift then
-            if Old_selection1.line == nil then
-              Selection1 = Old_cursor1
+--?           print('cursor', Editor_state.cursor1.line, Editor_state.cursor1.pos)
+          if Editor_state.mousepress_shift then
+            if Editor_state.old_selection1.line == nil then
+              Editor_state.selection1 = Editor_state.old_cursor1
             else
-              Selection1 = Old_selection1
+              Editor_state.selection1 = Editor_state.old_selection1
             end
           end
-          Old_cursor1, Old_selection1, Mousepress_shift = nil
-          if eq(Cursor1, Selection1) then
-            Selection1 = {}
+          Editor_state.old_cursor1, Editor_state.old_selection1, Editor_state.mousepress_shift = nil
+          if eq(Editor_state.cursor1, Editor_state.selection1) then
+            Editor_state.selection1 = {}
           end
           break
         end
       end
     end
---?     print('selection:', Selection1.line, Selection1.pos)
+--?     print('selection:', Editor_state.selection1.line, Editor_state.selection1.pos)
   end
 end
 
 function edit.textinput(t)
-  for _,line in ipairs(Lines) do line.y = nil end  -- just in case we scroll
-  if Search_term then
-    Search_term = Search_term..t
-    Search_text = nil
+  for _,line in ipairs(Editor_state.lines) do line.y = nil end  -- just in case we scroll
+  if Editor_state.search_term then
+    Editor_state.search_term = Editor_state.search_term..t
+    Editor_state.search_text = nil
     Text.search_next()
-  elseif Current_drawing_mode == 'name' then
-    local before = snapshot(Lines.current_drawing_index)
-    local drawing = Lines.current_drawing
+  elseif Editor_state.current_drawing_mode == 'name' then
+    local before = snapshot(Editor_state.lines.current_drawing_index)
+    local drawing = Editor_state.lines.current_drawing
     local p = drawing.points[drawing.pending.target_point]
     p.name = p.name..t
-    record_undo_event({before=before, after=snapshot(Lines.current_drawing_index)})
+    record_undo_event({before=before, after=snapshot(Editor_state.lines.current_drawing_index)})
   else
     Text.textinput(t)
   end
@@ -283,94 +293,94 @@ function edit.textinput(t)
 end
 
 function edit.keychord_pressed(chord, key)
-  if Selection1.line and
-      not Lines.current_drawing and
+  if Editor_state.selection1.line and
+      not Editor_state.lines.current_drawing and
       -- printable character created using shift key => delete selection
       -- (we're not creating any ctrl-shift- or alt-shift- combinations using regular/printable keys)
       (not App.shift_down() or utf8.len(key) == 1) and
       chord ~= 'C-c' and chord ~= 'C-x' and chord ~= 'backspace' and backspace ~= 'delete' and not App.is_cursor_movement(chord) then
-    Text.delete_selection(Margin_left, App.screen.width-Margin_right)
+    Text.delete_selection(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
   end
-  if Search_term then
+  if Editor_state.search_term then
     if chord == 'escape' then
-      Search_term = nil
-      Search_text = nil
-      Cursor1 = Search_backup.cursor
-      Screen_top1 = Search_backup.screen_top
-      Search_backup = nil
+      Editor_state.search_term = nil
+      Editor_state.search_text = nil
+      Editor_state.cursor1 = Editor_state.search_backup.cursor
+      Editor_state.screen_top1 = Editor_state.search_backup.screen_top
+      Editor_state.search_backup = nil
       Text.redraw_all()  -- if we're scrolling, reclaim all fragments to avoid memory leaks
     elseif chord == 'return' then
-      Search_term = nil
-      Search_text = nil
-      Search_backup = nil
+      Editor_state.search_term = nil
+      Editor_state.search_text = nil
+      Editor_state.search_backup = nil
     elseif chord == 'backspace' then
-      local len = utf8.len(Search_term)
-      local byte_offset = Text.offset(Search_term, len)
-      Search_term = string.sub(Search_term, 1, byte_offset-1)
-      Search_text = nil
+      local len = utf8.len(Editor_state.search_term)
+      local byte_offset = Text.offset(Editor_state.search_term, len)
+      Editor_state.search_term = string.sub(Editor_state.search_term, 1, byte_offset-1)
+      Editor_state.search_text = nil
     elseif chord == 'down' then
-      Cursor1.pos = Cursor1.pos+1
+      Editor_state.cursor1.pos = Editor_state.cursor1.pos+1
       Text.search_next()
     elseif chord == 'up' then
       Text.search_previous()
     end
     return
   elseif chord == 'C-f' then
-    Search_term = ''
-    Search_backup = {cursor={line=Cursor1.line, pos=Cursor1.pos}, screen_top={line=Screen_top1.line, pos=Screen_top1.pos}}
-    assert(Search_text == nil)
+    Editor_state.search_term = ''
+    Editor_state.search_backup = {cursor={line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos}, screen_top={line=Editor_state.screen_top1.line, pos=Editor_state.screen_top1.pos}}
+    assert(Editor_state.search_text == nil)
   elseif chord == 'C-=' then
-    initialize_font_settings(Font_height+2)
+    initialize_font_settings(Editor_state.font_height+2)
     Text.redraw_all()
   elseif chord == 'C--' then
-    initialize_font_settings(Font_height-2)
+    initialize_font_settings(Editor_state.font_height-2)
     Text.redraw_all()
   elseif chord == 'C-0' then
     initialize_font_settings(20)
     Text.redraw_all()
   elseif chord == 'C-z' then
-    for _,line in ipairs(Lines) do line.y = nil end  -- just in case we scroll
+    for _,line in ipairs(Editor_state.lines) do line.y = nil end  -- just in case we scroll
     local event = undo_event()
     if event then
       local src = event.before
-      Screen_top1 = deepcopy(src.screen_top)
-      Cursor1 = deepcopy(src.cursor)
-      Selection1 = deepcopy(src.selection)
-      patch(Lines, event.after, event.before)
+      Editor_state.screen_top1 = deepcopy(src.screen_top)
+      Editor_state.cursor1 = deepcopy(src.cursor)
+      Editor_state.selection1 = deepcopy(src.selection)
+      patch(Editor_state.lines, event.after, event.before)
       Text.redraw_all()  -- if we're scrolling, reclaim all fragments to avoid memory leaks
       schedule_save()
     end
   elseif chord == 'C-y' then
-    for _,line in ipairs(Lines) do line.y = nil end  -- just in case we scroll
+    for _,line in ipairs(Editor_state.lines) do line.y = nil end  -- just in case we scroll
     local event = redo_event()
     if event then
       local src = event.after
-      Screen_top1 = deepcopy(src.screen_top)
-      Cursor1 = deepcopy(src.cursor)
-      Selection1 = deepcopy(src.selection)
-      patch(Lines, event.before, event.after)
+      Editor_state.screen_top1 = deepcopy(src.screen_top)
+      Editor_state.cursor1 = deepcopy(src.cursor)
+      Editor_state.selection1 = deepcopy(src.selection)
+      patch(Editor_state.lines, event.before, event.after)
       Text.redraw_all()  -- if we're scrolling, reclaim all fragments to avoid memory leaks
       schedule_save()
     end
   -- clipboard
   elseif chord == 'C-c' then
-    for _,line in ipairs(Lines) do line.y = nil end  -- just in case we scroll
+    for _,line in ipairs(Editor_state.lines) do line.y = nil end  -- just in case we scroll
     local s = Text.selection()
     if s then
       App.setClipboardText(s)
     end
   elseif chord == 'C-x' then
-    for _,line in ipairs(Lines) do line.y = nil end  -- just in case we scroll
-    local s = Text.cut_selection(Margin_left, App.screen.width-Margin_right)
+    for _,line in ipairs(Editor_state.lines) do line.y = nil end  -- just in case we scroll
+    local s = Text.cut_selection(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
     if s then
       App.setClipboardText(s)
     end
     schedule_save()
   elseif chord == 'C-v' then
-    for _,line in ipairs(Lines) do line.y = nil end  -- just in case we scroll
+    for _,line in ipairs(Editor_state.lines) do line.y = nil end  -- just in case we scroll
     -- We don't have a good sense of when to scroll, so we'll be conservative
     -- and sometimes scroll when we didn't quite need to.
-    local before_line = Cursor1.line
+    local before_line = Editor_state.cursor1.line
     local before = snapshot(before_line)
     local clipboard_data = App.getClipboardText()
     for _,code in utf8.codes(clipboard_data) do
@@ -382,10 +392,10 @@ function edit.keychord_pressed(chord, key)
       end
     end
     if Text.cursor_past_screen_bottom() then
-      Text.snap_cursor_to_bottom_of_screen(Margin_left, App.screen.height-Margin_right)
+      Text.snap_cursor_to_bottom_of_screen(Editor_state.margin_left, App.screen.height-Editor_state.margin_right)
     end
     schedule_save()
-    record_undo_event({before=before, after=snapshot(before_line, Cursor1.line)})
+    record_undo_event({before=before, after=snapshot(before_line, Editor_state.cursor1.line)})
   -- dispatch to drawing or text
   elseif App.mouse_down(1) or chord:sub(1,2) == 'C-' then
     -- DON'T reset line.y here
@@ -397,33 +407,33 @@ function edit.keychord_pressed(chord, key)
       schedule_save()
     end
   elseif chord == 'escape' and not App.mouse_down(1) then
-    for _,line in ipairs(Lines) do
+    for _,line in ipairs(Editor_state.lines) do
       if line.mode == 'drawing' then
         line.show_help = false
       end
     end
-  elseif Current_drawing_mode == 'name' then
+  elseif Editor_state.current_drawing_mode == 'name' then
     if chord == 'return' then
-      Current_drawing_mode = Previous_drawing_mode
-      Previous_drawing_mode = nil
+      Editor_state.current_drawing_mode = Editor_state.previous_drawing_mode
+      Editor_state.previous_drawing_mode = nil
     else
-      local before = snapshot(Lines.current_drawing_index)
-      local drawing = Lines.current_drawing
+      local before = snapshot(Editor_state.lines.current_drawing_index)
+      local drawing = Editor_state.lines.current_drawing
       local p = drawing.points[drawing.pending.target_point]
       if chord == 'escape' then
         p.name = nil
-        record_undo_event({before=before, after=snapshot(Lines.current_drawing_index)})
+        record_undo_event({before=before, after=snapshot(Editor_state.lines.current_drawing_index)})
       elseif chord == 'backspace' then
         local len = utf8.len(p.name)
         local byte_offset = Text.offset(p.name, len-1)
         if len == 1 then byte_offset = 0 end
         p.name = string.sub(p.name, 1, byte_offset)
-        record_undo_event({before=before, after=snapshot(Lines.current_drawing_index)})
+        record_undo_event({before=before, after=snapshot(Editor_state.lines.current_drawing_index)})
       end
     end
     schedule_save()
   else
-    for _,line in ipairs(Lines) do line.y = nil end  -- just in case we scroll
+    for _,line in ipairs(Editor_state.lines) do line.y = nil end  -- just in case we scroll
     Text.keychord_pressed(chord)
   end
 end
diff --git a/help.lua b/help.lua
index 92cdb0a..c65e33d 100644
--- a/help.lua
+++ b/help.lua
@@ -1,144 +1,144 @@
 function draw_help_without_mouse_pressed(drawing)
   App.color(Help_color)
   local y = drawing.y+10
-  love.graphics.print("Things you can do:", Margin_left+30,y)
-  y = y + Line_height
-  love.graphics.print("* Press the mouse button to start drawing a "..current_shape(), Margin_left+30,y)
-  y = y + Line_height
-  love.graphics.print("* Hover on a point and press 'ctrl+u' to pick it up and start moving it,", Margin_left+30,y)
-  y = y + Line_height
-  love.graphics.print("then press the mouse button to drop it", Margin_left+30+bullet_indent(),y)
-  y = y + Line_height
-  love.graphics.print("* Hover on a point and press 'ctrl+n', type a name, then press 'enter'", Margin_left+30,y)
-  y = y + Line_height
-  love.graphics.print("* Hover on a point or shape and press 'ctrl+d' to delete it", Margin_left+30,y)
-  y = y + Line_height
-  if Current_drawing_mode ~= 'freehand' then
-    love.graphics.print("* Press 'ctrl+p' to switch to drawing freehand strokes", Margin_left+30,y)
-    y = y + Line_height
-  end
-  if Current_drawing_mode ~= 'line' then
-    love.graphics.print("* Press 'ctrl+l' to switch to drawing lines", Margin_left+30,y)
-    y = y + Line_height
-  end
-  if Current_drawing_mode ~= 'manhattan' then
-    love.graphics.print("* Press 'ctrl+m' to switch to drawing horizontal/vertical lines", Margin_left+30,y)
-    y = y + Line_height
-  end
-  if Current_drawing_mode ~= 'circle' then
-    love.graphics.print("* Press 'ctrl+o' to switch to drawing circles/arcs", Margin_left+30,y)
-    y = y + Line_height
-  end
-  if Current_drawing_mode ~= 'polygon' then
-    love.graphics.print("* Press 'ctrl+g' to switch to drawing polygons", Margin_left+30,y)
-    y = y + Line_height
-  end
-  if Current_drawing_mode ~= 'rectangle' then
-    love.graphics.print("* Press 'ctrl+r' to switch to drawing rectangles", Margin_left+30,y)
-    y = y + Line_height
-  end
-  if Current_drawing_mode ~= 'square' then
-    love.graphics.print("* Press 'ctrl+s' to switch to drawing squares", Margin_left+30,y)
-    y = y + Line_height
-  end
-  love.graphics.print("* Press 'ctrl+=' or 'ctrl+-' to zoom in or out, ctrl+0 to reset zoom", Margin_left+30,y)
-  y = y + Line_height
-  love.graphics.print("Press 'esc' now to hide this message", Margin_left+30,y)
-  y = y + Line_height
+  love.graphics.print("Things you can do:", Editor_state.margin_left+30,y)
+  y = y + Editor_state.line_height
+  love.graphics.print("* Press the mouse button to start drawing a "..current_shape(), Editor_state.margin_left+30,y)
+  y = y + Editor_state.line_height
+  love.graphics.print("* Hover on a point and press 'ctrl+u' to pick it up and start moving it,", Editor_state.margin_left+30,y)
+  y = y + Editor_state.line_height
+  love.graphics.print("then press the mouse button to drop it", Editor_state.margin_left+30+bullet_indent(),y)
+  y = y + Editor_state.line_height
+  love.graphics.print("* Hover on a point and press 'ctrl+n', type a name, then press 'enter'", Editor_state.margin_left+30,y)
+  y = y + Editor_state.line_height
+  love.graphics.print("* Hover on a point or shape and press 'ctrl+d' to delete it", Editor_state.margin_left+30,y)
+  y = y + Editor_state.line_height
+  if Editor_state.current_drawing_mode ~= 'freehand' then
+    love.graphics.print("* Press 'ctrl+p' to switch to drawing freehand strokes", Editor_state.margin_left+30,y)
+    y = y + Editor_state.line_height
+  end
+  if Editor_state.current_drawing_mode ~= 'line' then
+    love.graphics.print("* Press 'ctrl+l' to switch to drawing lines", Editor_state.margin_left+30,y)
+    y = y + Editor_state.line_height
+  end
+  if Editor_state.current_drawing_mode ~= 'manhattan' then
+    love.graphics.print("* Press 'ctrl+m' to switch to drawing horizontal/vertical lines", Editor_state.margin_left+30,y)
+    y = y + Editor_state.line_height
+  end
+  if Editor_state.current_drawing_mode ~= 'circle' then
+    love.graphics.print("* Press 'ctrl+o' to switch to drawing circles/arcs", Editor_state.margin_left+30,y)
+    y = y + Editor_state.line_height
+  end
+  if Editor_state.current_drawing_mode ~= 'polygon' then
+    love.graphics.print("* Press 'ctrl+g' to switch to drawing polygons", Editor_state.margin_left+30,y)
+    y = y + Editor_state.line_height
+  end
+  if Editor_state.current_drawing_mode ~= 'rectangle' then
+    love.graphics.print("* Press 'ctrl+r' to switch to drawing rectangles", Editor_state.margin_left+30,y)
+    y = y + Editor_state.line_height
+  end
+  if Editor_state.current_drawing_mode ~= 'square' then
+    love.graphics.print("* Press 'ctrl+s' to switch to drawing squares", Editor_state.margin_left+30,y)
+    y = y + Editor_state.line_height
+  end
+  love.graphics.print("* Press 'ctrl+=' or 'ctrl+-' to zoom in or out, ctrl+0 to reset zoom", Editor_state.margin_left+30,y)
+  y = y + Editor_state.line_height
+  love.graphics.print("Press 'esc' now to hide this message", Editor_state.margin_left+30,y)
+  y = y + Editor_state.line_height
   App.color(Help_background_color)
-  love.graphics.rectangle('fill', Margin_left,drawing.y, App.screen.width-Margin_width, math.max(Drawing.pixels(drawing.h),y-drawing.y))
+  love.graphics.rectangle('fill', Editor_state.margin_left,drawing.y, App.screen.width-Editor_state.margin_width, math.max(Drawing.pixels(drawing.h),y-drawing.y))
 end
 
 function draw_help_with_mouse_pressed(drawing)
   App.color(Help_color)
   local y = drawing.y+10
-  love.graphics.print("You're currently drawing a "..current_shape(drawing.pending), Margin_left+30,y)
-  y = y + Line_height
-  love.graphics.print('Things you can do now:', Margin_left+30,y)
-  y = y + Line_height
-  if Current_drawing_mode == 'freehand' then
-    love.graphics.print('* Release the mouse button to finish drawing the stroke', Margin_left+30,y)
-    y = y + Line_height
-  elseif Current_drawing_mode == 'line' or Current_drawing_mode == 'manhattan' then
-    love.graphics.print('* Release the mouse button to finish drawing the line', Margin_left+30,y)
-    y = y + Line_height
-  elseif Current_drawing_mode == 'circle' then
+  love.graphics.print("You're currently drawing a "..current_shape(drawing.pending), Editor_state.margin_left+30,y)
+  y = y + Editor_state.line_height
+  love.graphics.print('Things you can do now:', Editor_state.margin_left+30,y)
+  y = y + Editor_state.line_height
+  if Editor_state.current_drawing_mode == 'freehand' then
+    love.graphics.print('* Release the mouse button to finish drawing the stroke', Editor_state.margin_left+30,y)
+    y = y + Editor_state.line_height
+  elseif Editor_state.current_drawing_mode == 'line' or Editor_state.current_drawing_mode == 'manhattan' then
+    love.graphics.print('* Release the mouse button to finish drawing the line', Editor_state.margin_left+30,y)
+    y = y + Editor_state.line_height
+  elseif Editor_state.current_drawing_mode == 'circle' then
     if drawing.pending.mode == 'circle' then
-      love.graphics.print('* Release the mouse button to finish drawing the circle', Margin_left+30,y)
-      y = y + Line_height
-      love.graphics.print("* Press 'a' to draw just an arc of a circle", Margin_left+30,y)
+      love.graphics.print('* Release the mouse button to finish drawing the circle', Editor_state.margin_left+30,y)
+      y = y + Editor_state.line_height
+      love.graphics.print("* Press 'a' to draw just an arc of a circle", Editor_state.margin_left+30,y)
     else
-      love.graphics.print('* Release the mouse button to finish drawing the arc', Margin_left+30,y)
+      love.graphics.print('* Release the mouse button to finish drawing the arc', Editor_state.margin_left+30,y)
     end
-    y = y + Line_height
-  elseif Current_drawing_mode == 'polygon' then
-    love.graphics.print('* Release the mouse button to finish drawing the polygon', Margin_left+30,y)
-    y = y + Line_height
-    love.graphics.print("* Press 'p' to add a vertex to the polygon", Margin_left+30,y)
-    y = y + Line_height
-  elseif Current_drawing_mode == 'rectangle' then
+    y = y + Editor_state.line_height
+  elseif Editor_state.current_drawing_mode == 'polygon' then
+    love.graphics.print('* Release the mouse button to finish drawing the polygon', Editor_state.margin_left+30,y)
+    y = y + Editor_state.line_height
+    love.graphics.print("* Press 'p' to add a vertex to the polygon", Editor_state.margin_left+30,y)
+    y = y + Editor_state.line_height
+  elseif Editor_state.current_drawing_mode == 'rectangle' then
     if #drawing.pending.vertices < 2 then
-      love.graphics.print("* Press 'p' to add a vertex to the rectangle", Margin_left+30,y)
-      y = y + Line_height
+      love.graphics.print("* Press 'p' to add a vertex to the rectangle", Editor_state.margin_left+30,y)
+      y = y + Editor_state.line_height
     else
-      love.graphics.print('* Release the mouse button to finish drawing the rectangle', Margin_left+30,y)
-      y = y + Line_height
-      love.graphics.print("* Press 'p' to replace the second vertex of the rectangle", Margin_left+30,y)
-      y = y + Line_height
+      love.graphics.print('* Release the mouse button to finish drawing the rectangle', Editor_state.margin_left+30,y)
+      y = y + Editor_state.line_height
+      love.graphics.print("* Press 'p' to replace the second vertex of the rectangle", Editor_state.margin_left+30,y)
+      y = y + Editor_state.line_height
     end
-  elseif Current_drawing_mode == 'square' then
+  elseif Editor_state.current_drawing_mode == 'square' then
     if #drawing.pending.vertices < 2 then
-      love.graphics.print("* Press 'p' to add a vertex to the square", Margin_left+30,y)
-      y = y + Line_height
+      love.graphics.print("* Press 'p' to add a vertex to the square", Editor_state.margin_left+30,y)
+      y = y + Editor_state.line_height
     else
-      love.graphics.print('* Release the mouse button to finish drawing the square', Margin_left+30,y)
-      y = y + Line_height
-      love.graphics.print("* Press 'p' to replace the second vertex of the square", Margin_left+30,y)
-      y = y + Line_height
+      love.graphics.print('* Release the mouse button to finish drawing the square', Editor_state.margin_left+30,y)
+      y = y + Editor_state.line_height
+      love.graphics.print("* Press 'p' to replace the second vertex of the square", Editor_state.margin_left+30,y)
+      y = y + Editor_state.line_height
     end
   end
-  love.graphics.print("* Press 'esc' then release the mouse button to cancel the current shape", Margin_left+30,y)
-  y = y + Line_height
-  y = y + Line_height
-  if Current_drawing_mode ~= 'line' then
-    love.graphics.print("* Press 'l' to switch to drawing lines", Margin_left+30,y)
-    y = y + Line_height
+  love.graphics.print("* Press 'esc' then release the mouse button to cancel the current shape", Editor_state.margin_left+30,y)
+  y = y + Editor_state.line_height
+  y = y + Editor_state.line_height
+  if Editor_state.current_drawing_mode ~= 'line' then
+    love.graphics.print("* Press 'l' to switch to drawing lines", Editor_state.margin_left+30,y)
+    y = y + Editor_state.line_height
   end
-  if Current_drawing_mode ~= 'manhattan' then
-    love.graphics.print("* Press 'm' to switch to drawing horizontal/vertical lines", Margin_left+30,y)
-    y = y + Line_height
+  if Editor_state.current_drawing_mode ~= 'manhattan' then
+    love.graphics.print("* Press 'm' to switch to drawing horizontal/vertical lines", Editor_state.margin_left+30,y)
+    y = y + Editor_state.line_height
   end
-  if Current_drawing_mode ~= 'circle' then
-    love.graphics.print("* Press 'o' to switch to drawing circles/arcs", Margin_left+30,y)
-    y = y + Line_height
+  if Editor_state.current_drawing_mode ~= 'circle' then
+    love.graphics.print("* Press 'o' to switch to drawing circles/arcs", Editor_state.margin_left+30,y)
+    y = y + Editor_state.line_height
   end
-  if Current_drawing_mode ~= 'polygon' then
-    love.graphics.print("* Press 'g' to switch to drawing polygons", Margin_left+30,y)
-    y = y + Line_height
+  if Editor_state.current_drawing_mode ~= 'polygon' then
+    love.graphics.print("* Press 'g' to switch to drawing polygons", Editor_state.margin_left+30,y)
+    y = y + Editor_state.line_height
   end
-  if Current_drawing_mode ~= 'rectangle' then
-    love.graphics.print("* Press 'r' to switch to drawing rectangles", Margin_left+30,y)
-    y = y + Line_height
+  if Editor_state.current_drawing_mode ~= 'rectangle' then
+    love.graphics.print("* Press 'r' to switch to drawing rectangles", Editor_state.margin_left+30,y)
+    y = y + Editor_state.line_height
   end
-  if Current_drawing_mode ~= 'square' then
-    love.graphics.print("* Press 's' to switch to drawing squares", Margin_left+30,y)
-    y = y + Line_height
+  if Editor_state.current_drawing_mode ~= 'square' then
+    love.graphics.print("* Press 's' to switch to drawing squares", Editor_state.margin_left+30,y)
+    y = y + Editor_state.line_height
   end
   App.color(Help_background_color)
-  love.graphics.rectangle('fill', Margin_left,drawing.y, App.screen.width-Margin_width, math.max(Drawing.pixels(drawing.h),y-drawing.y))
+  love.graphics.rectangle('fill', Editor_state.margin_left,drawing.y, App.screen.width-Editor_state.margin_width, math.max(Drawing.pixels(drawing.h),y-drawing.y))
 end
 
 function current_shape(shape)
-  if Current_drawing_mode == 'freehand' then
+  if Editor_state.current_drawing_mode == 'freehand' then
     return 'freehand stroke'
-  elseif Current_drawing_mode == 'line' then
+  elseif Editor_state.current_drawing_mode == 'line' then
     return 'straight line'
-  elseif Current_drawing_mode == 'manhattan' then
+  elseif Editor_state.current_drawing_mode == 'manhattan' then
     return 'horizontal/vertical line'
-  elseif Current_drawing_mode == 'circle' and shape and shape.start_angle then
+  elseif Editor_state.current_drawing_mode == 'circle' and shape and shape.start_angle then
     return 'arc'
   else
-    return Current_drawing_mode
+    return Editor_state.current_drawing_mode
   end
 end
 
diff --git a/main.lua b/main.lua
index f1ac122..6b136b8 100644
--- a/main.lua
+++ b/main.lua
@@ -14,7 +14,7 @@ Editor_state = {}
 
 -- called both in tests and real run
 function App.initialize_globals()
-  edit.initialize_globals()
+  Editor_state = edit.initialize_state()
 
   -- resize
   Last_resize_time = nil
@@ -37,28 +37,28 @@ function App.initialize(arg)
   end
 
   if #arg > 0 then
-    Filename = arg[1]
-    Lines = load_from_disk(Filename)
-    Screen_top1 = {line=1, pos=1}
-    Cursor1 = {line=1, pos=1}
-    for i,line in ipairs(Lines) do
+    Editor_state.filename = arg[1]
+    Editor_state.lines = load_from_disk(Editor_state.filename)
+    Editor_state.screen_top1 = {line=1, pos=1}
+    Editor_state.cursor1 = {line=1, pos=1}
+    for i,line in ipairs(Editor_state.lines) do
       if line.mode == 'text' then
-        Cursor1.line = i
+        Editor_state.cursor1.line = i
         break
       end
     end
   else
-    Lines = load_from_disk(Filename)
-    if Cursor1.line > #Lines or Lines[Cursor1.line].mode ~= 'text' then
-      for i,line in ipairs(Lines) do
+    Editor_state.lines = load_from_disk(Editor_state.filename)
+    if Editor_state.cursor1.line > #Editor_state.lines or Editor_state.lines[Editor_state.cursor1.line].mode ~= 'text' then
+      for i,line in ipairs(Editor_state.lines) do
         if line.mode == 'text' then
-          Cursor1.line = i
+          Editor_state.cursor1.line = i
           break
         end
       end
     end
   end
-  love.window.setTitle('lines.love - '..Filename)
+  love.window.setTitle('lines.love - '..Editor_state.filename)
 
   if #arg > 1 then
     print('ignoring commandline args after '..arg[1])
@@ -83,10 +83,10 @@ function load_settings()
   App.screen.flags.minheight = math.min(App.screen.width, 200)
   App.screen.width, App.screen.height = settings.width, settings.height
   love.window.setMode(App.screen.width, App.screen.height, App.screen.flags)
-  Filename = settings.filename
+  Editor_state.filename = settings.filename
   initialize_font_settings(settings.font_height)
-  Screen_top1 = settings.screen_top
-  Cursor1 = settings.cursor
+  Editor_state.screen_top1 = settings.screen_top
+  Editor_state.cursor1 = settings.cursor
 end
 
 function load_defaults()
@@ -99,7 +99,7 @@ function initialize_window_geometry()
   love.window.setMode(0, 0)  -- maximize
   App.screen.width, App.screen.height, App.screen.flags = love.window.getMode()
   -- shrink slightly to account for window decoration
-  App.screen.width = 40*App.width(Em)
+  App.screen.width = 40*App.width(Editor_state.em)
   App.screen.height = App.screen.height-100
   App.screen.flags.resizable = true
   App.screen.flags.minwidth = math.min(App.screen.width, 200)
@@ -111,37 +111,37 @@ function App.resize(w, h)
 --?   print(("Window resized to width: %d and height: %d."):format(w, h))
   App.screen.width, App.screen.height = w, h
   Text.redraw_all()
-  Selection1 = {}  -- no support for shift drag while we're resizing
-  Text.tweak_screen_top_and_cursor(Margin_left, App.screen.height-Margin_right)
+  Editor_state.selection1 = {}  -- no support for shift drag while we're resizing
+  Text.tweak_screen_top_and_cursor(Editor_state.margin_left, App.screen.height-Editor_state.margin_right)
   Last_resize_time = App.getTime()
 end
 
 function initialize_font_settings(font_height)
-  Font_height = font_height
-  love.graphics.setFont(love.graphics.newFont(Font_height))
-  Line_height = math.floor(font_height*1.3)
+  Editor_state.font_height = font_height
+  love.graphics.setFont(love.graphics.newFont(Editor_state.font_height))
+  Editor_state.line_height = math.floor(font_height*1.3)
 
-  Em = App.newText(love.graphics.getFont(), 'm')
+  Editor_state.em = App.newText(love.graphics.getFont(), 'm')
 end
 
 function App.filedropped(file)
   -- first make sure to save edits on any existing file
-  if Next_save then
-    save_to_disk(Lines, Filename)
+  if Editor_state.next_save then
+    save_to_disk(Editor_state.lines, Editor_state.filename)
   end
   -- clear the slate for the new file
   App.initialize_globals()  -- in particular, forget all undo history
-  Filename = file:getFilename()
+  Editor_state.filename = file:getFilename()
   file:open('r')
-  Lines = load_from_file(file)
+  Editor_state.lines = load_from_file(file)
   file:close()
-  for i,line in ipairs(Lines) do
+  for i,line in ipairs(Editor_state.lines) do
     if line.mode == 'text' then
-      Cursor1.line = i
+      Editor_state.cursor1.line = i
       break
     end
   end
-  love.window.setTitle('Text with Lines - '..Filename)
+  love.window.setTitle('Text with Editor_state.lines - '..Editor_state.filename)
 end
 
 function App.draw()
@@ -166,16 +166,16 @@ function love.quit()
   edit.quit()
   -- save some important settings
   local x,y,displayindex = love.window.getPosition()
-  local filename = Filename
+  local filename = Editor_state.filename
   if filename:sub(1,1) ~= '/' then
     filename = love.filesystem.getWorkingDirectory()..'/'..filename  -- '/' should work even on Windows
   end
   local settings = {
     x=x, y=y, displayindex=displayindex,
     width=App.screen.width, height=App.screen.height,
-    font_height=Font_height,
+    font_height=Editor_state.font_height,
     filename=filename,
-    screen_top=Screen_top1, cursor=Cursor1}
+    screen_top=Editor_state.screen_top1, cursor=Editor_state.cursor1}
   love.filesystem.write('config', json.encode(settings))
 end
 
diff --git a/main_tests.lua b/main_tests.lua
index 98cc73d..7b5c4e8 100644
--- a/main_tests.lua
+++ b/main_tests.lua
@@ -1,8 +1,8 @@
 function test_resize_window()
   io.write('\ntest_resize_window')
-  Filename = 'foo'
-  App.screen.init{width=Margin_left+300, height=300}
-  check_eq(App.screen.width, Margin_left+300, 'F - test_resize_window/baseline/width')
+  Editor_state.filename = 'foo'
+  App.screen.init{width=Editor_state.margin_left+300, height=300}
+  check_eq(App.screen.width, Editor_state.margin_left+300, 'F - test_resize_window/baseline/width')
   check_eq(App.screen.height, 300, 'F - test_resize_window/baseline/height')
   App.resize(200, 400)
   check_eq(App.screen.width, 200, 'F - test_resize_window/width')
@@ -12,7 +12,7 @@ end
 
 function test_drop_file()
   io.write('\ntest_drop_file')
-  App.screen.init{width=Margin_left+300, height=300}
+  App.screen.init{width=Editor_state.margin_left+300, height=300}
   App.filesystem['foo'] = 'abc\ndef\nghi\n'
   local fake_dropped_file = {
     opened = false,
@@ -31,18 +31,18 @@ function test_drop_file()
             end,
   }
   App.filedropped(fake_dropped_file)
-  check_eq(#Lines, 3, 'F - test_drop_file/#lines')
-  check_eq(Lines[1].data, 'abc', 'F - test_drop_file/lines:1')
-  check_eq(Lines[2].data, 'def', 'F - test_drop_file/lines:2')
-  check_eq(Lines[3].data, 'ghi', 'F - test_drop_file/lines:3')
+  check_eq(#Editor_state.lines, 3, 'F - test_drop_file/#lines')
+  check_eq(Editor_state.lines[1].data, 'abc', 'F - test_drop_file/lines:1')
+  check_eq(Editor_state.lines[2].data, 'def', 'F - test_drop_file/lines:2')
+  check_eq(Editor_state.lines[3].data, 'ghi', 'F - test_drop_file/lines:3')
 end
 
 function test_drop_file_saves_previous()
   io.write('\ntest_drop_file_saves_previous')
-  App.screen.init{width=Margin_left+300, height=300}
+  App.screen.init{width=Editor_state.margin_left+300, height=300}
   -- initially editing a file called foo that hasn't been saved to filesystem yet
-  Lines = load_array{'abc', 'def'}
-  Filename = 'foo'
+  Editor_state.lines = load_array{'abc', 'def'}
+  Editor_state.filename = 'foo'
   schedule_save()
   -- now drag a new file bar from the filesystem
   App.filesystem['bar'] = 'abc\ndef\nghi\n'
diff --git a/search.lua b/search.lua
index eca7cd7..5d794f2 100644
--- a/search.lua
+++ b/search.lua
@@ -1,7 +1,7 @@
 -- helpers for the search bar (C-f)
 
 function Text.draw_search_bar()
-  local h = Line_height+2
+  local h = Editor_state.line_height+2
   local y = App.screen.height-h
   love.graphics.setColor(0.9,0.9,0.9)
   love.graphics.rectangle('fill', 0, y-10, App.screen.width-1, h+8)
@@ -12,92 +12,92 @@ function Text.draw_search_bar()
   love.graphics.setColor(0.6,0.6,0.6)
   love.graphics.rectangle('line', 20, y-6, App.screen.width-40, h+2, 2,2)
   App.color(Text_color)
-  App.screen.print(Search_term, 25,y-5)
+  App.screen.print(Editor_state.search_term, 25,y-5)
   App.color(Cursor_color)
-  if Search_text == nil then
-    Search_text = App.newText(love.graphics.getFont(), Search_term)
+  if Editor_state.search_text == nil then
+    Editor_state.search_text = App.newText(love.graphics.getFont(), Editor_state.search_term)
   end
-  love.graphics.circle('fill', 25+App.width(Search_text),y-5+h, 2)
+  love.graphics.circle('fill', 25+App.width(Editor_state.search_text),y-5+h, 2)
   App.color(Text_color)
 end
 
 function Text.search_next()
   -- search current line
-  local pos = Lines[Cursor1.line].data:find(Search_term, Cursor1.pos)
+  local pos = Editor_state.lines[Editor_state.cursor1.line].data:find(Editor_state.search_term, Editor_state.cursor1.pos)
   if pos then
-    Cursor1.pos = pos
+    Editor_state.cursor1.pos = pos
   end
   if pos == nil then
-    for i=Cursor1.line+1,#Lines do
-      pos = Lines[i].data:find(Search_term)
+    for i=Editor_state.cursor1.line+1,#Editor_state.lines do
+      pos = Editor_state.lines[i].data:find(Editor_state.search_term)
       if pos then
-        Cursor1.line = i
-        Cursor1.pos = pos
+        Editor_state.cursor1.line = i
+        Editor_state.cursor1.pos = pos
         break
       end
     end
   end
   if pos == nil then
     -- wrap around
-    for i=1,Cursor1.line-1 do
-      pos = Lines[i].data:find(Search_term)
+    for i=1,Editor_state.cursor1.line-1 do
+      pos = Editor_state.lines[i].data:find(Editor_state.search_term)
       if pos then
-        Cursor1.line = i
-        Cursor1.pos = pos
+        Editor_state.cursor1.line = i
+        Editor_state.cursor1.pos = pos
         break
       end
     end
   end
   if pos == nil then
-    Cursor1.line = Search_backup.cursor.line
-    Cursor1.pos = Search_backup.cursor.pos
-    Screen_top1.line = Search_backup.screen_top.line
-    Screen_top1.pos = Search_backup.screen_top.pos
+    Editor_state.cursor1.line = Editor_state.search_backup.cursor.line
+    Editor_state.cursor1.pos = Editor_state.search_backup.cursor.pos
+    Editor_state.screen_top1.line = Editor_state.search_backup.screen_top.line
+    Editor_state.screen_top1.pos = Editor_state.search_backup.screen_top.pos
   end
-  if Text.lt1(Cursor1, Screen_top1) or Text.lt1(Screen_bottom1, Cursor1) then
-    Screen_top1.line = Cursor1.line
-    local _, pos = Text.pos_at_start_of_cursor_screen_line(Margin_left, App.screen.width-Margin_right)
-    Screen_top1.pos = pos
+  if Text.lt1(Editor_state.cursor1, Editor_state.screen_top1) or Text.lt1(Editor_state.screen_bottom1, Editor_state.cursor1) then
+    Editor_state.screen_top1.line = Editor_state.cursor1.line
+    local _, pos = Text.pos_at_start_of_cursor_screen_line(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
+    Editor_state.screen_top1.pos = pos
   end
 end
 
 function Text.search_previous()
   -- search current line
-  local pos = rfind(Lines[Cursor1.line].data, Search_term, Cursor1.pos)
+  local pos = rfind(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.search_term, Editor_state.cursor1.pos)
   if pos then
-    Cursor1.pos = pos
+    Editor_state.cursor1.pos = pos
   end
   if pos == nil then
-    for i=Cursor1.line-1,1,-1 do
-      pos = rfind(Lines[i].data, Search_term)
+    for i=Editor_state.cursor1.line-1,1,-1 do
+      pos = rfind(Editor_state.lines[i].data, Editor_state.search_term)
       if pos then
-        Cursor1.line = i
-        Cursor1.pos = pos
+        Editor_state.cursor1.line = i
+        Editor_state.cursor1.pos = pos
         break
       end
     end
   end
   if pos == nil then
     -- wrap around
-    for i=#Lines,Cursor1.line+1,-1 do
-      pos = rfind(Lines[i].data, Search_term)
+    for i=#Editor_state.lines,Editor_state.cursor1.line+1,-1 do
+      pos = rfind(Editor_state.lines[i].data, Editor_state.search_term)
       if pos then
-        Cursor1.line = i
-        Cursor1.pos = pos
+        Editor_state.cursor1.line = i
+        Editor_state.cursor1.pos = pos
         break
       end
     end
   end
   if pos == nil then
-    Cursor1.line = Search_backup.cursor.line
-    Cursor1.pos = Search_backup.cursor.pos
-    Screen_top1.line = Search_backup.screen_top.line
-    Screen_top1.pos = Search_backup.screen_top.pos
+    Editor_state.cursor1.line = Editor_state.search_backup.cursor.line
+    Editor_state.cursor1.pos = Editor_state.search_backup.cursor.pos
+    Editor_state.screen_top1.line = Editor_state.search_backup.screen_top.line
+    Editor_state.screen_top1.pos = Editor_state.search_backup.screen_top.pos
   end
-  if Text.lt1(Cursor1, Screen_top1) or Text.lt1(Screen_bottom1, Cursor1) then
-    Screen_top1.line = Cursor1.line
-    local _, pos = Text.pos_at_start_of_cursor_screen_line(Margin_left, App.screen.width-Margin_right)
-    Screen_top1.pos = pos
+  if Text.lt1(Editor_state.cursor1, Editor_state.screen_top1) or Text.lt1(Editor_state.screen_bottom1, Editor_state.cursor1) then
+    Editor_state.screen_top1.line = Editor_state.cursor1.line
+    local _, pos = Text.pos_at_start_of_cursor_screen_line(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
+    Editor_state.screen_top1.pos = pos
   end
 end
 
diff --git a/select.lua b/select.lua
index 9e88c60..15d3690 100644
--- a/select.lua
+++ b/select.lua
@@ -1,20 +1,20 @@
 -- helpers for selecting portions of text
 
--- Return any intersection of the region from Selection1 to Cursor1 (or
+-- Return any intersection of the region from Editor_state.selection1 to Editor_state.cursor1 (or
 -- current mouse, if mouse is pressed; or recent mouse if mouse is pressed and
 -- currently over a drawing) with the region between {line=line_index, pos=apos}
 -- and {line=line_index, pos=bpos}.
--- apos must be less than bpos. However Selection1 and Cursor1 can be in any order.
+-- apos must be less than bpos. However Editor_state.selection1 and Editor_state.cursor1 can be in any order.
 -- Result: positions spos,epos between apos,bpos.
 function Text.clip_selection(line_index, apos, bpos, left, right)
-  if Selection1.line == nil then return nil,nil end
-  -- min,max = sorted(Selection1,Cursor1)
-  local minl,minp = Selection1.line,Selection1.pos
+  if Editor_state.selection1.line == nil then return nil,nil end
+  -- min,max = sorted(Editor_state.selection1,Editor_state.cursor1)
+  local minl,minp = Editor_state.selection1.line,Editor_state.selection1.pos
   local maxl,maxp
   if App.mouse_down(1) then
     maxl,maxp = Text.mouse_pos(left, right)
   else
-    maxl,maxp = Cursor1.line,Cursor1.pos
+    maxl,maxp = Editor_state.cursor1.line,Editor_state.cursor1.pos
   end
   if minl > maxl then
     minl,maxl = maxl,minl
@@ -69,7 +69,7 @@ function Text.draw_highlight(line, x,y, pos, lo,hi)
     local text = App.newText(love.graphics.getFont(), s)
     local text_width = App.width(text)
     App.color(Highlight_color)
-    love.graphics.rectangle('fill', x+lo_px,y, text_width,Line_height)
+    love.graphics.rectangle('fill', x+lo_px,y, text_width,Editor_state.line_height)
     App.color(Text_color)
     return lo_px
   end
@@ -78,20 +78,20 @@ end
 -- inefficient for some reason, so don't do it on every frame
 function Text.mouse_pos(left, right)
   local time = love.timer.getTime()
-  if Recent_mouse.time and Recent_mouse.time > time-0.1 then
-    return Recent_mouse.line, Recent_mouse.pos
+  if Editor_state.recent_mouse.time and Editor_state.recent_mouse.time > time-0.1 then
+    return Editor_state.recent_mouse.line, Editor_state.recent_mouse.pos
   end
-  Recent_mouse.time = time
+  Editor_state.recent_mouse.time = time
   local line,pos = Text.to_pos(App.mouse_x(), App.mouse_y(), left, right)
   if line then
-    Recent_mouse.line = line
-    Recent_mouse.pos = pos
+    Editor_state.recent_mouse.line = line
+    Editor_state.recent_mouse.pos = pos
   end
-  return Recent_mouse.line, Recent_mouse.pos
+  return Editor_state.recent_mouse.line, Editor_state.recent_mouse.pos
 end
 
 function Text.to_pos(x,y, left, right)
-  for line_index,line in ipairs(Lines) do
+  for line_index,line in ipairs(Editor_state.lines) do
     if line.mode == 'text' then
       if Text.in_line(line, x,y, left, right) then
         return line_index, Text.to_pos_on_line(line, x,y, left, right)
@@ -101,25 +101,25 @@ function Text.to_pos(x,y, left, right)
 end
 
 function Text.cut_selection(left, right)
-  if Selection1.line == nil then return end
+  if Editor_state.selection1.line == nil then return end
   local result = Text.selection()
   Text.delete_selection(left, right)
   return result
 end
 
 function Text.delete_selection(left, right)
-  if Selection1.line == nil then return end
-  local minl,maxl = minmax(Selection1.line, Cursor1.line)
+  if Editor_state.selection1.line == nil then return end
+  local minl,maxl = minmax(Editor_state.selection1.line, Editor_state.cursor1.line)
   local before = snapshot(minl, maxl)
   Text.delete_selection_without_undo(left, right)
-  record_undo_event({before=before, after=snapshot(Cursor1.line)})
+  record_undo_event({before=before, after=snapshot(Editor_state.cursor1.line)})
 end
 
 function Text.delete_selection_without_undo(left, right)
-  if Selection1.line == nil then return end
-  -- min,max = sorted(Selection1,Cursor1)
-  local minl,minp = Selection1.line,Selection1.pos
-  local maxl,maxp = Cursor1.line,Cursor1.pos
+  if Editor_state.selection1.line == nil then return end
+  -- min,max = sorted(Editor_state.selection1,Editor_state.cursor1)
+  local minl,minp = Editor_state.selection1.line,Editor_state.selection1.pos
+  local maxl,maxp = Editor_state.cursor1.line,Editor_state.cursor1.pos
   if minl > maxl then
     minl,maxl = maxl,minl
     minp,maxp = maxp,minp
@@ -128,36 +128,36 @@ function Text.delete_selection_without_undo(left, right)
       minp,maxp = maxp,minp
     end
   end
-  -- update Cursor1 and Selection1
-  Cursor1.line = minl
-  Cursor1.pos = minp
-  if Text.lt1(Cursor1, Screen_top1) then
-    Screen_top1.line = Cursor1.line
-    _,Screen_top1.pos = Text.pos_at_start_of_cursor_screen_line(left, right)
+  -- update Editor_state.cursor1 and Editor_state.selection1
+  Editor_state.cursor1.line = minl
+  Editor_state.cursor1.pos = minp
+  if Text.lt1(Editor_state.cursor1, Editor_state.screen_top1) then
+    Editor_state.screen_top1.line = Editor_state.cursor1.line
+    _,Editor_state.screen_top1.pos = Text.pos_at_start_of_cursor_screen_line(left, right)
   end
-  Selection1 = {}
+  Editor_state.selection1 = {}
   -- delete everything between min (inclusive) and max (exclusive)
-  Text.clear_cache(Lines[minl])
-  local min_offset = Text.offset(Lines[minl].data, minp)
-  local max_offset = Text.offset(Lines[maxl].data, maxp)
+  Text.clear_cache(Editor_state.lines[minl])
+  local min_offset = Text.offset(Editor_state.lines[minl].data, minp)
+  local max_offset = Text.offset(Editor_state.lines[maxl].data, maxp)
   if minl == maxl then
 --?     print('minl == maxl')
-    Lines[minl].data = Lines[minl].data:sub(1, min_offset-1)..Lines[minl].data:sub(max_offset)
+    Editor_state.lines[minl].data = Editor_state.lines[minl].data:sub(1, min_offset-1)..Editor_state.lines[minl].data:sub(max_offset)
     return
   end
   assert(minl < maxl)
-  local rhs = Lines[maxl].data:sub(max_offset)
+  local rhs = Editor_state.lines[maxl].data:sub(max_offset)
   for i=maxl,minl+1,-1 do
-    table.remove(Lines, i)
+    table.remove(Editor_state.lines, i)
   end
-  Lines[minl].data = Lines[minl].data:sub(1, min_offset-1)..rhs
+  Editor_state.lines[minl].data = Editor_state.lines[minl].data:sub(1, min_offset-1)..rhs
 end
 
 function Text.selection()
-  if Selection1.line == nil then return end
-  -- min,max = sorted(Selection1,Cursor1)
-  local minl,minp = Selection1.line,Selection1.pos
-  local maxl,maxp = Cursor1.line,Cursor1.pos
+  if Editor_state.selection1.line == nil then return end
+  -- min,max = sorted(Editor_state.selection1,Editor_state.cursor1)
+  local minl,minp = Editor_state.selection1.line,Editor_state.selection1.pos
+  local maxl,maxp = Editor_state.cursor1.line,Editor_state.cursor1.pos
   if minl > maxl then
     minl,maxl = maxl,minl
     minp,maxp = maxp,minp
@@ -166,18 +166,18 @@ function Text.selection()
       minp,maxp = maxp,minp
     end
   end
-  local min_offset = Text.offset(Lines[minl].data, minp)
-  local max_offset = Text.offset(Lines[maxl].data, maxp)
+  local min_offset = Text.offset(Editor_state.lines[minl].data, minp)
+  local max_offset = Text.offset(Editor_state.lines[maxl].data, maxp)
   if minl == maxl then
-    return Lines[minl].data:sub(min_offset, max_offset-1)
+    return Editor_state.lines[minl].data:sub(min_offset, max_offset-1)
   end
   assert(minl < maxl)
-  local result = {Lines[minl].data:sub(min_offset)}
+  local result = {Editor_state.lines[minl].data:sub(min_offset)}
   for i=minl+1,maxl-1 do
-    if Lines[i].mode == 'text' then
-      table.insert(result, Lines[i].data)
+    if Editor_state.lines[i].mode == 'text' then
+      table.insert(result, Editor_state.lines[i].data)
     end
   end
-  table.insert(result, Lines[maxl].data:sub(1, max_offset-1))
+  table.insert(result, Editor_state.lines[maxl].data:sub(1, max_offset-1))
   return table.concat(result, '\n')
 end
diff --git a/text.lua b/text.lua
index c61a488..0f3cd42 100644
--- a/text.lua
+++ b/text.lua
@@ -28,13 +28,13 @@ function Text.draw(line, line_index, top, left, right)
     local frag_width = App.width(frag_text)
     local frag_len = utf8.len(frag)
 --?     local s=tostring
---?     print('('..s(x)..','..s(y)..') '..frag..'('..s(frag_width)..' vs '..s(right)..') '..s(line_index)..' vs '..s(Screen_top1.line)..'; '..s(pos)..' vs '..s(Screen_top1.pos)..'; bottom: '..s(Screen_bottom1.line)..'/'..s(Screen_bottom1.pos))
+--?     print('('..s(x)..','..s(y)..') '..frag..'('..s(frag_width)..' vs '..s(right)..') '..s(line_index)..' vs '..s(Editor_state.screen_top1.line)..'; '..s(pos)..' vs '..s(Editor_state.screen_top1.pos)..'; bottom: '..s(Editor_state.screen_bottom1.line)..'/'..s(Editor_state.screen_bottom1.pos))
     if x + frag_width > right then
       assert(x > left)  -- no overfull lines
       -- update y only after drawing the first screen line of screen top
-      if Text.lt1(Screen_top1, {line=line_index, pos=pos}) then
-        y = y + Line_height
-        if y + Line_height > App.screen.height then
+      if Text.lt1(Editor_state.screen_top1, {line=line_index, pos=pos}) then
+        y = y + Editor_state.line_height
+        if y + Editor_state.line_height > App.screen.height then
 --?           print('b', y, App.screen.height, '=>', screen_line_starting_pos)
           return y, screen_line_starting_pos
         end
@@ -43,10 +43,10 @@ function Text.draw(line, line_index, top, left, right)
       end
       x = left
     end
---?     print('checking to draw', pos, Screen_top1.pos)
+--?     print('checking to draw', pos, Editor_state.screen_top1.pos)
     -- don't draw text above screen top
-    if Text.le1(Screen_top1, {line=line_index, pos=pos}) then
-      if Selection1.line then
+    if Text.le1(Editor_state.screen_top1, {line=line_index, pos=pos}) then
+      if Editor_state.selection1.line then
         local lo, hi = Text.clip_selection(line_index, pos, pos+frag_len, left, right)
         Text.draw_highlight(line, x,y, pos, lo,hi)
       end
@@ -54,24 +54,24 @@ function Text.draw(line, line_index, top, left, right)
       App.screen.draw(frag_text, x,y)
     end
     -- render cursor if necessary
-    if line_index == Cursor1.line then
-      if pos <= Cursor1.pos and pos + frag_len > Cursor1.pos then
-        if Search_term then
-          if Lines[Cursor1.line].data:sub(Cursor1.pos, Cursor1.pos+utf8.len(Search_term)-1) == Search_term then
-            local lo_px = Text.draw_highlight(line, x,y, pos, Cursor1.pos, Cursor1.pos+utf8.len(Search_term))
+    if line_index == Editor_state.cursor1.line then
+      if pos <= Editor_state.cursor1.pos and pos + frag_len > Editor_state.cursor1.pos then
+        if Editor_state.search_term then
+          if Editor_state.lines[Editor_state.cursor1.line].data:sub(Editor_state.cursor1.pos, Editor_state.cursor1.pos+utf8.len(Editor_state.search_term)-1) == Editor_state.search_term then
+            local lo_px = Text.draw_highlight(line, x,y, pos, Editor_state.cursor1.pos, Editor_state.cursor1.pos+utf8.len(Editor_state.search_term))
             App.color(Text_color)
-            love.graphics.print(Search_term, x+lo_px,y)
+            love.graphics.print(Editor_state.search_term, x+lo_px,y)
           end
         else
-          Text.draw_cursor(x+Text.x(frag, Cursor1.pos-pos+1), y)
+          Text.draw_cursor(x+Text.x(frag, Editor_state.cursor1.pos-pos+1), y)
         end
       end
     end
     x = x + frag_width
     pos = pos + frag_len
   end
-  if Search_term == nil then
-    if line_index == Cursor1.line and Cursor1.pos == pos then
+  if Editor_state.search_term == nil then
+    if line_index == Editor_state.cursor1.line and Editor_state.cursor1.pos == pos then
       Text.draw_cursor(x, y)
     end
   end
@@ -84,11 +84,11 @@ function Text.draw_cursor(x, y)
   -- blink every 0.5s
   if math.floor(Cursor_time*2)%2 == 0 then
     App.color(Cursor_color)
-    love.graphics.rectangle('fill', x,y, 3,Line_height)
+    love.graphics.rectangle('fill', x,y, 3,Editor_state.line_height)
     App.color(Text_color)
   end
-  Cursor_x = x
-  Cursor_y = y+Line_height
+  Editor_state.cursor_x = x
+  Editor_state.cursor_y = y+Editor_state.line_height
 end
 
 function Text.compute_fragments(line, left, right)
@@ -137,241 +137,241 @@ end
 function Text.textinput(t)
   if App.mouse_down(1) then return end
   if App.ctrl_down() or App.alt_down() or App.cmd_down() then return end
-  local before = snapshot(Cursor1.line)
---?   print(Screen_top1.line, Screen_top1.pos, Cursor1.line, Cursor1.pos, Screen_bottom1.line, Screen_bottom1.pos)
+  local before = snapshot(Editor_state.cursor1.line)
+--?   print(Editor_state.screen_top1.line, Editor_state.screen_top1.pos, Editor_state.cursor1.line, Editor_state.cursor1.pos, Editor_state.screen_bottom1.line, Editor_state.screen_bottom1.pos)
   Text.insert_at_cursor(t)
-  if Cursor_y >= App.screen.height - Line_height then
-    Text.populate_screen_line_starting_pos(Lines[Cursor1.line], Margin_left, App.screen.width-Margin_right)
-    Text.snap_cursor_to_bottom_of_screen(Margin_left, App.screen.width-Margin_right)
---?     print('=>', Screen_top1.line, Screen_top1.pos, Cursor1.line, Cursor1.pos, Screen_bottom1.line, Screen_bottom1.pos)
+  if Editor_state.cursor_y >= App.screen.height - Editor_state.line_height then
+    Text.populate_screen_line_starting_pos(Editor_state.lines[Editor_state.cursor1.line], Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
+    Text.snap_cursor_to_bottom_of_screen(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
+--?     print('=>', Editor_state.screen_top1.line, Editor_state.screen_top1.pos, Editor_state.cursor1.line, Editor_state.cursor1.pos, Editor_state.screen_bottom1.line, Editor_state.screen_bottom1.pos)
   end
-  record_undo_event({before=before, after=snapshot(Cursor1.line)})
+  record_undo_event({before=before, after=snapshot(Editor_state.cursor1.line)})
 end
 
 function Text.insert_at_cursor(t)
-  local byte_offset = Text.offset(Lines[Cursor1.line].data, Cursor1.pos)
-  Lines[Cursor1.line].data = string.sub(Lines[Cursor1.line].data, 1, byte_offset-1)..t..string.sub(Lines[Cursor1.line].data, byte_offset)
-  Text.clear_cache(Lines[Cursor1.line])
-  Cursor1.pos = Cursor1.pos+1
+  local byte_offset = Text.offset(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor1.pos)
+  Editor_state.lines[Editor_state.cursor1.line].data = string.sub(Editor_state.lines[Editor_state.cursor1.line].data, 1, byte_offset-1)..t..string.sub(Editor_state.lines[Editor_state.cursor1.line].data, byte_offset)
+  Text.clear_cache(Editor_state.lines[Editor_state.cursor1.line])
+  Editor_state.cursor1.pos = Editor_state.cursor1.pos+1
 end
 
 -- Don't handle any keys here that would trigger love.textinput above.
 function Text.keychord_pressed(chord)
---?   print('chord', chord, Selection1.line, Selection1.pos)
+--?   print('chord', chord, Editor_state.selection1.line, Editor_state.selection1.pos)
   --== shortcuts that mutate text
   if chord == 'return' then
-    local before_line = Cursor1.line
+    local before_line = Editor_state.cursor1.line
     local before = snapshot(before_line)
     Text.insert_return()
-    Selection1 = {}
-    if (Cursor_y + Line_height) > App.screen.height then
-      Text.snap_cursor_to_bottom_of_screen(Margin_left, App.screen.width-Margin_right)
+    Editor_state.selection1 = {}
+    if (Editor_state.cursor_y + Editor_state.line_height) > App.screen.height then
+      Text.snap_cursor_to_bottom_of_screen(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
     end
     schedule_save()
-    record_undo_event({before=before, after=snapshot(before_line, Cursor1.line)})
+    record_undo_event({before=before, after=snapshot(before_line, Editor_state.cursor1.line)})
   elseif chord == 'tab' then
-    local before = snapshot(Cursor1.line)
---?     print(Screen_top1.line, Screen_top1.pos, Cursor1.line, Cursor1.pos, Screen_bottom1.line, Screen_bottom1.pos)
+    local before = snapshot(Editor_state.cursor1.line)
+--?     print(Editor_state.screen_top1.line, Editor_state.screen_top1.pos, Editor_state.cursor1.line, Editor_state.cursor1.pos, Editor_state.screen_bottom1.line, Editor_state.screen_bottom1.pos)
     Text.insert_at_cursor('\t')
-    if Cursor_y >= App.screen.height - Line_height then
-      Text.populate_screen_line_starting_pos(Lines[Cursor1.line], Margin_left, App.screen.width-Margin_right)
-      Text.snap_cursor_to_bottom_of_screen(Margin_left, App.screen.width-Margin_right)
---?       print('=>', Screen_top1.line, Screen_top1.pos, Cursor1.line, Cursor1.pos, Screen_bottom1.line, Screen_bottom1.pos)
+    if Editor_state.cursor_y >= App.screen.height - Editor_state.line_height then
+      Text.populate_screen_line_starting_pos(Editor_state.lines[Editor_state.cursor1.line], Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
+      Text.snap_cursor_to_bottom_of_screen(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
+--?       print('=>', Editor_state.screen_top1.line, Editor_state.screen_top1.pos, Editor_state.cursor1.line, Editor_state.cursor1.pos, Editor_state.screen_bottom1.line, Editor_state.screen_bottom1.pos)
     end
     schedule_save()
-    record_undo_event({before=before, after=snapshot(Cursor1.line)})
+    record_undo_event({before=before, after=snapshot(Editor_state.cursor1.line)})
   elseif chord == 'backspace' then
-    if Selection1.line then
-      Text.delete_selection(Margin_left, App.screen.width-Margin_right)
+    if Editor_state.selection1.line then
+      Text.delete_selection(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
       schedule_save()
       return
     end
     local before
-    if Cursor1.pos > 1 then
-      before = snapshot(Cursor1.line)
-      local byte_start = utf8.offset(Lines[Cursor1.line].data, Cursor1.pos-1)
-      local byte_end = utf8.offset(Lines[Cursor1.line].data, Cursor1.pos)
+    if Editor_state.cursor1.pos > 1 then
+      before = snapshot(Editor_state.cursor1.line)
+      local byte_start = utf8.offset(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor1.pos-1)
+      local byte_end = utf8.offset(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor1.pos)
       if byte_start then
         if byte_end then
-          Lines[Cursor1.line].data = string.sub(Lines[Cursor1.line].data, 1, byte_start-1)..string.sub(Lines[Cursor1.line].data, byte_end)
+          Editor_state.lines[Editor_state.cursor1.line].data = string.sub(Editor_state.lines[Editor_state.cursor1.line].data, 1, byte_start-1)..string.sub(Editor_state.lines[Editor_state.cursor1.line].data, byte_end)
         else
-          Lines[Cursor1.line].data = string.sub(Lines[Cursor1.line].data, 1, byte_start-1)
+          Editor_state.lines[Editor_state.cursor1.line].data = string.sub(Editor_state.lines[Editor_state.cursor1.line].data, 1, byte_start-1)
         end
-        Cursor1.pos = Cursor1.pos-1
+        Editor_state.cursor1.pos = Editor_state.cursor1.pos-1
       end
-    elseif Cursor1.line > 1 then
-      before = snapshot(Cursor1.line-1, Cursor1.line)
-      if Lines[Cursor1.line-1].mode == 'drawing' then
-        table.remove(Lines, Cursor1.line-1)
+    elseif Editor_state.cursor1.line > 1 then
+      before = snapshot(Editor_state.cursor1.line-1, Editor_state.cursor1.line)
+      if Editor_state.lines[Editor_state.cursor1.line-1].mode == 'drawing' then
+        table.remove(Editor_state.lines, Editor_state.cursor1.line-1)
       else
         -- join lines
-        Cursor1.pos = utf8.len(Lines[Cursor1.line-1].data)+1
-        Lines[Cursor1.line-1].data = Lines[Cursor1.line-1].data..Lines[Cursor1.line].data
-        table.remove(Lines, Cursor1.line)
+        Editor_state.cursor1.pos = utf8.len(Editor_state.lines[Editor_state.cursor1.line-1].data)+1
+        Editor_state.lines[Editor_state.cursor1.line-1].data = Editor_state.lines[Editor_state.cursor1.line-1].data..Editor_state.lines[Editor_state.cursor1.line].data
+        table.remove(Editor_state.lines, Editor_state.cursor1.line)
       end
-      Cursor1.line = Cursor1.line-1
+      Editor_state.cursor1.line = Editor_state.cursor1.line-1
     end
-    if Text.lt1(Cursor1, Screen_top1) then
-      local top2 = Text.to2(Screen_top1, Margin_left, App.screen.width-Margin_right)
-      top2 = Text.previous_screen_line(top2, Margin_left, App.screen.width-Margin_right)
-      Screen_top1 = Text.to1(top2)
+    if Text.lt1(Editor_state.cursor1, Editor_state.screen_top1) then
+      local top2 = Text.to2(Editor_state.screen_top1, Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
+      top2 = Text.previous_screen_line(top2, Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
+      Editor_state.screen_top1 = Text.to1(top2)
       Text.redraw_all()  -- if we're scrolling, reclaim all fragments to avoid memory leaks
     end
-    Text.clear_cache(Lines[Cursor1.line])
-    assert(Text.le1(Screen_top1, Cursor1))
+    Text.clear_cache(Editor_state.lines[Editor_state.cursor1.line])
+    assert(Text.le1(Editor_state.screen_top1, Editor_state.cursor1))
     schedule_save()
-    record_undo_event({before=before, after=snapshot(Cursor1.line)})
+    record_undo_event({before=before, after=snapshot(Editor_state.cursor1.line)})
   elseif chord == 'delete' then
-    if Selection1.line then
-      Text.delete_selection(Margin_left, App.screen.width-Margin_right)
+    if Editor_state.selection1.line then
+      Text.delete_selection(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
       schedule_save()
       return
     end
     local before
-    if Cursor1.pos <= utf8.len(Lines[Cursor1.line].data) then
-      before = snapshot(Cursor1.line)
+    if Editor_state.cursor1.pos <= utf8.len(Editor_state.lines[Editor_state.cursor1.line].data) then
+      before = snapshot(Editor_state.cursor1.line)
     else
-      before = snapshot(Cursor1.line, Cursor1.line+1)
+      before = snapshot(Editor_state.cursor1.line, Editor_state.cursor1.line+1)
     end
-    if Cursor1.pos <= utf8.len(Lines[Cursor1.line].data) then
-      local byte_start = utf8.offset(Lines[Cursor1.line].data, Cursor1.pos)
-      local byte_end = utf8.offset(Lines[Cursor1.line].data, Cursor1.pos+1)
+    if Editor_state.cursor1.pos <= utf8.len(Editor_state.lines[Editor_state.cursor1.line].data) then
+      local byte_start = utf8.offset(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor1.pos)
+      local byte_end = utf8.offset(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor1.pos+1)
       if byte_start then
         if byte_end then
-          Lines[Cursor1.line].data = string.sub(Lines[Cursor1.line].data, 1, byte_start-1)..string.sub(Lines[Cursor1.line].data, byte_end)
+          Editor_state.lines[Editor_state.cursor1.line].data = string.sub(Editor_state.lines[Editor_state.cursor1.line].data, 1, byte_start-1)..string.sub(Editor_state.lines[Editor_state.cursor1.line].data, byte_end)
         else
-          Lines[Cursor1.line].data = string.sub(Lines[Cursor1.line].data, 1, byte_start-1)
+          Editor_state.lines[Editor_state.cursor1.line].data = string.sub(Editor_state.lines[Editor_state.cursor1.line].data, 1, byte_start-1)
         end
-        -- no change to Cursor1.pos
+        -- no change to Editor_state.cursor1.pos
       end
-    elseif Cursor1.line < #Lines then
-      if Lines[Cursor1.line+1].mode == 'drawing' then
-        table.remove(Lines, Cursor1.line+1)
+    elseif Editor_state.cursor1.line < #Editor_state.lines then
+      if Editor_state.lines[Editor_state.cursor1.line+1].mode == 'drawing' then
+        table.remove(Editor_state.lines, Editor_state.cursor1.line+1)
       else
         -- join lines
-        Lines[Cursor1.line].data = Lines[Cursor1.line].data..Lines[Cursor1.line+1].data
-        table.remove(Lines, Cursor1.line+1)
+        Editor_state.lines[Editor_state.cursor1.line].data = Editor_state.lines[Editor_state.cursor1.line].data..Editor_state.lines[Editor_state.cursor1.line+1].data
+        table.remove(Editor_state.lines, Editor_state.cursor1.line+1)
       end
     end
-    Text.clear_cache(Lines[Cursor1.line])
+    Text.clear_cache(Editor_state.lines[Editor_state.cursor1.line])
     schedule_save()
-    record_undo_event({before=before, after=snapshot(Cursor1.line)})
+    record_undo_event({before=before, after=snapshot(Editor_state.cursor1.line)})
   --== shortcuts that move the cursor
   elseif chord == 'left' then
-    Text.left(Margin_left, App.screen.width-Margin_right)
-    Selection1 = {}
+    Text.left(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
+    Editor_state.selection1 = {}
   elseif chord == 'right' then
-    Text.right(Margin_left, App.screen.width-Margin_right)
-    Selection1 = {}
+    Text.right(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
+    Editor_state.selection1 = {}
   elseif chord == 'S-left' then
-    if Selection1.line == nil then
-      Selection1 = {line=Cursor1.line, pos=Cursor1.pos}
+    if Editor_state.selection1.line == nil then
+      Editor_state.selection1 = {line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos}
     end
-    Text.left(Margin_left, App.screen.width-Margin_right)
+    Text.left(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
   elseif chord == 'S-right' then
-    if Selection1.line == nil then
-      Selection1 = {line=Cursor1.line, pos=Cursor1.pos}
+    if Editor_state.selection1.line == nil then
+      Editor_state.selection1 = {line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos}
     end
-    Text.right(Margin_left, App.screen.width-Margin_right)
+    Text.right(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
   -- C- hotkeys reserved for drawings, so we'll use M-
   elseif chord == 'M-left' then
-    Text.word_left(Margin_left, App.screen.width-Margin_right)
-    Selection1 = {}
+    Text.word_left(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
+    Editor_state.selection1 = {}
   elseif chord == 'M-right' then
-    Text.word_right(Margin_left, App.screen.width-Margin_right)
-    Selection1 = {}
+    Text.word_right(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
+    Editor_state.selection1 = {}
   elseif chord == 'M-S-left' then
-    if Selection1.line == nil then
-      Selection1 = {line=Cursor1.line, pos=Cursor1.pos}
+    if Editor_state.selection1.line == nil then
+      Editor_state.selection1 = {line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos}
     end
-    Text.word_left(Margin_left, App.screen.width-Margin_right)
+    Text.word_left(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
   elseif chord == 'M-S-right' then
-    if Selection1.line == nil then
-      Selection1 = {line=Cursor1.line, pos=Cursor1.pos}
+    if Editor_state.selection1.line == nil then
+      Editor_state.selection1 = {line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos}
     end
-    Text.word_right(Margin_left, App.screen.width-Margin_right)
+    Text.word_right(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
   elseif chord == 'home' then
     Text.start_of_line()
-    Selection1 = {}
+    Editor_state.selection1 = {}
   elseif chord == 'end' then
-    Text.end_of_line(Margin_left, App.screen.width-Margin_right)
-    Selection1 = {}
+    Text.end_of_line(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
+    Editor_state.selection1 = {}
   elseif chord == 'S-home' then
-    if Selection1.line == nil then
-      Selection1 = {line=Cursor1.line, pos=Cursor1.pos}
+    if Editor_state.selection1.line == nil then
+      Editor_state.selection1 = {line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos}
     end
     Text.start_of_line()
   elseif chord == 'S-end' then
-    if Selection1.line == nil then
-      Selection1 = {line=Cursor1.line, pos=Cursor1.pos}
+    if Editor_state.selection1.line == nil then
+      Editor_state.selection1 = {line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos}
     end
-    Text.end_of_line(Margin_left, App.screen.width-Margin_right)
+    Text.end_of_line(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
   elseif chord == 'up' then
-    Text.up(Margin_left, App.screen.width-Margin_right)
-    Selection1 = {}
+    Text.up(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
+    Editor_state.selection1 = {}
   elseif chord == 'down' then
-    Text.down(Margin_left, App.screen.width-Margin_right)
-    Selection1 = {}
+    Text.down(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
+    Editor_state.selection1 = {}
   elseif chord == 'S-up' then
-    if Selection1.line == nil then
-      Selection1 = {line=Cursor1.line, pos=Cursor1.pos}
+    if Editor_state.selection1.line == nil then
+      Editor_state.selection1 = {line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos}
     end
-    Text.up(Margin_left, App.screen.width-Margin_right)
+    Text.up(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
   elseif chord == 'S-down' then
-    if Selection1.line == nil then
-      Selection1 = {line=Cursor1.line, pos=Cursor1.pos}
+    if Editor_state.selection1.line == nil then
+      Editor_state.selection1 = {line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos}
     end
-    Text.down(Margin_left, App.screen.width-Margin_right)
+    Text.down(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
   elseif chord == 'pageup' then
-    Text.pageup(Margin_left, App.screen.width-Margin_right)
-    Selection1 = {}
+    Text.pageup(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
+    Editor_state.selection1 = {}
   elseif chord == 'pagedown' then
-    Text.pagedown(Margin_left, App.screen.width-Margin_right)
-    Selection1 = {}
+    Text.pagedown(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
+    Editor_state.selection1 = {}
   elseif chord == 'S-pageup' then
-    if Selection1.line == nil then
-      Selection1 = {line=Cursor1.line, pos=Cursor1.pos}
+    if Editor_state.selection1.line == nil then
+      Editor_state.selection1 = {line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos}
     end
-    Text.pageup(Margin_left, App.screen.width-Margin_right)
+    Text.pageup(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
   elseif chord == 'S-pagedown' then
-    if Selection1.line == nil then
-      Selection1 = {line=Cursor1.line, pos=Cursor1.pos}
+    if Editor_state.selection1.line == nil then
+      Editor_state.selection1 = {line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos}
     end
-    Text.pagedown(Margin_left, App.screen.width-Margin_right)
+    Text.pagedown(Editor_state.margin_left, App.screen.width-Editor_state.margin_right)
   end
 end
 
 function Text.insert_return()
-  local byte_offset = Text.offset(Lines[Cursor1.line].data, Cursor1.pos)
-  table.insert(Lines, Cursor1.line+1, {mode='text', data=string.sub(Lines[Cursor1.line].data, byte_offset)})
-  Lines[Cursor1.line].data = string.sub(Lines[Cursor1.line].data, 1, byte_offset-1)
-  Text.clear_cache(Lines[Cursor1.line])
-  Text.clear_cache(Lines[Cursor1.line+1])
-  Cursor1.line = Cursor1.line+1
-  Cursor1.pos = 1
+  local byte_offset = Text.offset(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor1.pos)
+  table.insert(Editor_state.lines, Editor_state.cursor1.line+1, {mode='text', data=string.sub(Editor_state.lines[Editor_state.cursor1.line].data, byte_offset)})
+  Editor_state.lines[Editor_state.cursor1.line].data = string.sub(Editor_state.lines[Editor_state.cursor1.line].data, 1, byte_offset-1)
+  Text.clear_cache(Editor_state.lines[Editor_state.cursor1.line])
+  Text.clear_cache(Editor_state.lines[Editor_state.cursor1.line+1])
+  Editor_state.cursor1.line = Editor_state.cursor1.line+1
+  Editor_state.cursor1.pos = 1
 end
 
 function Text.pageup(left, right)
 --?   print('pageup')
   -- duplicate some logic from love.draw
-  local top2 = Text.to2(Screen_top1, left, right)
+  local top2 = Text.to2(Editor_state.screen_top1, left, right)
 --?   print(App.screen.height)
-  local y = App.screen.height - Line_height
-  while y >= Margin_top do
+  local y = App.screen.height - Editor_state.line_height
+  while y >= Editor_state.margin_top do
 --?     print(y, top2.line, top2.screen_line, top2.screen_pos)
-    if Screen_top1.line == 1 and Screen_top1.pos == 1 then break end
-    if Lines[Screen_top1.line].mode == 'text' then
-      y = y - Line_height
-    elseif Lines[Screen_top1.line].mode == 'drawing' then
-      y = y - Drawing_padding_height - Drawing.pixels(Lines[Screen_top1.line].h)
+    if Editor_state.screen_top1.line == 1 and Editor_state.screen_top1.pos == 1 then break end
+    if Editor_state.lines[Editor_state.screen_top1.line].mode == 'text' then
+      y = y - Editor_state.line_height
+    elseif Editor_state.lines[Editor_state.screen_top1.line].mode == 'drawing' then
+      y = y - Editor_state.drawing_padding_height - Drawing.pixels(Editor_state.lines[Editor_state.screen_top1.line].h)
     end
     top2 = Text.previous_screen_line(top2, left, right)
   end
-  Screen_top1 = Text.to1(top2)
-  Cursor1.line = Screen_top1.line
-  Cursor1.pos = Screen_top1.pos
+  Editor_state.screen_top1 = Text.to1(top2)
+  Editor_state.cursor1.line = Editor_state.screen_top1.line
+  Editor_state.cursor1.pos = Editor_state.screen_top1.pos
   Text.move_cursor_down_to_next_text_line_while_scrolling_again_if_necessary(left, right)
---?   print(Cursor1.line, Cursor1.pos, Screen_top1.line, Screen_top1.pos)
+--?   print(Editor_state.cursor1.line, Editor_state.cursor1.pos, Editor_state.screen_top1.line, Editor_state.screen_top1.pos)
 --?   print('pageup end')
 end
 
@@ -380,133 +380,133 @@ function Text.pagedown(left, right)
   -- If a line/paragraph gets to a page boundary, I often want to scroll
   -- before I get to the bottom.
   -- However, only do this if it makes forward progress.
-  local top2 = Text.to2(Screen_bottom1, left, right)
+  local top2 = Text.to2(Editor_state.screen_bottom1, left, right)
   if top2.screen_line > 1 then
     top2.screen_line = math.max(top2.screen_line-10, 1)
   end
   local new_top1 = Text.to1(top2)
-  if Text.lt1(Screen_top1, new_top1) then
-    Screen_top1 = new_top1
+  if Text.lt1(Editor_state.screen_top1, new_top1) then
+    Editor_state.screen_top1 = new_top1
   else
-    Screen_top1.line = Screen_bottom1.line
-    Screen_top1.pos = Screen_bottom1.pos
+    Editor_state.screen_top1.line = Editor_state.screen_bottom1.line
+    Editor_state.screen_top1.pos = Editor_state.screen_bottom1.pos
   end
---?   print('setting top to', Screen_top1.line, Screen_top1.pos)
-  Cursor1.line = Screen_top1.line
-  Cursor1.pos = Screen_top1.pos
+--?   print('setting top to', Editor_state.screen_top1.line, Editor_state.screen_top1.pos)
+  Editor_state.cursor1.line = Editor_state.screen_top1.line
+  Editor_state.cursor1.pos = Editor_state.screen_top1.pos
   Text.move_cursor_down_to_next_text_line_while_scrolling_again_if_necessary(left, right)
---?   print('top now', Screen_top1.line)
+--?   print('top now', Editor_state.screen_top1.line)
   Text.redraw_all()  -- if we're scrolling, reclaim all fragments to avoid memory leaks
 --?   print('pagedown end')
 end
 
 function Text.up(left, right)
-  assert(Lines[Cursor1.line].mode == 'text')
---?   print('up', Cursor1.line, Cursor1.pos, Screen_top1.line, Screen_top1.pos)
+  assert(Editor_state.lines[Editor_state.cursor1.line].mode == 'text')
+--?   print('up', Editor_state.cursor1.line, Editor_state.cursor1.pos, Editor_state.screen_top1.line, Editor_state.screen_top1.pos)
   local screen_line_index,screen_line_starting_pos = Text.pos_at_start_of_cursor_screen_line(left, right)
   if screen_line_starting_pos == 1 then
 --?     print('cursor is at first screen line of its line')
     -- line is done; skip to previous text line
-    local new_cursor_line = Cursor1.line
+    local new_cursor_line = Editor_state.cursor1.line
     while new_cursor_line > 1 do
       new_cursor_line = new_cursor_line-1
-      if Lines[new_cursor_line].mode == 'text' then
+      if Editor_state.lines[new_cursor_line].mode == 'text' then
 --?         print('found previous text line')
-        Cursor1.line = new_cursor_line
-        Text.populate_screen_line_starting_pos(Lines[Cursor1.line], left, right)
+        Editor_state.cursor1.line = new_cursor_line
+        Text.populate_screen_line_starting_pos(Editor_state.lines[Editor_state.cursor1.line], left, right)
         -- previous text line found, pick its final screen line
 --?         print('has multiple screen lines')
-        local screen_line_starting_pos = Lines[Cursor1.line].screen_line_starting_pos
+        local screen_line_starting_pos = Editor_state.lines[Editor_state.cursor1.line].screen_line_starting_pos
 --?         print(#screen_line_starting_pos)
         screen_line_starting_pos = screen_line_starting_pos[#screen_line_starting_pos]
 --?         print('previous screen line starts at pos '..tostring(screen_line_starting_pos)..' of its line')
-        if Screen_top1.line > Cursor1.line then
-          Screen_top1.line = Cursor1.line
-          Screen_top1.pos = screen_line_starting_pos
---?           print('pos of top of screen is also '..tostring(Screen_top1.pos)..' of the same line')
+        if Editor_state.screen_top1.line > Editor_state.cursor1.line then
+          Editor_state.screen_top1.line = Editor_state.cursor1.line
+          Editor_state.screen_top1.pos = screen_line_starting_pos
+--?           print('pos of top of screen is also '..tostring(Editor_state.screen_top1.pos)..' of the same line')
         end
-        local screen_line_starting_byte_offset = Text.offset(Lines[Cursor1.line].data, screen_line_starting_pos)
-        local s = string.sub(Lines[Cursor1.line].data, screen_line_starting_byte_offset)
-        Cursor1.pos = screen_line_starting_pos + Text.nearest_cursor_pos(s, Cursor_x, left) - 1
+        local screen_line_starting_byte_offset = Text.offset(Editor_state.lines[Editor_state.cursor1.line].data, screen_line_starting_pos)
+        local s = string.sub(Editor_state.lines[Editor_state.cursor1.line].data, screen_line_starting_byte_offset)
+        Editor_state.cursor1.pos = screen_line_starting_pos + Text.nearest_cursor_pos(s, Editor_state.cursor_x, left) - 1
         break
       end
     end
-    if Cursor1.line < Screen_top1.line then
-      Screen_top1.line = Cursor1.line
+    if Editor_state.cursor1.line < Editor_state.screen_top1.line then
+      Editor_state.screen_top1.line = Editor_state.cursor1.line
     end
   else
     -- move up one screen line in current line
 --?     print('cursor is NOT at first screen line of its line')
     assert(screen_line_index > 1)
-    new_screen_line_starting_pos = Lines[Cursor1.line].screen_line_starting_pos[screen_line_index-1]
+    new_screen_line_starting_pos = Editor_state.lines[Editor_state.cursor1.line].screen_line_starting_pos[screen_line_index-1]
 --?     print('switching pos of screen line at cursor from '..tostring(screen_line_starting_pos)..' to '..tostring(new_screen_line_starting_pos))
-    if Screen_top1.line == Cursor1.line and Screen_top1.pos == screen_line_starting_pos then
-      Screen_top1.pos = new_screen_line_starting_pos
---?       print('also setting pos of top of screen to '..tostring(Screen_top1.pos))
+    if Editor_state.screen_top1.line == Editor_state.cursor1.line and Editor_state.screen_top1.pos == screen_line_starting_pos then
+      Editor_state.screen_top1.pos = new_screen_line_starting_pos
+--?       print('also setting pos of top of screen to '..tostring(Editor_state.screen_top1.pos))
     end
-    local new_screen_line_starting_byte_offset = Text.offset(Lines[Cursor1.line].data, new_screen_line_starting_pos)
-    local s = string.sub(Lines[Cursor1.line].data, new_screen_line_starting_byte_offset)
-    Cursor1.pos = new_screen_line_starting_pos + Text.nearest_cursor_pos(s, Cursor_x, left) - 1
---?     print('cursor pos is now '..tostring(Cursor1.pos))
+    local new_screen_line_starting_byte_offset = Text.offset(Editor_state.lines[Editor_state.cursor1.line].data, new_screen_line_starting_pos)
+    local s = string.sub(Editor_state.lines[Editor_state.cursor1.line].data, new_screen_line_starting_byte_offset)
+    Editor_state.cursor1.pos = new_screen_line_starting_pos + Text.nearest_cursor_pos(s, Editor_state.cursor_x, left) - 1
+--?     print('cursor pos is now '..tostring(Editor_state.cursor1.pos))
   end
 end
 
 function Text.down(left, right)
-  assert(Lines[Cursor1.line].mode == 'text')
---?   print('down', Cursor1.line, Cursor1.pos, Screen_top1.line, Screen_top1.pos, Screen_bottom1.line, Screen_bottom1.pos)
+  assert(Editor_state.lines[Editor_state.cursor1.line].mode == 'text')
+--?   print('down', Editor_state.cursor1.line, Editor_state.cursor1.pos, Editor_state.screen_top1.line, Editor_state.screen_top1.pos, Editor_state.screen_bottom1.line, Editor_state.screen_bottom1.pos)
   if Text.cursor_at_final_screen_line(left, right) then
     -- line is done, skip to next text line
 --?     print('cursor at final screen line of its line')
-    local new_cursor_line = Cursor1.line
-    while new_cursor_line < #Lines do
+    local new_cursor_line = Editor_state.cursor1.line
+    while new_cursor_line < #Editor_state.lines do
       new_cursor_line = new_cursor_line+1
-      if Lines[new_cursor_line].mode == 'text' then
-        Cursor1.line = new_cursor_line
-        Cursor1.pos = Text.nearest_cursor_pos(Lines[Cursor1.line].data, Cursor_x, left)
---?         print(Cursor1.pos)
+      if Editor_state.lines[new_cursor_line].mode == 'text' then
+        Editor_state.cursor1.line = new_cursor_line
+        Editor_state.cursor1.pos = Text.nearest_cursor_pos(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor_x, left)
+--?         print(Editor_state.cursor1.pos)
         break
       end
     end
-    if Cursor1.line > Screen_bottom1.line then
---?       print('screen top before:', Screen_top1.line, Screen_top1.pos)
+    if Editor_state.cursor1.line > Editor_state.screen_bottom1.line then
+--?       print('screen top before:', Editor_state.screen_top1.line, Editor_state.screen_top1.pos)
 --?       print('scroll up preserving cursor')
       Text.snap_cursor_to_bottom_of_screen(left, right)
---?       print('screen top after:', Screen_top1.line, Screen_top1.pos)
+--?       print('screen top after:', Editor_state.screen_top1.line, Editor_state.screen_top1.pos)
     end
   else
     -- move down one screen line in current line
     local scroll_down = false
-    if Text.le1(Screen_bottom1, Cursor1) then
+    if Text.le1(Editor_state.screen_bottom1, Editor_state.cursor1) then
       scroll_down = true
     end
 --?     print('cursor is NOT at final screen line of its line')
     local screen_line_index, screen_line_starting_pos = Text.pos_at_start_of_cursor_screen_line(left, right)
-    new_screen_line_starting_pos = Lines[Cursor1.line].screen_line_starting_pos[screen_line_index+1]
+    new_screen_line_starting_pos = Editor_state.lines[Editor_state.cursor1.line].screen_line_starting_pos[screen_line_index+1]
 --?     print('switching pos of screen line at cursor from '..tostring(screen_line_starting_pos)..' to '..tostring(new_screen_line_starting_pos))
-    local new_screen_line_starting_byte_offset = Text.offset(Lines[Cursor1.line].data, new_screen_line_starting_pos)
-    local s = string.sub(Lines[Cursor1.line].data, new_screen_line_starting_byte_offset)
-    Cursor1.pos = new_screen_line_starting_pos + Text.nearest_cursor_pos(s, Cursor_x, left) - 1
---?     print('cursor pos is now', Cursor1.line, Cursor1.pos)
+    local new_screen_line_starting_byte_offset = Text.offset(Editor_state.lines[Editor_state.cursor1.line].data, new_screen_line_starting_pos)
+    local s = string.sub(Editor_state.lines[Editor_state.cursor1.line].data, new_screen_line_starting_byte_offset)
+    Editor_state.cursor1.pos = new_screen_line_starting_pos + Text.nearest_cursor_pos(s, Editor_state.cursor_x, left) - 1
+--?     print('cursor pos is now', Editor_state.cursor1.line, Editor_state.cursor1.pos)
     if scroll_down then
 --?       print('scroll up preserving cursor')
       Text.snap_cursor_to_bottom_of_screen(left, right)
---?       print('screen top after:', Screen_top1.line, Screen_top1.pos)
+--?       print('screen top after:', Editor_state.screen_top1.line, Editor_state.screen_top1.pos)
     end
   end
---?   print('=>', Cursor1.line, Cursor1.pos, Screen_top1.line, Screen_top1.pos, Screen_bottom1.line, Screen_bottom1.pos)
+--?   print('=>', Editor_state.cursor1.line, Editor_state.cursor1.pos, Editor_state.screen_top1.line, Editor_state.screen_top1.pos, Editor_state.screen_bottom1.line, Editor_state.screen_bottom1.pos)
 end
 
 function Text.start_of_line()
-  Cursor1.pos = 1
-  if Text.lt1(Cursor1, Screen_top1) then
-    Screen_top1 = {line=Cursor1.line, pos=Cursor1.pos}  -- copy
+  Editor_state.cursor1.pos = 1
+  if Text.lt1(Editor_state.cursor1, Editor_state.screen_top1) then
+    Editor_state.screen_top1 = {line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos}  -- copy
   end
 end
 
 function Text.end_of_line(left, right)
-  Cursor1.pos = utf8.len(Lines[Cursor1.line].data) + 1
+  Editor_state.cursor1.pos = utf8.len(Editor_state.lines[Editor_state.cursor1.line].data) + 1
   local _,botpos = Text.pos_at_start_of_cursor_screen_line(left, right)
-  local botline1 = {line=Cursor1.line, pos=botpos}
+  local botline1 = {line=Editor_state.cursor1.line, pos=botpos}
   if Text.cursor_past_screen_bottom() then
     Text.snap_cursor_to_bottom_of_screen(left, right)
   end
@@ -515,10 +515,10 @@ end
 function Text.word_left(left, right)
   -- skip some whitespace
   while true do
-    if Cursor1.pos == 1 then
+    if Editor_state.cursor1.pos == 1 then
       break
     end
-    if Text.match(Lines[Cursor1.line].data, Cursor1.pos-1, '%S') then
+    if Text.match(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor1.pos-1, '%S') then
       break
     end
     Text.left(left, right)
@@ -526,11 +526,11 @@ function Text.word_left(left, right)
   -- skip some non-whitespace
   while true do
     Text.left(left, right)
-    if Cursor1.pos == 1 then
+    if Editor_state.cursor1.pos == 1 then
       break
     end
-    assert(Cursor1.pos > 1)
-    if Text.match(Lines[Cursor1.line].data, Cursor1.pos-1, '%s') then
+    assert(Editor_state.cursor1.pos > 1)
+    if Text.match(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor1.pos-1, '%s') then
       break
     end
   end
@@ -539,20 +539,20 @@ end
 function Text.word_right(left, right)
   -- skip some whitespace
   while true do
-    if Cursor1.pos > utf8.len(Lines[Cursor1.line].data) then
+    if Editor_state.cursor1.pos > utf8.len(Editor_state.lines[Editor_state.cursor1.line].data) then
       break
     end
-    if Text.match(Lines[Cursor1.line].data, Cursor1.pos, '%S') then
+    if Text.match(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor1.pos, '%S') then
       break
     end
     Text.right_without_scroll()
   end
   while true do
     Text.right_without_scroll()
-    if Cursor1.pos > utf8.len(Lines[Cursor1.line].data) then
+    if Editor_state.cursor1.pos > utf8.len(Editor_state.lines[Editor_state.cursor1.line].data) then
       break
     end
-    if Text.match(Lines[Cursor1.line].data, Cursor1.pos, '%s') then
+    if Text.match(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor1.pos, '%s') then
       break
     end
   end
@@ -571,24 +571,24 @@ function Text.match(s, pos, pat)
 end
 
 function Text.left(left, right)
-  assert(Lines[Cursor1.line].mode == 'text')
-  if Cursor1.pos > 1 then
-    Cursor1.pos = Cursor1.pos-1
+  assert(Editor_state.lines[Editor_state.cursor1.line].mode == 'text')
+  if Editor_state.cursor1.pos > 1 then
+    Editor_state.cursor1.pos = Editor_state.cursor1.pos-1
   else
-    local new_cursor_line = Cursor1.line
+    local new_cursor_line = Editor_state.cursor1.line
     while new_cursor_line > 1 do
       new_cursor_line = new_cursor_line-1
-      if Lines[new_cursor_line].mode == 'text' then
-        Cursor1.line = new_cursor_line
-        Cursor1.pos = utf8.len(Lines[Cursor1.line].data) + 1
+      if Editor_state.lines[new_cursor_line].mode == 'text' then
+        Editor_state.cursor1.line = new_cursor_line
+        Editor_state.cursor1.pos = utf8.len(Editor_state.lines[Editor_state.cursor1.line].data) + 1
         break
       end
     end
   end
-  if Text.lt1(Cursor1, Screen_top1) then
-    local top2 = Text.to2(Screen_top1, left, right)
+  if Text.lt1(Editor_state.cursor1, Editor_state.screen_top1) then
+    local top2 = Text.to2(Editor_state.screen_top1, left, right)
     top2 = Text.previous_screen_line(top2, left, right)
-    Screen_top1 = Text.to1(top2)
+    Editor_state.screen_top1 = Text.to1(top2)
   end
 end
 
@@ -600,16 +600,16 @@ function Text.right(left, right)
 end
 
 function Text.right_without_scroll()
-  assert(Lines[Cursor1.line].mode == 'text')
-  if Cursor1.pos <= utf8.len(Lines[Cursor1.line].data) then
-    Cursor1.pos = Cursor1.pos+1
+  assert(Editor_state.lines[Editor_state.cursor1.line].mode == 'text')
+  if Editor_state.cursor1.pos <= utf8.len(Editor_state.lines[Editor_state.cursor1.line].data) then
+    Editor_state.cursor1.pos = Editor_state.cursor1.pos+1
   else
-    local new_cursor_line = Cursor1.line
-    while new_cursor_line <= #Lines-1 do
+    local new_cursor_line = Editor_state.cursor1.line
+    while new_cursor_line <= #Editor_state.lines-1 do
       new_cursor_line = new_cursor_line+1
-      if Lines[new_cursor_line].mode == 'text' then
-        Cursor1.line = new_cursor_line
-        Cursor1.pos = 1
+      if Editor_state.lines[new_cursor_line].mode == 'text' then
+        Editor_state.cursor1.line = new_cursor_line
+        Editor_state.cursor1.pos = 1
         break
       end
     end
@@ -617,10 +617,10 @@ function Text.right_without_scroll()
 end
 
 function Text.pos_at_start_of_cursor_screen_line(left, right)
-  Text.populate_screen_line_starting_pos(Lines[Cursor1.line], left, right)
-  for i=#Lines[Cursor1.line].screen_line_starting_pos,1,-1 do
-    local spos = Lines[Cursor1.line].screen_line_starting_pos[i]
-    if spos <= Cursor1.pos then
+  Text.populate_screen_line_starting_pos(Editor_state.lines[Editor_state.cursor1.line], left, right)
+  for i=#Editor_state.lines[Editor_state.cursor1.line].screen_line_starting_pos,1,-1 do
+    local spos = Editor_state.lines[Editor_state.cursor1.line].screen_line_starting_pos[i]
+    if spos <= Editor_state.cursor1.pos then
       return i,spos
     end
   end
@@ -628,57 +628,57 @@ function Text.pos_at_start_of_cursor_screen_line(left, right)
 end
 
 function Text.cursor_at_final_screen_line(left, right)
-  Text.populate_screen_line_starting_pos(Lines[Cursor1.line], left, right)
-  local screen_lines = Lines[Cursor1.line].screen_line_starting_pos
---?   print(screen_lines[#screen_lines], Cursor1.pos)
-  return screen_lines[#screen_lines] <= Cursor1.pos
+  Text.populate_screen_line_starting_pos(Editor_state.lines[Editor_state.cursor1.line], left, right)
+  local screen_lines = Editor_state.lines[Editor_state.cursor1.line].screen_line_starting_pos
+--?   print(screen_lines[#screen_lines], Editor_state.cursor1.pos)
+  return screen_lines[#screen_lines] <= Editor_state.cursor1.pos
 end
 
 function Text.move_cursor_down_to_next_text_line_while_scrolling_again_if_necessary(left, right)
-  local y = Margin_top
-  while Cursor1.line <= #Lines do
-    if Lines[Cursor1.line].mode == 'text' then
+  local y = Editor_state.margin_top
+  while Editor_state.cursor1.line <= #Editor_state.lines do
+    if Editor_state.lines[Editor_state.cursor1.line].mode == 'text' then
       break
     end
---?     print('cursor skips', Cursor1.line)
-    y = y + Drawing_padding_height + Drawing.pixels(Lines[Cursor1.line].h)
-    Cursor1.line = Cursor1.line + 1
+--?     print('cursor skips', Editor_state.cursor1.line)
+    y = y + Editor_state.drawing_padding_height + Drawing.pixels(Editor_state.lines[Editor_state.cursor1.line].h)
+    Editor_state.cursor1.line = Editor_state.cursor1.line + 1
   end
   -- hack: insert a text line at bottom of file if necessary
-  if Cursor1.line > #Lines then
-    assert(Cursor1.line == #Lines+1)
-    table.insert(Lines, {mode='text', data=''})
+  if Editor_state.cursor1.line > #Editor_state.lines then
+    assert(Editor_state.cursor1.line == #Editor_state.lines+1)
+    table.insert(Editor_state.lines, {mode='text', data=''})
   end
---?   print(y, App.screen.height, App.screen.height-Line_height)
-  if y > App.screen.height - Line_height then
+--?   print(y, App.screen.height, App.screen.height-Editor_state.line_height)
+  if y > App.screen.height - Editor_state.line_height then
 --?     print('scroll up')
     Text.snap_cursor_to_bottom_of_screen(left, right)
   end
 end
 
--- should never modify Cursor1
+-- should never modify Editor_state.cursor1
 function Text.snap_cursor_to_bottom_of_screen(left, right)
-  local top2 = Text.to2(Cursor1, left, right)
+  local top2 = Text.to2(Editor_state.cursor1, left, right)
   top2.screen_pos = 1  -- start of screen line
---?   print('cursor pos '..tostring(Cursor1.pos)..' is on the #'..tostring(top2.screen_line)..' screen line down')
-  local y = App.screen.height - Line_height
+--?   print('cursor pos '..tostring(Editor_state.cursor1.pos)..' is on the #'..tostring(top2.screen_line)..' screen line down')
+  local y = App.screen.height - Editor_state.line_height
   -- duplicate some logic from love.draw
   while true do
 --?     print(y, 'top2:', top2.line, top2.screen_line, top2.screen_pos)
     if top2.line == 1 and top2.screen_line == 1 then break end
-    if top2.screen_line > 1 or Lines[top2.line-1].mode == 'text' then
-      local h = Line_height
-      if y - h < Margin_top then
+    if top2.screen_line > 1 or Editor_state.lines[top2.line-1].mode == 'text' then
+      local h = Editor_state.line_height
+      if y - h < Editor_state.margin_top then
         break
       end
       y = y - h
     else
       assert(top2.line > 1)
-      assert(Lines[top2.line-1].mode == 'drawing')
+      assert(Editor_state.lines[top2.line-1].mode == 'drawing')
       -- We currently can't draw partial drawings, so either skip it entirely
       -- or not at all.
-      local h = Drawing_padding_height + Drawing.pixels(Lines[top2.line-1].h)
-      if y - h < Margin_top then
+      local h = Editor_state.drawing_padding_height + Drawing.pixels(Editor_state.lines[top2.line-1].h)
+      if y - h < Editor_state.margin_top then
         break
       end
 --?       print('skipping drawing of height', h)
@@ -687,8 +687,8 @@ function Text.snap_cursor_to_bottom_of_screen(left, right)
     top2 = Text.previous_screen_line(top2, left, right)
   end
 --?   print('top2 finally:', top2.line, top2.screen_line, top2.screen_pos)
-  Screen_top1 = Text.to1(top2)
---?   print('top1 finally:', Screen_top1.line, Screen_top1.pos)
+  Editor_state.screen_top1 = Text.to1(top2)
+--?   print('top1 finally:', Editor_state.screen_top1.line, Editor_state.screen_top1.pos)
   Text.redraw_all()  -- if we're scrolling, reclaim all fragments to avoid memory leaks
 end
 
@@ -697,7 +697,7 @@ function Text.in_line(line, x,y, left,right)
   if x < left then return false end
   if y < line.starty then return false end
   Text.populate_screen_line_starting_pos(line, left, right)
-  return y < line.starty + Line_height*(#line.screen_line_starting_pos - Text.screen_line_index(line, line.startpos) + 1)
+  return y < line.starty + Editor_state.line_height*(#line.screen_line_starting_pos - Text.screen_line_index(line, line.startpos) + 1)
 end
 
 -- convert mx,my in pixels to schema-1 coordinates
@@ -713,7 +713,7 @@ function Text.to_pos_on_line(line, mx, my, left, right)
     local screen_line_starting_pos = line.screen_line_starting_pos[screen_line_index]
     local screen_line_starting_byte_offset = Text.offset(line.data, screen_line_starting_pos)
 --?     print('iter', y, screen_line_index, screen_line_starting_pos, string.sub(line.data, screen_line_starting_byte_offset))
-    local nexty = y + Line_height
+    local nexty = y + Editor_state.line_height
     if my < nexty then
       -- On all wrapped screen lines but the final one, clicks past end of
       -- line position cursor on final character of screen line.
@@ -738,12 +738,12 @@ end
 --  click inside e
 --  line_starting_pos = 1 + 3 = 4
 --  nearest_cursor_pos('defgh', mx) = 2
---  Cursor1.pos = 4 + 2 - 1 = 5
+--  Editor_state.cursor1.pos = 4 + 2 - 1 = 5
 -- manual test:
 --  click inside h
 --  line_starting_pos = 1 + 3 + 3 = 7
 --  nearest_cursor_pos('gh', mx) = 2
---  Cursor1.pos = 7 + 2 - 1 = 8
+--  Editor_state.cursor1.pos = 7 + 2 - 1 = 8
 
 function Text.screen_line_width(line, i)
   local start_pos = line.screen_line_starting_pos[i]
@@ -848,13 +848,13 @@ function Text.x(s, pos)
 end
 
 function Text.to2(pos1, left, right)
-  if Lines[pos1.line].mode == 'drawing' then
+  if Editor_state.lines[pos1.line].mode == 'drawing' then
     return {line=pos1.line, screen_line=1, screen_pos=1}
   end
   local result = {line=pos1.line, screen_line=1}
-  Text.populate_screen_line_starting_pos(Lines[pos1.line], left, right)
-  for i=#Lines[pos1.line].screen_line_starting_pos,1,-1 do
-    local spos = Lines[pos1.line].screen_line_starting_pos[i]
+  Text.populate_screen_line_starting_pos(Editor_state.lines[pos1.line], left, right)
+  for i=#Editor_state.lines[pos1.line].screen_line_starting_pos,1,-1 do
+    local spos = Editor_state.lines[pos1.line].screen_line_starting_pos[i]
     if spos <= pos1.pos then
       result.screen_line = i
       result.screen_pos = pos1.pos - spos + 1
@@ -868,7 +868,7 @@ end
 function Text.to1(pos2)
   local result = {line=pos2.line, pos=pos2.screen_pos}
   if pos2.screen_line > 1 then
-    result.pos = Lines[pos2.line].screen_line_starting_pos[pos2.screen_line] + pos2.screen_pos - 1
+    result.pos = Editor_state.lines[pos2.line].screen_line_starting_pos[pos2.screen_line] + pos2.screen_pos - 1
   end
   return result
 end
@@ -901,7 +901,7 @@ function Text.offset(s, pos1)
   if pos1 == 1 then return 1 end
   local result = utf8.offset(s, pos1)
   if result == nil then
-    print(Cursor1.line, Cursor1.pos, #Lines[Cursor1.line].data, Lines[Cursor1.line].data)
+    print(Editor_state.cursor1.line, Editor_state.cursor1.pos, #Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.lines[Editor_state.cursor1.line].data)
     print(pos1, #s, s)
   end
   assert(result)
@@ -913,12 +913,12 @@ function Text.previous_screen_line(pos2, left, right)
     return {line=pos2.line, screen_line=pos2.screen_line-1, screen_pos=1}
   elseif pos2.line == 1 then
     return pos2
-  elseif Lines[pos2.line-1].mode == 'drawing' then
+  elseif Editor_state.lines[pos2.line-1].mode == 'drawing' then
     return {line=pos2.line-1, screen_line=1, screen_pos=1}
   else
-    local l = Lines[pos2.line-1]
-    Text.populate_screen_line_starting_pos(Lines[pos2.line-1], left, right)
-    return {line=pos2.line-1, screen_line=#Lines[pos2.line-1].screen_line_starting_pos, screen_pos=1}
+    local l = Editor_state.lines[pos2.line-1]
+    Text.populate_screen_line_starting_pos(Editor_state.lines[pos2.line-1], left, right)
+    return {line=pos2.line-1, screen_line=#Editor_state.lines[pos2.line-1].screen_line_starting_pos, screen_pos=1}
   end
 end
 
@@ -948,36 +948,36 @@ function Text.populate_screen_line_starting_pos(line, left, right)
 end
 
 function Text.tweak_screen_top_and_cursor(left, right)
---?   print('a', Selection1.line)
-  if Screen_top1.pos == 1 then return end
-  local line = Lines[Screen_top1.line]
+--?   print('a', Editor_state.selection1.line)
+  if Editor_state.screen_top1.pos == 1 then return end
+  local line = Editor_state.lines[Editor_state.screen_top1.line]
   Text.populate_screen_line_starting_pos(line, left, right)
   for i=2,#line.screen_line_starting_pos do
     local pos = line.screen_line_starting_pos[i]
-    if pos == Screen_top1.pos then
+    if pos == Editor_state.screen_top1.pos then
       break
     end
-    if pos > Screen_top1.pos then
+    if pos > Editor_state.screen_top1.pos then
       -- make sure screen top is at start of a screen line
       local prev = line.screen_line_starting_pos[i-1]
-      if Screen_top1.pos - prev < pos - Screen_top1.pos then
-        Screen_top1.pos = prev
+      if Editor_state.screen_top1.pos - prev < pos - Editor_state.screen_top1.pos then
+        Editor_state.screen_top1.pos = prev
       else
-        Screen_top1.pos = pos
+        Editor_state.screen_top1.pos = pos
       end
       break
     end
   end
   -- make sure cursor is on screen
-  if Text.lt1(Cursor1, Screen_top1) then
-    Cursor1 = {line=Screen_top1.line, pos=Screen_top1.pos}
-  elseif Cursor1.line >= Screen_bottom1.line then
+  if Text.lt1(Editor_state.cursor1, Editor_state.screen_top1) then
+    Editor_state.cursor1 = {line=Editor_state.screen_top1.line, pos=Editor_state.screen_top1.pos}
+  elseif Editor_state.cursor1.line >= Editor_state.screen_bottom1.line then
 --?     print('too low')
     if Text.cursor_past_screen_bottom() then
 --?       print('tweak')
-      local line = Lines[Screen_bottom1.line]
-      Cursor1 = {
-          line=Screen_bottom1.line,
+      local line = Editor_state.lines[Editor_state.screen_bottom1.line]
+      Editor_state.cursor1 = {
+          line=Editor_state.screen_bottom1.line,
           pos=Text.to_pos_on_line(line, App.screen.width-5, App.screen.height-5, left, right),
       }
     end
@@ -987,17 +987,17 @@ end
 -- slightly expensive since it redraws the screen
 function Text.cursor_past_screen_bottom()
   App.draw()
-  return Cursor_y >= App.screen.height - Line_height
+  return Editor_state.cursor_y >= App.screen.height - Editor_state.line_height
   -- this approach is cheaper and almost works, except on the final screen
   -- where file ends above bottom of screen
 --?   local _,botpos = Text.pos_at_start_of_cursor_screen_line(left, right)
---?   local botline1 = {line=Cursor1.line, pos=botpos}
---?   return Text.lt1(Screen_bottom1, botline1)
+--?   local botline1 = {line=Editor_state.cursor1.line, pos=botpos}
+--?   return Text.lt1(Editor_state.screen_bottom1, botline1)
 end
 
 function Text.redraw_all()
 --?   print('clearing fragments')
-  for _,line in ipairs(Lines) do
+  for _,line in ipairs(Editor_state.lines) do
     line.starty = nil
     line.startpos = nil
     Text.clear_cache(line)
diff --git a/text_tests.lua b/text_tests.lua
index be6d0d9..29d59ae 100644
--- a/text_tests.lua
+++ b/text_tests.lua
@@ -3,50 +3,50 @@
 function test_initial_state()
   io.write('\ntest_initial_state')
   App.screen.init{width=120, height=60}
-  Lines = load_array{}
-  Margin_right = 0; Margin_width = Margin_left
+  Editor_state.lines = load_array{}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
   edit.draw()
-  check_eq(#Lines, 1, 'F - test_initial_state/#lines')
-  check_eq(Cursor1.line, 1, 'F - test_initial_state/cursor:line')
-  check_eq(Cursor1.pos, 1, 'F - test_initial_state/cursor:pos')
-  check_eq(Screen_top1.line, 1, 'F - test_initial_state/screen_top:line')
-  check_eq(Screen_top1.pos, 1, 'F - test_initial_state/screen_top:pos')
+  check_eq(#Editor_state.lines, 1, 'F - test_initial_state/#lines')
+  check_eq(Editor_state.cursor1.line, 1, 'F - test_initial_state/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 1, 'F - test_initial_state/cursor:pos')
+  check_eq(Editor_state.screen_top1.line, 1, 'F - test_initial_state/screen_top:line')
+  check_eq(Editor_state.screen_top1.pos, 1, 'F - test_initial_state/screen_top:pos')
 end
 
 function test_click_to_create_drawing()
   io.write('\ntest_click_to_create_drawing')
   App.screen.init{width=120, height=60}
-  Lines = load_array{}
-  Margin_right = 0; Margin_width = Margin_left
+  Editor_state.lines = load_array{}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
   edit.draw()
-  App.run_after_mouse_click(8,Margin_top+8, 1)
+  App.run_after_mouse_click(8,Editor_state.margin_top+8, 1)
   -- cursor skips drawing to always remain on text
-  check_eq(#Lines, 2, 'F - test_click_to_create_drawing/#lines')
-  check_eq(Cursor1.line, 2, 'F - test_click_to_create_drawing/cursor')
+  check_eq(#Editor_state.lines, 2, 'F - test_click_to_create_drawing/#lines')
+  check_eq(Editor_state.cursor1.line, 2, 'F - test_click_to_create_drawing/cursor')
 end
 
 function test_backspace_to_delete_drawing()
   io.write('\ntest_backspace_to_delete_drawing')
   -- display a drawing followed by a line of text (you shouldn't ever have a drawing right at the end)
   App.screen.init{width=120, height=60}
-  Lines = load_array{'```lines', '```', ''}
-  Margin_right = 0; Margin_width = Margin_left
+  Editor_state.lines = load_array{'```lines', '```', ''}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
   -- cursor is on text as always (outside tests this will get initialized correctly)
-  Cursor1.line = 2
+  Editor_state.cursor1.line = 2
   -- backspacing deletes the drawing
   App.run_after_keychord('backspace')
-  check_eq(#Lines, 1, 'F - test_backspace_to_delete_drawing/#lines')
-  check_eq(Cursor1.line, 1, 'F - test_backspace_to_delete_drawing/cursor')
+  check_eq(#Editor_state.lines, 1, 'F - test_backspace_to_delete_drawing/#lines')
+  check_eq(Editor_state.cursor1.line, 1, 'F - test_backspace_to_delete_drawing/cursor')
 end
 
 function test_insert_first_character()
   io.write('\ntest_insert_first_character')
   App.screen.init{width=120, height=60}
-  Lines = load_array{}
-  Margin_right = 0; Margin_width = Margin_left
+  Editor_state.lines = load_array{}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
   edit.draw()
   App.run_after_textinput('a')
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'a', 'F - test_insert_first_character/screen:1')
 end
 
@@ -54,264 +54,264 @@ function test_press_ctrl()
   io.write('\ntest_press_ctrl')
   -- press ctrl while the cursor is on text
   App.screen.init{width=50, height=80}
-  Lines = load_array{''}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{''}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   App.run_after_keychord('C-m')
 end
 
 function test_move_left()
   io.write('\ntest_move_left')
   App.screen.init{width=120, height=60}
-  Lines = load_array{'a'}
-  Cursor1 = {line=1, pos=2}
-  Margin_right = 0; Margin_width = Margin_left
+  Editor_state.lines = load_array{'a'}
+  Editor_state.cursor1 = {line=1, pos=2}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
   edit.draw()
   App.run_after_keychord('left')
-  check_eq(Cursor1.pos, 1, 'F - test_move_left')
+  check_eq(Editor_state.cursor1.pos, 1, 'F - test_move_left')
 end
 
 function test_move_right()
   io.write('\ntest_move_right')
   App.screen.init{width=120, height=60}
-  Lines = load_array{'a'}
-  Cursor1 = {line=1, pos=1}
-  Margin_right = 0; Margin_width = Margin_left
+  Editor_state.lines = load_array{'a'}
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
   edit.draw()
   App.run_after_keychord('right')
-  check_eq(Cursor1.pos, 2, 'F - test_move_right')
+  check_eq(Editor_state.cursor1.pos, 2, 'F - test_move_right')
 end
 
 function test_move_left_to_previous_line()
   io.write('\ntest_move_left_to_previous_line')
   App.screen.init{width=120, height=60}
-  Lines = load_array{'abc', 'def'}
-  Cursor1 = {line=2, pos=1}
-  Margin_right = 0; Margin_width = Margin_left
+  Editor_state.lines = load_array{'abc', 'def'}
+  Editor_state.cursor1 = {line=2, pos=1}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
   edit.draw()
   App.run_after_keychord('left')
-  check_eq(Cursor1.line, 1, 'F - test_move_left_to_previous_line/line')
-  check_eq(Cursor1.pos, 4, 'F - test_move_left_to_previous_line/pos')  -- past end of line
+  check_eq(Editor_state.cursor1.line, 1, 'F - test_move_left_to_previous_line/line')
+  check_eq(Editor_state.cursor1.pos, 4, 'F - test_move_left_to_previous_line/pos')  -- past end of line
 end
 
 function test_move_right_to_next_line()
   io.write('\ntest_move_right_to_next_line')
   App.screen.init{width=120, height=60}
-  Lines = load_array{'abc', 'def'}
-  Cursor1 = {line=1, pos=4}  -- past end of line
-  Margin_right = 0; Margin_width = Margin_left
+  Editor_state.lines = load_array{'abc', 'def'}
+  Editor_state.cursor1 = {line=1, pos=4}  -- past end of line
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
   edit.draw()
   App.run_after_keychord('right')
-  check_eq(Cursor1.line, 2, 'F - test_move_right_to_next_line/line')
-  check_eq(Cursor1.pos, 1, 'F - test_move_right_to_next_line/pos')
+  check_eq(Editor_state.cursor1.line, 2, 'F - test_move_right_to_next_line/line')
+  check_eq(Editor_state.cursor1.pos, 1, 'F - test_move_right_to_next_line/pos')
 end
 
 function test_move_to_start_of_word()
   io.write('\ntest_move_to_start_of_word')
   App.screen.init{width=120, height=60}
-  Lines = load_array{'abc'}
-  Cursor1 = {line=1, pos=3}
-  Margin_right = 0; Margin_width = Margin_left
+  Editor_state.lines = load_array{'abc'}
+  Editor_state.cursor1 = {line=1, pos=3}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
   edit.draw()
   App.run_after_keychord('M-left')
-  check_eq(Cursor1.pos, 1, 'F - test_move_to_start_of_word')
+  check_eq(Editor_state.cursor1.pos, 1, 'F - test_move_to_start_of_word')
 end
 
 function test_move_to_start_of_previous_word()
   io.write('\ntest_move_to_start_of_previous_word')
   App.screen.init{width=120, height=60}
-  Lines = load_array{'abc def'}
-  Cursor1 = {line=1, pos=4}  -- at the space between words
-  Margin_right = 0; Margin_width = Margin_left
+  Editor_state.lines = load_array{'abc def'}
+  Editor_state.cursor1 = {line=1, pos=4}  -- at the space between words
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
   edit.draw()
   App.run_after_keychord('M-left')
-  check_eq(Cursor1.pos, 1, 'F - test_move_to_start_of_previous_word')
+  check_eq(Editor_state.cursor1.pos, 1, 'F - test_move_to_start_of_previous_word')
 end
 
 function test_skip_to_previous_word()
   io.write('\ntest_skip_to_previous_word')
   App.screen.init{width=120, height=60}
-  Lines = load_array{'abc def'}
-  Cursor1 = {line=1, pos=5}  -- at the start of second word
-  Margin_right = 0; Margin_width = Margin_left
+  Editor_state.lines = load_array{'abc def'}
+  Editor_state.cursor1 = {line=1, pos=5}  -- at the start of second word
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
   edit.draw()
   App.run_after_keychord('M-left')
-  check_eq(Cursor1.pos, 1, 'F - test_skip_to_previous_word')
+  check_eq(Editor_state.cursor1.pos, 1, 'F - test_skip_to_previous_word')
 end
 
 function test_skip_past_tab_to_previous_word()
   io.write('\ntest_skip_past_tab_to_previous_word')
   App.screen.init{width=120, height=60}
-  Lines = load_array{'abc def\tghi'}
-  Cursor1 = {line=1, pos=10}  -- within third word
-  Margin_right = 0; Margin_width = Margin_left
+  Editor_state.lines = load_array{'abc def\tghi'}
+  Editor_state.cursor1 = {line=1, pos=10}  -- within third word
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
   edit.draw()
   App.run_after_keychord('M-left')
-  check_eq(Cursor1.pos, 9, 'F - test_skip_past_tab_to_previous_word')
+  check_eq(Editor_state.cursor1.pos, 9, 'F - test_skip_past_tab_to_previous_word')
 end
 
 function test_skip_multiple_spaces_to_previous_word()
   io.write('\ntest_skip_multiple_spaces_to_previous_word')
   App.screen.init{width=120, height=60}
-  Lines = load_array{'abc  def'}
-  Cursor1 = {line=1, pos=6}  -- at the start of second word
-  Margin_right = 0; Margin_width = Margin_left
+  Editor_state.lines = load_array{'abc  def'}
+  Editor_state.cursor1 = {line=1, pos=6}  -- at the start of second word
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
   edit.draw()
   App.run_after_keychord('M-left')
-  check_eq(Cursor1.pos, 1, 'F - test_skip_multiple_spaces_to_previous_word')
+  check_eq(Editor_state.cursor1.pos, 1, 'F - test_skip_multiple_spaces_to_previous_word')
 end
 
 function test_move_to_start_of_word_on_previous_line()
   io.write('\ntest_move_to_start_of_word_on_previous_line')
   App.screen.init{width=120, height=60}
-  Lines = load_array{'abc def', 'ghi'}
-  Cursor1 = {line=2, pos=1}
-  Margin_right = 0; Margin_width = Margin_left
+  Editor_state.lines = load_array{'abc def', 'ghi'}
+  Editor_state.cursor1 = {line=2, pos=1}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
   edit.draw()
   App.run_after_keychord('M-left')
-  check_eq(Cursor1.line, 1, 'F - test_move_to_start_of_word_on_previous_line/line')
-  check_eq(Cursor1.pos, 5, 'F - test_move_to_start_of_word_on_previous_line/pos')
+  check_eq(Editor_state.cursor1.line, 1, 'F - test_move_to_start_of_word_on_previous_line/line')
+  check_eq(Editor_state.cursor1.pos, 5, 'F - test_move_to_start_of_word_on_previous_line/pos')
 end
 
 function test_move_past_end_of_word()
   io.write('\ntest_move_past_end_of_word')
   App.screen.init{width=120, height=60}
-  Lines = load_array{'abc def'}
-  Cursor1 = {line=1, pos=1}
-  Margin_right = 0; Margin_width = Margin_left
+  Editor_state.lines = load_array{'abc def'}
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
   edit.draw()
   App.run_after_keychord('M-right')
-  check_eq(Cursor1.pos, 4, 'F - test_move_past_end_of_word')
+  check_eq(Editor_state.cursor1.pos, 4, 'F - test_move_past_end_of_word')
 end
 
 function test_skip_to_next_word()
   io.write('\ntest_skip_to_next_word')
   App.screen.init{width=120, height=60}
-  Lines = load_array{'abc def'}
-  Cursor1 = {line=1, pos=4}  -- at the space between words
-  Margin_right = 0; Margin_width = Margin_left
+  Editor_state.lines = load_array{'abc def'}
+  Editor_state.cursor1 = {line=1, pos=4}  -- at the space between words
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
   edit.draw()
   App.run_after_keychord('M-right')
-  check_eq(Cursor1.pos, 8, 'F - test_skip_to_next_word')
+  check_eq(Editor_state.cursor1.pos, 8, 'F - test_skip_to_next_word')
 end
 
 function test_skip_past_tab_to_next_word()
   io.write('\ntest_skip_past_tab_to_next_word')
   App.screen.init{width=120, height=60}
-  Lines = load_array{'abc\tdef'}
-  Cursor1 = {line=1, pos=1}  -- at the space between words
-  Margin_right = 0; Margin_width = Margin_left
+  Editor_state.lines = load_array{'abc\tdef'}
+  Editor_state.cursor1 = {line=1, pos=1}  -- at the space between words
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
   edit.draw()
   App.run_after_keychord('M-right')
-  check_eq(Cursor1.pos, 4, 'F - test_skip_past_tab_to_next_word')
+  check_eq(Editor_state.cursor1.pos, 4, 'F - test_skip_past_tab_to_next_word')
 end
 
 function test_skip_multiple_spaces_to_next_word()
   io.write('\ntest_skip_multiple_spaces_to_next_word')
   App.screen.init{width=120, height=60}
-  Lines = load_array{'abc  def'}
-  Cursor1 = {line=1, pos=4}  -- at the start of second word
-  Margin_right = 0; Margin_width = Margin_left
+  Editor_state.lines = load_array{'abc  def'}
+  Editor_state.cursor1 = {line=1, pos=4}  -- at the start of second word
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
   edit.draw()
   App.run_after_keychord('M-right')
-  check_eq(Cursor1.pos, 9, 'F - test_skip_multiple_spaces_to_next_word')
+  check_eq(Editor_state.cursor1.pos, 9, 'F - test_skip_multiple_spaces_to_next_word')
 end
 
 function test_move_past_end_of_word_on_next_line()
   io.write('\ntest_move_past_end_of_word_on_next_line')
   App.screen.init{width=120, height=60}
-  Lines = load_array{'abc def', 'ghi'}
-  Cursor1 = {line=1, pos=8}
-  Margin_right = 0; Margin_width = Margin_left
+  Editor_state.lines = load_array{'abc def', 'ghi'}
+  Editor_state.cursor1 = {line=1, pos=8}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
   edit.draw()
   App.run_after_keychord('M-right')
-  check_eq(Cursor1.line, 2, 'F - test_move_past_end_of_word_on_next_line/line')
-  check_eq(Cursor1.pos, 4, 'F - test_move_past_end_of_word_on_next_line/pos')
+  check_eq(Editor_state.cursor1.line, 2, 'F - test_move_past_end_of_word_on_next_line/line')
+  check_eq(Editor_state.cursor1.pos, 4, 'F - test_move_past_end_of_word_on_next_line/pos')
 end
 
 function test_click_with_mouse()
   io.write('\ntest_click_with_mouse')
   -- display two lines with cursor on one of them
   App.screen.init{width=50, height=80}
-  Lines = load_array{'abc', 'def'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=2, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc', 'def'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=2, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   -- click on the other line
   edit.draw()
-  App.run_after_mouse_click(Margin_left+8,Margin_top+5, 1)
+  App.run_after_mouse_click(Editor_state.margin_left+8,Editor_state.margin_top+5, 1)
   -- cursor moves
-  check_eq(Cursor1.line, 1, 'F - test_click_with_mouse/cursor')
-  check_nil(Selection1.line, 'F - test_click_with_mouse/selection is empty to avoid perturbing future edits')
+  check_eq(Editor_state.cursor1.line, 1, 'F - test_click_with_mouse/cursor')
+  check_nil(Editor_state.selection1.line, 'F - test_click_with_mouse/selection is empty to avoid perturbing future edits')
 end
 
 function test_click_with_mouse_on_empty_line()
   io.write('\ntest_click_with_mouse_on_empty_line')
   -- display two lines with the first one empty
   App.screen.init{width=50, height=80}
-  Lines = load_array{'', 'def'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=2, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'', 'def'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=2, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   -- click on the empty line
   edit.draw()
-  App.run_after_mouse_click(Margin_left+8,Margin_top+5, 1)
+  App.run_after_mouse_click(Editor_state.margin_left+8,Editor_state.margin_top+5, 1)
   -- cursor moves
-  check_eq(Cursor1.line, 1, 'F - test_click_with_mouse_on_empty_line/cursor')
+  check_eq(Editor_state.cursor1.line, 1, 'F - test_click_with_mouse_on_empty_line/cursor')
 end
 
 function test_draw_text()
   io.write('\ntest_draw_text')
   App.screen.init{width=120, height=60}
-  Lines = load_array{'abc', 'def', 'ghi'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_draw_text/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_draw_text/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi', 'F - test_draw_text/screen:3')
 end
 
 function test_draw_wrapping_text()
   io.write('\ntest_draw_wrapping_text')
   App.screen.init{width=50, height=60}
-  Lines = load_array{'abc', 'defgh', 'xyz'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc', 'defgh', 'xyz'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_draw_wrapping_text/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_draw_wrapping_text/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'gh', 'F - test_draw_wrapping_text/screen:3')
 end
 
 function test_draw_word_wrapping_text()
   io.write('\ntest_draw_word_wrapping_text')
   App.screen.init{width=60, height=60}
-  Lines = load_array{'abc def ghi', 'jkl'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc def ghi', 'jkl'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc ', 'F - test_draw_word_wrapping_text/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def ', 'F - test_draw_word_wrapping_text/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi', 'F - test_draw_word_wrapping_text/screen:3')
 end
 
@@ -319,17 +319,17 @@ function test_draw_text_wrapping_within_word()
   -- arrange a screen line that needs to be split within a word
   io.write('\ntest_draw_text_wrapping_within_word')
   App.screen.init{width=60, height=60}
-  Lines = load_array{'abcd e fghijk', 'xyz'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abcd e fghijk', 'xyz'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abcd ', 'F - test_draw_text_wrapping_within_word/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'e fghi', 'F - test_draw_text_wrapping_within_word/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'jk', 'F - test_draw_text_wrapping_within_word/screen:3')
 end
 
@@ -337,17 +337,17 @@ function test_draw_wrapping_text_containing_non_ascii()
   -- draw a long line containing non-ASCII
   io.write('\ntest_draw_wrapping_text_containing_non_ascii')
   App.screen.init{width=60, height=60}
-  Lines = load_array{'madam I’m adam', 'xyz'}  -- notice the non-ASCII apostrophe
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'madam I’m adam', 'xyz'}  -- notice the non-ASCII apostrophe
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'mada', 'F - test_draw_wrapping_text_containing_non_ascii/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'm I’', 'F - test_draw_wrapping_text_containing_non_ascii/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'm ad', 'F - test_draw_wrapping_text_containing_non_ascii/screen:3')
 end
 
@@ -356,22 +356,22 @@ function test_click_on_wrapping_line()
   -- display a wrapping line
   App.screen.init{width=75, height=80}
                   --  12345678901234
-  Lines = load_array{"madam I'm adam"}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{"madam I'm adam"}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'madam ', 'F - test_click_on_wrapping_line/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, "I'm ada", 'F - test_click_on_wrapping_line/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   -- click past end of second screen line
   App.run_after_mouse_click(App.screen.width-2,y-2, 1)
   -- cursor moves to end of screen line
-  check_eq(Cursor1.line, 1, 'F - test_click_on_wrapping_line/cursor:line')
-  check_eq(Cursor1.pos, 13, 'F - test_click_on_wrapping_line/cursor:pos')
+  check_eq(Editor_state.cursor1.line, 1, 'F - test_click_on_wrapping_line/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 13, 'F - test_click_on_wrapping_line/cursor:pos')
 end
 
 function test_click_on_wrapping_line_rendered_from_partway_at_top_of_screen()
@@ -379,20 +379,20 @@ function test_click_on_wrapping_line_rendered_from_partway_at_top_of_screen()
   -- display a wrapping line from its second screen line
   App.screen.init{width=75, height=80}
                   --  12345678901234
-  Lines = load_array{"madam I'm adam"}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=8}
-  Screen_top1 = {line=1, pos=7}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{"madam I'm adam"}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=8}
+  Editor_state.screen_top1 = {line=1, pos=7}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, "I'm ada", 'F - test_click_on_wrapping_line_rendered_from_partway_at_top_of_screen/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   -- click past end of second screen line
   App.run_after_mouse_click(App.screen.width-2,y-2, 1)
   -- cursor moves to end of screen line
-  check_eq(Cursor1.line, 1, 'F - test_click_on_wrapping_line_rendered_from_partway_at_top_of_screen/cursor:line')
-  check_eq(Cursor1.pos, 13, 'F - test_click_on_wrapping_line_rendered_from_partway_at_top_of_screen/cursor:pos')
+  check_eq(Editor_state.cursor1.line, 1, 'F - test_click_on_wrapping_line_rendered_from_partway_at_top_of_screen/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 13, 'F - test_click_on_wrapping_line_rendered_from_partway_at_top_of_screen/cursor:pos')
 end
 
 function test_click_past_end_of_wrapping_line()
@@ -400,23 +400,23 @@ function test_click_past_end_of_wrapping_line()
   -- display a wrapping line
   App.screen.init{width=75, height=80}
                   --  12345678901234
-  Lines = load_array{"madam I'm adam"}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{"madam I'm adam"}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'madam ', 'F - test_click_past_end_of_wrapping_line/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, "I'm ada", 'F - test_click_past_end_of_wrapping_line/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'm', 'F - test_click_past_end_of_wrapping_line/baseline/screen:3')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   -- click past the end of it
   App.run_after_mouse_click(App.screen.width-2,y-2, 1)
   -- cursor moves to end of line
-  check_eq(Cursor1.pos, 15, 'F - test_click_past_end_of_wrapping_line/cursor')  -- one more than the number of UTF-8 code-points
+  check_eq(Editor_state.cursor1.pos, 15, 'F - test_click_past_end_of_wrapping_line/cursor')  -- one more than the number of UTF-8 code-points
 end
 
 function test_click_on_wrapping_line_containing_non_ascii()
@@ -424,23 +424,23 @@ function test_click_on_wrapping_line_containing_non_ascii()
   -- display a wrapping line containing non-ASCII
   App.screen.init{width=75, height=80}
                   --  12345678901234
-  Lines = load_array{'madam I’m adam'}  -- notice the non-ASCII apostrophe
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'madam I’m adam'}  -- notice the non-ASCII apostrophe
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'madam ', 'F - test_click_on_wrapping_line_containing_non_ascii/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'I’m ada', 'F - test_click_on_wrapping_line_containing_non_ascii/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'm', 'F - test_click_on_wrapping_line_containing_non_ascii/baseline/screen:3')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   -- click past the end of it
   App.run_after_mouse_click(App.screen.width-2,y-2, 1)
   -- cursor moves to end of line
-  check_eq(Cursor1.pos, 15, 'F - test_click_on_wrapping_line_containing_non_ascii/cursor')  -- one more than the number of UTF-8 code-points
+  check_eq(Editor_state.cursor1.pos, 15, 'F - test_click_on_wrapping_line_containing_non_ascii/cursor')  -- one more than the number of UTF-8 code-points
 end
 
 function test_click_past_end_of_word_wrapping_line()
@@ -449,30 +449,30 @@ function test_click_past_end_of_word_wrapping_line()
   App.screen.init{width=160, height=80}
                    -- 0        1         2
                    -- 123456789012345678901
-  Lines = load_array{'the quick brown fox jumped over the lazy dog'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'the quick brown fox jumped over the lazy dog'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'the quick brown fox ', 'F - test_click_past_end_of_word_wrapping_line/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   -- click past the end of the screen line
   App.run_after_mouse_click(App.screen.width-2,y-2, 1)
   -- cursor moves to end of screen line
-  check_eq(Cursor1.pos, 20, 'F - test_click_past_end_of_word_wrapping_line/cursor')
+  check_eq(Editor_state.cursor1.pos, 20, 'F - test_click_past_end_of_word_wrapping_line/cursor')
 end
 
 function test_select_text()
   io.write('\ntest_select_text')
   -- display a line of text
   App.screen.init{width=75, height=80}
-  Lines = load_array{'abc def'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc def'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
   -- select a letter
   App.fake_key_press('lshift')
@@ -480,57 +480,57 @@ function test_select_text()
   App.fake_key_release('lshift')
   App.keyreleased('lshift')
   -- selection persists even after shift is released
-  check_eq(Selection1.line, 1, 'F - test_select_text/selection:line')
-  check_eq(Selection1.pos, 1, 'F - test_select_text/selection:pos')
-  check_eq(Cursor1.line, 1, 'F - test_select_text/cursor:line')
-  check_eq(Cursor1.pos, 2, 'F - test_select_text/cursor:pos')
+  check_eq(Editor_state.selection1.line, 1, 'F - test_select_text/selection:line')
+  check_eq(Editor_state.selection1.pos, 1, 'F - test_select_text/selection:pos')
+  check_eq(Editor_state.cursor1.line, 1, 'F - test_select_text/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 2, 'F - test_select_text/cursor:pos')
 end
 
 function test_cursor_movement_without_shift_resets_selection()
   io.write('\ntest_cursor_movement_without_shift_resets_selection')
   -- display a line of text with some part selected
   App.screen.init{width=75, height=80}
-  Lines = load_array{'abc'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Selection1 = {line=1, pos=2}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.selection1 = {line=1, pos=2}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
   -- press an arrow key without shift
   App.run_after_keychord('right')
   -- no change to data, selection is reset
-  check_nil(Selection1.line, 'F - test_cursor_movement_without_shift_resets_selection')
-  check_eq(Lines[1].data, 'abc', 'F - test_cursor_movement_without_shift_resets_selection/data')
+  check_nil(Editor_state.selection1.line, 'F - test_cursor_movement_without_shift_resets_selection')
+  check_eq(Editor_state.lines[1].data, 'abc', 'F - test_cursor_movement_without_shift_resets_selection/data')
 end
 
 function test_edit_deletes_selection()
   io.write('\ntest_edit_deletes_selection')
   -- display a line of text with some part selected
   App.screen.init{width=75, height=80}
-  Lines = load_array{'abc'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Selection1 = {line=1, pos=2}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.selection1 = {line=1, pos=2}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
   -- press a key
   App.run_after_textinput('x')
   -- selected text is deleted and replaced with the key
-  check_eq(Lines[1].data, 'xbc', 'F - test_edit_deletes_selection')
+  check_eq(Editor_state.lines[1].data, 'xbc', 'F - test_edit_deletes_selection')
 end
 
 function test_edit_with_shift_key_deletes_selection()
   io.write('\ntest_edit_with_shift_key_deletes_selection')
   -- display a line of text with some part selected
   App.screen.init{width=75, height=80}
-  Lines = load_array{'abc'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Selection1 = {line=1, pos=2}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.selection1 = {line=1, pos=2}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
   -- mimic precise keypresses for a capital letter
   App.fake_key_press('lshift')
@@ -539,56 +539,56 @@ function test_edit_with_shift_key_deletes_selection()
   App.keyreleased('d')
   App.fake_key_release('lshift')
   -- selected text is deleted and replaced with the key
-  check_nil(Selection1.line, 'F - test_edit_with_shift_key_deletes_selection')
-  check_eq(Lines[1].data, 'Dbc', 'F - test_edit_with_shift_key_deletes_selection/data')
+  check_nil(Editor_state.selection1.line, 'F - test_edit_with_shift_key_deletes_selection')
+  check_eq(Editor_state.lines[1].data, 'Dbc', 'F - test_edit_with_shift_key_deletes_selection/data')
 end
 
 function test_copy_does_not_reset_selection()
   io.write('\ntest_copy_does_not_reset_selection')
   -- display a line of text with a selection
   App.screen.init{width=75, height=80}
-  Lines = load_array{'abc'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Selection1 = {line=1, pos=2}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.selection1 = {line=1, pos=2}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
   -- copy selection
   App.run_after_keychord('C-c')
   check_eq(App.clipboard, 'a', 'F - test_copy_does_not_reset_selection/clipboard')
   -- selection is reset since shift key is not pressed
-  check(Selection1.line, 'F - test_copy_does_not_reset_selection')
+  check(Editor_state.selection1.line, 'F - test_copy_does_not_reset_selection')
 end
 
 function test_cut()
   io.write('\ntest_cut')
   -- display a line of text with some part selected
   App.screen.init{width=75, height=80}
-  Lines = load_array{'abc'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Selection1 = {line=1, pos=2}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.selection1 = {line=1, pos=2}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
   -- press a key
   App.run_after_keychord('C-x')
   check_eq(App.clipboard, 'a', 'F - test_cut/clipboard')
   -- selected text is deleted
-  check_eq(Lines[1].data, 'bc', 'F - test_cut/data')
+  check_eq(Editor_state.lines[1].data, 'bc', 'F - test_cut/data')
 end
 
 function test_paste_replaces_selection()
   io.write('\ntest_paste_replaces_selection')
   -- display a line of text with a selection
   App.screen.init{width=75, height=80}
-  Lines = load_array{'abc', 'def'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=2, pos=1}
-  Selection1 = {line=1, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc', 'def'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=2, pos=1}
+  Editor_state.selection1 = {line=1, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
   -- set clipboard
   App.clipboard = 'xyz'
@@ -596,259 +596,259 @@ function test_paste_replaces_selection()
   App.run_after_keychord('C-v')
   -- selection is reset since shift key is not pressed
   -- selection includes the newline, so it's also deleted
-  check_eq(Lines[1].data, 'xyzdef', 'F - test_paste_replaces_selection')
+  check_eq(Editor_state.lines[1].data, 'xyzdef', 'F - test_paste_replaces_selection')
 end
 
 function test_deleting_selection_may_scroll()
   io.write('\ntest_deleting_selection_may_scroll')
   -- display lines 2/3/4
   App.screen.init{width=120, height=60}
-  Lines = load_array{'abc', 'def', 'ghi', 'jkl'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=3, pos=2}
-  Screen_top1 = {line=2, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=3, pos=2}
+  Editor_state.screen_top1 = {line=2, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'def', 'F - test_deleting_selection_may_scroll/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi', 'F - test_deleting_selection_may_scroll/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'jkl', 'F - test_deleting_selection_may_scroll/baseline/screen:3')
   -- set up a selection starting above the currently displayed page
-  Selection1 = {line=1, pos=2}
+  Editor_state.selection1 = {line=1, pos=2}
   -- delete selection
   App.run_after_keychord('backspace')
   -- page scrolls up
-  check_eq(Screen_top1.line, 1, 'F - test_deleting_selection_may_scroll')
-  check_eq(Lines[1].data, 'ahi', 'F - test_deleting_selection_may_scroll/data')
+  check_eq(Editor_state.screen_top1.line, 1, 'F - test_deleting_selection_may_scroll')
+  check_eq(Editor_state.lines[1].data, 'ahi', 'F - test_deleting_selection_may_scroll/data')
 end
 
 function test_edit_wrapping_text()
   io.write('\ntest_edit_wrapping_text')
   App.screen.init{width=50, height=60}
-  Lines = load_array{'abc', 'def', 'xyz'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=2, pos=4}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc', 'def', 'xyz'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=2, pos=4}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
   App.run_after_textinput('g')
   App.run_after_textinput('h')
   App.run_after_textinput('i')
   App.run_after_textinput('j')
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_edit_wrapping_text/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_edit_wrapping_text/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghij', 'F - test_edit_wrapping_text/screen:3')
 end
 
 function test_insert_newline()
   io.write('\ntest_insert_newline')
   -- display a few lines
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc', 'def', 'ghi', 'jkl'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=2}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
-  edit.draw()
-  local y = Margin_top
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=2}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
+  edit.draw()
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_insert_newline/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_insert_newline/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi', 'F - test_insert_newline/baseline/screen:3')
   -- hitting the enter key splits the line
   App.run_after_keychord('return')
-  check_eq(Screen_top1.line, 1, 'F - test_insert_newline/screen_top')
-  check_eq(Cursor1.line, 2, 'F - test_insert_newline/cursor:line')
-  check_eq(Cursor1.pos, 1, 'F - test_insert_newline/cursor:pos')
-  y = Margin_top
+  check_eq(Editor_state.screen_top1.line, 1, 'F - test_insert_newline/screen_top')
+  check_eq(Editor_state.cursor1.line, 2, 'F - test_insert_newline/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 1, 'F - test_insert_newline/cursor:pos')
+  y = Editor_state.margin_top
   App.screen.check(y, 'a', 'F - test_insert_newline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'bc', 'F - test_insert_newline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_insert_newline/screen:3')
 end
 
 function test_insert_newline_at_start_of_line()
   io.write('\ntest_insert_newline_at_start_of_line')
   -- display a line
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   -- hitting the enter key splits the line
   App.run_after_keychord('return')
-  check_eq(Cursor1.line, 2, 'F - test_insert_newline_at_start_of_line/cursor:line')
-  check_eq(Cursor1.pos, 1, 'F - test_insert_newline_at_start_of_line/cursor:pos')
-  check_eq(Lines[1].data, '', 'F - test_insert_newline_at_start_of_line/data:1')
-  check_eq(Lines[2].data, 'abc', 'F - test_insert_newline_at_start_of_line/data:2')
+  check_eq(Editor_state.cursor1.line, 2, 'F - test_insert_newline_at_start_of_line/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 1, 'F - test_insert_newline_at_start_of_line/cursor:pos')
+  check_eq(Editor_state.lines[1].data, '', 'F - test_insert_newline_at_start_of_line/data:1')
+  check_eq(Editor_state.lines[2].data, 'abc', 'F - test_insert_newline_at_start_of_line/data:2')
 end
 
 function test_insert_from_clipboard()
   io.write('\ntest_insert_from_clipboard')
   -- display a few lines
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc', 'def', 'ghi', 'jkl'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=2}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
-  edit.draw()
-  local y = Margin_top
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=2}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
+  edit.draw()
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_insert_from_clipboard/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_insert_from_clipboard/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi', 'F - test_insert_from_clipboard/baseline/screen:3')
   -- paste some text including a newline, check that new line is created
   App.clipboard = 'xy\nz'
   App.run_after_keychord('C-v')
-  check_eq(Screen_top1.line, 1, 'F - test_insert_from_clipboard/screen_top')
-  check_eq(Cursor1.line, 2, 'F - test_insert_from_clipboard/cursor:line')
-  check_eq(Cursor1.pos, 2, 'F - test_insert_from_clipboard/cursor:pos')
-  y = Margin_top
+  check_eq(Editor_state.screen_top1.line, 1, 'F - test_insert_from_clipboard/screen_top')
+  check_eq(Editor_state.cursor1.line, 2, 'F - test_insert_from_clipboard/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 2, 'F - test_insert_from_clipboard/cursor:pos')
+  y = Editor_state.margin_top
   App.screen.check(y, 'axy', 'F - test_insert_from_clipboard/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'zbc', 'F - test_insert_from_clipboard/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_insert_from_clipboard/screen:3')
 end
 
 function test_move_cursor_using_mouse()
   io.write('\ntest_move_cursor_using_mouse')
   App.screen.init{width=50, height=60}
-  Lines = load_array{'abc', 'def', 'xyz'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
-  Selection1 = {}
-  edit.draw()  -- populate line.y for each line in Lines
-  App.run_after_mouse_release(Margin_left+8,Margin_top+5, 1)
-  check_eq(Cursor1.line, 1, 'F - test_move_cursor_using_mouse/cursor:line')
-  check_eq(Cursor1.pos, 2, 'F - test_move_cursor_using_mouse/cursor:pos')
-  check_nil(Selection1.line, 'F - test_move_cursor_using_mouse/selection:line')
-  check_nil(Selection1.pos, 'F - test_move_cursor_using_mouse/selection:pos')
+  Editor_state.lines = load_array{'abc', 'def', 'xyz'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
+  Editor_state.selection1 = {}
+  edit.draw()  -- populate line.y for each line in Editor_state.lines
+  App.run_after_mouse_release(Editor_state.margin_left+8,Editor_state.margin_top+5, 1)
+  check_eq(Editor_state.cursor1.line, 1, 'F - test_move_cursor_using_mouse/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 2, 'F - test_move_cursor_using_mouse/cursor:pos')
+  check_nil(Editor_state.selection1.line, 'F - test_move_cursor_using_mouse/selection:line')
+  check_nil(Editor_state.selection1.pos, 'F - test_move_cursor_using_mouse/selection:pos')
 end
 
 function test_select_text_using_mouse()
   io.write('\ntest_select_text_using_mouse')
   App.screen.init{width=50, height=60}
-  Lines = load_array{'abc', 'def', 'xyz'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
-  Selection1 = {}
-  edit.draw()  -- populate line.y for each line in Lines
+  Editor_state.lines = load_array{'abc', 'def', 'xyz'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
+  Editor_state.selection1 = {}
+  edit.draw()  -- populate line.y for each line in Editor_state.lines
   -- press and hold on first location
-  App.run_after_mouse_press(Margin_left+8,Margin_top+5, 1)
+  App.run_after_mouse_press(Editor_state.margin_left+8,Editor_state.margin_top+5, 1)
   -- drag and release somewhere else
-  App.run_after_mouse_release(Margin_left+20,Margin_top+Line_height+5, 1)
-  check_eq(Selection1.line, 1, 'F - test_select_text_using_mouse/selection:line')
-  check_eq(Selection1.pos, 2, 'F - test_select_text_using_mouse/selection:pos')
-  check_eq(Cursor1.line, 2, 'F - test_select_text_using_mouse/cursor:line')
-  check_eq(Cursor1.pos, 4, 'F - test_select_text_using_mouse/cursor:pos')
+  App.run_after_mouse_release(Editor_state.margin_left+20,Editor_state.margin_top+Editor_state.line_height+5, 1)
+  check_eq(Editor_state.selection1.line, 1, 'F - test_select_text_using_mouse/selection:line')
+  check_eq(Editor_state.selection1.pos, 2, 'F - test_select_text_using_mouse/selection:pos')
+  check_eq(Editor_state.cursor1.line, 2, 'F - test_select_text_using_mouse/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 4, 'F - test_select_text_using_mouse/cursor:pos')
 end
 
 function test_select_text_using_mouse_and_shift()
   io.write('\ntest_select_text_using_mouse_and_shift')
   App.screen.init{width=50, height=60}
-  Lines = load_array{'abc', 'def', 'xyz'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
-  Selection1 = {}
-  edit.draw()  -- populate line.y for each line in Lines
+  Editor_state.lines = load_array{'abc', 'def', 'xyz'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
+  Editor_state.selection1 = {}
+  edit.draw()  -- populate line.y for each line in Editor_state.lines
   -- click on first location
-  App.run_after_mouse_press(Margin_left+8,Margin_top+5, 1)
-  App.run_after_mouse_release(Margin_left+8,Margin_top+5, 1)
+  App.run_after_mouse_press(Editor_state.margin_left+8,Editor_state.margin_top+5, 1)
+  App.run_after_mouse_release(Editor_state.margin_left+8,Editor_state.margin_top+5, 1)
   -- hold down shift and click somewhere else
   App.fake_key_press('lshift')
-  App.run_after_mouse_press(Margin_left+20,Margin_top+5, 1)
-  App.run_after_mouse_release(Margin_left+20,Margin_top+Line_height+5, 1)
+  App.run_after_mouse_press(Editor_state.margin_left+20,Editor_state.margin_top+5, 1)
+  App.run_after_mouse_release(Editor_state.margin_left+20,Editor_state.margin_top+Editor_state.line_height+5, 1)
   App.fake_key_release('lshift')
-  check_eq(Selection1.line, 1, 'F - test_select_text_using_mouse_and_shift/selection:line')
-  check_eq(Selection1.pos, 2, 'F - test_select_text_using_mouse_and_shift/selection:pos')
-  check_eq(Cursor1.line, 2, 'F - test_select_text_using_mouse_and_shift/cursor:line')
-  check_eq(Cursor1.pos, 4, 'F - test_select_text_using_mouse_and_shift/cursor:pos')
+  check_eq(Editor_state.selection1.line, 1, 'F - test_select_text_using_mouse_and_shift/selection:line')
+  check_eq(Editor_state.selection1.pos, 2, 'F - test_select_text_using_mouse_and_shift/selection:pos')
+  check_eq(Editor_state.cursor1.line, 2, 'F - test_select_text_using_mouse_and_shift/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 4, 'F - test_select_text_using_mouse_and_shift/cursor:pos')
 end
 
 function test_select_text_repeatedly_using_mouse_and_shift()
   io.write('\ntest_select_text_repeatedly_using_mouse_and_shift')
   App.screen.init{width=50, height=60}
-  Lines = load_array{'abc', 'def', 'xyz'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
-  Selection1 = {}
-  edit.draw()  -- populate line.y for each line in Lines
+  Editor_state.lines = load_array{'abc', 'def', 'xyz'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
+  Editor_state.selection1 = {}
+  edit.draw()  -- populate line.y for each line in Editor_state.lines
   -- click on first location
-  App.run_after_mouse_press(Margin_left+8,Margin_top+5, 1)
-  App.run_after_mouse_release(Margin_left+8,Margin_top+5, 1)
+  App.run_after_mouse_press(Editor_state.margin_left+8,Editor_state.margin_top+5, 1)
+  App.run_after_mouse_release(Editor_state.margin_left+8,Editor_state.margin_top+5, 1)
   -- hold down shift and click on a second location
   App.fake_key_press('lshift')
-  App.run_after_mouse_press(Margin_left+20,Margin_top+5, 1)
-  App.run_after_mouse_release(Margin_left+20,Margin_top+Line_height+5, 1)
+  App.run_after_mouse_press(Editor_state.margin_left+20,Editor_state.margin_top+5, 1)
+  App.run_after_mouse_release(Editor_state.margin_left+20,Editor_state.margin_top+Editor_state.line_height+5, 1)
   -- hold down shift and click at a third location
   App.fake_key_press('lshift')
-  App.run_after_mouse_press(Margin_left+20,Margin_top+5, 1)
-  App.run_after_mouse_release(Margin_left+8,Margin_top+Line_height+5, 1)
+  App.run_after_mouse_press(Editor_state.margin_left+20,Editor_state.margin_top+5, 1)
+  App.run_after_mouse_release(Editor_state.margin_left+8,Editor_state.margin_top+Editor_state.line_height+5, 1)
   App.fake_key_release('lshift')
   -- selection is between first and third location. forget the second location, not the first.
-  check_eq(Selection1.line, 1, 'F - test_select_text_repeatedly_using_mouse_and_shift/selection:line')
-  check_eq(Selection1.pos, 2, 'F - test_select_text_repeatedly_using_mouse_and_shift/selection:pos')
-  check_eq(Cursor1.line, 2, 'F - test_select_text_repeatedly_using_mouse_and_shift/cursor:line')
-  check_eq(Cursor1.pos, 2, 'F - test_select_text_repeatedly_using_mouse_and_shift/cursor:pos')
+  check_eq(Editor_state.selection1.line, 1, 'F - test_select_text_repeatedly_using_mouse_and_shift/selection:line')
+  check_eq(Editor_state.selection1.pos, 2, 'F - test_select_text_repeatedly_using_mouse_and_shift/selection:pos')
+  check_eq(Editor_state.cursor1.line, 2, 'F - test_select_text_repeatedly_using_mouse_and_shift/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 2, 'F - test_select_text_repeatedly_using_mouse_and_shift/cursor:pos')
 end
 
 function test_cut_without_selection()
   io.write('\ntest_cut_without_selection')
   -- display a few lines
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc', 'def', 'ghi', 'jkl'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=2}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
-  Selection1 = {}
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=2}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
+  Editor_state.selection1 = {}
   edit.draw()
   -- try to cut without selecting text
   App.run_after_keychord('C-x')
   -- no crash
-  check_nil(Selection1.line, 'F - test_cut_without_selection')
+  check_nil(Editor_state.selection1.line, 'F - test_cut_without_selection')
 end
 
 function test_pagedown()
   io.write('\ntest_pagedown')
   App.screen.init{width=120, height=45}
-  Lines = load_array{'abc', 'def', 'ghi'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   -- initially the first two lines are displayed
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_pagedown/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_pagedown/baseline/screen:2')
   -- after pagedown the bottom line becomes the top
   App.run_after_keychord('pagedown')
-  check_eq(Screen_top1.line, 2, 'F - test_pagedown/screen_top')
-  check_eq(Cursor1.line, 2, 'F - test_pagedown/cursor')
-  y = Margin_top
+  check_eq(Editor_state.screen_top1.line, 2, 'F - test_pagedown/screen_top')
+  check_eq(Editor_state.cursor1.line, 2, 'F - test_pagedown/cursor')
+  y = Editor_state.margin_top
   App.screen.check(y, 'def', 'F - test_pagedown/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi', 'F - test_pagedown/screen:2')
 end
 
@@ -856,28 +856,28 @@ function test_pagedown_skips_drawings()
   io.write('\ntest_pagedown_skips_drawings')
   -- some lines of text with a drawing intermixed
   local drawing_width = 50
-  App.screen.init{width=Margin_left+drawing_width, height=80}
-  Lines = load_array{'abc',               -- height 15
+  App.screen.init{width=Editor_state.margin_left+drawing_width, height=80}
+  Editor_state.lines = load_array{'abc',               -- height 15
                      '```lines', '```',   -- height 25
                      'def',               -- height 15
                      'ghi'}               -- height 15
-  Margin_right = 0; Margin_width = Margin_left
-  check_eq(Lines[2].mode, 'drawing', 'F - test_pagedown_skips_drawings/baseline/lines')
-  Cursor1 = {line=1, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
-  local drawing_height = Drawing_padding_height + drawing_width/2  -- default
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  check_eq(Editor_state.lines[2].mode, 'drawing', 'F - test_pagedown_skips_drawings/baseline/lines')
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
+  local drawing_height = Editor_state.drawing_padding_height + drawing_width/2  -- default
   -- initially the screen displays the first line and the drawing
   -- 15px margin + 15px line1 + 10px margin + 25px drawing + 10px margin = 75px < screen height 80px
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_pagedown_skips_drawings/baseline/screen:1')
   -- after pagedown the screen draws the drawing up top
   -- 15px margin + 10px margin + 25px drawing + 10px margin + 15px line3 = 75px < screen height 80px
   App.run_after_keychord('pagedown')
-  check_eq(Screen_top1.line, 2, 'F - test_pagedown_skips_drawings/screen_top')
-  check_eq(Cursor1.line, 3, 'F - test_pagedown_skips_drawings/cursor')
-  y = Margin_top + drawing_height
+  check_eq(Editor_state.screen_top1.line, 2, 'F - test_pagedown_skips_drawings/screen_top')
+  check_eq(Editor_state.cursor1.line, 3, 'F - test_pagedown_skips_drawings/cursor')
+  y = Editor_state.margin_top + drawing_height
   App.screen.check(y, 'def', 'F - test_pagedown_skips_drawings/screen:1')
 end
 
@@ -885,86 +885,86 @@ function test_pagedown_often_shows_start_of_wrapping_line()
   io.write('\ntest_pagedown_often_shows_start_of_wrapping_line')
   -- draw a few lines ending in part of a wrapping line
   App.screen.init{width=50, height=60}
-  Lines = load_array{'abc', 'def ghi jkl', 'mno'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc', 'def ghi jkl', 'mno'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_pagedown_often_shows_start_of_wrapping_line/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def ', 'F - test_pagedown_often_shows_start_of_wrapping_line/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi ', 'F - test_pagedown_often_shows_start_of_wrapping_line/baseline/screen:3')
   -- after pagedown we start drawing from the bottom _line_ (multiple screen lines)
   App.run_after_keychord('pagedown')
-  check_eq(Screen_top1.line, 2, 'F - test_pagedown_often_shows_start_of_wrapping_line/screen_top:line')
-  check_eq(Screen_top1.pos, 1, 'F - test_pagedown_often_shows_start_of_wrapping_line/screen_top:pos')
-  check_eq(Cursor1.line, 2, 'F - test_pagedown_often_shows_start_of_wrapping_line/cursor:line')
-  check_eq(Cursor1.pos, 1, 'F - test_pagedown_often_shows_start_of_wrapping_line/cursor:pos')
-  y = Margin_top
+  check_eq(Editor_state.screen_top1.line, 2, 'F - test_pagedown_often_shows_start_of_wrapping_line/screen_top:line')
+  check_eq(Editor_state.screen_top1.pos, 1, 'F - test_pagedown_often_shows_start_of_wrapping_line/screen_top:pos')
+  check_eq(Editor_state.cursor1.line, 2, 'F - test_pagedown_often_shows_start_of_wrapping_line/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 1, 'F - test_pagedown_often_shows_start_of_wrapping_line/cursor:pos')
+  y = Editor_state.margin_top
   App.screen.check(y, 'def ', 'F - test_pagedown_often_shows_start_of_wrapping_line/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi ', 'F - test_pagedown_often_shows_start_of_wrapping_line/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'jkl', 'F - test_pagedown_often_shows_start_of_wrapping_line/screen:3')
 end
 
 function test_pagedown_can_start_from_middle_of_long_wrapping_line()
   io.write('\ntest_pagedown_can_start_from_middle_of_long_wrapping_line')
   -- draw a few lines starting from a very long wrapping line
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc def ghi jkl mno pqr stu vwx yza bcd efg hij', 'XYZ'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=2}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
-  edit.draw()
-  local y = Margin_top
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc def ghi jkl mno pqr stu vwx yza bcd efg hij', 'XYZ'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=2}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
+  edit.draw()
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc ', 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def ', 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi ', 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/baseline/screen:3')
   -- after pagedown we scroll down the very long wrapping line
   App.run_after_keychord('pagedown')
-  check_eq(Screen_top1.line, 1, 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/screen_top:line')
-  check_eq(Screen_top1.pos, 9, 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/screen_top:pos')
-  y = Margin_top
+  check_eq(Editor_state.screen_top1.line, 1, 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/screen_top:line')
+  check_eq(Editor_state.screen_top1.pos, 9, 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/screen_top:pos')
+  y = Editor_state.margin_top
   App.screen.check(y, 'ghi ', 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'jkl m', 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'no ', 'F - test_pagedown_can_start_from_middle_of_long_wrapping_line/screen:3')
 end
 
 function test_down_arrow_moves_cursor()
   io.write('\ntest_down_arrow_moves_cursor')
   App.screen.init{width=120, height=60}
-  Lines = load_array{'abc', 'def', 'ghi', 'jkl'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   -- initially the first three lines are displayed
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_down_arrow_moves_cursor/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_down_arrow_moves_cursor/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi', 'F - test_down_arrow_moves_cursor/baseline/screen:3')
   -- after hitting the down arrow, the cursor moves down by 1 line
   App.run_after_keychord('down')
-  check_eq(Screen_top1.line, 1, 'F - test_down_arrow_moves_cursor/screen_top')
-  check_eq(Cursor1.line, 2, 'F - test_down_arrow_moves_cursor/cursor')
+  check_eq(Editor_state.screen_top1.line, 1, 'F - test_down_arrow_moves_cursor/screen_top')
+  check_eq(Editor_state.cursor1.line, 2, 'F - test_down_arrow_moves_cursor/cursor')
   -- the screen is unchanged
-  y = Margin_top
+  y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_down_arrow_moves_cursor/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_down_arrow_moves_cursor/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi', 'F - test_down_arrow_moves_cursor/screen:3')
 end
 
@@ -972,118 +972,118 @@ function test_down_arrow_scrolls_down_by_one_line()
   io.write('\ntest_down_arrow_scrolls_down_by_one_line')
   -- display the first three lines with the cursor on the bottom line
   App.screen.init{width=120, height=60}
-  Lines = load_array{'abc', 'def', 'ghi', 'jkl'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=3, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=3, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_down_arrow_scrolls_down_by_one_line/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_down_arrow_scrolls_down_by_one_line/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi', 'F - test_down_arrow_scrolls_down_by_one_line/baseline/screen:3')
   -- after hitting the down arrow the screen scrolls down by one line
   App.run_after_keychord('down')
-  check_eq(Screen_top1.line, 2, 'F - test_down_arrow_scrolls_down_by_one_line/screen_top')
-  check_eq(Cursor1.line, 4, 'F - test_down_arrow_scrolls_down_by_one_line/cursor')
-  y = Margin_top
+  check_eq(Editor_state.screen_top1.line, 2, 'F - test_down_arrow_scrolls_down_by_one_line/screen_top')
+  check_eq(Editor_state.cursor1.line, 4, 'F - test_down_arrow_scrolls_down_by_one_line/cursor')
+  y = Editor_state.margin_top
   App.screen.check(y, 'def', 'F - test_down_arrow_scrolls_down_by_one_line/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi', 'F - test_down_arrow_scrolls_down_by_one_line/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'jkl', 'F - test_down_arrow_scrolls_down_by_one_line/screen:3')
 end
 
 function test_down_arrow_scrolls_down_by_one_screen_line()
   io.write('\ntest_down_arrow_scrolls_down_by_one_screen_line')
   -- display the first three lines with the cursor on the bottom line
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc', 'def', 'ghi jkl', 'mno'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=3, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
-  edit.draw()
-  local y = Margin_top
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi jkl', 'mno'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=3, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
+  edit.draw()
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_down_arrow_scrolls_down_by_one_screen_line/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_down_arrow_scrolls_down_by_one_screen_line/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi ', 'F - test_down_arrow_scrolls_down_by_one_screen_line/baseline/screen:3')  -- line wrapping includes trailing whitespace
   -- after hitting the down arrow the screen scrolls down by one line
   App.run_after_keychord('down')
-  check_eq(Screen_top1.line, 2, 'F - test_down_arrow_scrolls_down_by_one_screen_line/screen_top')
-  check_eq(Cursor1.line, 3, 'F - test_down_arrow_scrolls_down_by_one_screen_line/cursor:line')
-  check_eq(Cursor1.pos, 5, 'F - test_down_arrow_scrolls_down_by_one_screen_line/cursor:pos')
-  y = Margin_top
+  check_eq(Editor_state.screen_top1.line, 2, 'F - test_down_arrow_scrolls_down_by_one_screen_line/screen_top')
+  check_eq(Editor_state.cursor1.line, 3, 'F - test_down_arrow_scrolls_down_by_one_screen_line/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 5, 'F - test_down_arrow_scrolls_down_by_one_screen_line/cursor:pos')
+  y = Editor_state.margin_top
   App.screen.check(y, 'def', 'F - test_down_arrow_scrolls_down_by_one_screen_line/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi ', 'F - test_down_arrow_scrolls_down_by_one_screen_line/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'jkl', 'F - test_down_arrow_scrolls_down_by_one_screen_line/screen:3')
 end
 
 function test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word()
   io.write('\ntest_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word')
   -- display the first three lines with the cursor on the bottom line
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc', 'def', 'ghijkl', 'mno'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=3, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
-  edit.draw()
-  local y = Margin_top
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc', 'def', 'ghijkl', 'mno'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=3, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
+  edit.draw()
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghijk', 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/baseline/screen:3')
   -- after hitting the down arrow the screen scrolls down by one line
   App.run_after_keychord('down')
-  check_eq(Screen_top1.line, 2, 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/screen_top')
-  check_eq(Cursor1.line, 3, 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/cursor:line')
-  check_eq(Cursor1.pos, 6, 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/cursor:pos')
-  y = Margin_top
+  check_eq(Editor_state.screen_top1.line, 2, 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/screen_top')
+  check_eq(Editor_state.cursor1.line, 3, 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 6, 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/cursor:pos')
+  y = Editor_state.margin_top
   App.screen.check(y, 'def', 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghijk', 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'l', 'F - test_down_arrow_scrolls_down_by_one_screen_line_after_splitting_within_word/screen:3')
 end
 
 function test_page_down_followed_by_down_arrow_does_not_scroll_screen_up()
   io.write('\ntest_page_down_followed_by_down_arrow_does_not_scroll_screen_up')
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc', 'def', 'ghijkl', 'mno'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=3, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
-  edit.draw()
-  local y = Margin_top
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc', 'def', 'ghijkl', 'mno'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=3, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
+  edit.draw()
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghijk', 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/baseline/screen:3')
   -- after hitting pagedown the screen scrolls down to start of a long line
   App.run_after_keychord('pagedown')
-  check_eq(Screen_top1.line, 3, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/baseline2/screen_top')
-  check_eq(Cursor1.line, 3, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/baseline2/cursor:line')
-  check_eq(Cursor1.pos, 1, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/baseline2/cursor:pos')
+  check_eq(Editor_state.screen_top1.line, 3, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/baseline2/screen_top')
+  check_eq(Editor_state.cursor1.line, 3, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/baseline2/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 1, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/baseline2/cursor:pos')
   -- after hitting down arrow the screen doesn't scroll down further, and certainly doesn't scroll up
   App.run_after_keychord('down')
-  check_eq(Screen_top1.line, 3, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/screen_top')
-  check_eq(Cursor1.line, 3, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/cursor:line')
-  check_eq(Cursor1.pos, 6, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/cursor:pos')
-  y = Margin_top
+  check_eq(Editor_state.screen_top1.line, 3, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/screen_top')
+  check_eq(Editor_state.cursor1.line, 3, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 6, 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/cursor:pos')
+  y = Editor_state.margin_top
   App.screen.check(y, 'ghijk', 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'l', 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'mno', 'F - test_page_down_followed_by_down_arrow_does_not_scroll_screen_up/screen:3')
 end
 
@@ -1091,28 +1091,28 @@ function test_up_arrow_moves_cursor()
   io.write('\ntest_up_arrow_moves_cursor')
   -- display the first 3 lines with the cursor on the bottom line
   App.screen.init{width=120, height=60}
-  Lines = load_array{'abc', 'def', 'ghi', 'jkl'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=3, pos=1}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=3, pos=1}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_up_arrow_moves_cursor/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_up_arrow_moves_cursor/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi', 'F - test_up_arrow_moves_cursor/baseline/screen:3')
   -- after hitting the up arrow the cursor moves up by 1 line
   App.run_after_keychord('up')
-  check_eq(Screen_top1.line, 1, 'F - test_up_arrow_moves_cursor/screen_top')
-  check_eq(Cursor1.line, 2, 'F - test_up_arrow_moves_cursor/cursor')
+  check_eq(Editor_state.screen_top1.line, 1, 'F - test_up_arrow_moves_cursor/screen_top')
+  check_eq(Editor_state.cursor1.line, 2, 'F - test_up_arrow_moves_cursor/cursor')
   -- the screen is unchanged
-  y = Margin_top
+  y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_up_arrow_moves_cursor/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_up_arrow_moves_cursor/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi', 'F - test_up_arrow_moves_cursor/screen:3')
 end
 
@@ -1120,413 +1120,413 @@ function test_up_arrow_scrolls_up_by_one_line()
   io.write('\ntest_up_arrow_scrolls_up_by_one_line')
   -- display the lines 2/3/4 with the cursor on line 2
   App.screen.init{width=120, height=60}
-  Lines = load_array{'abc', 'def', 'ghi', 'jkl'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=2, pos=1}
-  Screen_top1 = {line=2, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=2, pos=1}
+  Editor_state.screen_top1 = {line=2, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'def', 'F - test_up_arrow_scrolls_up_by_one_line/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi', 'F - test_up_arrow_scrolls_up_by_one_line/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'jkl', 'F - test_up_arrow_scrolls_up_by_one_line/baseline/screen:3')
   -- after hitting the up arrow the screen scrolls up by one line
   App.run_after_keychord('up')
-  check_eq(Screen_top1.line, 1, 'F - test_up_arrow_scrolls_up_by_one_line/screen_top')
-  check_eq(Cursor1.line, 1, 'F - test_up_arrow_scrolls_up_by_one_line/cursor')
-  y = Margin_top
+  check_eq(Editor_state.screen_top1.line, 1, 'F - test_up_arrow_scrolls_up_by_one_line/screen_top')
+  check_eq(Editor_state.cursor1.line, 1, 'F - test_up_arrow_scrolls_up_by_one_line/cursor')
+  y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_up_arrow_scrolls_up_by_one_line/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_up_arrow_scrolls_up_by_one_line/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi', 'F - test_up_arrow_scrolls_up_by_one_line/screen:3')
 end
 
 function test_up_arrow_scrolls_up_by_one_screen_line()
   io.write('\ntest_up_arrow_scrolls_up_by_one_screen_line')
   -- display lines starting from second screen line of a line
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc', 'def', 'ghi jkl', 'mno'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=3, pos=6}
-  Screen_top1 = {line=3, pos=5}
-  Screen_bottom1 = {}
-  edit.draw()
-  local y = Margin_top
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi jkl', 'mno'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=3, pos=6}
+  Editor_state.screen_top1 = {line=3, pos=5}
+  Editor_state.screen_bottom1 = {}
+  edit.draw()
+  local y = Editor_state.margin_top
   App.screen.check(y, 'jkl', 'F - test_up_arrow_scrolls_up_by_one_screen_line/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'mno', 'F - test_up_arrow_scrolls_up_by_one_screen_line/baseline/screen:2')
   -- after hitting the up arrow the screen scrolls up to first screen line
   App.run_after_keychord('up')
-  y = Margin_top
+  y = Editor_state.margin_top
   App.screen.check(y, 'ghi ', 'F - test_up_arrow_scrolls_up_by_one_screen_line/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'jkl', 'F - test_up_arrow_scrolls_up_by_one_screen_line/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'mno', 'F - test_up_arrow_scrolls_up_by_one_screen_line/screen:3')
-  check_eq(Screen_top1.line, 3, 'F - test_up_arrow_scrolls_up_by_one_screen_line/screen_top')
-  check_eq(Screen_top1.pos, 1, 'F - test_up_arrow_scrolls_up_by_one_screen_line/screen_top')
-  check_eq(Cursor1.line, 3, 'F - test_up_arrow_scrolls_up_by_one_screen_line/cursor:line')
-  check_eq(Cursor1.pos, 1, 'F - test_up_arrow_scrolls_up_by_one_screen_line/cursor:pos')
+  check_eq(Editor_state.screen_top1.line, 3, 'F - test_up_arrow_scrolls_up_by_one_screen_line/screen_top')
+  check_eq(Editor_state.screen_top1.pos, 1, 'F - test_up_arrow_scrolls_up_by_one_screen_line/screen_top')
+  check_eq(Editor_state.cursor1.line, 3, 'F - test_up_arrow_scrolls_up_by_one_screen_line/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 1, 'F - test_up_arrow_scrolls_up_by_one_screen_line/cursor:pos')
 end
 
 function test_up_arrow_scrolls_up_to_final_screen_line()
   io.write('\ntest_up_arrow_scrolls_up_to_final_screen_line')
   -- display lines starting just after a long line
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc def', 'ghi', 'jkl', 'mno'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=2, pos=1}
-  Screen_top1 = {line=2, pos=1}
-  Screen_bottom1 = {}
-  edit.draw()
-  local y = Margin_top
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc def', 'ghi', 'jkl', 'mno'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=2, pos=1}
+  Editor_state.screen_top1 = {line=2, pos=1}
+  Editor_state.screen_bottom1 = {}
+  edit.draw()
+  local y = Editor_state.margin_top
   App.screen.check(y, 'ghi', 'F - test_up_arrow_scrolls_up_to_final_screen_line/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'jkl', 'F - test_up_arrow_scrolls_up_to_final_screen_line/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'mno', 'F - test_up_arrow_scrolls_up_to_final_screen_line/baseline/screen:3')
   -- after hitting the up arrow the screen scrolls up to final screen line of previous line
   App.run_after_keychord('up')
-  y = Margin_top
+  y = Editor_state.margin_top
   App.screen.check(y, 'def', 'F - test_up_arrow_scrolls_up_to_final_screen_line/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi', 'F - test_up_arrow_scrolls_up_to_final_screen_line/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'jkl', 'F - test_up_arrow_scrolls_up_to_final_screen_line/screen:3')
-  check_eq(Screen_top1.line, 1, 'F - test_up_arrow_scrolls_up_to_final_screen_line/screen_top')
-  check_eq(Screen_top1.pos, 5, 'F - test_up_arrow_scrolls_up_to_final_screen_line/screen_top')
-  check_eq(Cursor1.line, 1, 'F - test_up_arrow_scrolls_up_to_final_screen_line/cursor:line')
-  check_eq(Cursor1.pos, 5, 'F - test_up_arrow_scrolls_up_to_final_screen_line/cursor:pos')
+  check_eq(Editor_state.screen_top1.line, 1, 'F - test_up_arrow_scrolls_up_to_final_screen_line/screen_top')
+  check_eq(Editor_state.screen_top1.pos, 5, 'F - test_up_arrow_scrolls_up_to_final_screen_line/screen_top')
+  check_eq(Editor_state.cursor1.line, 1, 'F - test_up_arrow_scrolls_up_to_final_screen_line/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 5, 'F - test_up_arrow_scrolls_up_to_final_screen_line/cursor:pos')
 end
 
 function test_up_arrow_scrolls_up_to_empty_line()
   io.write('\ntest_up_arrow_scrolls_up_to_empty_line')
   -- display a screenful of text with an empty line just above it outside the screen
   App.screen.init{width=120, height=60}
-  Lines = load_array{'', 'abc', 'def', 'ghi', 'jkl'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=2, pos=1}
-  Screen_top1 = {line=2, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'', 'abc', 'def', 'ghi', 'jkl'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=2, pos=1}
+  Editor_state.screen_top1 = {line=2, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_up_arrow_scrolls_up_to_empty_line/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_up_arrow_scrolls_up_to_empty_line/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi', 'F - test_up_arrow_scrolls_up_to_empty_line/baseline/screen:3')
   -- after hitting the up arrow the screen scrolls up by one line
   App.run_after_keychord('up')
-  check_eq(Screen_top1.line, 1, 'F - test_up_arrow_scrolls_up_to_empty_line/screen_top')
-  check_eq(Cursor1.line, 1, 'F - test_up_arrow_scrolls_up_to_empty_line/cursor')
-  y = Margin_top
+  check_eq(Editor_state.screen_top1.line, 1, 'F - test_up_arrow_scrolls_up_to_empty_line/screen_top')
+  check_eq(Editor_state.cursor1.line, 1, 'F - test_up_arrow_scrolls_up_to_empty_line/cursor')
+  y = Editor_state.margin_top
   -- empty first line
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'abc', 'F - test_up_arrow_scrolls_up_to_empty_line/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_up_arrow_scrolls_up_to_empty_line/screen:3')
 end
 
 function test_pageup()
   io.write('\ntest_pageup')
   App.screen.init{width=120, height=45}
-  Lines = load_array{'abc', 'def', 'ghi'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=2, pos=1}
-  Screen_top1 = {line=2, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=2, pos=1}
+  Editor_state.screen_top1 = {line=2, pos=1}
+  Editor_state.screen_bottom1 = {}
   -- initially the last two lines are displayed
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'def', 'F - test_pageup/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi', 'F - test_pageup/baseline/screen:2')
   -- after pageup the cursor goes to first line
   App.run_after_keychord('pageup')
-  check_eq(Screen_top1.line, 1, 'F - test_pageup/screen_top')
-  check_eq(Cursor1.line, 1, 'F - test_pageup/cursor')
-  y = Margin_top
+  check_eq(Editor_state.screen_top1.line, 1, 'F - test_pageup/screen_top')
+  check_eq(Editor_state.cursor1.line, 1, 'F - test_pageup/cursor')
+  y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_pageup/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_pageup/screen:2')
 end
 
 function test_pageup_scrolls_up_by_screen_line()
   io.write('\ntest_pageup_scrolls_up_by_screen_line')
   -- display the first three lines with the cursor on the bottom line
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc def', 'ghi', 'jkl', 'mno'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=2, pos=1}
-  Screen_top1 = {line=2, pos=1}
-  Screen_bottom1 = {}
-  edit.draw()
-  local y = Margin_top
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc def', 'ghi', 'jkl', 'mno'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=2, pos=1}
+  Editor_state.screen_top1 = {line=2, pos=1}
+  Editor_state.screen_bottom1 = {}
+  edit.draw()
+  local y = Editor_state.margin_top
   App.screen.check(y, 'ghi', 'F - test_pageup_scrolls_up_by_screen_line/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'jkl', 'F - test_pageup_scrolls_up_by_screen_line/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'mno', 'F - test_pageup_scrolls_up_by_screen_line/baseline/screen:3')  -- line wrapping includes trailing whitespace
   -- after hitting the page-up key the screen scrolls up to top
   App.run_after_keychord('pageup')
-  check_eq(Screen_top1.line, 1, 'F - test_pageup_scrolls_up_by_screen_line/screen_top')
-  check_eq(Cursor1.line, 1, 'F - test_pageup_scrolls_up_by_screen_line/cursor:line')
-  check_eq(Cursor1.pos, 1, 'F - test_pageup_scrolls_up_by_screen_line/cursor:pos')
-  y = Margin_top
+  check_eq(Editor_state.screen_top1.line, 1, 'F - test_pageup_scrolls_up_by_screen_line/screen_top')
+  check_eq(Editor_state.cursor1.line, 1, 'F - test_pageup_scrolls_up_by_screen_line/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 1, 'F - test_pageup_scrolls_up_by_screen_line/cursor:pos')
+  y = Editor_state.margin_top
   App.screen.check(y, 'abc ', 'F - test_pageup_scrolls_up_by_screen_line/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_pageup_scrolls_up_by_screen_line/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi', 'F - test_pageup_scrolls_up_by_screen_line/screen:3')
 end
 
 function test_pageup_scrolls_up_from_middle_screen_line()
   io.write('\ntest_pageup_scrolls_up_from_middle_screen_line')
-  -- display a few lines starting from the middle of a line (Cursor1.pos > 1)
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc def', 'ghi jkl', 'mno'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=2, pos=5}
-  Screen_top1 = {line=2, pos=5}
-  Screen_bottom1 = {}
-  edit.draw()
-  local y = Margin_top
+  -- display a few lines starting from the middle of a line (Editor_state.cursor1.pos > 1)
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc def', 'ghi jkl', 'mno'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=2, pos=5}
+  Editor_state.screen_top1 = {line=2, pos=5}
+  Editor_state.screen_bottom1 = {}
+  edit.draw()
+  local y = Editor_state.margin_top
   App.screen.check(y, 'jkl', 'F - test_pageup_scrolls_up_from_middle_screen_line/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'mno', 'F - test_pageup_scrolls_up_from_middle_screen_line/baseline/screen:3')  -- line wrapping includes trailing whitespace
   -- after hitting the page-up key the screen scrolls up to top
   App.run_after_keychord('pageup')
-  check_eq(Screen_top1.line, 1, 'F - test_pageup_scrolls_up_from_middle_screen_line/screen_top')
-  check_eq(Cursor1.line, 1, 'F - test_pageup_scrolls_up_from_middle_screen_line/cursor:line')
-  check_eq(Cursor1.pos, 1, 'F - test_pageup_scrolls_up_from_middle_screen_line/cursor:pos')
-  y = Margin_top
+  check_eq(Editor_state.screen_top1.line, 1, 'F - test_pageup_scrolls_up_from_middle_screen_line/screen_top')
+  check_eq(Editor_state.cursor1.line, 1, 'F - test_pageup_scrolls_up_from_middle_screen_line/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 1, 'F - test_pageup_scrolls_up_from_middle_screen_line/cursor:pos')
+  y = Editor_state.margin_top
   App.screen.check(y, 'abc ', 'F - test_pageup_scrolls_up_from_middle_screen_line/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_pageup_scrolls_up_from_middle_screen_line/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi ', 'F - test_pageup_scrolls_up_from_middle_screen_line/screen:3')
 end
 
 function test_enter_on_bottom_line_scrolls_down()
   io.write('\ntest_enter_on_bottom_line_scrolls_down')
   -- display a few lines with cursor on bottom line
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc', 'def', 'ghi', 'jkl'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=3, pos=2}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
-  edit.draw()
-  local y = Margin_top
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=3, pos=2}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
+  edit.draw()
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_enter_on_bottom_line_scrolls_down/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_enter_on_bottom_line_scrolls_down/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi', 'F - test_enter_on_bottom_line_scrolls_down/baseline/screen:3')
   -- after hitting the enter key the screen scrolls down
   App.run_after_keychord('return')
-  check_eq(Screen_top1.line, 2, 'F - test_enter_on_bottom_line_scrolls_down/screen_top')
-  check_eq(Cursor1.line, 4, 'F - test_enter_on_bottom_line_scrolls_down/cursor:line')
-  check_eq(Cursor1.pos, 1, 'F - test_enter_on_bottom_line_scrolls_down/cursor:pos')
-  y = Margin_top
+  check_eq(Editor_state.screen_top1.line, 2, 'F - test_enter_on_bottom_line_scrolls_down/screen_top')
+  check_eq(Editor_state.cursor1.line, 4, 'F - test_enter_on_bottom_line_scrolls_down/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 1, 'F - test_enter_on_bottom_line_scrolls_down/cursor:pos')
+  y = Editor_state.margin_top
   App.screen.check(y, 'def', 'F - test_enter_on_bottom_line_scrolls_down/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'g', 'F - test_enter_on_bottom_line_scrolls_down/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'hi', 'F - test_enter_on_bottom_line_scrolls_down/screen:3')
 end
 
 function test_enter_on_final_line_avoids_scrolling_down_when_not_at_bottom()
   io.write('\ntest_enter_on_final_line_avoids_scrolling_down_when_not_at_bottom')
   -- display just the bottom line on screen
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc', 'def', 'ghi', 'jkl'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=4, pos=2}
-  Screen_top1 = {line=4, pos=1}
-  Screen_bottom1 = {}
-  edit.draw()
-  local y = Margin_top
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=4, pos=2}
+  Editor_state.screen_top1 = {line=4, pos=1}
+  Editor_state.screen_bottom1 = {}
+  edit.draw()
+  local y = Editor_state.margin_top
   App.screen.check(y, 'jkl', 'F - test_enter_on_final_line_avoids_scrolling_down_when_not_at_bottom/baseline/screen:1')
   -- after hitting the enter key the screen does not scroll down
   App.run_after_keychord('return')
-  check_eq(Screen_top1.line, 4, 'F - test_enter_on_final_line_avoids_scrolling_down_when_not_at_bottom/screen_top')
-  check_eq(Cursor1.line, 5, 'F - test_enter_on_final_line_avoids_scrolling_down_when_not_at_bottom/cursor:line')
-  check_eq(Cursor1.pos, 1, 'F - test_enter_on_final_line_avoids_scrolling_down_when_not_at_bottom/cursor:pos')
-  y = Margin_top
+  check_eq(Editor_state.screen_top1.line, 4, 'F - test_enter_on_final_line_avoids_scrolling_down_when_not_at_bottom/screen_top')
+  check_eq(Editor_state.cursor1.line, 5, 'F - test_enter_on_final_line_avoids_scrolling_down_when_not_at_bottom/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 1, 'F - test_enter_on_final_line_avoids_scrolling_down_when_not_at_bottom/cursor:pos')
+  y = Editor_state.margin_top
   App.screen.check(y, 'j', 'F - test_enter_on_final_line_avoids_scrolling_down_when_not_at_bottom/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'kl', 'F - test_enter_on_final_line_avoids_scrolling_down_when_not_at_bottom/screen:2')
 end
 
 function test_inserting_text_on_final_line_avoids_scrolling_down_when_not_at_bottom()
   io.write('\ntest_inserting_text_on_final_line_avoids_scrolling_down_when_not_at_bottom')
   -- display just an empty bottom line on screen
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc', ''}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=2, pos=1}
-  Screen_top1 = {line=2, pos=1}
-  Screen_bottom1 = {}
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc', ''}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=2, pos=1}
+  Editor_state.screen_top1 = {line=2, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
   -- after hitting the inserting_text key the screen does not scroll down
   App.run_after_textinput('a')
-  check_eq(Screen_top1.line, 2, 'F - test_inserting_text_on_final_line_avoids_scrolling_down_when_not_at_bottom/screen_top')
-  check_eq(Cursor1.line, 2, 'F - test_inserting_text_on_final_line_avoids_scrolling_down_when_not_at_bottom/cursor:line')
-  check_eq(Cursor1.pos, 2, 'F - test_inserting_text_on_final_line_avoids_scrolling_down_when_not_at_bottom/cursor:pos')
-  local y = Margin_top
+  check_eq(Editor_state.screen_top1.line, 2, 'F - test_inserting_text_on_final_line_avoids_scrolling_down_when_not_at_bottom/screen_top')
+  check_eq(Editor_state.cursor1.line, 2, 'F - test_inserting_text_on_final_line_avoids_scrolling_down_when_not_at_bottom/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 2, 'F - test_inserting_text_on_final_line_avoids_scrolling_down_when_not_at_bottom/cursor:pos')
+  local y = Editor_state.margin_top
   App.screen.check(y, 'a', 'F - test_inserting_text_on_final_line_avoids_scrolling_down_when_not_at_bottom/screen:1')
 end
 
 function test_typing_on_bottom_line_scrolls_down()
   io.write('\ntest_typing_on_bottom_line_scrolls_down')
   -- display a few lines with cursor on bottom line
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc', 'def', 'ghi', 'jkl'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=3, pos=4}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
-  edit.draw()
-  local y = Margin_top
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=3, pos=4}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
+  edit.draw()
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_typing_on_bottom_line_scrolls_down/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_typing_on_bottom_line_scrolls_down/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi', 'F - test_typing_on_bottom_line_scrolls_down/baseline/screen:3')
   -- after typing something the line wraps and the screen scrolls down
   App.run_after_textinput('j')
   App.run_after_textinput('k')
   App.run_after_textinput('l')
-  check_eq(Screen_top1.line, 2, 'F - test_typing_on_bottom_line_scrolls_down/screen_top')
-  check_eq(Cursor1.line, 3, 'F - test_typing_on_bottom_line_scrolls_down/cursor:line')
-  check_eq(Cursor1.pos, 7, 'F - test_typing_on_bottom_line_scrolls_down/cursor:pos')
-  y = Margin_top
+  check_eq(Editor_state.screen_top1.line, 2, 'F - test_typing_on_bottom_line_scrolls_down/screen_top')
+  check_eq(Editor_state.cursor1.line, 3, 'F - test_typing_on_bottom_line_scrolls_down/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 7, 'F - test_typing_on_bottom_line_scrolls_down/cursor:pos')
+  y = Editor_state.margin_top
   App.screen.check(y, 'def', 'F - test_typing_on_bottom_line_scrolls_down/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghijk', 'F - test_typing_on_bottom_line_scrolls_down/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'l', 'F - test_typing_on_bottom_line_scrolls_down/screen:3')
 end
 
 function test_left_arrow_scrolls_up_in_wrapped_line()
   io.write('\ntest_left_arrow_scrolls_up_in_wrapped_line')
   -- display lines starting from second screen line of a line
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc', 'def', 'ghi jkl', 'mno'}
-  Margin_right = 0; Margin_width = Margin_left
-  Screen_top1 = {line=3, pos=5}
-  Screen_bottom1 = {}
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi jkl', 'mno'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.screen_top1 = {line=3, pos=5}
+  Editor_state.screen_bottom1 = {}
   -- cursor is at top of screen
-  Cursor1 = {line=3, pos=5}
+  Editor_state.cursor1 = {line=3, pos=5}
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'jkl', 'F - test_left_arrow_scrolls_up_in_wrapped_line/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'mno', 'F - test_left_arrow_scrolls_up_in_wrapped_line/baseline/screen:2')
   -- after hitting the left arrow the screen scrolls up to first screen line
   App.run_after_keychord('left')
-  y = Margin_top
+  y = Editor_state.margin_top
   App.screen.check(y, 'ghi ', 'F - test_left_arrow_scrolls_up_in_wrapped_line/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'jkl', 'F - test_left_arrow_scrolls_up_in_wrapped_line/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'mno', 'F - test_left_arrow_scrolls_up_in_wrapped_line/screen:3')
-  check_eq(Screen_top1.line, 3, 'F - test_left_arrow_scrolls_up_in_wrapped_line/screen_top')
-  check_eq(Screen_top1.pos, 1, 'F - test_left_arrow_scrolls_up_in_wrapped_line/screen_top')
-  check_eq(Cursor1.line, 3, 'F - test_left_arrow_scrolls_up_in_wrapped_line/cursor:line')
-  check_eq(Cursor1.pos, 4, 'F - test_left_arrow_scrolls_up_in_wrapped_line/cursor:pos')
+  check_eq(Editor_state.screen_top1.line, 3, 'F - test_left_arrow_scrolls_up_in_wrapped_line/screen_top')
+  check_eq(Editor_state.screen_top1.pos, 1, 'F - test_left_arrow_scrolls_up_in_wrapped_line/screen_top')
+  check_eq(Editor_state.cursor1.line, 3, 'F - test_left_arrow_scrolls_up_in_wrapped_line/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 4, 'F - test_left_arrow_scrolls_up_in_wrapped_line/cursor:pos')
 end
 
 function test_right_arrow_scrolls_down_in_wrapped_line()
   io.write('\ntest_right_arrow_scrolls_down_in_wrapped_line')
   -- display the first three lines with the cursor on the bottom line
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc', 'def', 'ghi jkl', 'mno'}
-  Margin_right = 0; Margin_width = Margin_left
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi jkl', 'mno'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   -- cursor is at bottom right of screen
-  Cursor1 = {line=3, pos=5}
+  Editor_state.cursor1 = {line=3, pos=5}
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_right_arrow_scrolls_down_in_wrapped_line/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_right_arrow_scrolls_down_in_wrapped_line/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi ', 'F - test_right_arrow_scrolls_down_in_wrapped_line/baseline/screen:3')  -- line wrapping includes trailing whitespace
   -- after hitting the right arrow the screen scrolls down by one line
   App.run_after_keychord('right')
-  check_eq(Screen_top1.line, 2, 'F - test_right_arrow_scrolls_down_in_wrapped_line/screen_top')
-  check_eq(Cursor1.line, 3, 'F - test_right_arrow_scrolls_down_in_wrapped_line/cursor:line')
-  check_eq(Cursor1.pos, 6, 'F - test_right_arrow_scrolls_down_in_wrapped_line/cursor:pos')
-  y = Margin_top
+  check_eq(Editor_state.screen_top1.line, 2, 'F - test_right_arrow_scrolls_down_in_wrapped_line/screen_top')
+  check_eq(Editor_state.cursor1.line, 3, 'F - test_right_arrow_scrolls_down_in_wrapped_line/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 6, 'F - test_right_arrow_scrolls_down_in_wrapped_line/cursor:pos')
+  y = Editor_state.margin_top
   App.screen.check(y, 'def', 'F - test_right_arrow_scrolls_down_in_wrapped_line/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi ', 'F - test_right_arrow_scrolls_down_in_wrapped_line/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'jkl', 'F - test_right_arrow_scrolls_down_in_wrapped_line/screen:3')
 end
 
 function test_home_scrolls_up_in_wrapped_line()
   io.write('\ntest_home_scrolls_up_in_wrapped_line')
   -- display lines starting from second screen line of a line
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc', 'def', 'ghi jkl', 'mno'}
-  Margin_right = 0; Margin_width = Margin_left
-  Screen_top1 = {line=3, pos=5}
-  Screen_bottom1 = {}
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi jkl', 'mno'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.screen_top1 = {line=3, pos=5}
+  Editor_state.screen_bottom1 = {}
   -- cursor is at top of screen
-  Cursor1 = {line=3, pos=5}
+  Editor_state.cursor1 = {line=3, pos=5}
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'jkl', 'F - test_home_scrolls_up_in_wrapped_line/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'mno', 'F - test_home_scrolls_up_in_wrapped_line/baseline/screen:2')
   -- after hitting home the screen scrolls up to first screen line
   App.run_after_keychord('home')
-  y = Margin_top
+  y = Editor_state.margin_top
   App.screen.check(y, 'ghi ', 'F - test_home_scrolls_up_in_wrapped_line/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'jkl', 'F - test_home_scrolls_up_in_wrapped_line/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'mno', 'F - test_home_scrolls_up_in_wrapped_line/screen:3')
-  check_eq(Screen_top1.line, 3, 'F - test_home_scrolls_up_in_wrapped_line/screen_top')
-  check_eq(Screen_top1.pos, 1, 'F - test_home_scrolls_up_in_wrapped_line/screen_top')
-  check_eq(Cursor1.line, 3, 'F - test_home_scrolls_up_in_wrapped_line/cursor:line')
-  check_eq(Cursor1.pos, 1, 'F - test_home_scrolls_up_in_wrapped_line/cursor:pos')
+  check_eq(Editor_state.screen_top1.line, 3, 'F - test_home_scrolls_up_in_wrapped_line/screen_top')
+  check_eq(Editor_state.screen_top1.pos, 1, 'F - test_home_scrolls_up_in_wrapped_line/screen_top')
+  check_eq(Editor_state.cursor1.line, 3, 'F - test_home_scrolls_up_in_wrapped_line/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 1, 'F - test_home_scrolls_up_in_wrapped_line/cursor:pos')
 end
 
 function test_end_scrolls_down_in_wrapped_line()
   io.write('\ntest_end_scrolls_down_in_wrapped_line')
   -- display the first three lines with the cursor on the bottom line
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc', 'def', 'ghi jkl', 'mno'}
-  Margin_right = 0; Margin_width = Margin_left
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi jkl', 'mno'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   -- cursor is at bottom right of screen
-  Cursor1 = {line=3, pos=5}
+  Editor_state.cursor1 = {line=3, pos=5}
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_end_scrolls_down_in_wrapped_line/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_end_scrolls_down_in_wrapped_line/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi ', 'F - test_end_scrolls_down_in_wrapped_line/baseline/screen:3')  -- line wrapping includes trailing whitespace
   -- after hitting end the screen scrolls down by one line
   App.run_after_keychord('end')
-  check_eq(Screen_top1.line, 2, 'F - test_end_scrolls_down_in_wrapped_line/screen_top')
-  check_eq(Cursor1.line, 3, 'F - test_end_scrolls_down_in_wrapped_line/cursor:line')
-  check_eq(Cursor1.pos, 8, 'F - test_end_scrolls_down_in_wrapped_line/cursor:pos')
-  y = Margin_top
+  check_eq(Editor_state.screen_top1.line, 2, 'F - test_end_scrolls_down_in_wrapped_line/screen_top')
+  check_eq(Editor_state.cursor1.line, 3, 'F - test_end_scrolls_down_in_wrapped_line/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 8, 'F - test_end_scrolls_down_in_wrapped_line/cursor:pos')
+  y = Editor_state.margin_top
   App.screen.check(y, 'def', 'F - test_end_scrolls_down_in_wrapped_line/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi ', 'F - test_end_scrolls_down_in_wrapped_line/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'jkl', 'F - test_end_scrolls_down_in_wrapped_line/screen:3')
 end
 
@@ -1534,102 +1534,102 @@ function test_position_cursor_on_recently_edited_wrapping_line()
   -- draw a line wrapping over 2 screen lines
   io.write('\ntest_position_cursor_on_recently_edited_wrapping_line')
   App.screen.init{width=100, height=200}
-  Lines = load_array{'abc def ghi jkl mno pqr ', 'xyz'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=25}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc def ghi jkl mno pqr ', 'xyz'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=25}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc def ghi ', 'F - test_position_cursor_on_recently_edited_wrapping_line/baseline1/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'jkl mno pqr ', 'F - test_position_cursor_on_recently_edited_wrapping_line/baseline1/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'xyz', 'F - test_position_cursor_on_recently_edited_wrapping_line/baseline1/screen:3')
   -- add to the line until it's wrapping over 3 screen lines
   App.run_after_textinput('s')
   App.run_after_textinput('t')
   App.run_after_textinput('u')
-  check_eq(Cursor1.pos, 28, 'F - test_move_cursor_using_mouse/cursor:pos')
-  y = Margin_top
+  check_eq(Editor_state.cursor1.pos, 28, 'F - test_move_cursor_using_mouse/cursor:pos')
+  y = Editor_state.margin_top
   App.screen.check(y, 'abc def ghi ', 'F - test_position_cursor_on_recently_edited_wrapping_line/baseline2/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'jkl mno pqr ', 'F - test_position_cursor_on_recently_edited_wrapping_line/baseline2/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'stu', 'F - test_position_cursor_on_recently_edited_wrapping_line/baseline2/screen:3')
   -- try to move the cursor earlier in the third screen line by clicking the mouse
-  App.run_after_mouse_release(Margin_left+8,Margin_top+Line_height*2+5, 1)
+  App.run_after_mouse_release(Editor_state.margin_left+8,Editor_state.margin_top+Editor_state.line_height*2+5, 1)
   -- cursor should move
-  check_eq(Cursor1.line, 1, 'F - test_move_cursor_using_mouse/cursor:line')
-  check_eq(Cursor1.pos, 26, 'F - test_move_cursor_using_mouse/cursor:pos')
+  check_eq(Editor_state.cursor1.line, 1, 'F - test_move_cursor_using_mouse/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 26, 'F - test_move_cursor_using_mouse/cursor:pos')
 end
 
 function test_backspace_can_scroll_up()
   io.write('\ntest_backspace_can_scroll_up')
   -- display the lines 2/3/4 with the cursor on line 2
   App.screen.init{width=120, height=60}
-  Lines = load_array{'abc', 'def', 'ghi', 'jkl'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=2, pos=1}
-  Screen_top1 = {line=2, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=2, pos=1}
+  Editor_state.screen_top1 = {line=2, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
-  local y = Margin_top
+  local y = Editor_state.margin_top
   App.screen.check(y, 'def', 'F - test_backspace_can_scroll_up/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi', 'F - test_backspace_can_scroll_up/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'jkl', 'F - test_backspace_can_scroll_up/baseline/screen:3')
   -- after hitting backspace the screen scrolls up by one line
   App.run_after_keychord('backspace')
-  check_eq(Screen_top1.line, 1, 'F - test_backspace_can_scroll_up/screen_top')
-  check_eq(Cursor1.line, 1, 'F - test_backspace_can_scroll_up/cursor')
-  y = Margin_top
+  check_eq(Editor_state.screen_top1.line, 1, 'F - test_backspace_can_scroll_up/screen_top')
+  check_eq(Editor_state.cursor1.line, 1, 'F - test_backspace_can_scroll_up/cursor')
+  y = Editor_state.margin_top
   App.screen.check(y, 'abcdef', 'F - test_backspace_can_scroll_up/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'ghi', 'F - test_backspace_can_scroll_up/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'jkl', 'F - test_backspace_can_scroll_up/screen:3')
 end
 
 function test_backspace_can_scroll_up_screen_line()
   io.write('\ntest_backspace_can_scroll_up_screen_line')
   -- display lines starting from second screen line of a line
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc', 'def', 'ghi jkl', 'mno'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=3, pos=5}
-  Screen_top1 = {line=3, pos=5}
-  Screen_bottom1 = {}
-  edit.draw()
-  local y = Margin_top
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi jkl', 'mno'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=3, pos=5}
+  Editor_state.screen_top1 = {line=3, pos=5}
+  Editor_state.screen_bottom1 = {}
+  edit.draw()
+  local y = Editor_state.margin_top
   App.screen.check(y, 'jkl', 'F - test_backspace_can_scroll_up_screen_line/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'mno', 'F - test_backspace_can_scroll_up_screen_line/baseline/screen:2')
   -- after hitting backspace the screen scrolls up by one screen line
   App.run_after_keychord('backspace')
-  y = Margin_top
+  y = Editor_state.margin_top
   App.screen.check(y, 'ghijk', 'F - test_backspace_can_scroll_up_screen_line/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'l', 'F - test_backspace_can_scroll_up_screen_line/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'mno', 'F - test_backspace_can_scroll_up_screen_line/screen:3')
-  check_eq(Screen_top1.line, 3, 'F - test_backspace_can_scroll_up_screen_line/screen_top')
-  check_eq(Screen_top1.pos, 1, 'F - test_backspace_can_scroll_up_screen_line/screen_top')
-  check_eq(Cursor1.line, 3, 'F - test_backspace_can_scroll_up_screen_line/cursor:line')
-  check_eq(Cursor1.pos, 4, 'F - test_backspace_can_scroll_up_screen_line/cursor:pos')
+  check_eq(Editor_state.screen_top1.line, 3, 'F - test_backspace_can_scroll_up_screen_line/screen_top')
+  check_eq(Editor_state.screen_top1.pos, 1, 'F - test_backspace_can_scroll_up_screen_line/screen_top')
+  check_eq(Editor_state.cursor1.line, 3, 'F - test_backspace_can_scroll_up_screen_line/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 4, 'F - test_backspace_can_scroll_up_screen_line/cursor:pos')
 end
 
 function test_backspace_past_line_boundary()
   io.write('\ntest_backspace_past_line_boundary')
   -- position cursor at start of a (non-first) line
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc', 'def'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=2, pos=1}
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc', 'def'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=2, pos=1}
   -- backspace joins with previous line
   App.run_after_keychord('backspace')
-  check_eq(Lines[1].data, 'abcdef', "F - test_backspace_past_line_boundary")
+  check_eq(Editor_state.lines[1].data, 'abcdef', "F - test_backspace_past_line_boundary")
 end
 
 -- some tests for operating over selections created using Shift- chords
@@ -1638,165 +1638,165 @@ end
 function test_backspace_over_selection()
   io.write('\ntest_backspace_over_selection')
   -- select just one character within a line with cursor before selection
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Selection1 = {line=1, pos=2}
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.selection1 = {line=1, pos=2}
   -- backspace deletes the selected character, even though it's after the cursor
   App.run_after_keychord('backspace')
-  check_eq(Lines[1].data, 'bc', "F - test_backspace_over_selection/data")
+  check_eq(Editor_state.lines[1].data, 'bc', "F - test_backspace_over_selection/data")
   -- cursor (remains) at start of selection
-  check_eq(Cursor1.line, 1, "F - test_backspace_over_selection/cursor:line")
-  check_eq(Cursor1.pos, 1, "F - test_backspace_over_selection/cursor:pos")
+  check_eq(Editor_state.cursor1.line, 1, "F - test_backspace_over_selection/cursor:line")
+  check_eq(Editor_state.cursor1.pos, 1, "F - test_backspace_over_selection/cursor:pos")
   -- selection is cleared
-  check_nil(Selection1.line, "F - test_backspace_over_selection/selection")
+  check_nil(Editor_state.selection1.line, "F - test_backspace_over_selection/selection")
 end
 
 function test_backspace_over_selection_reverse()
   io.write('\ntest_backspace_over_selection_reverse')
   -- select just one character within a line with cursor after selection
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=2}
-  Selection1 = {line=1, pos=1}
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=2}
+  Editor_state.selection1 = {line=1, pos=1}
   -- backspace deletes the selected character
   App.run_after_keychord('backspace')
-  check_eq(Lines[1].data, 'bc', "F - test_backspace_over_selection_reverse/data")
+  check_eq(Editor_state.lines[1].data, 'bc', "F - test_backspace_over_selection_reverse/data")
   -- cursor moves to start of selection
-  check_eq(Cursor1.line, 1, "F - test_backspace_over_selection_reverse/cursor:line")
-  check_eq(Cursor1.pos, 1, "F - test_backspace_over_selection_reverse/cursor:pos")
+  check_eq(Editor_state.cursor1.line, 1, "F - test_backspace_over_selection_reverse/cursor:line")
+  check_eq(Editor_state.cursor1.pos, 1, "F - test_backspace_over_selection_reverse/cursor:pos")
   -- selection is cleared
-  check_nil(Selection1.line, "F - test_backspace_over_selection_reverse/selection")
+  check_nil(Editor_state.selection1.line, "F - test_backspace_over_selection_reverse/selection")
 end
 
 function test_backspace_over_multiple_lines()
   io.write('\ntest_backspace_over_multiple_lines')
   -- select just one character within a line with cursor after selection
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=2}
-  Selection1 = {line=4, pos=2}
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=2}
+  Editor_state.selection1 = {line=4, pos=2}
   -- backspace deletes the region and joins the remaining portions of lines on either side
   App.run_after_keychord('backspace')
-  check_eq(Lines[1].data, 'akl', "F - test_backspace_over_multiple_lines/data:1")
-  check_eq(Lines[2].data, 'mno', "F - test_backspace_over_multiple_lines/data:2")
+  check_eq(Editor_state.lines[1].data, 'akl', "F - test_backspace_over_multiple_lines/data:1")
+  check_eq(Editor_state.lines[2].data, 'mno', "F - test_backspace_over_multiple_lines/data:2")
   -- cursor remains at start of selection
-  check_eq(Cursor1.line, 1, "F - test_backspace_over_multiple_lines/cursor:line")
-  check_eq(Cursor1.pos, 2, "F - test_backspace_over_multiple_lines/cursor:pos")
+  check_eq(Editor_state.cursor1.line, 1, "F - test_backspace_over_multiple_lines/cursor:line")
+  check_eq(Editor_state.cursor1.pos, 2, "F - test_backspace_over_multiple_lines/cursor:pos")
   -- selection is cleared
-  check_nil(Selection1.line, "F - test_backspace_over_multiple_lines/selection")
+  check_nil(Editor_state.selection1.line, "F - test_backspace_over_multiple_lines/selection")
 end
 
 function test_backspace_to_end_of_line()
   io.write('\ntest_backspace_to_end_of_line')
   -- select region from cursor to end of line
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=2}
-  Selection1 = {line=1, pos=4}
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=2}
+  Editor_state.selection1 = {line=1, pos=4}
   -- backspace deletes rest of line without joining to any other line
   App.run_after_keychord('backspace')
-  check_eq(Lines[1].data, 'a', "F - test_backspace_to_start_of_line/data:1")
-  check_eq(Lines[2].data, 'def', "F - test_backspace_to_start_of_line/data:2")
+  check_eq(Editor_state.lines[1].data, 'a', "F - test_backspace_to_start_of_line/data:1")
+  check_eq(Editor_state.lines[2].data, 'def', "F - test_backspace_to_start_of_line/data:2")
   -- cursor remains at start of selection
-  check_eq(Cursor1.line, 1, "F - test_backspace_to_start_of_line/cursor:line")
-  check_eq(Cursor1.pos, 2, "F - test_backspace_to_start_of_line/cursor:pos")
+  check_eq(Editor_state.cursor1.line, 1, "F - test_backspace_to_start_of_line/cursor:line")
+  check_eq(Editor_state.cursor1.pos, 2, "F - test_backspace_to_start_of_line/cursor:pos")
   -- selection is cleared
-  check_nil(Selection1.line, "F - test_backspace_to_start_of_line/selection")
+  check_nil(Editor_state.selection1.line, "F - test_backspace_to_start_of_line/selection")
 end
 
 function test_backspace_to_start_of_line()
   io.write('\ntest_backspace_to_start_of_line')
   -- select region from cursor to start of line
-  App.screen.init{width=Margin_left+30, height=60}
-  Lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=2, pos=1}
-  Selection1 = {line=2, pos=3}
+  App.screen.init{width=Editor_state.margin_left+30, height=60}
+  Editor_state.lines = load_array{'abc', 'def', 'ghi', 'jkl', 'mno'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=2, pos=1}
+  Editor_state.selection1 = {line=2, pos=3}
   -- backspace deletes beginning of line without joining to any other line
   App.run_after_keychord('backspace')
-  check_eq(Lines[1].data, 'abc', "F - test_backspace_to_start_of_line/data:1")
-  check_eq(Lines[2].data, 'f', "F - test_backspace_to_start_of_line/data:2")
+  check_eq(Editor_state.lines[1].data, 'abc', "F - test_backspace_to_start_of_line/data:1")
+  check_eq(Editor_state.lines[2].data, 'f', "F - test_backspace_to_start_of_line/data:2")
   -- cursor remains at start of selection
-  check_eq(Cursor1.line, 2, "F - test_backspace_to_start_of_line/cursor:line")
-  check_eq(Cursor1.pos, 1, "F - test_backspace_to_start_of_line/cursor:pos")
+  check_eq(Editor_state.cursor1.line, 2, "F - test_backspace_to_start_of_line/cursor:line")
+  check_eq(Editor_state.cursor1.pos, 1, "F - test_backspace_to_start_of_line/cursor:pos")
   -- selection is cleared
-  check_nil(Selection1.line, "F - test_backspace_to_start_of_line/selection")
+  check_nil(Editor_state.selection1.line, "F - test_backspace_to_start_of_line/selection")
 end
 
 function test_undo_insert_text()
   io.write('\ntest_undo_insert_text')
   App.screen.init{width=120, height=60}
-  Lines = load_array{'abc', 'def', 'xyz'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=2, pos=4}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc', 'def', 'xyz'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=2, pos=4}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   -- insert a character
   edit.draw()
   App.run_after_textinput('g')
-  check_eq(Cursor1.line, 2, 'F - test_undo_insert_text/baseline/cursor:line')
-  check_eq(Cursor1.pos, 5, 'F - test_undo_insert_text/baseline/cursor:pos')
-  check_nil(Selection1.line, 'F - test_undo_insert_text/baseline/selection:line')
-  check_nil(Selection1.pos, 'F - test_undo_insert_text/baseline/selection:pos')
-  local y = Margin_top
+  check_eq(Editor_state.cursor1.line, 2, 'F - test_undo_insert_text/baseline/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 5, 'F - test_undo_insert_text/baseline/cursor:pos')
+  check_nil(Editor_state.selection1.line, 'F - test_undo_insert_text/baseline/selection:line')
+  check_nil(Editor_state.selection1.pos, 'F - test_undo_insert_text/baseline/selection:pos')
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_undo_insert_text/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'defg', 'F - test_undo_insert_text/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'xyz', 'F - test_undo_insert_text/baseline/screen:3')
   -- undo
   App.run_after_keychord('C-z')
-  check_eq(Cursor1.line, 2, 'F - test_undo_insert_text/cursor:line')
-  check_eq(Cursor1.pos, 4, 'F - test_undo_insert_text/cursor:pos')
-  check_nil(Selection1.line, 'F - test_undo_insert_text/selection:line')
-  check_nil(Selection1.pos, 'F - test_undo_insert_text/selection:pos')
-  y = Margin_top
+  check_eq(Editor_state.cursor1.line, 2, 'F - test_undo_insert_text/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 4, 'F - test_undo_insert_text/cursor:pos')
+  check_nil(Editor_state.selection1.line, 'F - test_undo_insert_text/selection:line')
+  check_nil(Editor_state.selection1.pos, 'F - test_undo_insert_text/selection:pos')
+  y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_undo_insert_text/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_undo_insert_text/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'xyz', 'F - test_undo_insert_text/screen:3')
 end
 
 function test_undo_delete_text()
   io.write('\ntest_undo_delete_text')
   App.screen.init{width=120, height=60}
-  Lines = load_array{'abc', 'defg', 'xyz'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=2, pos=5}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc', 'defg', 'xyz'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=2, pos=5}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   -- delete a character
   App.run_after_keychord('backspace')
-  check_eq(Cursor1.line, 2, 'F - test_undo_delete_text/baseline/cursor:line')
-  check_eq(Cursor1.pos, 4, 'F - test_undo_delete_text/baseline/cursor:pos')
-  check_nil(Selection1.line, 'F - test_undo_delete_text/baseline/selection:line')
-  check_nil(Selection1.pos, 'F - test_undo_delete_text/baseline/selection:pos')
-  local y = Margin_top
+  check_eq(Editor_state.cursor1.line, 2, 'F - test_undo_delete_text/baseline/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 4, 'F - test_undo_delete_text/baseline/cursor:pos')
+  check_nil(Editor_state.selection1.line, 'F - test_undo_delete_text/baseline/selection:line')
+  check_nil(Editor_state.selection1.pos, 'F - test_undo_delete_text/baseline/selection:pos')
+  local y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_undo_delete_text/baseline/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'def', 'F - test_undo_delete_text/baseline/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'xyz', 'F - test_undo_delete_text/baseline/screen:3')
   -- undo
 --?   -- after undo, the backspaced key is selected
   App.run_after_keychord('C-z')
-  check_eq(Cursor1.line, 2, 'F - test_undo_delete_text/cursor:line')
-  check_eq(Cursor1.pos, 5, 'F - test_undo_delete_text/cursor:pos')
-  check_nil(Selection1.line, 'F - test_undo_delete_text/selection:line')
-  check_nil(Selection1.pos, 'F - test_undo_delete_text/selection:pos')
---?   check_eq(Selection1.line, 2, 'F - test_undo_delete_text/selection:line')
---?   check_eq(Selection1.pos, 4, 'F - test_undo_delete_text/selection:pos')
-  y = Margin_top
+  check_eq(Editor_state.cursor1.line, 2, 'F - test_undo_delete_text/cursor:line')
+  check_eq(Editor_state.cursor1.pos, 5, 'F - test_undo_delete_text/cursor:pos')
+  check_nil(Editor_state.selection1.line, 'F - test_undo_delete_text/selection:line')
+  check_nil(Editor_state.selection1.pos, 'F - test_undo_delete_text/selection:pos')
+--?   check_eq(Editor_state.selection1.line, 2, 'F - test_undo_delete_text/selection:line')
+--?   check_eq(Editor_state.selection1.pos, 4, 'F - test_undo_delete_text/selection:pos')
+  y = Editor_state.margin_top
   App.screen.check(y, 'abc', 'F - test_undo_delete_text/screen:1')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'defg', 'F - test_undo_delete_text/screen:2')
-  y = y + Line_height
+  y = y + Editor_state.line_height
   App.screen.check(y, 'xyz', 'F - test_undo_delete_text/screen:3')
 end
 
@@ -1804,21 +1804,21 @@ function test_undo_restores_selection()
   io.write('\ntest_undo_restores_selection')
   -- display a line of text with some part selected
   App.screen.init{width=75, height=80}
-  Lines = load_array{'abc'}
-  Margin_right = 0; Margin_width = Margin_left
-  Cursor1 = {line=1, pos=1}
-  Selection1 = {line=1, pos=2}
-  Screen_top1 = {line=1, pos=1}
-  Screen_bottom1 = {}
+  Editor_state.lines = load_array{'abc'}
+  Editor_state.margin_right = 0; Editor_state.margin_width = Editor_state.margin_left
+  Editor_state.cursor1 = {line=1, pos=1}
+  Editor_state.selection1 = {line=1, pos=2}
+  Editor_state.screen_top1 = {line=1, pos=1}
+  Editor_state.screen_bottom1 = {}
   edit.draw()
   -- delete selected text
   App.run_after_textinput('x')
-  check_eq(Lines[1].data, 'xbc', 'F - test_undo_restores_selection/baseline')
-  check_nil(Selection1.line, 'F - test_undo_restores_selection/baseline:selection')
+  check_eq(Editor_state.lines[1].data, 'xbc', 'F - test_undo_restores_selection/baseline')
+  check_nil(Editor_state.selection1.line, 'F - test_undo_restores_selection/baseline:selection')
   -- undo
   App.run_after_keychord('C-z')
   App.run_after_keychord('C-z')
   -- selection is restored
-  check_eq(Selection1.line, 1, 'F - test_undo_restores_selection/line')
-  check_eq(Selection1.pos, 2, 'F - test_undo_restores_selection/pos')
+  check_eq(Editor_state.selection1.line, 1, 'F - test_undo_restores_selection/line')
+  check_eq(Editor_state.selection1.pos, 2, 'F - test_undo_restores_selection/pos')
 end
diff --git a/undo.lua b/undo.lua
index 3504577..8e5491c 100644
--- a/undo.lua
+++ b/undo.lua
@@ -7,27 +7,27 @@
 -- TODO: coalesce multiple similar operations
 
 function record_undo_event(data)
-  History[Next_history] = data
-  Next_history = Next_history+1
-  for i=Next_history,#History do
-    History[i] = nil
+  Editor_state.history[Editor_state.next_history] = data
+  Editor_state.next_history = Editor_state.next_history+1
+  for i=Editor_state.next_history,#Editor_state.history do
+    Editor_state.history[i] = nil
   end
 end
 
 function undo_event()
-  if Next_history > 1 then
---?     print('moving to history', Next_history-1)
-    Next_history = Next_history-1
-    local result = History[Next_history]
+  if Editor_state.next_history > 1 then
+--?     print('moving to history', Editor_state.next_history-1)
+    Editor_state.next_history = Editor_state.next_history-1
+    local result = Editor_state.history[Editor_state.next_history]
     return result
   end
 end
 
 function redo_event()
-  if Next_history <= #History then
---?     print('restoring history', Next_history+1)
-    local result = History[Next_history]
-    Next_history = Next_history+1
+  if Editor_state.next_history <= #Editor_state.history then
+--?     print('restoring history', Editor_state.next_history+1)
+    local result = Editor_state.history[Editor_state.next_history]
+    Editor_state.next_history = Editor_state.next_history+1
     return result
   end
 end
@@ -40,18 +40,18 @@ function snapshot(s,e)
   if e == nil then
     e = s
   end
-  assert(#Lines > 0)
+  assert(#Editor_state.lines > 0)
   if s < 1 then s = 1 end
-  if s > #Lines then s = #Lines end
+  if s > #Editor_state.lines then s = #Editor_state.lines end
   if e < 1 then e = 1 end
-  if e > #Lines then e = #Lines end
+  if e > #Editor_state.lines then e = #Editor_state.lines end
   -- compare with App.initialize_globals
   local event = {
-    screen_top=deepcopy(Screen_top1),
-    selection=deepcopy(Selection1),
-    cursor=deepcopy(Cursor1),
+    screen_top=deepcopy(Editor_state.screen_top1),
+    selection=deepcopy(Editor_state.selection1),
+    cursor=deepcopy(Editor_state.cursor1),
     current_drawing_mode=Drawing_mode,
-    previous_drawing_mode=Previous_drawing_mode,
+    previous_drawing_mode=Editor_state.previous_drawing_mode,
     lines={},
     start_line=s,
     end_line=e,
@@ -59,7 +59,7 @@ function snapshot(s,e)
   }
   -- deep copy lines without cached stuff like text fragments
   for i=s,e do
-    local line = Lines[i]
+    local line = Editor_state.lines[i]
     if line.mode == 'text' then
       table.insert(event.lines, {mode='text', data=line.data})
     elseif line.mode == 'drawing' then