This is quite useful because I used to have a long list of places in which to invalidate the cache.
2TCIWW6ZC73FHPZLO5QOBUFZCIL74U2MBYTPNXFYYFJ7IH4YAGUQC
FNJF2FMQJPQDVLHDZTVMUX5R3LGRKLGSNUPTHUT2WZY3RKVSNRIQC
YRJFJNUDVPX2OAK7OKRYCVYDGMJI4XL4JASN4JJ7QGIPCVQI22TAC
ZS5IYZH5EXXPSVIFWS7XW5POEVRRCK6XV6PB36D3EJXJRT22LKOQC
P6SYWBLBN2KAYQ6VJBPYZQNCD2WQHOZGC6XOKWW4SLAMFFGH3ZYQC
LXTTOB33N2HCUZFIUDRQGGBVHK2HODRG4NBLH6RXRQZDCHF27BSAC
LF7BWEG4DKQI7NMXMZC4LC2BE5PB42HK5PD6OYBNIDMAZBJASOKQC
IFTYOERMW7P3I24WISZN35X3GWJ5MSMRYDRBK3L52GCZTPP3CWZQC
WAR3HXHTN7JZVV6TFMU2F3QYAG6NDH7DN7KKPTM2ICEHRNQYP6PAC
6RYLD5ONDIQFWU5CNL4NGHJQ2LNAZZFGTPXQJDNJGLNYAUOTUI7QC
ZLJGZYQGQ2S4UFWTVF4PQDSGMP6A4IS4GDHCMBAAA5SK2N2NWR3QC
RMKMPFT5L67WIFWIO4GTC6XESX6UPKNL4GPNQLOBC5CXSUZABEHQC
TGHAJBESCIEGWUE2D3FGLNOIAYT4D2IRGZKRXRMTUFW7QZETC7OAC
ILOA5BYFTQKBSHLFMMZUVPQ2JXBFJD62ERQFBTDK2WSRXUN525VQC
BULPIBEGL7TMK6CVIE7IS7WGAHGOSUJBGJSFQK542MOWGHP2ADQQC
MXA3RZYKUI4UF2ISY7JEF6VKX6NOPZMZH5SLLCZHRJKFIXXXDPSAC
ODLKHO7BO2AODYO2OEQ6D4NSNBT5GR3CKLUXWMDLRYXL7DJOI7BAC
HYEAFRZ2UEKDYTAE2GDQLHEJBPQASP2NDLMXB7F6MTVK2BKOXKEAC
G3DLS5OUO77V4MC6754KTETRCTVUBYBHMGR7MTV52IYYM7QA3ROQC
BOFNXP5GZDCUMQG3LQVTSSFEQP7REQ4RIRJLDLETFSAGFTVDVEKAC
KOTNETIMJP2G753SAAQHR5LNOIC7LWLTFSY3QXA276L3TUN63UHQC
KKMFQDR43ZWVCDRHQLWWX3FCWCFA3ZSXYOBRJNPHUQZR2XPKWULAC
KMSL74GAMFNTAKGDKZFP2AMQXUMOC3XH373BO4IABZWBEP3YAXKAC
5SM6DRHKPLFWQPCZDTVM4ENVENWBYBQ3Q2KYKSWLWYUTOSEPCRLAC
G54H3YG2NEZPW2F6OYT5JPV7KSKVMNW5D3QT3FBCXTJHAQYTV5UAC
OI4FPFINEROK6GNDEMOBTGSPYIULCLRGGT5W3H7VLM7VFH22GMWQC
JYB3RFWHD6IXYGHJ77BEILJ5QNRPPH77DITIH4PKZM4D4OZSHRVQC
KYNGDE2CKNOKUC2XMAS5MEU6YT2C3IW5SIZLOJE64G3ERT7BSWFAC
6XCJX4DZB6UEAXEXXUGVVPBCF5SNDYOJGU3Q6BPB4ZMI5DZH4MYQC
VHQCNMARPMNBSIUFLJG7HVK4QGDNPCGNVFLHS3I4IGNVSV5MRLYQC
4KC7I3E2DIKLIP7LQRKB5WFA2Z5XZXAU46RFHNFQU5BVEJPDX6UQC
UHB4GARJI5AB5UCDCZRFSCJNXGJSLU5DYGUGX5ITYEXI7Q43Z4CAC
2L5MEZV344TOZLVY3432RHJFIRVXFD6O3GWLL5O4CV66BGAFTURQC
QAMVLUK22RP5RBDTDV5XVPQCSJUWDWESV4TRCUTNUM46E26BH2AQC
3OTESDW65UJ2W5RIXA6FNKRSD7TBCZTCCCEAYOQMEVGYZ6RCU34QC
LNUHQOGHIOFGJXNGA3DZLYEASLYYDGLN2I3EDZY5ANASQAHCG3YQC
ORRSP7FVCHI2TF5GXBRGQYYJAA3JFYXZBM3T663BKSBV22FCZVCAC
K2X6G75Z6XBC4DVIRWC5HC7XA3A2SKOM3MWSQTCFEYWIJL7LME2QC
BLWAYPKV3MLDZ4ALXLUJ25AIR6PCIL4RFYNRYLB26GFVC2KQBYBAC
JFFUF5ALUWPDM7IEDEZVAYG2SVXO334STONRGKVB3QKY2TT5QGBQC
7JH2ZT3FCW4WX52IJFSLGRVZWQQVYJXULSQM2BM4BJUZWG3IVGKAC
R3XGABERHYD7X42VXYENLVRSNFUXO5JAO4HCX3N4CMHZCHWEIW6AC
FZCKGO2IA5ZMX7TD4HL3WBUR6NPOYYMT4RGVWF7KFQBFV2V3RZBAC
AH744RFRNNEQ7THYLBD52BKUGPJJL36G5YLQY6NVU442UICAXUXQC
NYQ7HD4D5L44UORK52TH7CAEXYN5CE4ZUVLCWMY6XXPYHXVBTGHAC
KTZQ57HVZU4XGWRPXBA27G4GXZFV74YYKJRXCJCE7UKDS7NGJVBAC
QFC3WRDZEZJM3UICG2R7YZL35JJNWKAML4KLHCDX2ZDKREWV44GQC
DLQAEAC76KLM3KZXQ2C5DASP4IBS64GR6L7QYEP67CNXJ6LRL7LQC
PJEQCTBL2ZX5Q7NJQ3KCWSHHBV2QWGYS5NVMRDNK5LOOIIRRIPHAC
4PHGNJN64ELUEU4SJH6KG36WNTATT3QSZYTY4I5R3XGRZHZPAQ4QC
BXJMGTV2FMXDI5ML3OATRJ6O35L3T64S4TW4UYM37V3K3DICSC4AC
DRFE3B3ZKRG4RY2R5Q3SDFD3LH4EXUX3CZCDFBNAXVI2SLDS57PAC
RT6EV6OPUYCXYZOX2PHFXJ7KT77KHNEVINEGQXIQLHQVKPGTN6VQC
QXVD2RIFQPTO3H6J3IJHRHRDRBW6C6MLUWMCEDQ6Z75SW2TMRBIQC
SRVDX4I5QKWAH3Y5DX25PG34U7NY55H46ZYG2APH47BUZT3EJ2HAC
23MA4T3GWPOLM5S6JCNQJU2SRT7VQGYZ2JZJN26KA5MKI4LOCC4QC
XNFTJHC4QSHNSIWNN7K6QZEZ37GTQYKHS4EPNSVPQCUSWREROGIQC
BYG5CEMVXANDTBI2ORNVMEY6K3EBRIHZHS4QBK27VONJC5537COQC
3QNOKBFMKBGXBVJIRHR2444JRRMBTABHE4674NR3DT67RRM2X6GAC
CUFW4EJL75OAA5BS5EXGTM5RMRNJOBBPAXUJADGZ3VLP2ZMKFOTAC
end
-- return the top y coordinate of a given line_index,
-- or nil if no part of it is on screen
function Text.starty(State, line_index)
-- duplicate some logic from love.draw
-- does not modify State (except to populate line_cache)
if line_index < State.screen_top1.line then return end
local loc2 = Text.to2(State, State.screen_top1)
local y = State.top
while true do
if State.lines[loc2.line].mode == 'drawing' then
y = y + Drawing_padding_top
end
if loc2.line == line_index then return y end
if State.lines[loc2.line].mode == 'text' then
y = y + State.line_height
elseif State.lines[loc2.line].mode == 'drawing' then
y = y + Drawing.pixels(State.lines[loc2.line].h, State.width) + Drawing_padding_bottom
end
if y + State.line_height > App.screen.height then break end
local next_loc2 = Text.next_screen_line(State, loc2)
if Text.eq2(next_loc2, loc2) then break end -- end of file
loc2 = next_loc2
end
if line_cache.starty == nil then return false end -- outside current page
if y < line_cache.starty then return false end
local starty = Text.starty(State, line_index)
if starty == nil then return false end -- outside current page
if y < starty then return false end
return y < line_cache.starty + State.line_height*(#line_cache.screen_line_starting_pos - Text.screen_line_index(line_cache.screen_line_starting_pos, line_cache.startpos) + 1)
return y < starty + State.line_height*(#line_cache.screen_line_starting_pos - Text.screen_line_index(line_cache.screen_line_starting_pos, line_cache.startpos) + 1)
-- return the top y coordinate of a given line_index,
-- or nil if no part of it is on screen
function Text.starty(State, line_index)
-- duplicate some logic from love.draw
-- does not modify State (except to populate line_cache)
if line_index < State.screen_top1.line then return end
local loc2 = Text.to2(State, State.screen_top1)
local y = State.top
while true do
if loc2.line == line_index then return y end
if State.lines[loc2.line].mode == 'text' then
y = y + State.line_height
elseif State.lines[loc2.line].mode == 'drawing' then
y = y + Drawing_padding_height + Drawing.pixels(State.lines[loc2.line].h, State.width)
end
if y + State.line_height > App.screen.height then break end
local next_loc2 = Text.next_screen_line(State, loc2)
if Text.eq2(next_loc2, loc2) then break end -- end of file
loc2 = next_loc2
end
end
if line_cache.starty == nil then return false end -- outside current page
if y < line_cache.starty then return false end
local starty = Text.starty(State, line_index)
if starty == nil then return false end -- outside current page
if y < starty then return false end
return y < line_cache.starty + State.line_height*(#line_cache.screen_line_starting_pos - Text.screen_line_index(line_cache.screen_line_starting_pos, line_cache.startpos) + 1)
return y < starty + State.line_height*(#line_cache.screen_line_starting_pos - Text.screen_line_index(line_cache.screen_line_starting_pos, line_cache.startpos) + 1)
love.graphics.rectangle('fill', State.left,line_cache.starty, State.width, math.max(Drawing.pixels(drawing.h, State.width),y-line_cache.starty))
love.graphics.rectangle('fill', State.left,starty, State.width, math.max(Drawing.pixels(drawing.h, State.width),y-starty))
love.graphics.rectangle('fill', State.left,line_cache.starty, State.width, math.max(Drawing.pixels(drawing.h, State.width),y-line_cache.starty))
love.graphics.rectangle('fill', State.left,starty, State.width, math.max(Drawing.pixels(drawing.h, State.width),y-starty))
if pmx < State.right and pmy > line_cache.starty and pmy < line_cache.starty+Drawing.pixels(line.h, State.width) then
local starty = Text.starty(State, line_index)
if pmx < State.right and pmy > starty and pmy < starty+Drawing.pixels(line.h, State.width) then
function Drawing.in_drawing(drawing, line_cache, x,y, left,right)
if line_cache.starty == nil then return false end -- outside current page
function Drawing.in_current_drawing(State, x,y, left,right)
return Drawing.in_drawing(State, State.lines.current_drawing_index, x,y, left,right)
end
function Drawing.in_drawing(State, line_index, x,y, left,right)
assert(State.lines[line_index].mode == 'drawing')
local starty = Text.starty(State, line_index)
if starty == nil then return false end -- outside current page
local drawing = State.lines[line_index]
local _,drawing,line_cache = Drawing.current_drawing(State)
local mx,my = Drawing.coord(App.mouse_x()-State.left, State.width), Drawing.coord(App.mouse_y()-line_cache.starty, State.width)
local drawing_index,drawing = Drawing.current_drawing(State)
local starty = Text.starty(State, drawing_index)
local mx,my = Drawing.coord(App.mouse_x()-State.left, State.width), Drawing.coord(App.mouse_y()-starty, State.width)
local _,drawing,line_cache = Drawing.current_drawing(State)
local mx,my = Drawing.coord(App.mouse_x()-State.left, State.width), Drawing.coord(App.mouse_y()-line_cache.starty, State.width)
local drawing_index,drawing = Drawing.current_drawing(State)
local starty = Text.starty(State, drawing_index)
local mx,my = Drawing.coord(App.mouse_x()-State.left, State.width), Drawing.coord(App.mouse_y()-starty, State.width)
local line_cache = State.line_cache[drawing_index]
if Drawing.in_drawing(drawing, line_cache, x,y, State.left,State.right) then
return drawing_index,drawing,line_cache
if Drawing.in_drawing(State, drawing_index, x,y, State.left,State.right) then
return drawing_index,drawing
local line_cache = State.line_cache[drawing_index]
if Drawing.in_drawing(drawing, line_cache, x,y, State.left,State.right) then
local mx,my = Drawing.coord(x-State.left, State.width), Drawing.coord(y-line_cache.starty, State.width)
local starty = Text.starty(State, drawing_index)
if Drawing.in_drawing(State, drawing_index, x,y, State.left,State.right) then
local mx,my = Drawing.coord(x-State.left, State.width), Drawing.coord(y-starty, State.width)
local line_cache = State.line_cache[drawing_index]
if Drawing.in_drawing(drawing, line_cache, x,y, State.left,State.right) then
local mx,my = Drawing.coord(x-State.left, State.width), Drawing.coord(y-line_cache.starty, State.width)
local starty = Text.starty(State, drawing_index)
if Drawing.in_drawing(State, drawing_index, x,y, State.left,State.right) then
local mx,my = Drawing.coord(x-State.left, State.width), Drawing.coord(y-starty, State.width)