diff --git a/main.lua b/main.lua index d058e53..0cd5274 100644 --- a/main.lua +++ b/main.lua @@ -12,6 +12,7 @@ require 'icons' -- a text is a table with: -- mode = 'text' -- string data +-- 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), @@ -126,7 +127,6 @@ function love.draw() y = y + Drawing.pixels(line.h) + 10 -- padding else line.y = y ---? y = Text.draw(line, 100, line_index, Cursor_line, Cursor_pos) y = Text.draw(line, Line_width, line_index, Cursor_line, Cursor_pos) y = y + math.floor(15*Zoom) -- text height end @@ -145,7 +145,7 @@ function love.mousepressed(x,y, mouse_button) for line_index,line in ipairs(Lines) do if line.mode == 'text' then if Text.in_line(line, x,y) then - Text.move_cursor(line_index, line, x) + Text.move_cursor(line_index, line, x, y) end elseif line.mode == 'drawing' then if Drawing.in_drawing(line, x, y) then diff --git a/text.lua b/text.lua index 4f992d5..216ba32 100644 --- a/text.lua +++ b/text.lua @@ -39,8 +39,6 @@ function Text.compute_fragments(line, line_width) end function Text.draw(line, line_width, line_index, cursor_line, cursor_pos) ---? love.graphics.setColor(0.75,0.75,0.75) ---? love.graphics.line(line_width, 0, line_width, Screen_height) love.graphics.setColor(0,0,0) -- wrap long lines local x = 25 @@ -57,6 +55,11 @@ function Text.draw(line, line_width, line_index, cursor_line, cursor_pos) assert(x > 25) -- no overfull lines y = y + math.floor(15*Zoom) x = 25 + if line.screen_line_starting_pos == nil then + line.screen_line_starting_pos = {1, pos} + else + table.insert(line.screen_line_starting_pos, pos) + end end love.graphics.draw(frag_text, x,y, 0, Zoom) -- render cursor if necessary @@ -267,13 +270,55 @@ end function Text.in_line(line, x,y) if line.y == nil then return false end -- outside current page - return x >= 16 and y >= line.y and y < line.y + math.floor(15*Zoom) + if x < 16 then return false end + if y < line.y then return false end + if line.screen_line_starting_pos == nil then return y < line.y + math.floor(15*Zoom) end + return y < line.y + #line.screen_line_starting_pos * math.floor(15*Zoom) end -function Text.move_cursor(line_index, line, mx) +function Text.move_cursor(line_index, line, mx, my) Cursor_line = line_index - Cursor_pos = Text.nearest_cursor_pos(line.data, mx) + if line.screen_line_starting_pos == nil then +--? print('single screen line') + Cursor_pos = Text.nearest_cursor_pos(line.data, mx) + return + end + assert(line.fragments) + assert(my >= line.y) +--? print('move_cursor', mx, my) + if my < line.y + math.floor(15*Zoom) then +--? print('first screen line') + Cursor_pos = Text.nearest_cursor_pos(line.data, mx) + return + end + -- duplicate some logic from Text.draw + local y = line.y + for _,screen_line_starting_pos in ipairs(line.screen_line_starting_pos) do +--? print('screen line:', screen_line_starting_pos) + local nexty = y + math.floor(15*Zoom) + if my < nexty then + local s = string.sub(line.data, screen_line_starting_pos) + Cursor_pos = screen_line_starting_pos + Text.nearest_cursor_pos(s, mx) - 1 + return + end + y = nexty + end + assert(false) end +-- manual test: +-- line: abc +-- def +-- gh +-- fragments: abc, def, gh +-- click inside e +-- line_starting_pos = 1 + 3 = 4 +-- nearest_cursor_pos('defgh', mx) = 2 +-- Cursor_pos = 4 + 2 - 1 = 5 +-- manual test: +-- click inside h +-- line_starting_pos = 1 + 3 + 3 = 7 +-- nearest_cursor_pos('gh', mx) = 2 +-- Cursor_pos = 7 + 2 - 1 = 8 function Text.nearest_cursor_pos(line, x, hint) if x == 0 then