bugfix: crash in Text.up() after return
Let's just make all the utf8.offset calculations more defensive.
This commit is contained in:
parent
b6fa2aae6e
commit
703ed905c1
4
main.lua
4
main.lua
|
@ -422,7 +422,7 @@ function App.keychord_pressed(chord)
|
|||
Search_backup = nil
|
||||
elseif chord == 'backspace' then
|
||||
local len = utf8.len(Search_term)
|
||||
local byte_offset = utf8.offset(Search_term, len)
|
||||
local byte_offset = Text.offset(Search_term, len)
|
||||
Search_term = string.sub(Search_term, 1, byte_offset-1)
|
||||
Search_text = nil
|
||||
elseif chord == 'down' then
|
||||
|
@ -537,7 +537,7 @@ function App.keychord_pressed(chord)
|
|||
p.name = nil
|
||||
elseif chord == 'backspace' then
|
||||
local len = utf8.len(p.name)
|
||||
local byte_offset = utf8.offset(p.name, len-1)
|
||||
local byte_offset = Text.offset(p.name, len-1)
|
||||
p.name = string.sub(p.name, 1, byte_offset)
|
||||
end
|
||||
record_undo_event({before=before, after=snapshot(Lines.current_drawing_index)})
|
||||
|
|
14
select.lua
14
select.lua
|
@ -55,9 +55,9 @@ end
|
|||
-- Returns some intermediate computation useful elsewhere.
|
||||
function Text.draw_highlight(line, x,y, pos, lo,hi)
|
||||
if lo then
|
||||
local lo_offset = utf8.offset(line.data, lo)
|
||||
local hi_offset = utf8.offset(line.data, hi)
|
||||
local pos_offset = utf8.offset(line.data, pos)
|
||||
local lo_offset = Text.offset(line.data, lo)
|
||||
local hi_offset = Text.offset(line.data, hi)
|
||||
local pos_offset = Text.offset(line.data, pos)
|
||||
local lo_px
|
||||
if pos == lo then
|
||||
lo_px = 0
|
||||
|
@ -137,8 +137,8 @@ function Text.delete_selection_without_undo()
|
|||
-- delete everything between min (inclusive) and max (exclusive)
|
||||
Lines[minl].fragments = nil
|
||||
Lines[minl].screen_line_starting_pos = nil
|
||||
local min_offset = utf8.offset(Lines[minl].data, minp)
|
||||
local max_offset = utf8.offset(Lines[maxl].data, maxp)
|
||||
local min_offset = Text.offset(Lines[minl].data, minp)
|
||||
local max_offset = Text.offset(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)
|
||||
|
@ -165,8 +165,8 @@ function Text.selection()
|
|||
minp,maxp = maxp,minp
|
||||
end
|
||||
end
|
||||
local min_offset = utf8.offset(Lines[minl].data, minp)
|
||||
local max_offset = utf8.offset(Lines[maxl].data, maxp)
|
||||
local min_offset = Text.offset(Lines[minl].data, minp)
|
||||
local max_offset = Text.offset(Lines[maxl].data, maxp)
|
||||
if minl == maxl then
|
||||
return Lines[minl].data:sub(min_offset, max_offset-1)
|
||||
end
|
||||
|
|
51
text.lua
51
text.lua
|
@ -113,8 +113,7 @@ function Text.compute_fragments(line, line_width)
|
|||
-- We're not going to reimplement TeX here.
|
||||
local bpos = Text.nearest_pos_less_than(frag, line_width - x)
|
||||
assert(bpos > 0) -- avoid infinite loop when window is too narrow
|
||||
local boffset = utf8.offset(frag, bpos+1) -- byte _after_ bpos
|
||||
assert(boffset)
|
||||
local boffset = Text.offset(frag, bpos+1) -- byte _after_ bpos
|
||||
--? print('space for '..tostring(bpos)..' graphemes, '..tostring(boffset)..' bytes')
|
||||
local frag1 = string.sub(frag, 1, boffset-1)
|
||||
local frag1_text = App.newText(love.graphics.getFont(), frag1)
|
||||
|
@ -156,16 +155,7 @@ function Text.textinput(t)
|
|||
end
|
||||
|
||||
function Text.insert_at_cursor(t)
|
||||
local byte_offset
|
||||
if Cursor1.pos > 1 then
|
||||
byte_offset = utf8.offset(Lines[Cursor1.line].data, Cursor1.pos)
|
||||
else
|
||||
byte_offset = 1
|
||||
end
|
||||
if byte_offset == nil then
|
||||
print(Cursor1.line, Cursor1.pos, byte_offset, Lines[Cursor1.line].data)
|
||||
assert(false)
|
||||
end
|
||||
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)
|
||||
Lines[Cursor1.line].fragments = nil
|
||||
Lines[Cursor1.line].screen_line_starting_pos = nil
|
||||
|
@ -174,7 +164,7 @@ end
|
|||
|
||||
-- Don't handle any keys here that would trigger love.textinput above.
|
||||
function Text.keychord_pressed(chord)
|
||||
--? print(chord)
|
||||
--? print('chord')
|
||||
--== shortcuts that mutate text
|
||||
if chord == 'return' then
|
||||
local before_line = Cursor1.line
|
||||
|
@ -380,10 +370,7 @@ function Text.keychord_pressed(chord)
|
|||
end
|
||||
|
||||
function Text.insert_return()
|
||||
local byte_offset = utf8.offset(Lines[Cursor1.line].data, Cursor1.pos)
|
||||
--? print(Cursor1.line, Cursor1.pos, #Lines[Cursor1.line].data)
|
||||
--? print(Lines[Cursor1.line].data)
|
||||
assert(byte_offset)
|
||||
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)
|
||||
Lines[Cursor1.line].fragments = nil
|
||||
|
@ -465,8 +452,7 @@ function Text.up()
|
|||
Screen_top1.pos = screen_line_starting_pos
|
||||
--? print('pos of top of screen is also '..tostring(Screen_top1.pos)..' of the same line')
|
||||
end
|
||||
local screen_line_starting_byte_offset = utf8.offset(Lines[Cursor1.line].data, screen_line_starting_pos)
|
||||
assert(screen_line_starting_byte_offset)
|
||||
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) - 1
|
||||
break
|
||||
|
@ -485,8 +471,7 @@ function Text.up()
|
|||
Screen_top1.pos = new_screen_line_starting_pos
|
||||
--? print('also setting pos of top of screen to '..tostring(Screen_top1.pos))
|
||||
end
|
||||
local new_screen_line_starting_byte_offset = utf8.offset(Lines[Cursor1.line].data, new_screen_line_starting_pos)
|
||||
assert(new_screen_line_starting_byte_offset)
|
||||
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) - 1
|
||||
--? print('cursor pos is now '..tostring(Cursor1.pos))
|
||||
|
@ -525,8 +510,7 @@ function Text.down()
|
|||
local screen_line_index, screen_line_starting_pos = Text.pos_at_start_of_cursor_screen_line()
|
||||
new_screen_line_starting_pos = Lines[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 = utf8.offset(Lines[Cursor1.line].data, new_screen_line_starting_pos)
|
||||
assert(new_screen_line_starting_byte_offset)
|
||||
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) - 1
|
||||
--? print('cursor pos is now', Cursor1.line, Cursor1.pos)
|
||||
|
@ -544,7 +528,7 @@ function Text.word_left()
|
|||
Text.left()
|
||||
if Cursor1.pos == 1 then break end
|
||||
assert(Cursor1.pos > 1)
|
||||
local offset = utf8.offset(Lines[Cursor1.line].data, Cursor1.pos)
|
||||
local offset = Text.offset(Lines[Cursor1.line].data, Cursor1.pos)
|
||||
assert(offset > 1)
|
||||
if Lines[Cursor1.line].data:sub(offset-1,offset-1) == ' ' then
|
||||
break
|
||||
|
@ -556,7 +540,7 @@ function Text.word_right()
|
|||
while true do
|
||||
Text.right()
|
||||
if Cursor1.pos > utf8.len(Lines[Cursor1.line].data) then break end
|
||||
local offset = utf8.offset(Lines[Cursor1.line].data, Cursor1.pos)
|
||||
local offset = Text.offset(Lines[Cursor1.line].data, Cursor1.pos)
|
||||
if Lines[Cursor1.line].data:sub(offset,offset) == ' ' then -- TODO: other space characters
|
||||
break
|
||||
end
|
||||
|
@ -696,8 +680,7 @@ function Text.to_pos_on_line(line, mx, my)
|
|||
-- 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 = utf8.offset(line.data, screen_line_starting_pos)
|
||||
assert(screen_line_starting_byte_offset)
|
||||
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
|
||||
|
@ -802,8 +785,7 @@ function Text.nearest_pos_less_than(line, x) -- x DOES NOT include left margin
|
|||
end
|
||||
|
||||
function Text.x(s, pos)
|
||||
local offset = utf8.offset(s, pos)
|
||||
assert(offset)
|
||||
local offset = Text.offset(s, pos)
|
||||
local s_before = s:sub(1, offset-1)
|
||||
local text_before = App.newText(love.graphics.getFont(), s_before)
|
||||
return App.width(text_before)
|
||||
|
@ -859,6 +841,17 @@ function Text.le1(a, b)
|
|||
return a.pos <= b.pos
|
||||
end
|
||||
|
||||
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(pos1, #s, s)
|
||||
end
|
||||
assert(result)
|
||||
return result
|
||||
end
|
||||
|
||||
function Text.previous_screen_line(pos2)
|
||||
if pos2.screen_line > 1 then
|
||||
return {line=pos2.line, screen_line=pos2.screen_line-1, screen_pos=1}
|
||||
|
|
Loading…
Reference in New Issue