diff options
Diffstat (limited to 'tex/context/base/page-lin.lua')
-rw-r--r-- | tex/context/base/page-lin.lua | 580 |
1 files changed, 290 insertions, 290 deletions
diff --git a/tex/context/base/page-lin.lua b/tex/context/base/page-lin.lua index e6b500e8b..5f7ea7eed 100644 --- a/tex/context/base/page-lin.lua +++ b/tex/context/base/page-lin.lua @@ -1,290 +1,290 @@ -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 -> will become builders - -local trace_numbers = false trackers.register("lines.numbers", function(v) trace_numbers = v end) - -local report_lines = logs.reporter("lines") - -local texbox = tex.box - -local attributes, nodes, node, context = attributes, nodes, node, context - -nodes.lines = nodes.lines or { } -local lines = nodes.lines - -lines.data = lines.data or { } -- start step tag -local data = lines.data -local last = #data - -lines.scratchbox = lines.scratchbox or 0 - -local leftmarginwidth = nodes.leftmarginwidth - -storage.register("lines/data", lines.data, "nodes.lines.data") - --- if there is demand for it, we can support multiple numbering streams --- and use more than one attibute - -local variables = interfaces.variables - -local nodecodes = nodes.nodecodes - -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist -local whatsit_code = nodecodes.whatsit - -local a_displaymath = attributes.private('displaymath') -local a_linenumber = attributes.private('linenumber') -local a_linereference = attributes.private('linereference') -local a_verbatimline = attributes.private('verbatimline') - -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 - --- cross referencing - -function 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_code then -- why whatsit - local a = n[a_linereference] - if a then - cross_references[a] = m - end - elseif id == hlist_code or id == vlist_code then - resolve(n.list,m) - end - n = n.next - end -end - -function lines.finalize(t) - local getnumber = lines.number - for _,p in next, t do - for _,r in next, p do - local m = r.metadata - if m and m.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 = structures.references.filters -local helpers = structures.helpers - -structures.references.registerfinalizer(lines.finalize) - -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") -end - -function filters.line.page(data,prefixspec,pagespec) -- redundant - helpers.prefixpage(data,prefixspec,pagespec) -end - -function filters.line.linenumber(data) -- raw - context(data.entries.linenumber or "0") -end - --- boxed variant, todo: use number mechanism - -lines.boxed = { } -local boxed = lines.boxed - --- todo: cache setups, and free id no longer used --- use interfaces.cachesetup(t) - -function boxed.register(configuration) - last = last + 1 - data[last] = configuration - if trace_numbers then - report_lines("registering setup %a",last) - end - return last -end - -function commands.registerlinenumbering(configuration) - context(boxed.register(configuration)) -end - -function boxed.setup(n,configuration) - local d = data[n] - if d then - if trace_numbers then - report_lines("updating setup %a",n) - end - for k,v in next, configuration do - d[k] = v - end - else - if trace_numbers then - report_lines("registering setup %a (br)",n) - end - data[n] = configuration - end - return n -end - -commands.setuplinenumbering = boxed.setup - -local function check_number(n,a,skip,sameline) - local d = data[a] - if d then - local tag, skipflag, s = d.tag or "", 0, d.start or 1 - current_list[#current_list+1] = { n, s } - 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") - 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") - 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") - end - end - context.makelinenumber(tag,skipflag,s,n.shift,n.width,leftmarginwidth(n.list),n.dir) - end -end - --- xlist --- xlist --- hlist - -local function identify(list) - if list then - for n in traverse_id(hlist_code,list) do - if n[a_linenumber] then - return list - end - end - local n = list - while n do - local id = n.id - if id == hlist_code or id == vlist_code then - local ok = identify(n.list) - if ok then - return ok - end - end - n = n.next - end - end -end - -function boxed.stage_zero(n) - return identify(texbox[n].list) -end - --- reset ranges per page --- store first and last per page --- maybe just set marks directly - -function boxed.stage_one(n,nested) - current_list = { } - local head = texbox[n] - if head then - local list = head.list - if nested then - list = 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") - end - end - if n[a_displaymath] then - if nodes.is_display_math(n) then - check_number(n,a,skip) - end - else - local v = 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 - 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,texbox[m].list) do - tn = tn + 1 - t[tn] = 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] - if ti then - ti.next, n.list = n.list, ti - resolve(n,m) - else - report_lines("error in linenumbering (1)") - return - end - end - end -end - -commands.linenumbersstageone = boxed.stage_one -commands.linenumbersstagetwo = boxed.stage_two +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 -> will become builders
+
+local trace_numbers = false trackers.register("lines.numbers", function(v) trace_numbers = v end)
+
+local report_lines = logs.reporter("lines")
+
+local texbox = tex.box
+
+local attributes, nodes, node, context = attributes, nodes, node, context
+
+nodes.lines = nodes.lines or { }
+local lines = nodes.lines
+
+lines.data = lines.data or { } -- start step tag
+local data = lines.data
+local last = #data
+
+lines.scratchbox = lines.scratchbox or 0
+
+local leftmarginwidth = nodes.leftmarginwidth
+
+storage.register("lines/data", lines.data, "nodes.lines.data")
+
+-- if there is demand for it, we can support multiple numbering streams
+-- and use more than one attibute
+
+local variables = interfaces.variables
+
+local nodecodes = nodes.nodecodes
+
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local whatsit_code = nodecodes.whatsit
+
+local a_displaymath = attributes.private('displaymath')
+local a_linenumber = attributes.private('linenumber')
+local a_linereference = attributes.private('linereference')
+local a_verbatimline = attributes.private('verbatimline')
+
+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
+
+-- cross referencing
+
+function 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_code then -- why whatsit
+ local a = n[a_linereference]
+ if a then
+ cross_references[a] = m
+ end
+ elseif id == hlist_code or id == vlist_code then
+ resolve(n.list,m)
+ end
+ n = n.next
+ end
+end
+
+function lines.finalize(t)
+ local getnumber = lines.number
+ for _,p in next, t do
+ for _,r in next, p do
+ local m = r.metadata
+ if m and m.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 = structures.references.filters
+local helpers = structures.helpers
+
+structures.references.registerfinalizer(lines.finalize)
+
+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")
+end
+
+function filters.line.page(data,prefixspec,pagespec) -- redundant
+ helpers.prefixpage(data,prefixspec,pagespec)
+end
+
+function filters.line.linenumber(data) -- raw
+ context(data.entries.linenumber or "0")
+end
+
+-- boxed variant, todo: use number mechanism
+
+lines.boxed = { }
+local boxed = lines.boxed
+
+-- todo: cache setups, and free id no longer used
+-- use interfaces.cachesetup(t)
+
+function boxed.register(configuration)
+ last = last + 1
+ data[last] = configuration
+ if trace_numbers then
+ report_lines("registering setup %a",last)
+ end
+ return last
+end
+
+function commands.registerlinenumbering(configuration)
+ context(boxed.register(configuration))
+end
+
+function boxed.setup(n,configuration)
+ local d = data[n]
+ if d then
+ if trace_numbers then
+ report_lines("updating setup %a",n)
+ end
+ for k,v in next, configuration do
+ d[k] = v
+ end
+ else
+ if trace_numbers then
+ report_lines("registering setup %a (br)",n)
+ end
+ data[n] = configuration
+ end
+ return n
+end
+
+commands.setuplinenumbering = boxed.setup
+
+local function check_number(n,a,skip,sameline)
+ local d = data[a]
+ if d then
+ local tag, skipflag, s = d.tag or "", 0, d.start or 1
+ current_list[#current_list+1] = { n, s }
+ 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")
+ 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")
+ 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")
+ end
+ end
+ context.makelinenumber(tag,skipflag,s,n.shift,n.width,leftmarginwidth(n.list),n.dir)
+ end
+end
+
+-- xlist
+-- xlist
+-- hlist
+
+local function identify(list)
+ if list then
+ for n in traverse_id(hlist_code,list) do
+ if n[a_linenumber] then
+ return list
+ end
+ end
+ local n = list
+ while n do
+ local id = n.id
+ if id == hlist_code or id == vlist_code then
+ local ok = identify(n.list)
+ if ok then
+ return ok
+ end
+ end
+ n = n.next
+ end
+ end
+end
+
+function boxed.stage_zero(n)
+ return identify(texbox[n].list)
+end
+
+-- reset ranges per page
+-- store first and last per page
+-- maybe just set marks directly
+
+function boxed.stage_one(n,nested)
+ current_list = { }
+ local head = texbox[n]
+ if head then
+ local list = head.list
+ if nested then
+ list = 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")
+ end
+ end
+ if n[a_displaymath] then
+ if nodes.is_display_math(n) then
+ check_number(n,a,skip)
+ end
+ else
+ local v = 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
+ 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,texbox[m].list) do
+ tn = tn + 1
+ t[tn] = 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]
+ if ti then
+ ti.next, n.list = n.list, ti
+ resolve(n,m)
+ else
+ report_lines("error in linenumbering (1)")
+ return
+ end
+ end
+ end
+end
+
+commands.linenumbersstageone = boxed.stage_one
+commands.linenumbersstagetwo = boxed.stage_two
|