diff options
Diffstat (limited to 'tex/context/base/page-lin.lua')
-rw-r--r-- | tex/context/base/page-lin.lua | 298 |
1 files changed, 220 insertions, 78 deletions
diff --git a/tex/context/base/page-lin.lua b/tex/context/base/page-lin.lua index 7e8e9ad8a..5a447c458 100644 --- a/tex/context/base/page-lin.lua +++ b/tex/context/base/page-lin.lua @@ -8,37 +8,49 @@ if not modules then modules = { } end modules ['page-lin'] = { -- experimental -> will become builders -local trace_numbers = false trackers.register("lines.numbers", function(v) trace_numbers = v end) +-- if there is demand for it, we can support multiple numbering streams +-- and use more than one attibute -local report_lines = logs.reporter("lines") +local next, tonumber = next, tonumber -local attributes, nodes, node, context = attributes, nodes, node, context +local trace_numbers = false trackers.register("lines.numbers", function(v) trace_numbers = v end) -nodes.lines = nodes.lines or { } -local lines = nodes.lines +local report_lines = logs.reporter("lines") -lines.data = lines.data or { } -- start step tag -local data = lines.data -local last = #data +local attributes = attributes +local nodes = nodes +local context = context -local texgetbox = tex.getbox +local implement = interfaces.implement -lines.scratchbox = lines.scratchbox or 0 +nodes.lines = nodes.lines or { } +local lines = nodes.lines -local leftmarginwidth = nodes.leftmarginwidth +lines.data = lines.data or { } -- start step tag +local data = lines.data +local last = #data -storage.register("lines/data", lines.data, "nodes.lines.data") +lines.scratchbox = lines.scratchbox or 0 --- if there is demand for it, we can support multiple numbering streams --- and use more than one attibute +storage.register("lines/data", data, "nodes.lines.data") local variables = interfaces.variables +local v_next = variables.next +local v_page = variables.page +local v_no = variables.no + local nodecodes = nodes.nodecodes +local skipcodes = nodes.skipcodes +local whatcodes = nodes.whatcodes local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist local whatsit_code = nodecodes.whatsit +local glue_code = nodecodes.glue +local glyph_code = nodecodes.glyph +local leftskip_code = skipcodes.leftskip +local textdir_code = whatcodes.dir local a_displaymath = attributes.private('displaymath') local a_linenumber = attributes.private('linenumber') @@ -49,12 +61,32 @@ local current_list = { } local cross_references = { } local chunksize = 250 -- not used in boxed -local traverse_id = node.traverse_id -local traverse = node.traverse -local copy_node = node.copy -local hpack_node = node.hpack -local insert_node_after = node.insert_after -local insert_node_before = node.insert_before +local nuts = nodes.nuts + +local getid = nuts.getid +local getsubtype = nuts.getsubtype +local getnext = nuts.getnext +local getattr = nuts.getattr +local getlist = nuts.getlist +local getbox = nuts.getbox +local getfield = nuts.getfield + +local setfield = nuts.setfield + +local traverse_id = nuts.traverse_id +local traverse = nuts.traverse +local copy_node = nuts.copy +local hpack_node = nuts.hpack +local insert_node_after = nuts.insert_after +local insert_node_before = nuts.insert_before +local is_display_math = nuts.is_display_math +local leftmarginwidth = nuts.leftmarginwidth + +local negated_glue = nuts.pool.negatedglue +local new_hlist = nuts.pool.hlist + +local ctx_convertnumber = context.convertnumber +local ctx_makelinenumber = context.makelinenumber -- cross referencing @@ -67,16 +99,16 @@ end local function resolve(n,m) -- we can now check the 'line' flag (todo) while n do - local id = n.id + local id = getid(n) if id == whatsit_code then -- why whatsit - local a = n[a_linereference] + local a = getattr(n,a_linereference) if a then cross_references[a] = m end elseif id == hlist_code or id == vlist_code then - resolve(n.list,m) + resolve(getlist(n),m) end - n = n.next + n = getnext(n) end end @@ -105,7 +137,7 @@ filters.line = filters.line or { } function filters.line.default(data) -- helpers.title(data.entries.linenumber or "?",data.metadata) - context.convertnumber(data.entries.conversion or "numbers",data.entries.linenumber or "0") + ctx_convertnumber(data.entries.conversion or "numbers",data.entries.linenumber or "0") end function filters.line.page(data,prefixspec,pagespec) -- redundant @@ -133,9 +165,19 @@ function boxed.register(configuration) return last end -function commands.registerlinenumbering(configuration) - context(boxed.register(configuration)) -end +implement { + name = "registerlinenumbering", + actions = { boxed.register, context }, + arguments = { + { + { "continue" }, + { "start", "integer" }, + { "step", "integer" }, + { "method" }, + { "tag" }, + } + } +} function boxed.setup(n,configuration) local d = data[n] @@ -155,7 +197,20 @@ function boxed.setup(n,configuration) return n end -commands.setuplinenumbering = boxed.setup +implement { + name = "setuplinenumbering", + actions = boxed.setup, + arguments = { + "integer", + { + { "continue" }, + { "start", "integer" }, + { "step", "integer" }, + { "method" }, + { "tag" }, + } + } +} local function check_number(n,a,skip,sameline) local d = data[a] @@ -165,20 +220,20 @@ local function check_number(n,a,skip,sameline) if sameline then skipflag = 0 if trace_numbers then - report_lines("skipping broken line number %s for setup %a: %s (%s)",#current_list,a,s,d.continue or "no") + report_lines("skipping broken line number %s for setup %a: %s (%s)",#current_list,a,s,d.continue or v_no) end elseif not skip and s % d.step == 0 then skipflag, d.start = 1, s + 1 -- (d.step or 1) if trace_numbers then - report_lines("making number %s for setup %a: %s (%s)",#current_list,a,s,d.continue or "no") + report_lines("making number %s for setup %a: %s (%s)",#current_list,a,s,d.continue or v_no) end else skipflag, d.start = 0, s + 1 -- (d.step or 1) if trace_numbers then - report_lines("skipping line number %s for setup %a: %s (%s)",#current_list,a,s,d.continue or "no") + report_lines("skipping line number %s for setup %a: %s (%s)",#current_list,a,s,d.continue or v_no) end end - context.makelinenumber(tag,skipflag,s,n.shift,n.width,leftmarginwidth(n.list),n.dir) + ctx_makelinenumber(tag,skipflag,s,getfield(n,"shift"),getfield(n,"width"),leftmarginwidth(getlist(n)),getfield(n,"dir")) end end @@ -189,26 +244,27 @@ end local function identify(list) if list then for n in traverse_id(hlist_code,list) do - if n[a_linenumber] then - return list + local a = getattr(n,a_linenumber) + if a then + return list, a end end local n = list while n do - local id = n.id + local id = getid(n) if id == hlist_code or id == vlist_code then - local ok = identify(n.list) + local ok, a = identify(getlist(n)) if ok then - return ok + return ok, a end end - n = n.next + n = getnext(n) end end end function boxed.stage_zero(n) - return identify(texgetbox(n).list) + return identify(getlist(getbox(n))) end -- reset ranges per page @@ -217,66 +273,143 @@ end function boxed.stage_one(n,nested) current_list = { } - local box = texgetbox(n) + local box = getbox(n) if box then - local list = box.list - if nested then - list = identify(list) + local found = nil + local list = getlist(box) + if list and nested then + list, found = identify(list) end - local last_a, last_v, skip = nil, -1, false - for n in traverse_id(hlist_code,list) do -- attr test here and quit as soon as zero found - if n.height == 0 and n.depth == 0 then - -- skip funny hlists -- todo: check line subtype - else - local list = n.list - local a = list[a_linenumber] - if a and a > 0 then - if last_a ~= a then - local da = data[a] - local ma = da.method - if ma == variables.next then - skip = true - elseif ma == variables.page then - da.start = 1 -- eventually we will have a normal counter - end - last_a = a - if trace_numbers then - report_lines("starting line number range %s: start %s, continue",a,da.start,da.continue or "no") + if list then + local last_a, last_v, skip = nil, -1, false + for n in traverse_id(hlist_code,list) do -- attr test here and quit as soon as zero found + if getfield(n,"height") == 0 and getfield(n,"depth") == 0 then + -- skip funny hlists -- todo: check line subtype + else + local list = getlist(n) + local a = getattr(list,a_linenumber) + if not a or a == 0 then + local n = getnext(list) + while n do + local id = getid(n) + if id == whatsit_code and getsubtype(n) == textdir_code then + n = getnext(n) + elseif id == glue_code and getsubtype(n) == leftskip_code then + n = getnext(n) + else +if id == glyph_code then + break +else + -- can be hlist or skip (e.g. footnote line) + n = getnext(n) +end + end end + a = n and getattr(n,a_linenumber) end - if n[a_displaymath] then - if nodes.is_display_math(n) then - check_number(n,a,skip) + if a and a > 0 then + if last_a ~= a then + local da = data[a] + local ma = da.method + if ma == v_next then + skip = true + elseif ma == v_page then + da.start = 1 -- eventually we will have a normal counter + end + last_a = a + if trace_numbers then + report_lines("starting line number range %s: start %s, continue %s",a,da.start,da.continue or v_no) + end end - else - local v = list[a_verbatimline] - if not v or v ~= last_v then - last_v = v - check_number(n,a,skip) + if getattr(n,a_displaymath) then + if is_display_math(n) then + check_number(n,a,skip) + end else - check_number(n,a,skip,true) + local v = getattr(list,a_verbatimline) + if not v or v ~= last_v then + last_v = v + check_number(n,a,skip) + else + check_number(n,a,skip,true) + end end + skip = false end - skip = false end end end end end +-- [dir][leftskip][content] + +function boxed.stage_two(n,m) + if #current_list > 0 then + m = m or lines.scratchbox + local t, tn = { }, 0 + for l in traverse_id(hlist_code,getlist(getbox(m))) do + tn = tn + 1 + t[tn] = copy_node(l) -- use take_box instead + end + for i=1,#current_list do + local li = current_list[i] + local n, m, ti = li[1], li[2], t[i] + if ti then + local l = getlist(n) + -- we want to keep leftskip at the start +-- local id = getid(l) +-- if id == whatsit_code and getsubtype(l) == textdir_code then +-- l = getnext(l) +-- id = getid(l) +-- end +-- if getid(l) == glue_code and getsubtype(l) == leftskip_code then +-- -- [leftskip] [number] [rest] +-- local forward = copy_node(l) +-- local backward = negated_glue(l) +-- local next = getnext(l) +-- setfield(l,"next",backward) +-- setfield(backward,"prev",l) +-- setfield(backward,"next",ti) +-- setfield(ti,"prev",backward) +-- setfield(ti,"next",forward) +-- setfield(forward,"prev",ti) +-- setfield(forward,"next",next) +-- setfield(next,"prev",forward) +-- else + -- [number] [rest] + setfield(ti,"next",l) + setfield(l,"prev",ti) + setfield(n,"list",ti) +-- end + resolve(n,m) + else + report_lines("error in linenumbering (1)") + return + end + end + end +end + function boxed.stage_two(n,m) if #current_list > 0 then m = m or lines.scratchbox local t, tn = { }, 0 - for l in traverse_id(hlist_code,texgetbox(m).list) do + for l in traverse_id(hlist_code,getlist(getbox(m))) do tn = tn + 1 - t[tn] = copy_node(l) + t[tn] = copy_node(l) -- use take_box instead end for i=1,#current_list do local li = current_list[i] local n, m, ti = li[1], li[2], t[i] if ti then - ti.next, n.list = n.list, ti + local l = getlist(n) + setfield(ti,"next",l) + setfield(l,"prev",ti) + local h = copy_node(n) + setfield(h,"dir","TLT") + setfield(h,"list",ti) + setfield(n,"list",h) resolve(n,m) else report_lines("error in linenumbering (1)") @@ -286,5 +419,14 @@ function boxed.stage_two(n,m) end end -commands.linenumbersstageone = boxed.stage_one -commands.linenumbersstagetwo = boxed.stage_two +implement { + name = "linenumbersstageone", + actions = boxed.stage_one, + arguments = { "integer", "boolean" } +} + +implement { + name = "linenumbersstagetwo", + actions = boxed.stage_two, + arguments = { "integer", "integer" } +} |