about summary refs log tree commit diff stats
path: root/text.lua
diff options
context:
space:
mode:
Diffstat (limited to 'text.lua')
-rw-r--r--text.lua197
1 files changed, 46 insertions, 151 deletions
diff --git a/text.lua b/text.lua
index 4c87ad8..da4d2a1 100644
--- a/text.lua
+++ b/text.lua
@@ -82,7 +82,6 @@ end
 
 function Text.populate_screen_line_starting_pos(State, line_index)
   local line = State.lines[line_index]
-  if line.mode ~= 'text' then return end
   local line_cache = State.line_cache[line_index]
   if line_cache.screen_line_starting_pos then
     return
@@ -141,7 +140,6 @@ function Text.text_input(State, t)
 end
 
 function Text.insert_at_cursor(State, t)
-  assert(State.lines[State.cursor1.line].mode == 'text', 'line is not text')
   local byte_offset = Text.offset(State.lines[State.cursor1.line].data, State.cursor1.pos)
   State.lines[State.cursor1.line].data = string.sub(State.lines[State.cursor1.line].data, 1, byte_offset-1)..t..string.sub(State.lines[State.cursor1.line].data, byte_offset)
   Text.clear_screen_line_cache(State, State.cursor1.line)
@@ -193,16 +191,11 @@ function Text.keychord_press(State, chord)
       end
     elseif State.cursor1.line > 1 then
       before = snapshot(State, State.cursor1.line-1, State.cursor1.line)
-      if State.lines[State.cursor1.line-1].mode == 'drawing' then
-        table.remove(State.lines, State.cursor1.line-1)
-        table.remove(State.line_cache, State.cursor1.line-1)
-      else
-        -- join lines
-        State.cursor1.pos = utf8.len(State.lines[State.cursor1.line-1].data)+1
-        State.lines[State.cursor1.line-1].data = State.lines[State.cursor1.line-1].data..State.lines[State.cursor1.line].data
-        table.remove(State.lines, State.cursor1.line)
-        table.remove(State.line_cache, State.cursor1.line)
-      end
+      -- join lines
+      State.cursor1.pos = utf8.len(State.lines[State.cursor1.line-1].data)+1
+      State.lines[State.cursor1.line-1].data = State.lines[State.cursor1.line-1].data..State.lines[State.cursor1.line].data
+      table.remove(State.lines, State.cursor1.line)
+      table.remove(State.line_cache, State.cursor1.line)
       State.cursor1.line = State.cursor1.line-1
     end
     if State.screen_top1.line > #State.lines then
@@ -244,10 +237,8 @@ function Text.keychord_press(State, chord)
         -- no change to State.cursor1.pos
       end
     elseif State.cursor1.line < #State.lines then
-      if State.lines[State.cursor1.line+1].mode == 'text' then
-        -- join lines
-        State.lines[State.cursor1.line].data = State.lines[State.cursor1.line].data..State.lines[State.cursor1.line+1].data
-      end
+      -- join lines
+      State.lines[State.cursor1.line].data = State.lines[State.cursor1.line].data..State.lines[State.cursor1.line+1].data
       table.remove(State.lines, State.cursor1.line+1)
       table.remove(State.line_cache, State.cursor1.line+1)
     end
@@ -341,7 +332,7 @@ end
 
 function Text.insert_return(State)
   local byte_offset = Text.offset(State.lines[State.cursor1.line].data, State.cursor1.pos)
-  table.insert(State.lines, State.cursor1.line+1, {mode='text', data=string.sub(State.lines[State.cursor1.line].data, byte_offset)})
+  table.insert(State.lines, State.cursor1.line+1, {data=string.sub(State.lines[State.cursor1.line].data, byte_offset)})
   table.insert(State.line_cache, State.cursor1.line+1, {})
   State.lines[State.cursor1.line].data = string.sub(State.lines[State.cursor1.line].data, 1, byte_offset-1)
   Text.clear_screen_line_cache(State, State.cursor1.line)
@@ -364,15 +355,8 @@ function Text.starty(State, line_index)
   local loc2 = Text.to2(State, State.screen_top1)
   local y = State.top
   while true do
-    if State.lines[loc2.line].mode == 'drawing' then
-      y = y + Drawing_padding_top
-    end
     if loc2.line == line_index then return y end
