summaryrefslogtreecommitdiff
path: root/tex/context/base/page-lin.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/page-lin.lua')
-rw-r--r--tex/context/base/page-lin.lua215
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