diff options
Diffstat (limited to 'tex/context/base/mkiv/node-ref.lua')
-rw-r--r-- | tex/context/base/mkiv/node-ref.lua | 291 |
1 files changed, 208 insertions, 83 deletions
diff --git a/tex/context/base/mkiv/node-ref.lua b/tex/context/base/mkiv/node-ref.lua index 1ec77e83d..e12bd95bd 100644 --- a/tex/context/base/mkiv/node-ref.lua +++ b/tex/context/base/mkiv/node-ref.lua @@ -67,21 +67,25 @@ local getattr = nuts.getattr local setattr = nuts.setattr local getsubtype = nuts.getsubtype local getwhd = nuts.getwhd -local getdir = nuts.getdir +local getdirection = nuts.getdirection local setshift = nuts.setshift local getboxglue = nuts.getboxglue local hpack_list = nuts.hpack local vpack_list = nuts.vpack -local list_dimensions = nuts.dimensions -local list_rangedimensions = nuts.rangedimensions +local getdimensions = nuts.dimensions +local getrangedimensions = nuts.rangedimensions local traverse = nuts.traverse local find_node_tail = nuts.tail local nodecodes = nodes.nodecodes -local skipcodes = nodes.skipcodes +local gluecodes = nodes.gluecodes 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 @@ -90,11 +94,11 @@ local rule_code = nodecodes.rule local dir_code = nodecodes.dir local localpar_code = nodecodes.localpar -local leftskip_code = skipcodes.leftskip -local rightskip_code = skipcodes.rightskip -local parfillskip_code = skipcodes.parfillskip +local leftskip_code = gluecodes.leftskip +local rightskip_code = gluecodes.rightskip +local parfillskip_code = gluecodes.parfillskip -local line_code = listcodes.line +----- linelist_code = listcodes.line local new_rule = nodepool.rule local new_kern = nodepool.kern @@ -113,9 +117,9 @@ local implement = interfaces.implement local function hlist_dimensions(start,stop,parent) local last = stop and getnext(stop) if parent then - return list_rangedimensions(parent,start,last) + return getrangedimensions(parent,start,last) else - return list_dimensions(start,last) + return getdimensions(start,last) end end @@ -250,11 +254,13 @@ 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 == "+TRT" or (txtdir == "===" and pardir == "TRT") then -- KH: textdir == "===" test added + if txtdir == righttoleft_code then + width = - width + elseif textdir == lefttoright_code then + -- go on + elseif pardir == righttoleft_code then width = - width end local result, resolved = make(width,height,depth,reference) @@ -264,7 +270,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) @@ -273,7 +279,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) @@ -281,7 +287,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 @@ -306,7 +312,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 -- box_code line_code + if id == hlist_code then -- boxlist_code linelist_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] @@ -337,7 +343,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 == "TRT" then + if pardir == righttoleft_code then width = - width end local result, resolved = make(width,height,depth,reference) @@ -345,7 +351,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) @@ -370,12 +376,6 @@ 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, ok - h, ok, pardir, txtdir = inject_areas(list,attribute,make,stack,done,r or skip or 0,current,pardir,txtdir) + 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 @@ -416,9 +416,12 @@ 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 - txtdir = getdir(current) - elseif id == localpar_code then -- only test at begin - pardir = getdir(current) + 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 else local r = getattr(current,attribute) if not r then @@ -441,46 +444,183 @@ 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, true, pardir, txtdir + return head, pardir, txtdir 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 = "===" +-- -- 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 -- 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) --- 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) +-- 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 -- end -- local list = getlist(current) -- if list then --- local h = inject_area(list,attribute,make,stack,done,current,pardir,txtdir) +-- 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 == glue_code and getsubtype(current) == leftskip_code then -- any glue at the left? +-- -- -- elseif id == dir_code then --- txtdir = getdir(current) --- elseif id == localpar_code then --- pardir = getdir(current) --- else --- 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) +-- 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 +-- else +-- reference, first, last, firstdir = r, current, current, txtdir -- end +-- ::next:: -- current = getnext(current) -- end --- return head, true +-- 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 -- end -- tracing: todo: use predefined colors @@ -595,11 +735,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) +local function setreference(h,d,r) -- h and d can be nil 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, d, codeinjections.prerollreference(r) } + stack[topofstack] = { r, h or false, d or false, codeinjections.prerollreference(r) } -- texsetattribute(attribute,topofstack) -- todo -> at tex end texsetcount("lastreferenceattribute",topofstack) end @@ -615,7 +755,11 @@ local function makereference(width,height,depth,reference) -- height and depth a if trace_references then report_reference("resolving attribute %a",reference) end - local resolved, ht, dp, set, n = sr[1], sr[2], sr[3], sr[4], sr[5] + local resolved = sr[1] + local ht = sr[2] + local dp = sr[3] + local set = sr[4] + local n = 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 @@ -672,11 +816,9 @@ end function nodes.references.handler(head) if head and topofstack > 0 then - local head = tonut(head) - local head, done = inject_areas(head,attribute,makereference,stack,done) - return tonode(head), done + return (inject_areas(head,attribute,makereference,stack,done)) else - return head, false + return head end end @@ -706,7 +848,11 @@ local function makedestination(width,height,depth,reference) if trace_destinations then report_destination("resolving attribute %a",reference) end - local resolved, ht, dp, name, view = sr[1], sr[2], sr[3], sr[4], sr[5] -- sr[4] will change to just internal + local resolved = sr[1] + local ht = sr[2] + local dp = sr[3] + local name = sr[4] + local view = sr[5] if ht then if height < ht then height = ht end if depth < dp then depth = dp end @@ -783,21 +929,12 @@ 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 - local head = tonut(head) - local head, done = inject_areas(head,attribute,makedestination,stack,done) - return tonode(head), done + return (inject_areas(head,attribute,makedestination,stack,done)) else - return head, false + return head end end @@ -907,15 +1044,3 @@ 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 -} |