diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkiv/node-ref.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/mkiv/node-ref.lua | 291 |
1 files changed, 83 insertions, 208 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkiv/node-ref.lua b/Master/texmf-dist/tex/context/base/mkiv/node-ref.lua index e12bd95bdd6..1ec77e83de3 100644 --- a/Master/texmf-dist/tex/context/base/mkiv/node-ref.lua +++ b/Master/texmf-dist/tex/context/base/mkiv/node-ref.lua @@ -67,25 +67,21 @@ local getattr = nuts.getattr local setattr = nuts.setattr local getsubtype = nuts.getsubtype local getwhd = nuts.getwhd -local getdirection = nuts.getdirection +local getdir = nuts.getdir local setshift = nuts.setshift local getboxglue = nuts.getboxglue local hpack_list = nuts.hpack local vpack_list = nuts.vpack -local getdimensions = nuts.dimensions -local getrangedimensions = nuts.rangedimensions +local list_dimensions = nuts.dimensions +local list_rangedimensions = nuts.rangedimensions local traverse = nuts.traverse local find_node_tail = nuts.tail local nodecodes = nodes.nodecodes -local gluecodes = nodes.gluecodes +local skipcodes = nodes.skipcodes local listcodes = nodes.listcodes -local dirvalues = nodes.dirvalues -local lefttoright_code = dirvalues.lefttoright -local righttoleft_code = dirvalues.righttoleft - local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist local glue_code = nodecodes.glue @@ -94,11 +90,11 @@ local rule_code = nodecodes.rule local dir_code = nodecodes.dir local localpar_code = nodecodes.localpar -local leftskip_code = gluecodes.leftskip -local rightskip_code = gluecodes.rightskip -local parfillskip_code = gluecodes.parfillskip +local leftskip_code = skipcodes.leftskip +local rightskip_code = skipcodes.rightskip +local parfillskip_code = skipcodes.parfillskip ------ linelist_code = listcodes.line +local line_code = listcodes.line local new_rule = nodepool.rule local new_kern = nodepool.kern @@ -117,9 +113,9 @@ local implement = interfaces.implement local function hlist_dimensions(start,stop,parent) local last = stop and getnext(stop) if parent then - return getrangedimensions(parent,start,last) + return list_rangedimensions(parent,start,last) else - return getdimensions(start,last) + return list_dimensions(start,last) end end @@ -254,13 +250,11 @@ local function dimensions(parent,start,stop) -- in principle we could move some end end +-- is pardir important at all? + local function inject_range(head,first,last,reference,make,stack,parent,pardir,txtdir) local width, height, depth, line = dimensions(parent,first,last) - if txtdir == righttoleft_code then - width = - width - elseif textdir == lefttoright_code then - -- go on - elseif pardir == righttoleft_code then + if txtdir == "+TRT" or (txtdir == "===" and pardir == "TRT") then -- KH: textdir == "===" test added width = - width end local result, resolved = make(width,height,depth,reference) @@ -270,7 +264,7 @@ local function inject_range(head,first,last,reference,make,stack,parent,pardir,t local l = getlist(line) if trace_areas then report_area("%s: %i : %s %s %s => w=%p, h=%p, d=%p","line", - reference,pardir or "?",txtdir or "?", + reference,pardir or "---",txtdir or "---", tosequence(l,nil,true),width,height,depth) end setlist(line,result) @@ -279,7 +273,7 @@ local function inject_range(head,first,last,reference,make,stack,parent,pardir,t elseif head == first then if trace_areas then report_area("%s: %i : %s %s %s => w=%p, h=%p, d=%p","head", - reference,pardir or "?",txtdir or "?", + reference,pardir or "---",txtdir or "---", tosequence(first,last,true),width,height,depth) end setlink(result,first) @@ -287,7 +281,7 @@ local function inject_range(head,first,last,reference,make,stack,parent,pardir,t else if trace_areas then report_area("%s: %i : %s %s %s => w=%p, h=%p, d=%p","middle", - reference,pardir or "?",txtdir or "?", + reference,pardir or "---",txtdir or "---", tosequence(first,last,true),width,height,depth) end if first == last and getid(parent) == vlist_code and getid(first) == hlist_code then @@ -312,7 +306,7 @@ local function inject_list(id,current,reference,make,stack,pardir,txtdir) local correction = 0 local moveright = false local first = getlist(current) - if id == hlist_code then -- boxlist_code linelist_code + 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) local sr = stack[reference] @@ -343,7 +337,7 @@ local function inject_list(id,current,reference,make,stack,pardir,txtdir) correction = height + depth height, depth = depth, height -- ugly hack, needed because pdftex backend does something funny end - if pardir == righttoleft_code then + if pardir == "TRT" then width = - width end local result, resolved = make(width,height,depth,reference) @@ -351,7 +345,7 @@ local function inject_list(id,current,reference,make,stack,pardir,txtdir) if result and resolved then if trace_areas then 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) + reference,pardir or "---",txtdir or "----","[]",width,height,depth,resolved) end if not first then setlist(current,result) @@ -376,6 +370,12 @@ end local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,txtdir) -- main local first, last, firstdir, reference + if not pardir then + pardir = "===" + end + if not texdir then + txtdir = "===" + end local current = head while current do local id = getid(current) @@ -404,8 +404,8 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx end local list = getlist(current) if list then - local h - h, 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) if h ~= current then setlist(current,h) end @@ -416,12 +416,9 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx elseif id == glue_code and getsubtype(current) == leftskip_code then -- any glue at the left? -- elseif id == dir_code then - local direction, pop = getdirection(current) - txtdir = not pop and direction -- we might need a stack - elseif id == localpar_code then - if getsubtype(current) == 0 then - pardir = getdirection(current) - end + txtdir = getdir(current) + elseif id == localpar_code then -- only test at begin + pardir = getdir(current) else local r = getattr(current,attribute) if not r then @@ -444,183 +441,46 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx if reference and (done[reference] or 0) == 0 then head = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir) end - return head, pardir, txtdir + return head, true, pardir, txtdir end --- -- not faster either: --- --- local findattr = node.direct.find_attribute --- --- local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,txtdir) -- main --- local first, last, firstdir, reference --- local someatt = findattr(head,attribute) --- if someatt then --- local current = head --- while current do --- local id = getid(current) --- if id == hlist_code or id == vlist_code then --- 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 = getlist(current) --- if list then --- local h --- h, pardir, txtdir = inject_areas(list,attribute,make,stack,done,r or skip or 0,current,pardir,txtdir) --- if h ~= current then --- setlist(current,h) --- end --- end --- if r then --- done[r] = done[r] - 1 --- end --- elseif id == dir_code then --- local direction, pop = getdirection(current) --- txtdir = not pop and direction -- we might need a stack --- elseif id == localpar_code then -- only test at begin --- pardir = getdirection(current) --- elseif id == glue_code and getsubtype(current) == leftskip_code then -- any glue at the left? --- -- --- else --- 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 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 --- end --- else --- reference, first, last, firstdir = r, current, current, txtdir --- end --- end --- 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) --- end --- else --- local current = head --- while current do --- local id = getid(current) --- if id == hlist_code or id == vlist_code then --- local list = getlist(current) --- if list then --- local h = inject_areas(list,attribute,make,stack,done,skip or 0,current,pardir,txtdir) --- if h ~= current then --- setlist(current,h) --- end --- end --- elseif id == dir_code then --- local direction, pop = getdirection(current) --- txtdir = not pop and direction -- we might need a stack --- elseif id == localpar_code then -- only test at begin --- pardir = getdirection(current) --- end --- current = getnext(current) --- end +-- local function inject_area(head,attribute,make,stack,done,parent,pardir,txtdir) -- singular ! +-- if not pardir then +-- pardir = "===" +-- end +-- if not texdir then +-- txtdir = "===" -- end --- return head, pardir, txtdir --- end - --- -- maybe first check for glyphs and use a goto: --- --- local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,txtdir) -- main --- local first, last, firstdir, reference -- local current = head -- while current do -- local id = getid(current) --- local r -- else scope message due to goto --- if id == glyph_code then --- goto rest --- elseif id == hlist_code or id == vlist_code then --- 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 +-- if id == hlist_code or id == vlist_code then +-- 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 = getlist(current) -- if list then --- local h --- h, pardir, txtdir = inject_areas(list,attribute,make,stack,done,r or skip or 0,current,pardir,txtdir) +-- local h = inject_area(list,attribute,make,stack,done,current,pardir,txtdir) -- if h ~= current then -- setlist(current,h) -- end -- end --- if r then --- done[r] = done[r] - 1 --- end --- elseif id == glue_code and getsubtype(current) == leftskip_code then -- any glue at the left? --- -- -- elseif id == dir_code then --- local direction, pop = getdirection(current) --- txtdir = not pop and direction -- we might need a stack --- elseif id == localpar_code then -- only test at begin --- pardir = getdirection(current) --- end --- goto next --- ::rest:: --- 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 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 --- end +-- txtdir = getdir(current) +-- elseif id == localpar_code then +-- pardir = getdir(current) -- else --- reference, first, last, firstdir = r, current, current, txtdir +-- 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 --- ::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) --- end --- return head, pardir, txtdir +-- return head, true -- end -- tracing: todo: use predefined colors @@ -735,11 +595,11 @@ nodes.references = { -- todo: get rid of n (n is just a number, can be used for tracing, obsolete) -local function setreference(h,d,r) -- h and d can be nil +local function setreference(h,d,r) topofstack = topofstack + 1 -- 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 or false, d or false, codeinjections.prerollreference(r) } + stack[topofstack] = { r, h, d, codeinjections.prerollreference(r) } -- texsetattribute(attribute,topofstack) -- todo -> at tex end texsetcount("lastreferenceattribute",topofstack) end @@ -755,11 +615,7 @@ local function makereference(width,height,depth,reference) -- height and depth a if trace_references then report_reference("resolving attribute %a",reference) end - local resolved = sr[1] - local ht = sr[2] - local dp = sr[3] - local set = sr[4] - local n = sr[5] + local resolved, ht, dp, set, n = sr[1], sr[2], sr[3], sr[4], sr[5] -- logs.report("temp","child: ht=%p dp=%p, parent: ht=%p dp=%p",ht,dp,height,depth) if ht then if height < ht then height = ht end @@ -816,9 +672,11 @@ end function nodes.references.handler(head) if head and topofstack > 0 then - return (inject_areas(head,attribute,makereference,stack,done)) + local head = tonut(head) + local head, done = inject_areas(head,attribute,makereference,stack,done) + return tonode(head), done else - return head + return head, false end end @@ -848,11 +706,7 @@ local function makedestination(width,height,depth,reference) if trace_destinations then report_destination("resolving attribute %a",reference) end - local resolved = sr[1] - local ht = sr[2] - local dp = sr[3] - local name = sr[4] - local view = sr[5] + local resolved, ht, dp, name, view = sr[1], sr[2], sr[3], sr[4], sr[5] -- sr[4] will change to just internal if ht then if height < ht then height = ht end if depth < dp then depth = dp end @@ -929,12 +783,21 @@ local function makedestination(width,height,depth,reference) end end +-- function nodes.destinations.handler(head) +-- if head and topofstack > 0 then +-- return inject_area(head,attribute,makedestination,stack,done) -- singular +-- else +-- return head, false +-- end +-- end function nodes.destinations.handler(head) if head and topofstack > 0 then - return (inject_areas(head,attribute,makedestination,stack,done)) + local head = tonut(head) + local head, done = inject_areas(head,attribute,makedestination,stack,done) + return tonode(head), done else - return head + return head, false end end @@ -1044,3 +907,15 @@ statistics.register("interactive elements", function() return nil end end) + +function references.enableinteraction() + enableaction("shipouts","nodes.references.handler") + enableaction("shipouts","nodes.destinations.handler") + function references.enableinteraction() end +end + +implement { + name = "enableinteraction", + actions = references.enableinteraction, + onlyonce = true +} |