PTTZ7YRF3AKTO3LKL2PDC67H34NFKY2FRWL5HK6PZ2YWLPT5IUAAC ICUW7F3XQLURK4LSNPH5E3NDEFSRHKATEUHH2UPFJTMHYR3ZJF3QC 4GYPLUDYEF4NPB3HUGSOXAMCZ3UEV5ODM35IRA4DYL5IPDVDHD3QC A2PRHMXT3T2I2MKSOIKDWJGL5ZSTJWBYUZGGBXPTXZJZ7VYXKM7QC KWIVKQQ7AANRG6R4ZRB5TDBZ2TZTXAXIR2P6JNT362KIAJ7JQ4VQC R5QXEHUIZLELJGGCZAE7ATNS3CLRJ7JFRENMGH4XXH24C5WABZDQC JOPVPUSAMMU6RFVDQR4NJC4GNNUFB7GPKVH7OS5FKCYS5QZ53VLQC ZLJYLPOTXIVBVWJ4NTRM2YCQPT2FCSN7446P56MJFEFY45QTB7IAC 73OCE2MCBJJZZMN2KYPJTBOUCKBZAOQ2QIAMTGCNOOJ2AJAXFT2AC MUJTM6REGQAK3LZTIFWGJRXE2UPCM4HSLXQYSF5ITLXLS6JCVPMQC LLQC2M2IMEJBJQXZTKC3OAKG5WKHSERXKAKCYHQRUZZD6CVRIHAQC BW2IUB3KA4AKD35DYLCUCUM4Z32FMKGZNUBQBAEDIQJJYPA547MAC BULPIBEGL7TMK6CVIE7IS7WGAHGOSUJBGJSFQK542MOWGHP2ADQQC EVZAO6TCTTJCBZNRFW6YTIYVCR6S5OQ24S7TS4WJYWFBU43N24XQC I64IPGJXWRTGHHVAYJUBUIWFR4BY6NM5P7TLTV4JOD7K4BVYDECQC XNFTJHC4QSHNSIWNN7K6QZEZ37GTQYKHS4EPNSVPQCUSWREROGIQC ELJNEPW26FUIIFY6D24274J7KZICRLE3TJHCFNRVLR5NZBNNV37AC 3SMSYTKNRPZXV5TFOVAKW7FUPPPDSTG6BWVT3ZAXB23YCH36MXCAC F52PSTYSIIUD7UPEVLEJPVSBQU7IKVHM4GN4YASNSKFP4MRE6S6AC 3VHUIIATPOF7FXB7NTL5MESCV5BCQACII2D7QZ4UIUCBX3CWXMMAC 3IGFCRNEH3FIUWUFVRDDTGP3SRNPEJCWB3ELVEK6R45PRYXDKNSAC 5XMBCKJZ7YCUOOQWWZRNLXMXD3MUYC2VAF3VKA4BIEHQRPDQMUMAC 5E7BBR7HWGOEJJ6YWPL3NJKZVBTUZWET7OQNCRU2MMNVEGCEIAWQC 3PSFWAILGRA4OYXWS2DX7VF332AIBPYBXHEA4GIQY2XEJVD65UMAC 2TQUKHBC2EB3WDBD5UL62DQYV7CV6B7OJYK7CHOEDNOZENSOG42AC D4B52CQ2QKG2HQKFUQOO5S2ME325DTW3PH2D7SBXCW4BPQFYG7CAC 4QCR4O2V63WVOTGBWRP6AQVAF4QQAL5VQMEBA26GJMB6LJXXDLCQC VBU5YHLRO5ZSKFWBJRX7DWQGWPEHEWZMRRVV2WMWDJ54PKUNYCNQC FXI74QCLOZ4BS7UVZ3U2PE3LOL7MX3FWGHZCTGH3DYFXGTXVVIRAC INVLLFPN46D7CXCPILG76LQMPALJHAPFJY3WJSL6IT3AMKJSNYWQC KEFZWDCOCLPTLSZJKRV4VYAHRITV5T33YKG2VGT332YAUCOBS3EAC 2L5MEZV344TOZLVY3432RHJFIRVXFD6O3GWLL5O4CV66BGAFTURQC Text.draw(State, line_index, y, --[[startpos]] 1)State.left,State.right = old_left,old_rightelseheight = log_render[line.data.name](line.data, xleft, y, xright-xleft)endendif App.mouse_x() > Log_browser_state.left and line_index == mouse_line_index thenApp.color(Cursor_line_background_color)love.graphics.rectangle('fill', xleft,y, xright-xleft, height)endy = y + heightendendendfunction render_stack_left_margin(State, line_index, line, y)if line.section_stack == nil then-- assertion messagefor k,v in pairs(line) doprint(k)endendApp.color(Section_border_color)for i=1,#line.section_stack dolocal x = State.left + (i-1)*Section_border_padding_horizontallove.graphics.line(x,y, x,y+log_browser.height(State, line_index))if y < 30 thenlove.graphics.print(line.section_stack[i].name, x+State.font_height+5, y+5, --[[vertically]] math.pi/2)endif y > App.screen.height-log_browser.height(State, line_index) then
endfunction Text.screen_line(line, line_cache, i)local pos = line_cache.screen_line_starting_pos[i]local offset = Text.offset(line.data, pos)if i >= #line_cache.screen_line_starting_pos thenreturn line.data:sub(offset)
for _, f in ipairs(line_cache.fragments) doApp.color(Text_color)select_color(f)local frag_len = utf8.len(f)--? print('text.draw:', f, 'at', line_index,pos, 'after', x,y)
assert(#line_cache.screen_line_starting_pos >= 1)for i=1,#line_cache.screen_line_starting_pos dolocal pos = line_cache.screen_line_starting_pos[i]
-- render fragmentlocal frag_width = App.width(f)if x + frag_width > State.right thenassert(x > State.left) -- no overfull linesy = y + State.line_heightif y + State.line_height > App.screen.height thenreturn y, screen_line_starting_posendscreen_line_starting_pos = posx = State.leftendif State.selection1.line thenlocal lo, hi = Text.clip_selection(State, line_index, pos, pos+frag_len)Text.draw_highlight(State, line, x,y, pos, lo,hi)end-- Make [[WikiWords]] (single word, all in one screen line) clickable.local trimmed_word = rtrim(f) -- compute_fragments puts whitespace at the endif starts_with(trimmed_word, '[[') and ends_with(trimmed_word, ']]') thenlocal filename = trimmed_word:gsub('^..(.*)..$', '%1')if source.link_exists(State, filename) thenbutton(State, 'link', {x=x+App.width('[['), y=y, w=App.width(filename), h=State.line_height, color={1,1,1},icon = icon.hyperlink_decoration,onpress1 = function()source.switch_to_file(filename)end,})endendApp.screen.print(f, x,y)-- render cursor if necessaryif line_index == State.cursor1.line thenif pos <= State.cursor1.pos and pos + frag_len > State.cursor1.pos thenif State.search_term thenif State.lines[State.cursor1.line].data:sub(State.cursor1.pos, State.cursor1.pos+utf8.len(State.search_term)-1) == State.search_term thenlocal lo_px = Text.draw_highlight(State, line, x,y, pos, State.cursor1.pos, State.cursor1.pos+utf8.len(State.search_term))App.color(Text_color)love.graphics.print(State.search_term, x+lo_px,y)endelseif Focus == 'edit' thenText.draw_cursor(State, x+Text.x(f, State.cursor1.pos-pos+1), y)App.color(Text_color)endendendx = x + frag_widthendpos = pos + frag_lenendif Focus == 'edit' and not hide_cursor and State.search_term == nil thenif line_index == State.cursor1.line and State.cursor1.pos == pos thenText.draw_cursor(State, x, y)endendreturn y, screen_line_starting_posendfunction Text.draw_cursor(State, x, y)-- blink every 0.5sif math.floor(Cursor_time*2)%2 == 0 thenApp.color(Cursor_color)love.graphics.rectangle('fill', x,y, 3,State.line_height)endState.cursor_x = xState.cursor_y = y+State.line_heightendfunction Text.populate_screen_line_starting_pos(State, line_index)local line = State.lines[line_index]if line.mode ~= 'text' then return endlocal line_cache = State.line_cache[line_index]if line_cache.screen_line_starting_pos thenreturnend-- duplicate some logic from Text.drawText.compute_fragments(State, line_index)line_cache.screen_line_starting_pos = {1}local x = State.leftlocal pos = 1for _, f in ipairs(line_cache.fragments) do-- render fragmentlocal frag_width = App.width(f)if x + frag_width > State.right thenx = State.lefttable.insert(line_cache.screen_line_starting_pos, pos)endx = x + frag_widthpos = pos + utf8.len(f)endendfunction Text.compute_fragments(State, line_index)local line = State.lines[line_index]-- return y for the next line, and position of start of final screen line drawnlocal final_screen_line_starting_pos = startpos -- track value to returnText.populate_link_offsets(State, line_index)assert(#line_cache.screen_line_starting_pos >= 1)for i=1,#line_cache.screen_line_starting_pos dolocal pos = line_cache.screen_line_starting_pos[i]
final_screen_line_starting_pos = poslocal f = Text.screen_line(line, line_cache, i)--? print('text.draw:', f, 'at', line_index,pos, 'after', x,y)local frag_len = utf8.len(f)-- render any link decorationsfor _,link_offsets in ipairs(line_cache.link_offsets) dolocal s,e,filename = unpack(link_offsets)local lo, hi = Text.clip_wikiword_with_screen_line(line, line_cache, i, s, e)if lo thenbutton(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()if file_exists(filename) thensource.switch_to_file(filename)endend,})-- render fragmentText.draw_highlight(State, line, State.left,y, pos, lo,hi)select_color(f)App.screen.print(f, State.left,y)if not hide_cursor and line_index == State.cursor1.line thenif pos <= State.cursor1.pos and pos + frag_len >= State.cursor1.pos thenlocal lo_px = Text.draw_highlight(State, line, State.left,y, pos, State.cursor1.pos, State.cursor1.pos+utf8.len(State.search_term))love.graphics.print(State.search_term, State.left+lo_px,y)Text.draw_cursor(State, State.left+Text.x(f, State.cursor1.pos-pos+1), y)y = y + State.line_heightif y >= App.screen.height thenbreakendreturn y, final_screen_line_starting_posendfunction Text.screen_line(line, line_cache, i)local pos = line_cache.screen_line_starting_pos[i]local offset = Text.offset(line.data, pos)if i >= #line_cache.screen_line_starting_pos thenreturn line.data:sub(offset)local endpos = line_cache.screen_line_starting_pos[i+1]-1local end_offset = Text.offset(line.data, endpos)return line.data:sub(offset, end_offset)local x = 0-- try to wrap at word boundariesfor frag in line.data:gmatch('%S*%s*') dolocal frag_width = App.width(frag)--? print('-- frag:', frag, pos, x, frag_width, State.width)while x + frag_width > State.width do--? print('frag:', frag, pos, x, frag_width, State.width)if x < 0.8 * State.width then-- long word; chop it at some letter-- We're not going to reimplement TeX here.local bpos = Text.nearest_pos_less_than(frag, State.width - x)-- everything works if bpos == 0, but is a little inefficientpos = pos + bposlocal boffset = Text.offset(frag, bpos+1) -- byte _after_ bposfrag = string.sub(frag, boffset)--? if bpos > 0 then--? print('after chop:', frag)--? endfrag_width = App.width(frag)end--? print('screen line:', pos)x = 0 -- new screen linepos = pos + utf8.len(frag)function Text.populate_link_offsets(State, line_index)
endfunction Text.draw_cursor(State, x, y)-- blink every 0.5sif math.floor(Cursor_time*2)%2 == 0 thenApp.color(Cursor_color)love.graphics.rectangle('fill', x,y, 3,State.line_height)endState.cursor_x = xState.cursor_y = y+State.line_heightendfunction Text.populate_screen_line_starting_pos(State, line_index)local line = State.lines[line_index]if line.mode ~= 'text' then return endlocal line_cache = State.line_cache[line_index]if line_cache.screen_line_starting_pos thenreturnendline_cache.screen_line_starting_pos = {1}
for frag in line.data:gmatch('%S*%s*') dolocal frag_width = App.width(frag)while x + frag_width > State.right doif (x-State.left) < 0.8 * (State.right-State.left) then-- long word; chop it at some letter-- We're not going to reimplement TeX here.local bpos = Text.nearest_pos_less_than(frag, State.right - x)if bpos == 0 then break end -- avoid infinite loop when window is too narrowlocal boffset = Text.offset(frag, bpos+1) -- byte _after_ bposlocal frag1 = string.sub(frag, 1, boffset-1)local frag1_width = App.width(frag1)assert(x + frag1_width <= State.right)table.insert(line_cache.fragments, frag1)frag = string.sub(frag, boffset)frag_width = App.width(frag)endx = State.left -- new lineendif #frag > 0 thentable.insert(line_cache.fragments, frag)
local s, e = 1, 0while s <= #line.data dos, e = line.data:find('%[%[%S+%]%]', s)if s == nil then break endlocal word = line.data:sub(s+2, e-2) -- strip out surrounding '[[..]]'--? print('wikiword:', s, e, word)table.insert(line_cache.link_offsets, {s, e, word})s = e + 1endend-- 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_wikiword_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 thenreturnendlocal eoffif i < #line_cache.screen_line_starting_pos thenlocal epos = line_cache.screen_line_starting_pos[i+1]eoff = Text.offset(line.data, epos)if s > eoff thenreturn
if line_cache.link_offsets thenline_cache.link_offsets = {}local pos = 1local s, e = 1, 0while s <= #line.data dos, e = line.data:find('%[%[%S+%]%]', s)if s == nil then break endlocal word = line.data:sub(s+2, e-2) -- strip out surrounding '[[..]]'--? print('wikiword:', s, e, word)table.insert(line_cache.link_offsets, {s, e, word})s = e + 1endend-- 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_wikiword_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 thenreturnendlocal eoffif i < #line_cache.screen_line_starting_pos thenlocal epos = line_cache.screen_line_starting_pos[i+1]eoff = Text.offset(line.data, epos)if s > eoff thenreturnendlocal loff = math.max(s, soff)local hoffif eoff thenhoff = math.min(e, eoff)elsehoff = e--? print(s, e, soff, eoff, loff, hoff)return App.width(line.data:sub(1, loff-1)), App.width(line.data:sub(1, hoff))