summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/node-ref.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/context/base/node-ref.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/node-ref.lua257
1 files changed, 148 insertions, 109 deletions
diff --git a/Master/texmf-dist/tex/context/base/node-ref.lua b/Master/texmf-dist/tex/context/base/node-ref.lua
index 7128b1a6d20..19d602ed673 100644
--- a/Master/texmf-dist/tex/context/base/node-ref.lua
+++ b/Master/texmf-dist/tex/context/base/node-ref.lua
@@ -14,10 +14,21 @@ if not modules then modules = { } end modules ['node-bck'] = {
-- helper, will end up in luatex
+-- is grouplevel still used?
+
+local allocate, mark = utilities.storage.allocate, utilities.storage.mark
+
local cleanupreferences, cleanupdestinations = false, true
-local nodeinjections = backends.nodeinjections
-local codeinjections = backends.codeinjections
+local attributes, nodes, node = attributes, nodes, node
+
+local nodeinjections = backends.nodeinjections
+local codeinjections = backends.codeinjections
+
+local transparencies = attributes.transparencies
+local colors = attributes.colors
+local references = structures.references
+local tasks = nodes.tasks
local hpack_list = node.hpack
local list_dimensions = node.dimensions
@@ -28,17 +39,37 @@ local trace_backend = false trackers.register("nodes.backend", functi
local trace_references = false trackers.register("nodes.references", function(v) trace_references = v end)
local trace_destinations = false trackers.register("nodes.destinations", function(v) trace_destinations = v end)
-local hlist = node.id("hlist")
-local vlist = node.id("vlist")
-local glue = node.id("glue")
-local whatsit = node.id("whatsit")
+local report_reference = logs.reporter("backend","references")
+local report_destination = logs.reporter("backend","destinations")
+local report_area = logs.reporter("backend","areas")
+
+local nodecodes = nodes.nodecodes
+local skipcodes = nodes.skipcodes
+local whatcodes = nodes.whatcodes
+local listcodes = nodes.listcodes
+
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local glue_code = nodecodes.glue
+local whatsit_code = nodecodes.whatsit
-local new_kern = nodes.kern
+local leftskip_code = skipcodes.leftskip
+local rightskip_code = skipcodes.rightskip
+local parfillskip_code = skipcodes.parfillskip
-local has_attribute = node.has_attribute
-local traverse = node.traverse
-local find_node_tail = node.tail or node.slide
-local tosequence = nodes.tosequence
+local localpar_code = whatcodes.localpar
+local dir_code = whatcodes.dir
+
+local line_code = listcodes.line
+
+local nodepool = nodes.pool
+
+local new_kern = nodepool.kern
+
+local has_attribute = node.has_attribute
+local traverse = node.traverse
+local find_node_tail = node.tail or node.slide
+local tosequence = nodes.tosequence
local function dimensions(parent,start,stop)
stop = stop and stop.next
@@ -78,14 +109,14 @@ local function inject_range(head,first,last,reference,make,stack,parent,pardir,t
if result and resolved then
if head == first then
if trace_backend then
- logs.report("backend","head: %04i %s %s %s => w=%s, h=%s, d=%s, c=%s",reference,pardir or "---",txtdir or "----",tosequence(first,last,true),width,height,depth,resolved)
+ report_area("head: %04i %s %s %s => w=%s, h=%s, d=%s, c=%s",reference,pardir or "---",txtdir or "----",tosequence(first,last,true),width,height,depth,resolved)
end
result.next = first
first.prev = result
return result, last
else
if trace_backend then
- logs.report("backend","middle: %04i %s %s => w=%s, h=%s, d=%s, c=%s",reference,pardir or "---",txtdir or "----",tosequence(first,last,true),width,height,depth,resolved)
+ report_area("middle: %04i %s %s => w=%s, h=%s, d=%s, c=%s",reference,pardir or "---",txtdir or "----",tosequence(first,last,true),width,height,depth,resolved)
end
local prev = first.prev
if prev then
@@ -111,20 +142,17 @@ local function inject_list(id,current,reference,make,stack,pardir,txtdir)
local width, height, depth, correction = current.width, current.height, current.depth, 0
local moveright = false
local first = current.list
- if id == hlist then
+ if id == hlist_code then -- box_code line_code
-- can be either an explicit hbox or a line and there is no way
-- to recognize this; anyway only if ht/dp (then inline)
- --
- -- to be tested: 0=unknown, 1=linebreak, 2=hbox
---~ if id.subtype == 1 then
local sr = stack[reference]
if first then
if sr and sr[2] then
local last = find_node_tail(first)
- if last.id == glue and last.subtype == 9 then
+ if last.id == glue_code and last.subtype == rightskip_code then
local prev = last.prev
- moveright = first.id == glue and first.subtype == 8
- if prev and prev.id == glue and prev.subtype == 15 then
+ moveright = first.id == glue_code and first.subtype == leftskip_code
+ if prev and prev.id == glue_code and prev.subtype == parfillskip_code then
width = dimensions(current,first,prev.prev) -- maybe not current as we already take care of it
else
if moveright and first.writable then
@@ -138,10 +166,6 @@ local function inject_list(id,current,reference,make,stack,pardir,txtdir)
else
-- also weird
end
---~ else
---~ print("!!!!!!!!!!!!!!!!!")
- -- simple
---~ end
else
-- ok
end
@@ -156,7 +180,7 @@ local function inject_list(id,current,reference,make,stack,pardir,txtdir)
local result, resolved = make(width,height,depth,reference)
if result and resolved then
if trace_backend then
- logs.report("backend","box: %04i %s %s: w=%s, h=%s, d=%s, c=%s",reference,pardir or "---",txtdir or "----",width,height,depth,resolved)
+ report_area("box: %04i %s %s: w=%s, h=%s, d=%s, c=%s",reference,pardir or "---",txtdir or "----",width,height,depth,resolved)
end
if not first then
current.list = result
@@ -186,15 +210,21 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx
while current do
local id = current.id
local r = has_attribute(current,attribute)
- if id == whatsit then
+ if id == whatsit_code then
local subtype = current.subtype
- if subtype == 6 then
+ if subtype == localpar_code then
pardir = current.dir
- elseif subtype == 7 then
+ elseif subtype == dir_code then
txtdir = current.dir
end
- elseif id == hlist or id == vlist then
- if not reference and r and (not skip or r > skip) then
+ elseif id == glue_code and current.subtype == leftskip_code then -- any glue at the left?
+ --
+ elseif id == hlist_code or id == vlist_code then
+-- somehow reference is true so teh following fails (second one not done) in
+-- test \goto{test}[page(2)] test \gotobox{test}[page(2)]
+-- so let's wait till this fails again
+-- if not reference and r and (not skip or r > skip) then -- > or ~=
+ if r and (not skip or r > skip) then -- > or ~=
inject_list(id,current,r,make,stack,pardir,txtdir)
end
if r then
@@ -214,8 +244,8 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx
reference, first, last, firstdir = r, current, current, txtdir
elseif r == reference then
last = current
- elseif (done[reference] or 0) == 0 then
- if not skip or r > skip then
+ elseif (done[reference] or 0) == 0 then -- or id == glue_code and current.subtype == right_skip_code
+ if not skip or r > skip then -- maybe no > test
head, current = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir)
reference, first, last, firstdir = nil, nil, nil, nil
end
@@ -239,14 +269,14 @@ local function inject_area(head,attribute,make,stack,done,parent,pardir,txtdir)
while current do
local id = current.id
local r = has_attribute(current,attribute)
- if id == whatsit then
+ if id == whatsit_code then
local subtype = current.subtype
- if subtype == 6 then
+ if subtype == localpar_code then
pardir = current.dir
- elseif subtype == 7 then
+ elseif subtype == dir_code then
txtdir = current.dir
end
- elseif id == hlist or id == vlist then
+ elseif id == hlist_code or id == vlist_code then
if r and not done[r] then
done[r] = true
inject_list(id,current,r,make,stack,pardir,txtdir)
@@ -264,8 +294,12 @@ end
-- tracing
-local new_rule = nodes.rule
-local new_kern = nodes.kern
+
+local nodepool = nodes.pool
+
+local new_rule = nodepool.rule
+local new_kern = nodepool.kern
+
local set_attribute = node.set_attribute
local register_color = colors.register
@@ -293,6 +327,15 @@ local function colorize(width,height,depth,n)
end
u_colors[n] = u_color
end
+ if width == 0 then
+ report_area("reference %s has no horizontal dimensions: width=%s, height=%s, depth=%s",reference,width,height,depth)
+ width = 65536
+ end
+ if height + depth <= 0 then
+ report_area("reference %s has no vertical dimensions: width=%s, height=%s, depth=%s",reference,width,height,depth)
+ height = 65536/2
+ depth = height
+ end
local rule = new_rule(width,height,depth)
set_attribute(rule,a_colormodel,1) -- gray color model
set_attribute(rule,a_color,u_color)
@@ -308,35 +351,51 @@ local function colorize(width,height,depth,n)
end
end
-local new_kern = nodes.kern
+local nodepool = nodes.pool
+
+local new_kern = nodepool.kern
+
local texattribute = tex.attribute
local texcount = tex.count
-- references:
+local stack = { }
+local done = { }
+local attribute = attributes.private('reference')
+local nofreferences = 0
+local topofstack = 0
+
nodes.references = {
- attribute = attributes.private('reference'),
- stack = { },
- done = { },
+ attribute = attribute,
+ stack = stack,
+ done = done,
}
-local stack, done, attribute = nodes.references.stack, nodes.references.done, nodes.references.attribute
-
-local nofreferences, topofstack = 0, 0
+-- todo: get rid of n (n is just a number, can be used for tracing, obsolete)
-local function setreference(n,h,d,r) -- n is just a number, can be used for tracing
+local function setreference(n,h,d,r)
topofstack = topofstack + 1
- stack[topofstack] = { n, h, d, codeinjections.prerollreference(r) } -- the preroll permits us to determine samepage (but delayed also has some advantages)
---~ texattribute[attribute] = topofstack -- todo -> at tex end
+ -- the preroll permits us to determine samepage (but delayed also has some advantages)
+ -- so some part of the backend work is already done here
+--~ stack[topofstack] = { n, h, d, codeinjections.prerollreference(r) }
+ stack[topofstack] = { r, h, d, codeinjections.prerollreference(r) }
+ -- texattribute[attribute] = topofstack -- todo -> at tex end
texcount.lastreferenceattribute = topofstack
end
-nodes.setreference = setreference
+function references.get(n) -- not public so functionality can change
+ local sn = stack[n]
+ return sn and sn[1]
+end
local function makereference(width,height,depth,reference)
local sr = stack[reference]
if sr then
- local resolved, ht, dp, set = sr[1], sr[2], sr[3], sr[4]
+ if trace_references then
+ report_reference("resolving attribute %s",reference)
+ end
+ local resolved, ht, dp, set, n = sr[1], sr[2], sr[3], sr[4], sr[5]
if ht then
if height < ht then height = ht end
if depth < dp then depth = dp end
@@ -347,7 +406,7 @@ local function makereference(width,height,depth,reference)
local result, current
if trace_references then
local step = 65536
- result = hpack_list(colorize(width,height-step,depth-step,2)) -- step subtracted so that we can see seperate links
+ result = hpack_list(colorize(width,height-step,depth-step,2,reference)) -- step subtracted so that we can see seperate links
result.width = 0
current = result
end
@@ -356,19 +415,20 @@ local function makereference(width,height,depth,reference)
else
result = annot
end
+ references.registerpage(n)
result = hpack_list(result,0)
result.width, result.height, result.depth = 0, 0, 0
if cleanupreferences then stack[reference] = nil end
return result, resolved
- else
- logs.report("backends","unable to resolve reference annotation %s",reference)
+ elseif trace_references then
+ report_reference("unable to resolve annotation %s",reference)
end
- else
- logs.report("backends","unable to resolve reference attribute %s",reference)
+ elseif trace_references then
+ report_reference("unable to resolve attribute %s",reference)
end
end
-function nodes.add_references(head)
+function nodes.references.handler(head)
if topofstack > 0 then
return inject_areas(head,attribute,makereference,stack,done)
else
@@ -376,29 +436,32 @@ function nodes.add_references(head)
end
end
--- destinations (we can clean up once set!)
+-- destinations (we can clean up once set, unless tagging!)
+
+local stack = { }
+local done = { }
+local attribute = attributes.private('destination')
+local nofdestinations = 0
+local topofstack = 0
nodes.destinations = {
- attribute = attributes.private('destination'),
- stack = { },
- done = { },
+ attribute = attribute,
+ stack = stack,
+ done = done,
}
-local stack, done, attribute = nodes.destinations.stack, nodes.destinations.done, nodes.destinations.attribute
-
-local nofdestinations, topofstack = 0, 0
-
local function setdestination(n,h,d,name,view) -- n = grouplevel, name == table
topofstack = topofstack + 1
stack[topofstack] = { n, h, d, name, view }
return topofstack
end
-nodes.setdestination = setdestination
-
local function makedestination(width,height,depth,reference)
local sr = stack[reference]
if sr then
+ if trace_destinations then
+ report_destination("resolving attribute %s",reference)
+ end
local resolved, ht, dp, name, view = sr[1], sr[2], sr[3], sr[4], sr[5]
if ht then
if height < ht then height = ht end
@@ -412,7 +475,7 @@ local function makedestination(width,height,depth,reference)
width, height, depth = 5*step, 5*step, 0
end
for n=1,#name do
- local rule = hpack_list(colorize(width,height,depth,3))
+ local rule = hpack_list(colorize(width,height,depth,3,reference))
rule.width = 0
if not result then
result, current = rule, rule
@@ -435,16 +498,19 @@ local function makedestination(width,height,depth,reference)
current = annot
end
end
- result = hpack_list(result,0)
- result.width, result.height, result.depth = 0, 0, 0
+ if result then
+ -- some internal error
+ result = hpack_list(result,0)
+ result.width, result.height, result.depth = 0, 0, 0
+ end
if cleanupdestinations then stack[reference] = nil end
return result, resolved
- else
- logs.report("backends","unable to resolve destination attribute %s",reference)
+ elseif trace_destinations then
+ report_destination("unable to resolve attribute %s",reference)
end
end
-function nodes.add_destinations(head)
+function nodes.destinations.handler(head)
if topofstack > 0 then
return inject_area(head,attribute,makedestination,stack,done) -- singular
else
@@ -454,12 +520,12 @@ end
-- will move
-function jobreferences.mark(reference,h,d,view)
+function references.mark(reference,h,d,view)
return setdestination(tex.currentgrouplevel,h,d,reference,view)
end
-function jobreferences.inject(prefix,reference,h,d,highlight,newwindow,layer) -- todo: use currentreference is possible
- local set, bug = jobreferences.identify(prefix,reference)
+function references.inject(prefix,reference,h,d,highlight,newwindow,layer) -- todo: use currentreference is possible
+ local set, bug = references.identify(prefix,reference)
if bug or #set == 0 then
-- unknown ref, just don't set it and issue an error
else
@@ -469,8 +535,8 @@ function jobreferences.inject(prefix,reference,h,d,highlight,newwindow,layer) --
end
end
-function jobreferences.injectcurrentset(h,d) -- used inside doifelse
- local currentset = jobreferences.currentset
+function references.injectcurrentset(h,d) -- used inside doifelse
+ local currentset = references.currentset
if currentset then
setreference(tex.currentgrouplevel,h,d,currentset) -- sets attribute / todo: for set[*].error
end
@@ -480,43 +546,16 @@ end
local function checkboth(open,close)
if open and open ~= "" then
- local set, bug = jobreferences.identify("",open)
+ local set, bug = references.identify("",open)
open = not bug and #set > 0 and set
end
if close and close ~= "" then
- local set, bug = jobreferences.identify("",close)
+ local set, bug = references.identify("",close)
close = not bug and #set > 0 and set
end
return open, close
end
--- expansion is temp hack
-
-local opendocument, closedocument, openpage, closepage
-
-local function check(what)
- if what and what ~= "" then
- local set, bug = jobreferences.identify("",what)
- return not bug and #set > 0 and set
- end
-end
-
-function jobreferences.checkopendocumentactions (open) opendocument = check(open) end
-function jobreferences.checkclosedocumentactions(close) closedocument = check(close) end
-function jobreferences.checkopenpageactions (open) openpage = check(open) end
-function jobreferences.checkclosepageactions (close) closepage = check(close) end
-
-function jobreferences.flushdocumentactions()
- if opendocument or closedocument then
- backends.codeinjections.flushdocumentactions(opendocument,closedocument) -- backend
- end
-end
-function jobreferences.flushpageactions()
- if openpage or closepage then
- backends.codeinjections.flushpageactions(openpage,closepage) -- backend
- end
-end
-
-- end temp hack
statistics.register("interactive elements", function()
@@ -527,7 +566,7 @@ statistics.register("interactive elements", function()
end
end)
-function jobreferences.enable_interaction()
- tasks.enableaction("shipouts","nodes.add_references")
- tasks.enableaction("shipouts","nodes.add_destinations")
+function references.enableinteraction()
+ tasks.enableaction("shipouts","nodes.references.handler")
+ tasks.enableaction("shipouts","nodes.destinations.handler")
end