about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--main.lua9
-rw-r--r--text.lua29
-rw-r--r--text_tests.lua21
3 files changed, 48 insertions, 11 deletions
diff --git a/main.lua b/main.lua
index b63c7fc..de50b65 100644
--- a/main.lua
+++ b/main.lua
@@ -20,7 +20,8 @@ function App.initialize_globals()
 -- a text is a table with:
 --    mode = 'text',
 --    string data,
---    a (y) coord in pixels (updated while painting screen),
+--    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
@@ -275,7 +276,11 @@ function App.draw()
         y = y + Drawing.pixels(line.h) + Drawing_padding_bottom
       else
 --?         print('text')
-        line.y = y
+        line.starty = y
+        line.startpos = 1
+        if line_index == Screen_top1.line then
+          line.startpos = Screen_top1.pos
+        end
         y, Screen_bottom1.pos = Text.draw(line, Line_width, line_index)
         y = y + Line_height
 --?         print('=> y', y)
diff --git a/text.lua b/text.lua
index 22e7349..2defbc8 100644
--- a/text.lua
+++ b/text.lua
@@ -17,7 +17,7 @@ function Text.draw(line, line_width, line_index)
 --?   love.graphics.line(Line_width,0, Line_width,App.screen.height)
   -- wrap long lines
   local x = Margin_left
-  local y = line.y
+  local y = line.starty
   local pos = 1
   local screen_line_starting_pos = 1
   if line.fragments == nil then
@@ -659,11 +659,11 @@ function Text.snap_cursor_to_bottom_of_screen()
 end
 
 function Text.in_line(line_index,line, x,y)
-  if line.y == nil then return false end  -- outside current page
+  if line.starty == nil then return false end  -- outside current page
   if x < Margin_left then return false end
-  if y < line.y then return false end
+  if y < line.starty then return false end
   Text.populate_screen_line_starting_pos(line_index)
-  return y < line.y + #line.screen_line_starting_pos * Line_height
+  return y < line.starty + 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
@@ -672,11 +672,13 @@ function Text.to_pos_on_line(line, mx, my)
   if line.fragments == nil then
     Text.compute_fragments(line, Line_width)
   end
-  assert(my >= line.y)
+  assert(my >= line.starty)
   -- duplicate some logic from Text.draw
-  local y = line.y
-  for screen_line_index,screen_line_starting_pos in ipairs(line.screen_line_starting_pos) do
-      local screen_line_starting_byte_offset = Text.offset(line.data, screen_line_starting_pos)
+  local y = line.starty
+  local start_screen_line_index = Text.screen_line_index(line, line.startpos)
+  for screen_line_index = start_screen_line_index,#line.screen_line_starting_pos do
+    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
     if my < nexty then
@@ -725,6 +727,14 @@ function Text.screen_line_width(line, i)
   return App.width(screen_line_text)
 end
 
+function Text.screen_line_index(line, pos)
+  for i = #line.screen_line_starting_pos,1,-1 do
+    if line.screen_line_starting_pos[i] <= pos then
+      return i
+    end
+  end
+end
+
 function Text.nearest_cursor_pos(line, x)  -- x includes left margin
   if x == 0 then
     return 1
@@ -909,7 +919,8 @@ end
 function Text.redraw_all()
 --?   print('clearing fragments')
   for _,line in ipairs(Lines) do
-    line.y = nil
+    line.starty = nil
+    line.startpos = nil
     Text.clear_cache(line)
   end
 end
diff --git a/text_tests.lua b/text_tests.lua
index 2a6c45d..5c21038 100644
--- a/text_tests.lua
+++ b/text_tests.lua
@@ -184,6 +184,27 @@ function test_click_on_wrapping_line()
   check_eq(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()
+  io.write('\ntest_click_on_wrapping_line_rendered_from_partway_at_top_of_screen')
+  -- display a wrapping line from its second screen line
+  App.screen.init{width=80, height=80}
+                  --  12345678901234
+  Lines = load_array{"madam I'm adam"}
+  Line_width = 75
+  Cursor1 = {line=1, pos=8}
+  Screen_top1 = {line=1, pos=7}
+  Screen_bottom1 = {}
+  App.draw()
+  local y = 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
+  -- 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')
+end
+
 function test_click_past_end_of_wrapping_line()
   io.write('\ntest_click_past_end_of_wrapping_line')
   -- display a wrapping line