This is a non-trivial merge. My new approach to rendering text has many advantages, but complicates link rendering.
To limit the complications for now, I'm changing behavior slightly. I'm coloring just the underlines and leaving link text the same color as regular text.
OEIR7M74D747NZME7BK6YHKHNBIYLVE6HD7FZN2HITFF7MX4JLUAC
6K5PFF6XBFTM6CXUVVFIH4CQMCMPHTND3ICDMRMNOME5BUBF27NQC
KGBSEDPFDYJPBLXQ5KL5DTRUMXPY7DGSSKOUK4DBNSLZMXZAV3LAC
I64IPGJXWRTGHHVAYJUBUIWFR4BY6NM5P7TLTV4JOD7K4BVYDECQC
V5SYDHPQ7IKNLZZ3NJ24FDW3IG4O23AASLP2DTKOBPWUUZ5KUPOAC
BULPIBEGL7TMK6CVIE7IS7WGAHGOSUJBGJSFQK542MOWGHP2ADQQC
6WDBV52ZFEYAUK6L66LDOKJ5JGHP63VY5R4NDOROZDY6HZJF45KAC
HALS7E5UGKCP3DFY456F7Z3Y6WNGIABOCV2SHT34D5ZAGNCPV5PQC
VG34LDWYWKMKO76MEKWLUV4RGZCY26LZNSGRA5U2EMAYNGB6LGXQC
X3F7ECSLGXCH6NBSDIH7LY47I4EG2RR5VFPEMM6ZVDYQIGFID4HQC
PFT5Y2ZYGQA6XXOZ5HH75WVUGA4B3KTDRHSFOZRAUKTPSFOPMNRAC
2CK5QI7WA7M4IVSACFGOJYAIDKRUTZVMMPSFWEJTUNMWTN7AX4NAC
TGHAJBESCIEGWUE2D3FGLNOIAYT4D2IRGZKRXRMTUFW7QZETC7OAC
-- render any link decorations
for _,link_offsets in ipairs(line_cache.link_offsets) do
local s,e,filename = unpack(link_offsets)
local lo, hi = Text.clip_filename_with_screen_line(line, line_cache, i, s, e)
if lo then
button(State, 'link', {x=State.left+lo, y=y, w=hi-lo, h=State.line_height, color={1,1,1},
icon = icon.hyperlink_decoration,
onpress1 = function()
run.switch_to_file(filename)
end,
})
end
-- If fragment is a filename relative to the current directory, register
-- a button for clicks on it.
local filename = rtrim(frag) -- compute_fragments puts whitespace at the end
if file_exists(filename) then
local filename_text = App.newText(love.graphics.getFont(), filename)
button(State, 'link', {x=x,y=y, w=App.width(filename_text), h=State.line_height, color={1,1,1},
icon = icon.hyperlink_decoration,
onpress1 = function()
run.switch_to_file(filename)
end,
})
-- render fragment
end
end
function Text.populate_link_offsets(State, line_index)
local line = State.lines[line_index]
if line.mode ~= 'text' then return end
local line_cache = State.line_cache[line_index]
if line_cache.link_offsets then
return
end
line_cache.link_offsets = {}
local pos = 1
-- try to wrap at word boundaries
local s, e = 1, 0
while s <= #line.data do
s, e = line.data:find('%w+', s)
if s == nil then break end
local word = line.data:sub(s, e)
if file_exists(word) then
--? print('filename:', s, e, word)
table.insert(line_cache.link_offsets, {s, e, word})
end
s = e + 1
-- Intersect the filename between byte offsets s,e with the bounds of screen line i.
-- Return the left/right pixel coordinates of of the intersection,
-- or nil if it doesn't intersect with screen line i.
function Text.clip_filename_with_screen_line(line, line_cache, i, s, e)
local spos = line_cache.screen_line_starting_pos[i]
local soff = Text.offset(line.data, spos)
if e < soff then
return
end
local eoff
if i < #line_cache.screen_line_starting_pos then
local epos = line_cache.screen_line_starting_pos[i+1]
eoff = Text.offset(line.data, epos)
if s > eoff then
return
end
end
local loff = math.max(s, soff)
local hoff
if eoff then
hoff = math.min(e, eoff)
else
hoff = e
end
--? print(s, e, soff, eoff, loff, hoff)
return App.width(line.data:sub(1, loff-1)), App.width(line.data:sub(1, hoff))
end