QCPXQ2E3USF3Z6R6WJ2JKHTRMPKA6QWXFKKRMLXA3MXABJEL543AC WLJCIXYMSTCNSYCFOEBQNDLBZ5D2Z3WTF4E4WYL5CFGIJ434FKNQC 3MAZEQK5AR3IJJ2ENHHYDPDICIK645NE5QWR54Z52BHGHE6VR5XQC BULPIBEGL7TMK6CVIE7IS7WGAHGOSUJBGJSFQK542MOWGHP2ADQQC SPSW74Y5OJ54Y7VQ3SJFCJR5CYDKTR4A3TOEVZODDZLUSDDU2GZAC 3TDOZESEOYHGF6LYKR6PYSPNFI3QUGED2BKM5LUDEKJKRIX3ACEAC OGUV4HSA7XGSQLUVWBAE3AE263Z7Z6G3BZOB4CN2AOYD2DEJMOZAC LF7BWEG4DKQI7NMXMZC4LC2BE5PB42HK5PD6OYBNIDMAZBJASOKQC HMODUNJEQLZ3W46GKYIDL55F6COVXHTIC6UW4AK3SXOOKOPE6NNAC XNFTJHC4QSHNSIWNN7K6QZEZ37GTQYKHS4EPNSVPQCUSWREROGIQC KOYAJWE4NJ2J4X3SHEAVMRXYZPZGOMTI7OX3PTUQIDIZ2GQI6UKAC Z5HLXU4PJWWJJDBCK52NBD6PIRIA3TAN2BKZB5HBYFGIDBX4F5HAC 2CH77LZCSHAKRKLCCJGDGECVYFNCEV23NF3PFXHAQ2E33AJGSNVAC ZPUQSPQPQFVRUIHGLAWW3IDBYODIWDHO62HAC3WWF5TM3CIJGHNQC 2LOQ5ALJYHWSMU7ROSKD66BYGMK3O6HYNUQMGCZVKTRDOLEI75NQC CVSRHMJ2BM4LPVG67ULIVQMP2NW3YY2JC2ZQBEA6EB5KVM4O2L5AC KZ5GAYRPWF2BA5VEIW3A4G2TULATBL7YEDGFJU42GBP5DET7BI3AC GGJEDJOOKE5LM5KERQOWLM5FRIJGIF5UZBFPGY4F4MWBHY6Y5YUQC QCQTMUZ7M3BKJFTKXTTXL4TS4CAQNIUNK3LR3WQIJDU3VVTOPS6AC YJJ4X4JGABMVA5JBQW5UAWI543P3Y7NDVFTOHA6LIDA5KSFGUFNQC HTWAM4NZFOY463TNSKYIM2EWB7QNBGDRRTTGHF5N3Z4TGC7Q3SFAC 62PZGSUCEXJOCVWEOOENSDJITJFR27BGW7BPGFYVD3E5M6446RQQC KECEMMMRW2VVBZ567HJQPGLC57LTSBKWH7UFP32IW43D23X6WTEQC F65ADDGLR2PNXVSM2XBHM3OSLQC2OTRR3GQBI7DJWIKPJCJ5CSOAC 5OALPNN3FGDKFM4K5EQZV6FU6GCKHEVSJDXM6XFFC7LGXES7GLWQC HYEAFRZ2UEKDYTAE2GDQLHEJBPQASP2NDLMXB7F6MTVK2BKOXKEAC PR4KIAZDOBQMEUOV2G7ZEZUW3E4L5ZCHYSS7PTYWGXPSNVRAGHCAC 242L3OQXTU2TCAINRJXQEEDSXQXM7Y7USUPBK37ZNM3A7V5TUDSAC MDXGMZU2MBEDMTB755D3RRYEFKF54GTTYTI5XJYKKKN5ZFQWZXTAC KOTI3MFGQ4PDS4I75JIJG734LTET6745VGTSMNFYYASVIO6H2KPAC TRNWIQN6RPLDLYWULLKG5L255E7E3DPNGLCSLAF6IJWYQRCCLARQC 3OKKTUT4Q7W44JHILOFV5BVUA7ZOBIHBCEXGZ65CPXV4PRLI2W4QC CTJ3IZGSPY4DBHC6OYNL4DZE24MXYQBM3KVJZTQHM5DI5TED5ZLQC MYC7XR5QOT2AXHF6UNGSNFFD5VL6UHGUZQBP7PWWLZ5NNXE7UMTAC UV4EWOLYCQ27TL6IGGLKNQX3UUOF7HJ5EJVCZYW345X6BK4J7YQAC 5FW7YOFTLKHRND6IOR4HG4X3C5BO2WV5KTEUW3PPKCRU5L5GXKXQC K4OBZSHEBIZBAKPH3F7ASDGCPLB7D5W5QLFJQYSM5XOYDPB4BUHAC U52E2XZNDEMIX5QJC6TREX5BSLNYG23Y4XQVFFKS6OFB2KIBW7BAC CPZGQT72EBP3SEDBPDWQRK5IUGA664PHXNP2GOHJLP43PKPWF25AC BOFNXP5GZDCUMQG3LQVTSSFEQP7REQ4RIRJLDLETFSAGFTVDVEKAC 2RXZ3PGOTTZ6M4R372JXIKPLBQKPVBMAXNPIEO2HZDN4EMYW4GNAC H2DPLWMVRFYTO2CQTG54FMT2LF3B6UKLXH32CUA22DNQJVP5XBNQC EGH7XDBKE3R74VXLNTCAP5LJTRBPFUEMPS647MJARDGCMUHJG2QQC MP2TBKU6CNDMZKENYMBV62F5KQ27ZWEVPVRFS2RESVDQQT2IRR4AC AYE2VEGJ63AWWX76SFQZLOTBIZOQRWBG4AZMIOSVOI2WZVRQJXYAC HOSPP2ANSW654DYRTC6CQUQA2GUKV6T2FI7QBKXD2DZS3R32IMGAC GK47BBCYVEZ3OEQ7ISE2WCJULAFZ35WC6EYJ5CTBYNM26RSAELOQC WOXIYUTL4NU7ACHQYXEXJDSXCRDLQ2X457KO6C7GEXFQZ43F3L7QC QLTJG7Q33ABBTDJ55K3OPLNSYBFBIVRS3UABXEY73RHYMOOJ542QC LXTTOB33N2HCUZFIUDRQGGBVHK2HODRG4NBLH6RXRQZDCHF27BSAC RF5ALVNYB2FMU7LRRD5LMQC7P6OO4BX3NXIGWNZTQ2CD62RBRRFAC K464QQR4FTXFUMHFWAGOD5DJ6YHUBUKRHLXF2ORE74DVT7TVQ35QC OTIBCAUJ3KDQJLVDN3A536DLZGNRYMGJLORZVR3WLCGXGO6UGO6AC PX7DDEMOBGPVK3FXKK5XEPG24CJXZSVW67DLG2JZZ5E77NVEAA3AC 2L5MEZV344TOZLVY3432RHJFIRVXFD6O3GWLL5O4CV66BGAFTURQC LNUHQOGHIOFGJXNGA3DZLYEASLYYDGLN2I3EDZY5ANASQAHCG3YQC PTDO2SOTXEI6FROZ2AVRFXSKKNKCRMPPTQSI5LWD45UVGDJPMSGQC local top2 = Text.to2(State.screen_top1, State.margin_left, App.screen.width-State.margin_right)top2 = Text.previous_screen_line(top2, State.margin_left, App.screen.width-State.margin_right)State.screen_top1 = Text.to1(top2)Text.redraw_all() -- if we're scrolling, reclaim all fragments to avoid memory leaks
local top2 = Text.to2(State, State.screen_top1, State.margin_left, App.screen.width-State.margin_right)top2 = Text.previous_screen_line(State, top2, State.margin_left, App.screen.width-State.margin_right)State.screen_top1 = Text.to1(State, top2)Text.redraw_all(State) -- if we're scrolling, reclaim all fragments to avoid memory leaks
local top2 = Text.to2(State.screen_top1, left, right)top2 = Text.previous_screen_line(top2, left, right)State.screen_top1 = Text.to1(top2)
local top2 = Text.to2(State, State.screen_top1, left, right)top2 = Text.previous_screen_line(State, top2, left, right)State.screen_top1 = Text.to1(State, top2)
function Text.cursor_at_final_screen_line(left, right)Text.populate_screen_line_starting_pos(Editor_state.lines[Editor_state.cursor1.line], left, right)local screen_lines = Editor_state.lines[Editor_state.cursor1.line].screen_line_starting_pos--? print(screen_lines[#screen_lines], Editor_state.cursor1.pos)return screen_lines[#screen_lines] <= Editor_state.cursor1.pos
function Text.cursor_at_final_screen_line(State, left, right)Text.populate_screen_line_starting_pos(State.lines[State.cursor1.line], left, right)local screen_lines = State.lines[State.cursor1.line].screen_line_starting_pos--? print(screen_lines[#screen_lines], State.cursor1.pos)return screen_lines[#screen_lines] <= State.cursor1.pos
function Text.move_cursor_down_to_next_text_line_while_scrolling_again_if_necessary(left, right)local y = Editor_state.margin_topwhile Editor_state.cursor1.line <= #Editor_state.lines doif Editor_state.lines[Editor_state.cursor1.line].mode == 'text' then
function Text.move_cursor_down_to_next_text_line_while_scrolling_again_if_necessary(State, left, right)local y = State.margin_topwhile State.cursor1.line <= #State.lines doif State.lines[State.cursor1.line].mode == 'text' then
--? print('cursor skips', Editor_state.cursor1.line)y = y + Editor_state.drawing_padding_height + Drawing.pixels(Editor_state.lines[Editor_state.cursor1.line].h)Editor_state.cursor1.line = Editor_state.cursor1.line + 1
--? print('cursor skips', State.cursor1.line)y = y + State.drawing_padding_height + Drawing.pixels(State.lines[State.cursor1.line].h)State.cursor1.line = State.cursor1.line + 1
if Editor_state.cursor1.line > #Editor_state.lines thenassert(Editor_state.cursor1.line == #Editor_state.lines+1)table.insert(Editor_state.lines, {mode='text', data=''})
if State.cursor1.line > #State.lines thenassert(State.cursor1.line == #State.lines+1)table.insert(State.lines, {mode='text', data=''})
-- should never modify Editor_state.cursor1function Text.snap_cursor_to_bottom_of_screen(left, right)local top2 = Text.to2(Editor_state.cursor1, left, right)
-- should never modify State.cursor1function Text.snap_cursor_to_bottom_of_screen(State, left, right)local top2 = Text.to2(State, State.cursor1, left, right)
--? print('cursor pos '..tostring(Editor_state.cursor1.pos)..' is on the #'..tostring(top2.screen_line)..' screen line down')local y = App.screen.height - Editor_state.line_height
--? print('cursor pos '..tostring(State.cursor1.pos)..' is on the #'..tostring(top2.screen_line)..' screen line down')local y = App.screen.height - State.line_height
if top2.screen_line > 1 or Editor_state.lines[top2.line-1].mode == 'text' thenlocal h = Editor_state.line_heightif y - h < Editor_state.margin_top then
if top2.screen_line > 1 or State.lines[top2.line-1].mode == 'text' thenlocal h = State.line_heightif y - h < State.margin_top then
local h = Editor_state.drawing_padding_height + Drawing.pixels(Editor_state.lines[top2.line-1].h)if y - h < Editor_state.margin_top then
local h = State.drawing_padding_height + Drawing.pixels(State.lines[top2.line-1].h)if y - h < State.margin_top then
Editor_state.screen_top1 = Text.to1(top2)--? print('top1 finally:', Editor_state.screen_top1.line, Editor_state.screen_top1.pos)Text.redraw_all() -- if we're scrolling, reclaim all fragments to avoid memory leaks
State.screen_top1 = Text.to1(State, top2)--? print('top1 finally:', State.screen_top1.line, State.screen_top1.pos)Text.redraw_all(State) -- if we're scrolling, reclaim all fragments to avoid memory leaks
return y < line.starty + Editor_state.line_height*(#line.screen_line_starting_pos - Text.screen_line_index(line, line.startpos) + 1)
return y < line.starty + State.line_height*(#line.screen_line_starting_pos - Text.screen_line_index(line, line.startpos) + 1)
-- 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-- Editor_state.cursor1.pos = 4 + 2 - 1 = 5-- manual test:-- click inside h-- line_starting_pos = 1 + 3 + 3 = 7-- nearest_cursor_pos('gh', mx) = 2-- Editor_state.cursor1.pos = 7 + 2 - 1 = 8
Text.populate_screen_line_starting_pos(Editor_state.lines[pos1.line], left, right)for i=#Editor_state.lines[pos1.line].screen_line_starting_pos,1,-1 dolocal spos = Editor_state.lines[pos1.line].screen_line_starting_pos[i]
Text.populate_screen_line_starting_pos(State.lines[pos1.line], left, right)for i=#State.lines[pos1.line].screen_line_starting_pos,1,-1 dolocal spos = State.lines[pos1.line].screen_line_starting_pos[i]
local l = Editor_state.lines[pos2.line-1]Text.populate_screen_line_starting_pos(Editor_state.lines[pos2.line-1], left, right)return {line=pos2.line-1, screen_line=#Editor_state.lines[pos2.line-1].screen_line_starting_pos, screen_pos=1}
local l = State.lines[pos2.line-1]Text.populate_screen_line_starting_pos(State.lines[pos2.line-1], left, right)return {line=pos2.line-1, screen_line=#State.lines[pos2.line-1].screen_line_starting_pos, screen_pos=1}
function Text.tweak_screen_top_and_cursor(left, right)--? print('a', Editor_state.selection1.line)if Editor_state.screen_top1.pos == 1 then return endlocal line = Editor_state.lines[Editor_state.screen_top1.line]
-- resize helperfunction Text.tweak_screen_top_and_cursor(State, left, right)--? print('a', State.selection1.line)if State.screen_top1.pos == 1 then return endlocal line = State.lines[State.screen_top1.line]
if Text.lt1(Editor_state.cursor1, Editor_state.screen_top1) thenEditor_state.cursor1 = {line=Editor_state.screen_top1.line, pos=Editor_state.screen_top1.pos}elseif Editor_state.cursor1.line >= Editor_state.screen_bottom1.line then
if Text.lt1(State.cursor1, State.screen_top1) thenState.cursor1 = {line=State.screen_top1.line, pos=State.screen_top1.pos}elseif State.cursor1.line >= State.screen_bottom1.line then
local line = Editor_state.lines[Editor_state.screen_bottom1.line]Editor_state.cursor1 = {line=Editor_state.screen_bottom1.line,pos=Text.to_pos_on_line(line, App.screen.width-5, App.screen.height-5, left, right),
local line = State.lines[State.screen_bottom1.line]State.cursor1 = {line=State.screen_bottom1.line,pos=Text.to_pos_on_line(State, line, App.screen.width-5, App.screen.height-5, left, right),
if Text.in_line(line, x,y, left, right) thenreturn line_index, Text.to_pos_on_line(line, x,y, left, right)
if Text.in_line(State, line, x,y, left, right) thenreturn line_index, Text.to_pos_on_line(State, line, x,y, left, right)