Grotesque duplication, but it's something working.
I'm not sure line_cache is the place to put the expanded state. Resizing clears it.
AIP57TM4LFTWNVGTPJQXKAIY3H5CJWNG5LMK6ZH7LW7CICVP5O2AC
MUJTM6REGQAK3LZTIFWGJRXE2UPCM4HSLXQYSF5ITLXLS6JCVPMQC
GSIYZ7K25HG2BYKUF3G5JKI4M3MBWC2LRC5KJIHKG2JES6GYX5DAC
BULPIBEGL7TMK6CVIE7IS7WGAHGOSUJBGJSFQK542MOWGHP2ADQQC
ILOA5BYFTQKBSHLFMMZUVPQ2JXBFJD62ERQFBTDK2WSRXUN525VQC
H2DPLWMVRFYTO2CQTG54FMT2LF3B6UKLXH32CUA22DNQJVP5XBNQC
QYIFOHW3WDDQMK4ATY6IOSQRFHJOQ5QCPDKRC4GVGWLQEH4HGWVQC
local frag, frag_text = f.data, f.text
local frag_len = utf8.len(frag)
--? print('text.draw:', frag, 'at', line_index,pos, 'after', x,y)
if pos < startpos then
-- render nothing
--? print('skipping', frag)
else
-- render fragment
local frag_width = App.width(frag_text)
if x + frag_width > State.right then
assert(x > State.left) -- no overfull lines
y = y + State.line_height
if y + State.line_height > App.screen.height then
return --[[screen filled]] true, x,y, pos, screen_line_starting_pos
end
screen_line_starting_pos = pos
x = State.left
end
if State.selection1.line then
local lo, hi = Text.clip_selection(State, line_index, pos, pos+frag_len)
Text.draw_highlight(State, line, x,y, pos, lo,hi)
end
App.screen.draw(frag_text, x,y)
-- render cursor if necessary
if line_index == State.cursor1.line then
if pos <= State.cursor1.pos and pos + frag_len > State.cursor1.pos then
if State.search_term then
if State.lines[State.cursor1.line].data:sub(State.cursor1.pos, State.cursor1.pos+utf8.len(State.search_term)-1) == State.search_term then
local lo_px = Text.draw_highlight(State, line, x,y, pos, State.cursor1.pos, State.cursor1.pos+utf8.len(State.search_term))
App.color(Text_color)
love.graphics.print(State.search_term, x+lo_px,y)
end
else
Text.draw_cursor(State, x+Text.x(frag, State.cursor1.pos-pos+1), y)
end
end
end
x = x + frag_width
end
pos = pos + frag_len
end
return false, x,y, pos, screen_line_starting_pos
end
function Text.draw_wrapping_line2(State, line_index, x,y, startpos)
local line = State.lines[line_index]
local line_cache = State.line_cache[line_index]
local screen_line_starting_pos = startpos
Text.populate_screen_line_starting_pos2(State, line_index, x)
local pos = 1
for _, f in ipairs(line_cache.fragments2) do
local frag_text = App.newText(love.graphics.getFont(), frag)
local frag_width = App.width(frag_text)
--? print('x: '..tostring(x)..'; '..tostring(State.right-x)..'px to go')
while x + frag_width > State.right do
--? print(('checking whether to split fragment ^%s$ of width %d when rendering from %d'):format(frag, frag_width, x))
if (x-State.left) < 0.8 * (State.right-State.left) then
--? print('splitting')
-- long word; chop it at some letter
-- We're not going to reimplement TeX here.
local bpos = Text.nearest_pos_less_than(frag, State.right - x)
--? print('bpos', bpos)
if bpos == 0 then break end -- avoid infinite loop when window is too narrow
local boffset = Text.offset(frag, bpos+1) -- byte _after_ bpos
--? print('space for '..tostring(bpos)..' graphemes, '..tostring(boffset-1)..' bytes')
local frag1 = string.sub(frag, 1, boffset-1)
local frag1_text = App.newText(love.graphics.getFont(), frag1)
local frag1_width = App.width(frag1_text)
--? print('extracting ^'..frag1..'$ of width '..tostring(frag1_width)..'px')
assert(x + frag1_width <= State.right)
table.insert(result, {data=frag1, text=frag1_text})
frag = string.sub(frag, boffset)
frag_text = App.newText(love.graphics.getFont(), frag)
frag_width = App.width(frag_text)
end
x = State.left -- new line
end
if #frag > 0 then
--? print('inserting ^'..frag..'$ of width '..tostring(frag_width)..'px')
table.insert(result, {data=frag, text=frag_text})
end
x = x + frag_width
end
return result
end
function Text.populate_screen_line_starting_pos2(State, line_index, x)
local line = State.lines[line_index]
local line_cache = State.line_cache[line_index]
if line_cache.screen_line_starting_pos2 then
return
end
-- duplicate some logic from Text.draw
if line_cache.fragments2 == nil then
line_cache.fragments2 = Text.compute_fragments2(State, line, x)
end
line_cache.screen_line_starting_pos2 = {1}
local pos = 1
for _, f in ipairs(line_cache.fragments2) do
local frag, frag_text = f.data, f.text
-- render fragment
local frag_width = App.width(frag_text)
if x + frag_width > State.right then
x = State.left
table.insert(line_cache.screen_line_starting_pos2, pos)
end
x = x + frag_width
local frag_len = utf8.len(frag)
pos = pos + frag_len
end
end
function Text.compute_fragments2(State, line, x)
--? print('compute_fragments2', line_index, 'between', x, State.right)
local result = {}
-- try to wrap at word boundaries
for frag in line.data2:gmatch('%S*%s*') do