-    if State.lines[loc2.line].mode == 'text' then
-      y = y + State.line_height
-    elseif State.lines[loc2.line].mode == 'drawing' then
-      y = y + Drawing.pixels(State.lines[loc2.line].h, State.width) + Drawing_padding_bottom
-    end
+    y = y + State.line_height
     if y + State.line_height > App.screen.height then break end
     local next_loc2 = Text.next_screen_line(State, loc2)
     if Text.eq2(next_loc2, loc2) then break end  -- end of file
@@ -387,11 +371,7 @@ function Text.previous_screen_top1(State)
   local y = App.screen.height - State.line_height
   while y >= State.top do
     if loc2.line == 1 and loc2.screen_line == 1 and loc2.screen_pos == 1 then break end
-    if State.lines[loc2.line].mode == 'text' then
-      y = y - State.line_height
-    elseif State.lines[loc2.line].mode == 'drawing' then
-      y = y - Drawing_padding_height - Drawing.pixels(State.lines[loc2.line].h, State.width)
-    end
+    y = y - State.line_height
     loc2 = Text.previous_screen_line(State, loc2)
   end
   return Text.to1(State, loc2)
@@ -411,11 +391,7 @@ function Text.screen_bottom1(State)
   local loc2 = Text.to2(State, State.screen_top1)
   local y = State.top
   while true do
-    if State.lines[loc2.line].mode == 'text' then
-      y = y + State.line_height
-    elseif State.lines[loc2.line].mode == 'drawing' then
-      y = y + Drawing_padding_height + Drawing.pixels(State.lines[loc2.line].h, State.width)
-    end
+    y = y + State.line_height
     if y + State.line_height > App.screen.height then break end
     local next_loc2 = Text.next_screen_line(State, loc2)
     if Text.eq2(next_loc2, loc2) then break end
@@ -425,29 +401,24 @@ function Text.screen_bottom1(State)
 end
 
 function Text.up(State)
-  assert(State.lines[State.cursor1.line].mode == 'text', 'line is not text')
 --?   print('up', State.cursor1.line, State.cursor1.pos, State.screen_top1.line, State.screen_top1.pos)
   local screen_line_starting_pos, screen_line_index = Text.pos_at_start_of_screen_line(State, State.cursor1)
   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 = State.cursor1.line
