summaryrefslogtreecommitdiff
path: root/tex/context/base/node-fin.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/node-fin.lua')
-rw-r--r--tex/context/base/node-fin.lua338
1 files changed, 203 insertions, 135 deletions
diff --git a/tex/context/base/node-fin.lua b/tex/context/base/node-fin.lua
index 63a5ef83e..84c5b9a2f 100644
--- a/tex/context/base/node-fin.lua
+++ b/tex/context/base/node-fin.lua
@@ -8,42 +8,63 @@ if not modules then modules = { } end modules ['node-fin'] = {
-- this module is being reconstructed
-- local functions, only slightly slower
+--
+-- leaders are also triggers ... see colo-ext for an example (negate a box)
local next, type, format = next, type, string.format
local attributes, nodes, node = attributes, nodes, node
-local copy_node = node.copy
-local find_tail = node.slide
+local nuts = nodes.nuts
+local tonode = nuts.tonode
+local tonut = nuts.tonut
+
+local getfield = nuts.getfield
+local setfield = nuts.setfield
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getid = nuts.getid
+local getlist = nuts.getlist
+local getleader = nuts.getleader
+local getattr = nuts.getattr
+
+local copy_node = nuts.copy
+local insert_node_before = nuts.insert_before
+local insert_node_after = nuts.insert_after
-local nodecodes = nodes.nodecodes
-local whatcodes = nodes.whatcodes
+local nodecodes = nodes.nodecodes
+local whatcodes = nodes.whatcodes
-local glyph_code = nodecodes.glyph
-local disc_code = nodecodes.disc
-local glue_code = nodecodes.glue
-local rule_code = nodecodes.rule
-local whatsit_code = nodecodes.whatsit
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
+local glyph_code = nodecodes.glyph
+local disc_code = nodecodes.disc
+local glue_code = nodecodes.glue
+local rule_code = nodecodes.rule
+local whatsit_code = nodecodes.whatsit
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
-local pdfliteral_code = whatcodes.pdfliteral
+local pdfliteral_code = whatcodes.pdfliteral
-local states = attributes.states
-local numbers = attributes.numbers
-local a_trigger = attributes.private('trigger')
-local triggering = false
+local states = attributes.states
+local numbers = attributes.numbers
+local a_trigger = attributes.private('trigger')
+local triggering = false
-local starttiming = statistics.starttiming
-local stoptiming = statistics.stoptiming
-local loadstripped = utilities.lua.loadstripped
-local unsetvalue = attributes.unsetvalue
+local implement = interfaces.implement
+
+local starttiming = statistics.starttiming
+local stoptiming = statistics.stoptiming
+local loadstripped = utilities.lua.loadstripped
+local unsetvalue = attributes.unsetvalue
-- these two will be like trackers
function states.enabletriggering () triggering = true end
function states.disabletriggering() triggering = false end
+implement { name = "enablestatetriggering", actions = states.enabletriggering }
+implement { name = "disablestatetriggering", actions = states.disabletriggering }
+
nodes.plugindata = nil
-- inheritance: -0x7FFFFFFF -- we can best use nil and skip !
@@ -102,14 +123,17 @@ function nodes.installattributehandler(plugin)
return loadstripped(template)()
end
--- the injectors
+-- for the moment:
-local insert_node_before = node.insert_before
-local insert_node_after = node.insert_after
+local function copied(n)
+ return copy_node(tonut(n))
+end
+
+-- the injectors
local nsdata, nsnone, nslistwise, nsforced, nsselector, nstrigger
local current, current_selector, done = 0, 0, false -- nb, stack has a local current !
-local nsbegin, nsend
+local nsbegin, nsend, nsreset
function states.initialize(namespace,attribute,head)
nsdata = namespace.data
@@ -123,6 +147,7 @@ function states.initialize(namespace,attribute,head)
done = false -- todo: done cleanup
nsstep = namespace.resolve_step
if nsstep then
+ nsreset = namespace.resolve_reset
nsbegin = namespace.resolve_begin
nsend = namespace.resolve_end
nspush = namespace.push
@@ -132,23 +157,24 @@ end
function states.finalize(namespace,attribute,head) -- is this one ok?
if current > 0 and nsnone then
- local id = head.id
+ head = tonut(head)
+ local id = getid(head)
if id == hlist_code or id == vlist_code then
- local list = head.list
+ local list = getlist(head)
if list then
- head.list = insert_node_before(list,list,copy_node(nsnone))
+ list = insert_node_before(list,list,copied(nsnone)) -- two return values
+ setfield(head,"list",list)
end
else
- head = insert_node_before(head,head,copy_node(nsnone))
+ head = insert_node_before(head,head,copied(nsnone))
end
- return head, true, true
+ return tonode(head), true, true
end
return head, false, false
end
--- disc nodes can be ignored
-- we need to deal with literals too (reset as well as oval)
--- if id == glyph_code or (id == whatsit_code and stack.subtype == pdfliteral_code) or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then
+-- if id == glyph_code or (id == whatsit_code and getsubtype(stack) == pdfliteral_code) or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then
local function process(namespace,attribute,head,inheritance,default) -- one attribute
local stack = head
@@ -156,53 +182,59 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr
local check = false
local leader = nil
while stack do
- local id = stack.id
+ local id = getid(stack)
if id == glyph_code then
check = true
+ -- elseif id == disc_code then
+ -- check = true -- no longer needed as we flatten replace
elseif id == glue_code then
- leader = stack.leader
+ leader = getleader(stack)
if leader then
check = true
end
elseif id == hlist_code or id == vlist_code then
- local content = stack.list
+ local content = getlist(stack)
if content then
-- begin nested --
- local ok
- if nstrigger and stack[nstrigger] then
- local outer = stack[attribute]
+ if nstrigger and getattr(stack,nstrigger) then
+ local outer = getattr(stack,attribute)
if outer ~= inheritance then
- stack.list, ok = process(namespace,attribute,content,inheritance,outer)
+ local list, ok = process(namespace,attribute,content,inheritance,outer)
+ setfield(stack,"list",list)
+ done = done or ok
else
- stack.list, ok = process(namespace,attribute,content,inheritance,default)
+ local list, ok = process(namespace,attribute,content,inheritance,default)
+ setfield(stack,"list",list)
+ done = done or ok
end
else
- stack.list, ok = process(namespace,attribute,content,inheritance,default)
+ local list, ok = process(namespace,attribute,content,inheritance,default)
+ setfield(stack,"list",list)
+ done = done or ok
end
-- end nested --
- done = done or ok
end
elseif id == rule_code then
- check = stack.width ~= 0
+ check = getfield(stack,"width") ~= 0
end
-- much faster this way than using a check() and nested() function
if check then
- local c = stack[attribute]
+ local c = getattr(stack,attribute)
if c then
if default and c == inheritance then
if current ~= default then
- head = insert_node_before(head,stack,copy_node(nsdata[default]))
+ head = insert_node_before(head,stack,copied(nsdata[default]))
current = default
done = true
end
elseif current ~= c then
- head = insert_node_before(head,stack,copy_node(nsdata[c]))
+ head = insert_node_before(head,stack,copied(nsdata[c]))
current = c
done = true
end
if leader then
local savedcurrent = current
- local ci = leader.id
+ local ci = getid(leader)
if ci == hlist_code or ci == vlist_code then
-- else we reset inside a box unneeded, okay, the downside is
-- that we trigger color in each repeated box, so there is room
@@ -210,41 +242,48 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr
current = 0
end
-- begin nested --
- local ok = false
- if nstrigger and stack[nstrigger] then
- local outer = stack[attribute]
+ if nstrigger and getattr(stack,nstrigger) then
+ local outer = getattr(stack,attribute)
if outer ~= inheritance then
- stack.leader, ok = process(namespace,attribute,leader,inheritance,outer)
+ local list, ok = process(namespace,attribute,leader,inheritance,outer)
+ setfield(stack,"leader",list)
+ done = done or ok
else
- stack.leader, ok = process(namespace,attribute,leader,inheritance,default)
+ local list, ok = process(namespace,attribute,leader,inheritance,default)
+ setfield(stack,"leader",list)
+ done = done or ok
end
else
- stack.leader, ok = process(namespace,attribute,leader,inheritance,default)
+ local list, ok = process(namespace,attribute,leader,inheritance,default)
+ setfield(stack,"leader",list)
+ done = done or ok
end
-- end nested --
- done = done or ok
current = savedcurrent
leader = false
end
elseif default and inheritance then
if current ~= default then
- head = insert_node_before(head,stack,copy_node(nsdata[default]))
+ head = insert_node_before(head,stack,copied(nsdata[default]))
current = default
done = true
end
elseif current > 0 then
- head = insert_node_before(head,stack,copy_node(nsnone))
+ head = insert_node_before(head,stack,copied(nsnone))
current = 0
done = true
end
check = false
end
- stack = stack.next
+ stack = getnext(stack)
end
return head, done
end
-states.process = process
+states.process = function(namespace,attribute,head,default)
+ local head, done = process(namespace,attribute,tonut(head),default)
+ return tonode(head), done
+end
-- we can force a selector, e.g. document wide color spaces, saves a little
-- watch out, we need to check both the selector state (like colorspace) and
@@ -258,93 +297,105 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at
local check = false
local leader = nil
while stack do
- local id = stack.id
+ local id = getid(stack)
if id == glyph_code then
check = true
+ -- elseif id == disc_code then
+ -- check = true -- no longer needed as we flatten replace
elseif id == glue_code then
- leader = stack.leader
+ leader = getleader(stack)
if leader then
check = true
end
elseif id == hlist_code or id == vlist_code then
- local content = stack.list
+ local content = getlist(stack)
if content then
- local ok = false
-- begin nested
- if nstrigger and stack[nstrigger] then
- local outer = stack[attribute]
+ if nstrigger and getattr(stack,nstrigger) then
+ local outer = getattr(stack,attribute)
if outer ~= inheritance then
- stack.list, ok = selective(namespace,attribute,content,inheritance,outer)
+ local list, ok = selective(namespace,attribute,content,inheritance,outer)
+ setfield(stack,"list",list)
+ done = done or ok
else
- stack.list, ok = selective(namespace,attribute,content,inheritance,default)
+ local list, ok = selective(namespace,attribute,content,inheritance,default)
+ setfield(stack,"list",list)
+ done = done or ok
end
else
- stack.list, ok = selective(namespace,attribute,content,inheritance,default)
+ local list, ok = selective(namespace,attribute,content,inheritance,default)
+ setfield(stack,"list",list)
+ done = done or ok
end
-- end nested
- done = done or ok
end
elseif id == rule_code then
- check = stack.width ~= 0
+ check = getfield(stack,"width") ~= 0
end
if check then
- local c = stack[attribute]
+ local c = getattr(stack,attribute)
if c then
if default and c == inheritance then
if current ~= default then
local data = nsdata[default]
- head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector]))
+ head = insert_node_before(head,stack,copied(data[nsforced or getattr(stack,nsselector) or nsselector]))
current = default
done = true
end
else
- local s = stack[nsselector]
+ local s = getattr(stack,nsselector)
if current ~= c or current_selector ~= s then
local data = nsdata[c]
- head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector]))
+ head = insert_node_before(head,stack,copied(data[nsforced or getattr(stack,nsselector) or nsselector]))
current = c
current_selector = s
done = true
end
end
if leader then
- local ok = false
-- begin nested
- if nstrigger and stack[nstrigger] then
- local outer = stack[attribute]
+ if nstrigger and getattr(stack,nstrigger) then
+ local outer = getatribute(stack,attribute)
if outer ~= inheritance then
- stack.leader, ok = selective(namespace,attribute,leader,inheritance,outer)
+ local list, ok = selective(namespace,attribute,leader,inheritance,outer)
+ setfield(stack,"leader",list)
+ done = done or ok
else
- stack.leader, ok = selective(namespace,attribute,leader,inheritance,default)
+ local list, ok = selective(namespace,attribute,leader,inheritance,default)
+ setfield(stack,"leader",list)
+ done = done or ok
end
else
- stack.leader, ok = selective(namespace,attribute,leader,inheritance,default)
+ local list, ok = selective(namespace,attribute,leader,inheritance,default)
+ setfield(stack,"leader",list)
+ done = done or ok
end
-- end nested
- done = done or ok
leader = false
end
elseif default and inheritance then
if current ~= default then
local data = nsdata[default]
- head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector]))
+ head = insert_node_before(head,stack,copied(data[nsforced or getattr(stack,nsselector) or nsselector]))
current = default
done = true
end
elseif current > 0 then
- head = insert_node_before(head,stack,copy_node(nsnone))
+ head = insert_node_before(head,stack,copied(nsnone))
current, current_selector, done = 0, 0, true
end
check = false
end
-
- stack = stack.next
+ stack = getnext(stack)
end
return head, done
end
-states.selective = selective
+states.selective = function(namespace,attribute,head,default)
+ local head, done = selective(namespace,attribute,tonut(head),default)
+ return tonode(head), done
+end
-- Ideally the next one should be merged with the previous but keeping it separate is
-- safer. We deal with two situations: efficient boxwise (layoutareas) and mixed layers
@@ -363,135 +414,145 @@ local function stacked(namespace,attribute,head,default) -- no triggering, no in
local check = false
local leader = false
while stack do
- local id = stack.id
+ local id = getid(stack)
if id == glyph_code then
check = true
elseif id == glue_code then
- leader = stack.leader
+ leader = getleader(stack)
if leader then
check = true
end
elseif id == hlist_code or id == vlist_code then
- local content = stack.list
+ local content = getlist(stack)
if content then
-- the problem is that broken lines gets the attribute which can be a later one
if nslistwise then
- local a = stack[attribute]
+ local a = getattr(stack,attribute)
if a and current ~= a and nslistwise[a] then -- viewerlayer / needs checking, see below
local p = current
- current, done = a, true
- head = insert_node_before(head,stack,copy_node(nsdata[a]))
- stack.list = stacked(namespace,attribute,content,current)
- head, stack = insert_node_after(head,stack,copy_node(nsnone))
+ current = a
+ head = insert_node_before(head,stack,copied(nsdata[a]))
+ local list = stacked(namespace,attribute,content,current) -- two return values
+ setfield(stack,"list",list)
+ done = true
+ head, stack = insert_node_after(head,stack,copied(nsnone))
current = p
else
- local ok = false
- stack.list, ok = stacked(namespace,attribute,content,current)
+ local list, ok = stacked(namespace,attribute,content,current)
+ setfield(stack,"list",list) -- only if ok
done = done or ok
end
else
- local ok = false
- stack.list, ok = stacked(namespace,attribute,content,current)
+ local list, ok = stacked(namespace,attribute,content,current)
+ setfield(stack,"list",list) -- only if ok
done = done or ok
end
end
elseif id == rule_code then
- check = stack.width ~= 0
+ check = getfield(stack,"width") ~= 0
end
if check then
- local a = stack[attribute]
+ local a = getattr(stack,attribute)
if a then
if current ~= a then
- head = insert_node_before(head,stack,copy_node(nsdata[a]))
+ head = insert_node_before(head,stack,copied(nsdata[a]))
depth = depth + 1
current, done = a, true
end
if leader then
- local ok = false
- stack.leader, ok = stacked(namespace,attribute,content,current)
+ local list, ok = stacked(namespace,attribute,content,current)
+ setfield(stack,"leader",list) -- only if ok
done = done or ok
leader = false
end
elseif default > 0 then
--
elseif current > 0 then
- head = insert_node_before(head,stack,copy_node(nsnone))
+ head = insert_node_before(head,stack,copied(nsnone))
depth = depth - 1
current, done = 0, true
end
check = false
end
-
- stack = stack.next
+ stack = getnext(stack)
end
while depth > 0 do
- head = insert_node_after(head,stack,copy_node(nsnone))
+ head = insert_node_after(head,stack,copied(nsnone))
depth = depth - 1
end
return head, done
end
-states.stacked = stacked
+states.stacked = function(namespace,attribute,head,default)
+ local head, done = stacked(namespace,attribute,tonut(head),default)
+ return tonode(head), done
+end
-- experimental
local function stacker(namespace,attribute,head,default) -- no triggering, no inheritance, but list-wise
- nsbegin()
+
+-- nsbegin()
+ local stacked = false
+
local current = head
local previous = head
local done = false
- local okay = false
local attrib = default or unsetvalue
local check = false
local leader = false
+
while current do
- local id = current.id
+ local id = getid(current)
if id == glyph_code then
check = true
elseif id == glue_code then
- leader = current.leader
+ leader = getleader(current)
if leader then
check = true
end
elseif id == hlist_code or id == vlist_code then
- local content = current.list
+ local content = getlist(current)
if not content then
-- skip
elseif nslistwise then
- local a = current[attribute]
+ local a = getattr(current,attribute)
if a and attrib ~= a and nslistwise[a] then -- viewerlayer
+ head = insert_node_before(head,current,copied(nsdata[a]))
+ local list = stacker(namespace,attribute,content,a)
+ setfield(current,"list",list)
done = true
- head = insert_node_before(head,current,copy_node(nsdata[a]))
- current.list = stacker(namespace,attribute,content,a)
- head, current = insert_node_after(head,current,copy_node(nsnone))
+ head, current = insert_node_after(head,current,copied(nsnone))
else
- local ok = false
- current.list, ok = stacker(namespace,attribute,content,attrib)
+ local list, ok = stacker(namespace,attribute,content,attrib)
+ setfield(current,"list",list)
done = done or ok
end
else
- local ok = false
- current.list, ok = stacker(namespace,attribute,content,default)
+ local list, ok = stacker(namespace,attribute,content,default)
+ setfield(current,"list",list)
done = done or ok
end
elseif id == rule_code then
- check = current.width ~= 0
+ check = getfield(current,"width") ~= 0
end
if check then
- local a = current[attribute] or unsetvalue
+ local a = getattr(current,attribute) or unsetvalue
if a ~= attrib then
+ if not stacked then
+ stacked = true
+ nsbegin()
+ end
local n = nsstep(a)
if n then
- -- !!!! TEST CODE !!!!
- -- head = insert_node_before(head,current,copy_node(nsdata[tonumber(n)])) -- a
- head = insert_node_before(head,current,n) -- a
+ head = insert_node_before(head,current,tonut(n)) -- a
end
- attrib, done, okay = a, true, true
+ attrib, done = a, true
if leader then
-- tricky as a leader has to be a list so we cannot inject before
- local _, ok = stacker(namespace,attribute,leader,attrib)
+ local list, ok = stacker(namespace,attribute,leader,attrib)
done = done or ok
leader = false
end
@@ -500,20 +561,27 @@ local function stacker(namespace,attribute,head,default) -- no triggering, no in
end
previous = current
- current = current.next
+ current = getnext(current)
end
- if okay then
- local n = nsend()
- if n then
- -- !!!! TEST CODE !!!!
- -- head = insert_node_after(head,previous,copy_node(nsdata[tostring(n)]))
- head = insert_node_after(head,previous,n)
- end
+
+if stacked then
+
+ local n = nsend()
+ while n do
+ head = insert_node_after(head,previous,tonut(n))
+ n = nsend()
end
+
+end
+
return head, done
end
-states.stacker = stacker
+states.stacker = function(namespace,attribute,head,default)
+ local head, done = stacker(namespace,attribute,tonut(head),default)
+ nsreset()
+ return tonode(head), done
+end
-- -- --