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.lua298
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" }
+}