diff options
Diffstat (limited to 'tex/context/base/page-lin.lua')
-rw-r--r-- | tex/context/base/page-lin.lua | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/tex/context/base/page-lin.lua b/tex/context/base/page-lin.lua new file mode 100644 index 000000000..1f2c96251 --- /dev/null +++ b/tex/context/base/page-lin.lua @@ -0,0 +1,215 @@ +if not modules then modules = { } end modules ['page-lin'] = { + version = 1.001, + comment = "companion to page-lin.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- experimental + +local trace_numbers = false trackers.register("lines.numbers", function(v) trace_numbers = v end) + +local format = string.format +local texsprint, texwrite, texbox = tex.sprint, tex.write, tex.box + +local ctxcatcodes = tex.ctxcatcodes +local variables = interfaces.variables + +nodes = nodes or { } +nodes.lines = nodes.lines or { } +nodes.lines.data = nodes.lines.data or { } -- start step tag + +storage.register("lines/data", nodes.lines.data, "nodes.lines.data") + +-- if there is demand for it, we can support multiple numbering streams +-- and use more than one attibute + +local hlist, vlist, whatsit = node.id('hlist'), node.id('vlist'), node.id('whatsit') + +local display_math = attributes.private('display-math') +local line_number = attributes.private('line-number') +local line_reference = attributes.private('line-reference') + +local current_list = { } +local cross_references = { } +local chunksize = 250 -- not used in boxed + +local has_attribute = node.has_attribute +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 whatsit = node.id("whatsit") + +local data = nodes.lines.data +local last = #data + +nodes.lines.scratchbox = nodes.lines.scratchbox or 0 + +-- cross referencing + +function nodes.lines.number(n) + n = tonumber(n) + local cr = cross_references[n] or 0 + cross_references[n] = nil + return cr +end + +local function resolve(n,m) -- we can now check the 'line' flag (todo) + while n do + local id = n.id + if id == whatsit then -- why whatsit + local a = has_attribute(n,line_reference) + if a then + cross_references[a] = m + end + elseif id == hlist or id == vlist then + resolve(n.list,m) + end + n = n.next + end +end + +function nodes.lines.finalize(t) + local getnumber = nodes.lines.number + for _,p in next, t do + for _,r in next, p do + if r.metadata.kind == "line" then + local e = r.entries + local u = r.userdata + e.linenumber = getnumber(e.text or 0) -- we can nil e.text + e.conversion = u and u.conversion + r.userdata = nil -- hack + end + end + end +end + +local filters = jobreferences.filters +local helpers = structure.helpers + +jobreferences.registerfinalizer(nodes.lines.finalize) + +filters.line = filters.line or { } + +function filters.line.default(data) +-- helpers.title(data.entries.linenumber or "?",data.metadata) + texsprint(ctxcatcodes,format("\\convertnumber{%s}{%s}",data.entries.conversion or "numbers",data.entries.linenumber or "0")) +end + +function filters.line.page(data,prefixspec,pagespec) -- redundant + helpers.prefixpage(data,prefixspec,pagespec) +end + +function filters.line.linenumber(data) -- raw + texwrite(data.entries.linenumber or "0") +end + +-- boxed variant, todo: use number mechanism + +nodes.lines.boxed = { } + +-- todo: cache setups, and free id no longer used +-- use interfaces.cachesetup(t) + +function nodes.lines.boxed.register(configuration) + last = last + 1 + data[last] = configuration + if trace_numbers then + logs.report("lines","registering setup %s",last) + end + return last +end + +function nodes.lines.boxed.setup(n,configuration) + local d = data[n] + if d then + if trace_numbers then + logs.report("lines","updating setup %s",n) + end + for k,v in next, configuration do + d[k] = v + end + else + if trace_numbers then + logs.report("lines","registering setup %s (br)",n) + end + data[n] = configuration + end + return n +end + +local the_left_margin = nodes.the_left_margin + +local function check_number(n,a,skip) -- move inline + local d = data[a] + if d then + local s = d.start or 1 + current_list[#current_list+1] = { n, s } + if not skip and s % d.step == 0 then + local tag = d.tag or "" + texsprint(ctxcatcodes, format("\\makenumber{%s}{%s}{%s}{%s}{%s}{%s}\\endgraf",tag,s,n.shift,n.width,the_left_margin(n.list),n.dir)) + if trace_numbers then + logs.report("numbers","making number %s for setup %s: %s (%s)",#current_list,a,s,d.continue or "no") + end + else + texsprint(ctxcatcodes, "\\skipnumber\\endgraf") + end + d.start = s + 1 -- (d.step or 1) + end +end + +function nodes.lines.boxed.stage_one(n) + current_list = { } + local head = texbox[n] + if head then + local list = head.list + local last_a, skip = nil, false + for n in traverse_id(hlist,list) do -- attr test here and quit as soon as zero found + if n.height == 0 and n.depth == 0 then + -- skip funny hlists + else + local a = has_attribute(n.list,line_number) + if a and a > 0 then + if last_a ~= a then + if data[a].method == variables.next then + skip = true + end + last_a = a + end + if has_attribute(n,display_math) then + if nodes.is_display_math(n) then + check_number(n,a,skip) + end + else + -- the following test fails somehow (change in luatex?) + -- if node.first_character(n.list) then + check_number(n,a,skip) + -- end + end + skip = false + end + end + end + end +end + +function nodes.lines.boxed.stage_two(n,m) + if #current_list > 0 then + m = m or nodes.lines.scratchbox + local t, i = { }, 0 + for l in traverse_id(hlist,texbox[m].list) do + t[#t+1] = copy_node(l) + end + for i=1,#current_list do + local li = current_list[i] + local n, m, ti = li[1], li[2], t[i] + ti.next, n.list = n.list, ti + resolve(n,m) + end + end +end |