Z5HLXU4PJWWJJDBCK52NBD6PIRIA3TAN2BKZB5HBYFGIDBX4F5HAC
SPSW74Y5OJ54Y7VQ3SJFCJR5CYDKTR4A3TOEVZODDZLUSDDU2GZAC
3MAZEQK5AR3IJJ2ENHHYDPDICIK645NE5QWR54Z52BHGHE6VR5XQC
G6OYAYHUSMSPKLRW52LQDAF4NBHFPWY3GZAHZZDLJY2ZL6NLTNEQC
2ZYV7D3W2HPQW2HYB7XDPM4T7KEWPUFPZ77BDLCCDSCLRPJFK6PQC
BULPIBEGL7TMK6CVIE7IS7WGAHGOSUJBGJSFQK542MOWGHP2ADQQC
IRCKL6VNSFB7TQEKPQUPJCN37N5QW7D54DSZMESVXGK7NEHGSIPAC
VJ77YABHVJZWJKLHAGIPC562GYM73AUGRLCP4JLKP5JPWPT2RIHAC
LF7BWEG4DKQI7NMXMZC4LC2BE5PB42HK5PD6OYBNIDMAZBJASOKQC
XNFTJHC4QSHNSIWNN7K6QZEZ37GTQYKHS4EPNSVPQCUSWREROGIQC
GN3IF4WF352YK5K4YHVMAIMPL7PNTCEMDWW22PTKDOXKV2FZJ7NQC
SQLVYKVJ5O4UMKTT56LMFPDQX66SZJJ7FZSFEN5MTWPXXWL7X3WQC
73OCE2MCBJJZZMN2KYPJTBOUCKBZAOQ2QIAMTGCNOOJ2AJAXFT2AC
CG3264MMJTTSCJWUA2EMTBOPTDB2NZIJ7XICKHWUTZ4UWLFP7POAC
DHI6IJCNSTHGED67T6H5X6Y636C7PIDGIJD32HBEKLT5WIMRS5MAC
HTWAM4NZFOY463TNSKYIM2EWB7QNBGDRRTTGHF5N3Z4TGC7Q3SFAC
X75QPYVWFSE7RVAJXRPA2I3AJOXOP653W7Y7NZG5XAEBR7MZU5QQC
AMSESRTH4T7EIEMXEFPMZFC55QAOVSWAN2XOQUUEB5ECHRDZUAYQC
KOYAJWE4NJ2J4X3SHEAVMRXYZPZGOMTI7OX3PTUQIDIZ2GQI6UKAC
ZHLO7K3MQNI6OMK6226SSO2Z6Z4ZXF4T73VOG36DVAG6CHR6OHWAC
KZ5GAYRPWF2BA5VEIW3A4G2TULATBL7YEDGFJU42GBP5DET7BI3AC
ZPUQSPQPQFVRUIHGLAWW3IDBYODIWDHO62HAC3WWF5TM3CIJGHNQC
2LOQ5ALJYHWSMU7ROSKD66BYGMK3O6HYNUQMGCZVKTRDOLEI75NQC
CVSRHMJ2BM4LPVG67ULIVQMP2NW3YY2JC2ZQBEA6EB5KVM4O2L5AC
OGUV4HSA7XGSQLUVWBAE3AE263Z7Z6G3BZOB4CN2AOYD2DEJMOZAC
2TQR4PSY2FBIKEEKC2Y5ZPVPOD2QJ3EATII47PPWNMTAQA7EQ6GAC
GGJEDJOOKE5LM5KERQOWLM5FRIJGIF5UZBFPGY4F4MWBHY6Y5YUQC
SVJZZDC3K6AKAXHGRNAZKRE2ZXEKJANNLG7LSSUZJARFBL5F7C4AC
QCQTMUZ7M3BKJFTKXTTXL4TS4CAQNIUNK3LR3WQIJDU3VVTOPS6AC
CUIV2LE5D6GUQ4NU7K2TGUVO5CTUXVJDRCZUIV47LXTOUSEPEJHQC
YJJ4X4JGABMVA5JBQW5UAWI543P3Y7NDVFTOHA6LIDA5KSFGUFNQC
V3EABA35RWCOOU5OMIYRWXAKZOLHO4XPGTPOKY24RR2LOAD7ZQAQC
62PZGSUCEXJOCVWEOOENSDJITJFR27BGW7BPGFYVD3E5M6446RQQC
2L5MEZV344TOZLVY3432RHJFIRVXFD6O3GWLL5O4CV66BGAFTURQC
function Text.insert_at_cursor(t)
local byte_offset = Text.offset(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor1.pos)
Editor_state.lines[Editor_state.cursor1.line].data = string.sub(Editor_state.lines[Editor_state.cursor1.line].data, 1, byte_offset-1)..t..string.sub(Editor_state.lines[Editor_state.cursor1.line].data, byte_offset)
Text.clear_cache(Editor_state.lines[Editor_state.cursor1.line])
Editor_state.cursor1.pos = Editor_state.cursor1.pos+1
function Text.insert_at_cursor(State, t)
local byte_offset = Text.offset(State.lines[State.cursor1.line].data, State.cursor1.pos)
State.lines[State.cursor1.line].data = string.sub(State.lines[State.cursor1.line].data, 1, byte_offset-1)..t..string.sub(State.lines[State.cursor1.line].data, byte_offset)
Text.clear_cache(State.lines[State.cursor1.line])
State.cursor1.pos = State.cursor1.pos+1
function Text.insert_return()
local byte_offset = Text.offset(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor1.pos)
table.insert(Editor_state.lines, Editor_state.cursor1.line+1, {mode='text', data=string.sub(Editor_state.lines[Editor_state.cursor1.line].data, byte_offset)})
Editor_state.lines[Editor_state.cursor1.line].data = string.sub(Editor_state.lines[Editor_state.cursor1.line].data, 1, byte_offset-1)
Text.clear_cache(Editor_state.lines[Editor_state.cursor1.line])
Text.clear_cache(Editor_state.lines[Editor_state.cursor1.line+1])
Editor_state.cursor1.line = Editor_state.cursor1.line+1
Editor_state.cursor1.pos = 1
function Text.insert_return(State)
local byte_offset = Text.offset(State.lines[State.cursor1.line].data, State.cursor1.pos)
table.insert(State.lines, State.cursor1.line+1, {mode='text', data=string.sub(State.lines[State.cursor1.line].data, byte_offset)})
State.lines[State.cursor1.line].data = string.sub(State.lines[State.cursor1.line].data, 1, byte_offset-1)
Text.clear_cache(State.lines[State.cursor1.line])
Text.clear_cache(State.lines[State.cursor1.line+1])
State.cursor1.line = State.cursor1.line+1
State.cursor1.pos = 1
if Editor_state.screen_top1.line == 1 and Editor_state.screen_top1.pos == 1 then break end
if Editor_state.lines[Editor_state.screen_top1.line].mode == 'text' then
y = y - Editor_state.line_height
elseif Editor_state.lines[Editor_state.screen_top1.line].mode == 'drawing' then
y = y - Editor_state.drawing_padding_height - Drawing.pixels(Editor_state.lines[Editor_state.screen_top1.line].h)
if State.screen_top1.line == 1 and State.screen_top1.pos == 1 then break end
if State.lines[State.screen_top1.line].mode == 'text' then
y = y - State.line_height
elseif State.lines[State.screen_top1.line].mode == 'drawing' then
y = y - State.drawing_padding_height - Drawing.pixels(State.lines[State.screen_top1.line].h)
Editor_state.screen_top1 = Text.to1(top2)
Editor_state.cursor1.line = Editor_state.screen_top1.line
Editor_state.cursor1.pos = Editor_state.screen_top1.pos
State.screen_top1 = Text.to1(top2)
State.cursor1.line = State.screen_top1.line
State.cursor1.pos = State.screen_top1.pos
--? print('setting top to', Editor_state.screen_top1.line, Editor_state.screen_top1.pos)
Editor_state.cursor1.line = Editor_state.screen_top1.line
Editor_state.cursor1.pos = Editor_state.screen_top1.pos
--? print('setting top to', State.screen_top1.line, State.screen_top1.pos)
State.cursor1.line = State.screen_top1.line
State.cursor1.pos = State.screen_top1.pos
function Text.up(left, right)
assert(Editor_state.lines[Editor_state.cursor1.line].mode == 'text')
--? print('up', Editor_state.cursor1.line, Editor_state.cursor1.pos, Editor_state.screen_top1.line, Editor_state.screen_top1.pos)
function Text.up(State, left, right)
assert(State.lines[State.cursor1.line].mode == 'text')
--? print('up', State.cursor1.line, State.cursor1.pos, State.screen_top1.line, State.screen_top1.pos)
Editor_state.cursor1.line = new_cursor_line
Text.populate_screen_line_starting_pos(Editor_state.lines[Editor_state.cursor1.line], left, right)
State.cursor1.line = new_cursor_line
Text.populate_screen_line_starting_pos(State.lines[State.cursor1.line], left, right)
if Editor_state.screen_top1.line > Editor_state.cursor1.line then
Editor_state.screen_top1.line = Editor_state.cursor1.line
Editor_state.screen_top1.pos = screen_line_starting_pos
--? print('pos of top of screen is also '..tostring(Editor_state.screen_top1.pos)..' of the same line')
if State.screen_top1.line > State.cursor1.line then
State.screen_top1.line = State.cursor1.line
State.screen_top1.pos = screen_line_starting_pos
--? print('pos of top of screen is also '..tostring(State.screen_top1.pos)..' of the same line')
local screen_line_starting_byte_offset = Text.offset(Editor_state.lines[Editor_state.cursor1.line].data, screen_line_starting_pos)
local s = string.sub(Editor_state.lines[Editor_state.cursor1.line].data, screen_line_starting_byte_offset)
Editor_state.cursor1.pos = screen_line_starting_pos + Text.nearest_cursor_pos(s, Editor_state.cursor_x, left) - 1
local screen_line_starting_byte_offset = Text.offset(State.lines[State.cursor1.line].data, screen_line_starting_pos)
local s = string.sub(State.lines[State.cursor1.line].data, screen_line_starting_byte_offset)
State.cursor1.pos = screen_line_starting_pos + Text.nearest_cursor_pos(s, State.cursor_x, left) - 1
if Editor_state.screen_top1.line == Editor_state.cursor1.line and Editor_state.screen_top1.pos == screen_line_starting_pos then
Editor_state.screen_top1.pos = new_screen_line_starting_pos
--? print('also setting pos of top of screen to '..tostring(Editor_state.screen_top1.pos))
if State.screen_top1.line == State.cursor1.line and State.screen_top1.pos == screen_line_starting_pos then
State.screen_top1.pos = new_screen_line_starting_pos
--? print('also setting pos of top of screen to '..tostring(State.screen_top1.pos))
local new_screen_line_starting_byte_offset = Text.offset(Editor_state.lines[Editor_state.cursor1.line].data, new_screen_line_starting_pos)
local s = string.sub(Editor_state.lines[Editor_state.cursor1.line].data, new_screen_line_starting_byte_offset)
Editor_state.cursor1.pos = new_screen_line_starting_pos + Text.nearest_cursor_pos(s, Editor_state.cursor_x, left) - 1
--? print('cursor pos is now '..tostring(Editor_state.cursor1.pos))
local new_screen_line_starting_byte_offset = Text.offset(State.lines[State.cursor1.line].data, new_screen_line_starting_pos)
local s = string.sub(State.lines[State.cursor1.line].data, new_screen_line_starting_byte_offset)
State.cursor1.pos = new_screen_line_starting_pos + Text.nearest_cursor_pos(s, State.cursor_x, left) - 1
--? print('cursor pos is now '..tostring(State.cursor1.pos))
function Text.down(left, right)
assert(Editor_state.lines[Editor_state.cursor1.line].mode == 'text')
--? print('down', Editor_state.cursor1.line, Editor_state.cursor1.pos, Editor_state.screen_top1.line, Editor_state.screen_top1.pos, Editor_state.screen_bottom1.line, Editor_state.screen_bottom1.pos)
function Text.down(State, left, right)
assert(State.lines[State.cursor1.line].mode == 'text')
--? print('down', State.cursor1.line, State.cursor1.pos, State.screen_top1.line, State.screen_top1.pos, State.screen_bottom1.line, State.screen_bottom1.pos)
if Editor_state.lines[new_cursor_line].mode == 'text' then
Editor_state.cursor1.line = new_cursor_line
Editor_state.cursor1.pos = Text.nearest_cursor_pos(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor_x, left)
--? print(Editor_state.cursor1.pos)
if State.lines[new_cursor_line].mode == 'text' then
State.cursor1.line = new_cursor_line
State.cursor1.pos = Text.nearest_cursor_pos(State.lines[State.cursor1.line].data, State.cursor_x, left)
--? print(State.cursor1.pos)
if Editor_state.cursor1.line > Editor_state.screen_bottom1.line then
--? print('screen top before:', Editor_state.screen_top1.line, Editor_state.screen_top1.pos)
if State.cursor1.line > State.screen_bottom1.line then
--? print('screen top before:', State.screen_top1.line, State.screen_top1.pos)
local new_screen_line_starting_byte_offset = Text.offset(Editor_state.lines[Editor_state.cursor1.line].data, new_screen_line_starting_pos)
local s = string.sub(Editor_state.lines[Editor_state.cursor1.line].data, new_screen_line_starting_byte_offset)
Editor_state.cursor1.pos = new_screen_line_starting_pos + Text.nearest_cursor_pos(s, Editor_state.cursor_x, left) - 1
--? print('cursor pos is now', Editor_state.cursor1.line, Editor_state.cursor1.pos)
local new_screen_line_starting_byte_offset = Text.offset(State.lines[State.cursor1.line].data, new_screen_line_starting_pos)
local s = string.sub(State.lines[State.cursor1.line].data, new_screen_line_starting_byte_offset)
State.cursor1.pos = new_screen_line_starting_pos + Text.nearest_cursor_pos(s, State.cursor_x, left) - 1
--? print('cursor pos is now', State.cursor1.line, State.cursor1.pos)
--? print('=>', Editor_state.cursor1.line, Editor_state.cursor1.pos, Editor_state.screen_top1.line, Editor_state.screen_top1.pos, Editor_state.screen_bottom1.line, Editor_state.screen_bottom1.pos)
--? print('=>', State.cursor1.line, State.cursor1.pos, State.screen_top1.line, State.screen_top1.pos, State.screen_bottom1.line, State.screen_bottom1.pos)
function Text.start_of_line()
Editor_state.cursor1.pos = 1
if Text.lt1(Editor_state.cursor1, Editor_state.screen_top1) then
Editor_state.screen_top1 = {line=Editor_state.cursor1.line, pos=Editor_state.cursor1.pos} -- copy
function Text.start_of_line(State)
State.cursor1.pos = 1
if Text.lt1(State.cursor1, State.screen_top1) then
State.screen_top1 = {line=State.cursor1.line, pos=State.cursor1.pos} -- copy
function Text.end_of_line(left, right)
Editor_state.cursor1.pos = utf8.len(Editor_state.lines[Editor_state.cursor1.line].data) + 1
function Text.end_of_line(State, left, right)
State.cursor1.pos = utf8.len(State.lines[State.cursor1.line].data) + 1
assert(Editor_state.cursor1.pos > 1)
if Text.match(Editor_state.lines[Editor_state.cursor1.line].data, Editor_state.cursor1.pos-1, '%s') then
assert(State.cursor1.pos > 1)
if Text.match(State.lines[State.cursor1.line].data, State.cursor1.pos-1, '%s') then