-    while new_cursor_line > 1 do
-      new_cursor_line = new_cursor_line-1
-      if State.lines[new_cursor_line].mode == 'text' then
---?         print('found previous text line')
-        State.cursor1 = {line=new_cursor_line, pos=nil}
-        Text.populate_screen_line_starting_pos(State, State.cursor1.line)
-        -- previous text line found, pick its final screen line
---?         print('has multiple screen lines')
-        local screen_line_starting_pos = State.line_cache[State.cursor1.line].screen_line_starting_pos
---?         print(#screen_line_starting_pos)
-        screen_line_starting_pos = screen_line_starting_pos[#screen_line_starting_pos]
-        local screen_line_starting_byte_offset = Text.offset(State.lines[State.cursor1.line].data, screen_line_starting_pos)
-        local s = string.sub(State.lines[State.cursor1.line].data, screen_line_starting_byte_offset)
-        State.cursor1.pos = screen_line_starting_pos + Text.nearest_cursor_pos(State.font, s, State.cursor_x, State.left) - 1
-        break
-      end
+    if State.cursor1.line > 1 then
+      local new_cursor_line = State.cursor1.line-1
+--?       print('found previous text line')
+      State.cursor1 = {line=new_cursor_line, pos=nil}
+      Text.populate_screen_line_starting_pos(State, State.cursor1.line)
+      -- previous text line found, pick its final screen line
+--?       print('has multiple screen lines')
+      local screen_line_starting_pos = State.line_cache[State.cursor1.line].screen_line_starting_pos
+--?       print(#screen_line_starting_pos)
+      screen_line_starting_pos = screen_line_starting_pos[#screen_line_starting_pos]
+      local screen_line_starting_byte_offset = Text.offset(State.lines[State.cursor1.line].data, screen_line_starting_pos)
+      local s = string.sub(State.lines[State.cursor1.line].data, screen_line_starting_byte_offset)
+      State.cursor1.pos = screen_line_starting_pos + Text.nearest_cursor_pos(State.font, s, State.cursor_x, State.left) - 1
     end
   else
     -- move up one screen line in current line
@@ -468,23 +439,16 @@ function Text.up(State)
 end
 
 function Text.down(State)
-  assert(State.lines[State.cursor1.line].mode == 'text', 'line is not text')
 --?   print('down', State.cursor1.line, State.cursor1.pos, State.screen_top1.line, State.screen_top1.pos)
   assert(State.cursor1.pos, 'cursor has no pos')
   if Text.cursor_at_final_screen_line(State) then
     -- line is done, skip to next text line
 --?     print('cursor at final screen line of its line')
-    local new_cursor_line = State.cursor1.line
-    while new_cursor_line < #State.lines do
-      new_cursor_line = new_cursor_line+1
-      if State.lines[new_cursor_line].mode == 'text' then
-        State.cursor1 = {
-          line = new_cursor_line,
-          pos = Text.nearest_cursor_pos(State.font, State.lines[new_cursor_line].data, State.cursor_x, State.left),
-        }
---?         print(State.cursor1.pos)
-        break
-      end
+    if State.cursor1.line < #State.lines then
+      local new_cursor_line = State.cursor1.line+1
+      State.cursor1.line = new_cursor_line
+      State.cursor1.pos = Text.nearest_cursor_pos(State.font, State.lines[State.cursor1.line].data, State.cursor_x, State.left)
+--?       print(State.cursor1.pos)
     end
     local screen_bottom1 = Text.screen_bottom1(State)
 --?   print('down 2', State.cursor1.line, State.cursor1.pos, State.screen_top1.line, State.screen_top1.pos, screen_bottom1.line, screen_bottom1.pos)
@@ -588,21 +552,11 @@ function Text.match(s, pos, pat)
 end
 
 function Text.left(State)
-  assert(State.lines[State.cursor1.line].mode == 'text', 'line is not text')
   if State.cursor1.pos > 1 then
     State.cursor1.pos = State.cursor1.pos-1
-  else
-    local new_cursor_line = State.cursor1.line
-    while new_cursor_line > 1 do
-      new_cursor_line = new_cursor_line-1
-      if State.lines[new_cursor_line].mode == 'text' then
-        State.cursor1 = {
-          line = new_cursor_line,
-          pos = utf8.len(State.lines[new_cursor_line].data) + 1,
-        }
-        break
-      end
-    end
+  elseif State.cursor1.line > 1 then
+    State.cursor1.line = State.cursor1.line-1
+    State.cursor1.pos = utf8.len(State.lines[State.cursor1.line].data) + 1
   end
   if Text.lt1(State.cursor1, State.screen_top1) then
     State.screen_top1 = {
@@ -621,18 +575,11 @@ function Text.right(State)
 end
 
 function Text.right_without_scroll(State)
-  assert(State.lines[State.cursor1.line].mode == 'text', 'line is not text')
   if State.cursor1.pos <= utf8.len(State.lines[State.cursor1.line].data) then
     State.cursor1.pos = State.cursor1.pos+1
-  else
-    local new_cursor_line = State.cursor1.line
-    while new_cursor_line <= #State.lines-1 do
-      new_cursor_line = new_cursor_line+1
-      if State.lines[new_cursor_line].mode == 'text' then
-        State.cursor1 = {line=new_cursor_line, pos=1}
-        break
-      end
-    end
+  elseif State.cursor1.line <= #State.lines-1 then
+    State.cursor1.line = State.cursor1.line+1
+    State.cursor1.pos = 1
   end
 end
 
@@ -650,7 +597,6 @@ function Text.pos_at_start_of_screen_line(State, loc1)
 end
 
 function Text.pos_at_end_of_screen_line(State, loc1)
-  assert(State.lines[loc1.line].mode == 'text')
   Text.populate_screen_line_starting_pos(State, loc1.line)
   local line_cache = State.line_cache[loc1.line]
   local most_recent_final_pos = utf8.len(State.lines[loc1.line].data)+1
@@ -664,23 +610,12 @@ function Text.pos_at_end_of_screen_line(State, loc1)
   assert(false, ('invalid pos %d'):format(loc1.pos))
 end
 
-function Text.final_text_loc_on_screen(State)
+function Text.final_loc_on_screen(State)
   local screen_bottom1 = Text.screen_bottom1(State)
-  if State.lines[screen_bottom1.line].mode == 'text' then
-    return {
-      line=screen_bottom1.line,
-      pos=Text.pos_at_end_of_screen_line(State, screen_bottom1),
-    }
-  end
-  local loc2 = Text.to2(State, screen_bottom1)
-  while true do
-    if State.lines[loc2.line].mode == 'text' then break end
-    assert(loc2.line > 1 or loc2.screen_line > 1 and loc2.screen_pos > 1)  -- elsewhere we're making sure there's always at least one text line on screen
-    loc2 = Text.previous_screen_line(State, loc2)
-  end
-  local result = Text.to1(State, loc2)
-  result.pos = Text.pos_at_end_of_screen_line(State, result)
-  return result
+  return {
+    line=screen_bottom1.line,
+    pos=Text.pos_at_end_of_screen_line(State, screen_bottom1),
+  }
 end
 
 function Text.cursor_at_final_screen_line(State)
@@ -691,26 +626,7 @@ function Text.cursor_at_final_screen_line(State)
 end
 
 function Text.move_cursor_down_to_next_text_line_while_scrolling_again_if_necessary(State)
-  local y = State.top
-  while State.cursor1.line <= #State.lines do
-    if State.lines[State.cursor1.line].mode == 'text' then
-      break
-    end
---?     print('cursor skips', State.cursor1.line)
-    y = y + Drawing_padding_height + Drawing.pixels(State.lines[State.cursor1.line].h, State.width)
-    State.cursor1.line = State.cursor1.line + 1
-  end
-  if State.cursor1.pos == nil then
-    State.cursor1.pos = 1
-  end
-  -- hack: insert a text line at bottom of file if necessary
-  if State.cursor1.line > #State.lines then
-    assert(State.cursor1.line == #State.lines+1, 'tried to ensure bottom line of file is text, but failed')
-    table.insert(State.lines, {mode='text', data=''})
-    table.insert(State.line_cache, {})
-  end
---?   print(y, App.screen.height, App.screen.height-State.line_height)
-  if y > App.screen.height - State.line_height then
+  if State.top > App.screen.height - State.line_height then
 --?     print('scroll up')
     Text.snap_cursor_to_bottom_of_screen(State)
   end
@@ -730,24 +646,11 @@ function Text.snap_cursor_to_bottom_of_screen(State)
   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 State.lines[top2.line-1].mode == 'text' then
-      local h = State.line_height
-      if y - h < State.top then
-        break
-      end
-      y = y - h
-    else
-      assert(top2.line > 1, 'tried to snap cursor to buttom of screen but failed')
-      assert(State.lines[top2.line-1].mode == 'drawing', "expected a drawing but it's not")
-      -- We currently can't draw partial drawings, so either skip it entirely
-      -- or not at all.
-      local h = Drawing_padding_height + Drawing.pixels(State.lines[top2.line-1].h, State.width)
-      if y - h < State.top then
-        break
-      end
---?       print('skipping drawing of height', h)
-      y = y - h
+    local h = State.line_height
+    if y - h < State.top then
+      break
     end
+    y = y - h
     top2 = Text.previous_screen_line(State, top2)
   end
 --?   print('top2 finally:', top2.line, top2.screen_line, top2.screen_pos)
@@ -910,9 +813,6 @@ function Text.x(font, s, pos)
 end
 
 function Text.to2(State, loc1)
-  if State.lines[loc1.line].mode == 'drawing' then
-    return {line=loc1.line, screen_line=1, screen_pos=1}
-  end
   local result = {line=loc1.line}
   local line_cache = State.line_cache[loc1.line]
   Text.populate_screen_line_starting_pos(State, loc1.line)
@@ -978,8 +878,6 @@ function Text.previous_screen_line(State, loc2)
     return {line=loc2.line, screen_line=loc2.screen_line-1, screen_pos=1}
   elseif loc2.line == 1 then
     return loc2
-  elseif State.lines[loc2.line-1].mode == 'drawing' then
-    return {line=loc2.line-1, screen_line=1, screen_pos=1}
   else
     local l = State.lines[loc2.line-1]
     Text.populate_screen_line_starting_pos(State, loc2.line-1)
@@ -988,9 +886,6 @@ function Text.previous_screen_line(State, loc2)
 end
 
 function Text.next_screen_line(State, loc2)
-  if State.lines[loc2.line].mode == 'drawing' then
-    return {line=loc2.line+1, screen_line=1, screen_pos=1}
-  end
   Text.populate_screen_line_starting_pos(State, loc2.line)
   if loc2.screen_line >= #State.line_cache[loc2.line].screen_line_starting_pos then
     if loc2.line < #State.lines then
@@ -1031,7 +926,7 @@ function Text.tweak_screen_top_and_cursor(State)
     State.cursor1 = deepcopy(State.screen_top1)
   elseif State.cursor1.line >= screen_bottom1.line then
     if Text.cursor_out_of_screen(State) then
-      State.cursor1 = Text.final_text_loc_on_screen(State)
+      State.cursor1 = Text.final_loc_on_screen(State)
     end
   end
 end