summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/node-ref.lua
diff options
context:
space:
mode:
authorMojca Miklavec <mojca.miklavec@gmail.com>2014-05-05 20:29:55 +0000
committerMojca Miklavec <mojca.miklavec@gmail.com>2014-05-05 20:29:55 +0000
commitba9a57343987f1c2c72396e7c38f1fa30352c24c (patch)
tree66a8b12cdf67427ce96770fd0e9e581759aade1c /Master/texmf-dist/tex/context/base/node-ref.lua
parent15242121b8ddf7d4a041fb3998d295dd8232e1eb (diff)
ConTeXt 2014.04.28 23:24
git-svn-id: svn://tug.org/texlive/trunk@33856 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/context/base/node-ref.lua')
-rw-r--r--Master/texmf-dist/tex/context/base/node-ref.lua361
1 files changed, 202 insertions, 159 deletions
diff --git a/Master/texmf-dist/tex/context/base/node-ref.lua b/Master/texmf-dist/tex/context/base/node-ref.lua
index 09e066434a6..c55db4ea36a 100644
--- a/Master/texmf-dist/tex/context/base/node-ref.lua
+++ b/Master/texmf-dist/tex/context/base/node-ref.lua
@@ -16,69 +16,82 @@ if not modules then modules = { } end modules ['node-ref'] = {
-- is grouplevel still used?
-local format = string.format
+local attributes, nodes, node = attributes, nodes, node
-local allocate, mark = utilities.storage.allocate, utilities.storage.mark
+local allocate = utilities.storage.allocate, utilities.storage.mark
+local 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 cleanupreferences = false
+local cleanupdestinations = true
-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 transparencies = attributes.transparencies
-local colors = attributes.colors
-local references = structures.references
-local tasks = nodes.tasks
+local trace_backend = false trackers.register("nodes.backend", function(v) trace_backend = v end)
+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 hpack_list = node.hpack
-local list_dimensions = node.dimensions
+local report_reference = logs.reporter("backend","references")
+local report_destination = logs.reporter("backend","destinations")
+local report_area = logs.reporter("backend","areas")
--- current.glue_set current.glue_sign
+local nuts = nodes.nuts
+local nodepool = nuts.pool
-local trace_backend = false trackers.register("nodes.backend", function(v) trace_backend = v end)
-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 tonode = nuts.tonode
+local tonut = nuts.tonut
-local report_reference = logs.reporter("backend","references")
-local report_destination = logs.reporter("backend","destinations")
-local report_area = logs.reporter("backend","areas")
+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 getattr = nuts.getattr
+local setattr = nuts.setattr
+local getsubtype = nuts.getsubtype
-local nodecodes = nodes.nodecodes
-local skipcodes = nodes.skipcodes
-local whatcodes = nodes.whatcodes
-local listcodes = nodes.listcodes
+local hpack_list = nuts.hpack
+local list_dimensions = nuts.dimensions
+local traverse = nuts.traverse
+local find_node_tail = nuts.tail
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
-local glue_code = nodecodes.glue
-local whatsit_code = nodecodes.whatsit
+local nodecodes = nodes.nodecodes
+local skipcodes = nodes.skipcodes
+local whatcodes = nodes.whatcodes
+local listcodes = nodes.listcodes
-local leftskip_code = skipcodes.leftskip
-local rightskip_code = skipcodes.rightskip
-local parfillskip_code = skipcodes.parfillskip
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local glue_code = nodecodes.glue
+local whatsit_code = nodecodes.whatsit
-local localpar_code = whatcodes.localpar
-local dir_code = whatcodes.dir
+local leftskip_code = skipcodes.leftskip
+local rightskip_code = skipcodes.rightskip
+local parfillskip_code = skipcodes.parfillskip
-local line_code = listcodes.line
+local localpar_code = whatcodes.localpar
+local dir_code = whatcodes.dir
-local nodepool = nodes.pool
+local line_code = listcodes.line
-local new_kern = nodepool.kern
+local new_rule = nodepool.rule
+local new_kern = nodepool.kern
-local traverse = node.traverse
-local find_node_tail = node.tail or node.slide
-local tosequence = nodes.tosequence
+local tosequence = nodes.tosequence
-- local function dimensions(parent,start,stop)
--- stop = stop and stop.next
+-- stop = stop and getnext(stop)
-- if parent then
-- if stop then
--- return list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,start,stop)
+-- return list_dimensions(getfield(parent,"glue_set"),getfield(parent,"glue_sign"),getfield(parent,"glue_order"),start,stop)
-- else
--- return list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,start)
+-- return list_dimensions(getfield(parent,"glue_set"),getfield(parent,"glue_sign",getfield(parent,"glue_order"),start)
-- end
-- else
-- if stop then
@@ -93,9 +106,9 @@ local tosequence = nodes.tosequence
local function dimensions(parent,start,stop)
if parent then
- return list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,start,stop and stop.next)
+ return list_dimensions(getfield(parent,"glue_set"),getfield(parent,"glue_sign"),getfield(parent,"glue_order"),start,stop and getnext(stop))
else
- return list_dimensions(start,stop and stop.next)
+ return list_dimensions(start,stop and getnext(stop))
end
end
@@ -110,28 +123,27 @@ 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
- report_area("head: %04i %s %s %s => w=%p, h=%p, d=%p, c=%s",reference,pardir or "---",txtdir or "----",tosequence(first,last,true),width,height,depth,resolved)
+ report_area("%s: %04i %s %s %s => w=%p, h=%p, d=%p, c=%S","head",
+ reference,pardir or "---",txtdir or "---",tosequence(first,last,true),width,height,depth,resolved)
end
- result.next = first
- first.prev = result
+ setfield(result,"next",first)
+ setfield(first,"prev",result)
return result, last
else
if trace_backend then
- report_area("middle: %04i %s %s => w=%p, h=%p, d=%p, c=%s",reference,pardir or "---",txtdir or "----",tosequence(first,last,true),width,height,depth,resolved)
+ report_area("%s: %04i %s %s %s => w=%p, h=%p, d=%p, c=%S","middle",
+ reference,pardir or "---",txtdir or "---",tosequence(first,last,true),width,height,depth,resolved)
end
- local prev = first.prev
+ local prev = getprev(first)
if prev then
- result.next = first
- result.prev = prev
- prev.next = result
- first.prev = result
- else
- result.next = first
- first.prev = result
- end
- if first == head.next then
- head.next = result -- hm, weird
+ setfield(prev,"next",result)
+ setfield(result,"prev",prev)
end
+ setfield(result,"next",first)
+ setfield(first,"prev",result)
+-- if first == getnext(head) then
+-- setfield(head,"next",result) -- hm, weird
+-- end
return head, last
end
else
@@ -140,9 +152,9 @@ local function inject_range(head,first,last,reference,make,stack,parent,pardir,t
end
local function inject_list(id,current,reference,make,stack,pardir,txtdir)
- local width, height, depth, correction = current.width, current.height, current.depth, 0
+ local width, height, depth, correction = getfield(current,"width"), getfield(current,"height"), getfield(current,"depth"), 0
local moveright = false
- local first = current.list
+ local first = getlist(current)
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)
@@ -150,17 +162,17 @@ local function inject_list(id,current,reference,make,stack,pardir,txtdir)
if first then
if sr and sr[2] then
local last = find_node_tail(first)
- if last.id == glue_code and last.subtype == rightskip_code then
- local prev = last.prev
- 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
+ if getid(last) == glue_code and getsubtype(last) == rightskip_code then
+ local prev = getprev(last)
+ moveright = getid(first) == glue_code and getsubtype(first) == leftskip_code
+ if prev and getid(prev) == glue_code and getsubtype(prev) == parfillskip_code then
+ width = dimensions(current,first,getprev(prev)) -- maybe not current as we already take care of it
else
- if moveright and first.writable then
- width = width - first.spec.stretch*current.glue_set * current.glue_sign
+ if moveright and getfield(first,"writable") then
+ width = width - getfield(getfield(first,"spec"),"stretch") * getfield(current,"glue_set") * getfield(current,"glue_sign")
end
- if last.writable then
- width = width - last.spec.stretch*current.glue_set * current.glue_sign
+ if getfield(last,"writable") then
+ width = width - getfield(getfield(last,"spec"),"stretch") * getfield(current,"glue_set") * getfield(current,"glue_sign")
end
end
end
@@ -182,22 +194,25 @@ local function inject_list(id,current,reference,make,stack,pardir,txtdir)
-- todo: only when width is ok
if result and resolved then
if trace_backend then
- report_area("box: %04i %s %s: w=%p, h=%p, d=%p, c=%s",reference,pardir or "---",txtdir or "----",width,height,depth,resolved)
+ report_area("%s: %04i %s %s %s: w=%p, h=%p, d=%p, c=%S","box",
+ reference,pardir or "---",txtdir or "----","[]",width,height,depth,resolved)
end
if not first then
- current.list = result
+ setfield(current,"list",result)
elseif moveright then -- brr no prevs done
-- result after first
- local n = first.next
- result.next = n
- first.next = result
- result.prev = first
- if n then n.prev = result end
+ local n = getnext(first)
+ setfield(result,"next",n)
+ setfield(first,"next",result)
+ setfield(result,"prev",first)
+ if n then
+ setfield(n,"prev",result)
+ end
else
-- first after result
- result.next = first
- first.prev = result
- current.list = result
+ setfield(result,"next",first)
+ setfield(first,"prev",result)
+ setfield(current,"list",result)
end
end
end
@@ -210,45 +225,57 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx
pardir = pardir or "==="
txtdir = txtdir or "==="
while current do
- local id = current.id
+ local id = getid(current)
if id == hlist_code or id == vlist_code then
- local r = current[attribute]
- -- somehow reference is true so the 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
+ local r = getattr(current,attribute)
+ -- test \goto{test}[page(2)] test \gotobox{test}[page(2)]
+ -- test \goto{\TeX}[page(2)] test \gotobox{\hbox {x} \hbox {x}}[page(2)]
+ -- if r and (not skip or r >) skip then -- maybe no > test
+ -- inject_list(id,current,r,make,stack,pardir,txtdir)
+ -- end
if r then
+ if not reference then
+ reference, first, last, firstdir = r, current, current, txtdir
+ elseif r == reference then
+ -- same link
+ last = current
+ elseif (done[reference] or 0) == 0 then
+ 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
+ else
+ reference, first, last, firstdir = r, current, current, txtdir
+ end
done[r] = (done[r] or 0) + 1
end
- local list = current.list
+ local list = getlist(current)
if list then
- local _
- current.list, _, pardir, txtdir = inject_areas(list,attribute,make,stack,done,r or skip or 0,current,pardir,txtdir)
+ local h, ok
+ h, ok , pardir, txtdir = inject_areas(list,attribute,make,stack,done,r or skip or 0,current,pardir,txtdir)
+ setfield(current,"list",h)
end
if r then
done[r] = done[r] - 1
end
elseif id == whatsit_code then
- local subtype = current.subtype
+ local subtype = getsubtype(current)
if subtype == localpar_code then
- pardir = current.dir
+ pardir = getfield(current,"dir")
elseif subtype == dir_code then
- txtdir = current.dir
+ txtdir = getfield(current,"dir")
end
- elseif id == glue_code and current.subtype == leftskip_code then -- any glue at the left?
+ elseif id == glue_code and getsubtype(current) == leftskip_code then -- any glue at the left?
--
else
- local r = current[attribute]
+ local r = getattr(current,attribute)
if not r then
-- just go on, can be kerns
elseif not reference then
reference, first, last, firstdir = r, current, current, txtdir
elseif r == reference then
last = current
- elseif (done[reference] or 0) == 0 then -- or id == glue_code and current.subtype == right_skip_code
+ elseif (done[reference] or 0) == 0 then -- or id == glue_code and getsubtype(current) == 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
@@ -257,7 +284,7 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx
reference, first, last, firstdir = r, current, current, txtdir
end
end
- current = current.next
+ current = getnext(current)
end
if reference and (done[reference] or 0) == 0 then
head = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir)
@@ -272,32 +299,32 @@ local function inject_area(head,attribute,make,stack,done,parent,pardir,txtdir)
txtdir = txtdir or "==="
local current = head
while current do
- local id = current.id
+ local id = getid(current)
if id == hlist_code or id == vlist_code then
- local r = current[attribute]
+ local r = getattr(current,attribute)
if r and not done[r] then
done[r] = true
inject_list(id,current,r,make,stack,pardir,txtdir)
end
- local list = current.list
+ local list = getlist(current)
if list then
- current.list = inject_area(list,attribute,make,stack,done,current,pardir,txtdir)
+ setfield(current,"list",(inject_area(list,attribute,make,stack,done,current,pardir,txtdir)))
end
elseif id == whatsit_code then
- local subtype = current.subtype
+ local subtype = getsubtype(current)
if subtype == localpar_code then
- pardir = current.dir
+ pardir = getfield(current,"dir")
elseif subtype == dir_code then
- txtdir = current.dir
+ txtdir = getfield(current,"dir")
end
else
- local r = current[attribute]
+ local r = getattr(current,attribute)
if r and not done[r] then
done[r] = true
head, current = inject_range(head,current,current,r,make,stack,parent,pardir,txtdir)
end
end
- current = current.next
+ current = getnext(current)
end
end
return head, true
@@ -305,12 +332,6 @@ end
-- tracing
-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
local a_color = attributes.private('color')
@@ -347,35 +368,31 @@ local function colorize(width,height,depth,n,reference,what)
height = 65536/2
depth = height
end
- local rule = new_rule(width,height,depth)
- rule[a_colormodel] = 1 -- gray color model
- rule[a_color] = u_color
- rule[a_transparency] = u_transparency
+ local rule = new_rule(width,height,depth) -- todo: use tracer rule
+ setattr(rule,a_colormodel,1) -- gray color model
+ setattr(rule,a_color,u_color)
+ setattr(rule,a_transparency,u_transparency)
if width < 0 then
local kern = new_kern(width)
- rule.width = -width
- kern.next = rule
- rule.prev = kern
+ setfield(rule,"width",-width)
+ setfield(kern,"next",rule)
+ setfield(rule,"prev",kern)
return kern
else
return rule
end
end
-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
+local texsetattribute = tex.setattribute
+local texsetcount = tex.setcount
+
+local stack = { }
+local done = { }
+local attribute = attributes.private('reference')
+local nofreferences = 0
+local topofstack = 0
nodes.references = {
attribute = attribute,
@@ -390,8 +407,8 @@ local function setreference(h,d,r)
-- 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] = { r, h, d, codeinjections.prerollreference(r) }
- -- texattribute[attribute] = topofstack -- todo -> at tex end
- texcount.lastreferenceattribute = topofstack
+ -- texsetattribute(attribute,topofstack) -- todo -> at tex end
+ texsetcount("lastreferenceattribute",topofstack)
end
function references.get(n) -- not public so functionality can change
@@ -412,22 +429,26 @@ local function makereference(width,height,depth,reference)
end
local annot = nodeinjections.reference(width,height,depth,set)
if annot then
+annot = tonut(annot)
nofreferences = nofreferences + 1
local result, current
if trace_references then
local step = 65536
result = hpack_list(colorize(width,height-step,depth-step,2,reference,"reference")) -- step subtracted so that we can see seperate links
- result.width = 0
+ setfield(result,"width",0)
current = result
end
if current then
- current.next = annot
+ setfield(current,"next",annot)
+ setfield(annot,"prev",current)
else
result = annot
end
references.registerpage(n)
result = hpack_list(result,0)
- result.width, result.height, result.depth = 0, 0, 0
+ setfield(result,"width",0)
+ setfield(result,"height",0)
+ setfield(result,"depth",0)
if cleanupreferences then stack[reference] = nil end
return result, resolved
elseif trace_references then
@@ -438,9 +459,19 @@ local function makereference(width,height,depth,reference)
end
end
+-- function nodes.references.handler(head)
+-- if topofstack > 0 then
+-- return inject_areas(head,attribute,makereference,stack,done)
+-- else
+-- return head, false
+-- end
+-- end
+
function nodes.references.handler(head)
if topofstack > 0 then
- return inject_areas(head,attribute,makereference,stack,done)
+ head = tonut(head)
+ local head, done = inject_areas(head,attribute,makereference,stack,done)
+ return tonode(head), done
else
return head, false
end
@@ -484,34 +515,35 @@ local function makedestination(width,height,depth,reference)
step = 4*65536
width, height, depth = 5*step, 5*step, 0
end
- for n=1,#name do
- local rule = hpack_list(colorize(width,height,depth,3,reference,"destination"))
- rule.width = 0
- if not result then
- result, current = rule, rule
- else
- current.next = rule
- rule.prev = current
- current = rule
- end
- width, height = width - step, height - step
+ local rule = hpack_list(colorize(width,height,depth,3,reference,"destination"))
+ setfield(rule,"width",0)
+ if not result then
+ result, current = rule, rule
+ else
+ setfield(current,"next",rule)
+ setfield(rule,"prev",current)
+ current = rule
end
+ width, height = width - step, height - step
end
nofdestinations = nofdestinations + 1
- for n=1,#name do
- local annot = nodeinjections.destination(width,height,depth,name[n],view)
- if not result then
- result = annot
+ local annot = nodeinjections.destination(width,height,depth,name,view)
+ if annot then
+ annot = tonut(annot) -- obsolete soon
+ if result then
+ setfield(current,"next",annot)
+ setfield(annot,"prev",current)
else
- current.next = annot
- annot.prev = current
+ result = annot
end
current = find_node_tail(annot)
end
if result then
-- some internal error
result = hpack_list(result,0)
- result.width, result.height, result.depth = 0, 0, 0
+ setfield(result,"width",0)
+ setfield(result,"height",0)
+ setfield(result,"depth",0)
end
if cleanupdestinations then stack[reference] = nil end
return result, resolved
@@ -520,14 +552,25 @@ local function makedestination(width,height,depth,reference)
end
end
+-- function nodes.destinations.handler(head)
+-- if topofstack > 0 then
+-- return inject_area(head,attribute,makedestination,stack,done) -- singular
+-- else
+-- return head, false
+-- end
+-- end
+
function nodes.destinations.handler(head)
if topofstack > 0 then
- return inject_area(head,attribute,makedestination,stack,done) -- singular
+ head = tonut(head)
+ local head, done = inject_areas(head,attribute,makedestination,stack,done)
+ return tonode(head), done
else
return head, false
end
end
+
-- will move
function references.mark(reference,h,d,view)
@@ -540,7 +583,7 @@ function references.inject(prefix,reference,h,d,highlight,newwindow,layer) -- to
-- unknown ref, just don't set it and issue an error
else
-- check
- set.highlight, set.newwindow,set.layer = highlight, newwindow, layer
+ set.highlight, set.newwindow, set.layer = highlight, newwindow, layer
setreference(h,d,set) -- sets attribute / todo: for set[*].error
end
end
@@ -573,7 +616,7 @@ end
statistics.register("interactive elements", function()
if nofreferences > 0 or nofdestinations > 0 then
- return format("%s references, %s destinations",nofreferences,nofdestinations)
+ return string.format("%s references, %s destinations",nofreferences,nofdestinations)
else
return nil
end