Still no testing, and tons of duplication. But I colorized the A and B variables separately, took screenshots and compared that the colors are in the right place for the duplicated code. So at least I've updated ___B variables in the right places.
CG5PH4DWFEUEICYJAPPGAMDCCTOGUB7475IC5IFKSB4ADL2KCJZQC
MUJTM6REGQAK3LZTIFWGJRXE2UPCM4HSLXQYSF5ITLXLS6JCVPMQC
5FW7YOFTLKHRND6IOR4HG4X3C5BO2WV5KTEUW3PPKCRU5L5GXKXQC
FKNXK2OAH4U2V2TXCHWE4C3Z5DROBIIPSXUWFKP7Q3DSNOKFFL5AC
BULPIBEGL7TMK6CVIE7IS7WGAHGOSUJBGJSFQK542MOWGHP2ADQQC
ILOA5BYFTQKBSHLFMMZUVPQ2JXBFJD62ERQFBTDK2WSRXUN525VQC
QCPXQ2E3USF3Z6R6WJ2JKHTRMPKA6QWXFKKRMLXA3MXABJEL543AC
5L7K4GBDEAFH44LMLNKVFMHLWDNXXBKRPEI347VE5ZLXVFSMD2FAC
EKKFWP4D2MNOHU265UCJU37KIFQV424CRLVASQMHDYUYY5T67D3QC
4VKEE43Z7MUPNIAOCK36INVBNHRTSWRRN37TIKRPXPH3DRKGHHAQC
MXA3RZYKUI4UF2ISY7JEF6VKX6NOPZMZH5SLLCZHRJKFIXXXDPSAC
MD3W5IRAC6UQALQE4LJC52VQNDO3I3HXF3XE2XHDABXBYJBUVAXQC
BOFNXP5GZDCUMQG3LQVTSSFEQP7REQ4RIRJLDLETFSAGFTVDVEKAC
-- scenarios:
-- line without B side
-- line with B side collapsed
-- line with B side expanded
-- line starting rendering in A side (startpos ~= nil)
-- line starting rendering in B side (startposB ~= nil)
-- my on final screen line of A side
-- mx to right of A side with no B side
-- mx to right of A side but left of B side
-- mx to right of B side
-- preconditions:
-- startpos xor startposB
-- expanded -> dataB
local start_screen_line_index = Text.screen_line_index(line_cache.screen_line_starting_pos, line_cache.startpos)
for screen_line_index = start_screen_line_index,#line_cache.screen_line_starting_pos do
local screen_line_starting_pos = line_cache.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))
if line_cache.startpos then
local start_screen_line_index = Text.screen_line_index(line_cache.screen_line_starting_pos, line_cache.startpos)
for screen_line_index = start_screen_line_index,#line_cache.screen_line_starting_pos do
local screen_line_starting_pos = line_cache.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 + State.line_height
if my < nexty then
-- On all wrapped screen lines but the final one, clicks past end of
-- line position cursor on final character of screen line.
-- (The final screen line positions past end of screen line as always.)
if screen_line_index < #line_cache.screen_line_starting_pos and mx > State.left + Text.screen_line_width(State, line_index, screen_line_index) then
--? print('past end of non-final line; return')
return line_cache.screen_line_starting_pos[screen_line_index+1]-1
end
local s = string.sub(line.data, screen_line_starting_byte_offset)
--? print('return', mx, Text.nearest_cursor_pos(s, mx, State.left), '=>', screen_line_starting_pos + Text.nearest_cursor_pos(s, mx, State.left) - 1)
if not line.expanded then
-- no B side
return screen_line_starting_pos + Text.nearest_cursor_pos(s, mx, State.left) - 1
else
local screen_line_posA = Text.nearest_cursor_pos(s, mx, State.left)
if not line.expanded then
-- B side is not expanded
return screen_line_starting_pos + screen_line_posA - 1
end
local lenA = utf8.len(s)
if screen_line_posA < lenA then
-- mx is within A side
return screen_line_starting_pos + screen_line_posA - 1
end
local max_xA = left+Text.x(s, len+1)
if mx < max_xA + AB_padding then
-- mx is in the space between A and B side
return screen_line_starting_pos + screen_line_posA - 1
end
local mx = mx - max_xA - AB_padding
local screen_line_posB = Text.nearest_cursor_pos(line.dataB, mx, --[[no left margin]] 0)
return nil, screen_line_posB
end
end
y = nexty
end
end
-- look in screen lines composed entirely of the B side
assert(line.expanded)
assert(line_cache.startposB)
local start_screen_line_indexB = Text.screen_line_indexB(line_cache.screen_line_starting_posB, line_cache.startposB)
for screen_line_indexB = start_screen_line_indexB,#line_cache.screen_line_starting_posB do
local screen_line_starting_posB = line_cache.screen_line_starting_posB[screen_line_indexB]
local screen_line_starting_byte_offsetB = Text.offset(line.dataB, screen_line_starting_posB)
--? print('iter', y, screen_line_indexB, screen_line_starting_pos, string.sub(line.dataB, screen_line_starting_byte_offsetB))
if screen_line_index < #line_cache.screen_line_starting_pos and mx > State.left + Text.screen_line_width(State, line_index, screen_line_index) then
if screen_line_indexB < #line_cache.screen_line_starting_posB and mx > State.left + Text.screen_line_widthB(State, line_index, screen_line_indexB) then
local s = string.sub(line.data, screen_line_starting_byte_offset)
--? print('return', mx, Text.nearest_cursor_pos(s, mx, State.left), '=>', screen_line_starting_pos + Text.nearest_cursor_pos(s, mx, State.left) - 1)
return screen_line_starting_pos + Text.nearest_cursor_pos(s, mx, State.left) - 1
local s = string.sub(line.dataB, screen_line_starting_byte_offsetB)
--? print('return', mx, Text.nearest_cursor_pos(s, mx, State.left), '=>', screen_line_starting_posB + Text.nearest_cursor_pos(s, mx, State.left) - 1)
return screen_line_starting_posB + Text.nearest_cursor_pos(s, mx, State.left) - 1