diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/typo-mar.lua')
-rw-r--r-- | Master/texmf-dist/tex/context/base/typo-mar.lua | 222 |
1 files changed, 137 insertions, 85 deletions
diff --git a/Master/texmf-dist/tex/context/base/typo-mar.lua b/Master/texmf-dist/tex/context/base/typo-mar.lua index ec827883db1..4ea6b1e1d86 100644 --- a/Master/texmf-dist/tex/context/base/typo-mar.lua +++ b/Master/texmf-dist/tex/context/base/typo-mar.lua @@ -76,6 +76,7 @@ if not modules then modules = { } end modules ['typo-mar'] = { local format, validstring = string.format, string.valid local insert, remove = table.insert, table.remove local setmetatable, next = setmetatable, next +local formatters = string.formatters local attributes, nodes, node, variables = attributes, nodes, node, variables @@ -115,15 +116,30 @@ local v_first = variables.first local v_text = variables.text local v_column = variables.column -local copy_node_list = node.copy_list -local slide_nodes = node.slide -local hpack_nodes = node.hpack -- nodes.fasthpack not really faster here -local traverse_id = node.traverse_id -local free_node_list = node.flush_list -local insert_node_after = node.insert_after -local insert_node_before = node.insert_before - -local concat_nodes = nodes.concat +local nuts = nodes.nuts +local nodepool = nuts.pool + +local tonode = nuts.tonode +local tonut = nuts.tonut + +local copy_node_list = nuts.copy_list +local hpack_nodes = nuts.hpack -- nodes.fasthpack not really faster here +local traverse_id = nuts.traverse_id +local free_node_list = nuts.flush_list +local insert_node_after = nuts.insert_after +local insert_node_before = nuts.insert_before +local linked_nodes = nuts.linked + +local getfield = nuts.getfield +local setfield = nuts.setfield +local getnext = nuts.getnext +local getprev = nuts.getprev +local getid = nuts.getid +local getattr = nuts.getattr +local setattr = nuts.setattr +local getsubtype = nuts.getsubtype +local getbox = nuts.getbox +local getlist = nuts.getlist local nodecodes = nodes.nodecodes local listcodes = nodes.listcodes @@ -146,7 +162,7 @@ local userdefined_code = whatsitcodes.userdefined local dir_code = whatsitcodes.dir local localpar_code = whatsitcodes.localpar -local nodepool = nodes.pool +local nodepool = nuts.pool local new_kern = nodepool.kern local new_glue = nodepool.glue @@ -155,23 +171,27 @@ local new_stretch = nodepool.stretch local new_usernumber = nodepool.usernumber local new_latelua = nodepool.latelua -local texcount = tex.count -local texdimen = tex.dimen -local texbox = tex.box +local lateluafunction = nodepool.lateluafunction + +local texgetcount = tex.getcount +local texgetdimen = tex.getdimen +local texget = tex.get local points = number.points local isleftpage = layouts.status.isleftpage -local registertogether = builders.paragraphs.registertogether - -local jobpositions = job.positions -local getposition = jobpositions.position +local registertogether = builders.paragraphs.registertogether -- tonode local a_margindata = attributes.private("margindata") local inline_mark = nodepool.userids["margins.inline"] -local margins = { } +local jobpositions = job.positions +local getposition = jobpositions.get +local setposition = jobpositions.set +local getreserved = jobpositions.getreserved + +local margins = { } typesetters.margins = margins local locations = { v_left, v_right, v_inner, v_outer } -- order might change @@ -234,7 +254,7 @@ local function showstore(store,banner,location) if next(store) then for i, si in table.sortedpairs(store) do local si =store[i] - report_margindata("%s: stored in %a at %s: %a => %s",banner,location,i,validstring(si.name,"no name"),nodes.toutf(si.box.list)) + report_margindata("%s: stored in %a at %s: %a => %s",banner,location,i,validstring(si.name,"no name"),nodes.toutf(getlist(si.box))) end else report_margindata("%s: nothing stored in location %a",banner,location) @@ -243,7 +263,7 @@ end function margins.save(t) setmetatable(t,defaults) - local content = texbox[t.number] + local content = getbox(t.number) local location = t.location local category = t.category local inline = t.inline @@ -309,25 +329,26 @@ function margins.save(t) t.n = nofsaved -- used later (we will clean up this natural mess later) -- nice is to make a special status table mechanism - local leftmargindistance = texdimen.naturalleftmargindistance - local rightmargindistance = texdimen.naturalrightmargindistance - t.strutdepth = texbox.strutbox.depth - t.strutheight = texbox.strutbox.height - t.leftskip = tex.leftskip.width -- we're not in forgetall - t.rightskip = tex.rightskip.width -- we're not in forgetall + local leftmargindistance = texgetdimen("naturalleftmargindistance") + local rightmargindistance = texgetdimen("naturalrightmargindistance") + local strutbox = getbox("strutbox") + t.strutdepth = getfield(strutbox,"depth") + t.strutheight = getfield(strutbox,"height") + t.leftskip = getfield(texget("leftskip"),"width") -- we're not in forgetall + t.rightskip = getfield(texget("rightskip"),"width") -- we're not in forgetall t.leftmargindistance = leftmargindistance -- todo:layoutstatus table t.rightmargindistance = rightmargindistance - t.leftedgedistance = texdimen.naturalleftedgedistance - + texdimen.leftmarginwidth + t.leftedgedistance = texgetdimen("naturalleftedgedistance") + + texgetdimen("leftmarginwidth") + leftmargindistance - t.rightedgedistance = texdimen.naturalrightedgedistance - + texdimen.rightmarginwidth + t.rightedgedistance = texgetdimen("naturalrightedgedistance") + + texgetdimen("rightmarginwidth") + rightmargindistance - t.lineheight = texdimen.lineheight + t.lineheight = texgetdimen("lineheight") -- - -- t.realpageno = texcount.realpageno + -- t.realpageno = texgetcount("realpageno") if inline then - context(new_usernumber(inline_mark,nofsaved)) + context(tonode(new_usernumber(inline_mark,nofsaved))) -- or use a normal node store[nofsaved] = t -- no insert nofinlined = nofinlined + 1 else @@ -352,6 +373,16 @@ end local status, nofstatus = { }, 0 +local f_anchor = formatters["_plib_.set('md:h',%i,{x=true,c=true})"] +local function setanchor(h_anchor) + return new_latelua(f_anchor(h_anchor)) +end + +-- local t_anchor = { x = true, c = true } +-- local function setanchor(h_anchor) +-- return lateluafunction(function() setposition("md:h",h_anchor,t_anchor) end) +-- end + local function realign(current,candidate) local location = candidate.location local margin = candidate.margin @@ -404,7 +435,7 @@ local function realign(current,candidate) -- we assume that list is a hbox, otherwise we had to take the whole current -- in order to get it right - current.width = 0 + setfield(current,"width",0) local anchornode, move_x -- this mess is needed for alignments (combinations) so we use that @@ -420,10 +451,10 @@ local function realign(current,candidate) if inline or anchor ~= v_text or candidate.psubtype == alignment_code then -- the alignment_code check catches margintexts ste before a tabulate h_anchors = h_anchors + 1 - anchornode = new_latelua(format("_plib_.set('md:h',%i,{x=true,c=true})",h_anchors)) - local blob = jobpositions.get('md:h', h_anchors) + anchornode = setanchor(h_anchors) + local blob = getposition('md:h',h_anchors) if blob then - local reference = jobpositions.getreserved(anchor,blob.c) + local reference = getreserved(anchor,blob.c) if reference then if location == v_left then move_x = (reference.x or 0) - (blob.x or 0) @@ -446,9 +477,9 @@ local function realign(current,candidate) report_margindata("realigned %a, location %a, margin %a",candidate.n,location,margin) end end - - current.list = hpack_nodes(concat_nodes{anchornode,new_kern(-delta),current.list,new_kern(delta)}) - current.width = 0 + local list = hpack_nodes(linked_nodes(anchornode,new_kern(-delta),getlist(current),new_kern(delta))) + setfield(current,"list",list) + setfield(current,"width",0) end local function realigned(current,a) @@ -478,24 +509,36 @@ end -- resetstacked() -function margins.ha(tag) -- maybe l/r keys ipv left/right keys +local function ha(tag) -- maybe l/r keys ipv left/right keys local p = cache[tag] p.p = true p.y = true - jobpositions.set('md:v',tag,p) + setposition('md:v',tag,p) cache[tag] = nil end -local function markovershoot(current) +margins.ha = ha + +local f_anchor = formatters["typesetters.margins.ha(%s)"] +local function setanchor(v_anchor) + return new_latelua(f_anchor(v_anchor)) +end + +-- local function setanchor(v_anchor) -- freezes the global here +-- return lateluafunction(function() ha(v_anchor) end) +-- end + +local function markovershoot(current) -- todo: alleen als offset > line v_anchors = v_anchors + 1 cache[v_anchors] = stacked - local anchor = new_latelua(format("typesetters.margins.ha(%s)",v_anchors)) -- todo: alleen als offset > line - current.list = hpack_nodes(concat_nodes{anchor,current.list}) + local anchor = setanchor(v_anchors) + local list = hpack_nodes(linked_nodes(anchor,getlist(current))) + setfield(current,"list",list) end local function getovershoot(location) - local p = jobpositions.get("md:v",v_anchors) - local c = jobpositions.get("md:v",v_anchors+1) + local p = getposition("md:v",v_anchors) + local c = getposition("md:v",v_anchors+1) if p and c and p.p and p.p == c.p then local distance = p.y - c.y local offset = p[location] or 0 @@ -512,10 +555,10 @@ end local function inject(parent,head,candidate) local box = candidate.box - local width = box.width - local height = box.height - local depth = box.depth - local shift = box.shift + local width = getfield(box,"width") + local height = getfield(box,"height") + local depth = getfield(box,"depth") + local shift = getfield(box,"shift") local stack = candidate.stack local location = candidate.location local method = candidate.method @@ -524,7 +567,7 @@ local function inject(parent,head,candidate) local baseline = candidate.baseline local strutheight = candidate.strutheight local strutdepth = candidate.strutdepth - local psubtype = parent.subtype + local psubtype = getsubtype(parent) local offset = stacked[location] local firstonstack = offset == false or offset == nil nofstatus = nofstatus + 1 @@ -546,7 +589,7 @@ local function inject(parent,head,candidate) end end candidate.width = width - candidate.hsize = parent.width -- we can also pass textwidth + candidate.hsize = getfield(parent,"width") -- we can also pass textwidth candidate.psubtype = psubtype if trace_margindata then report_margindata("processing, index %s, height %p, depth %p, parent %s",candidate.n,height,depth,listcodes[psubtype]) @@ -573,7 +616,7 @@ local function inject(parent,head,candidate) -- experimental. -- -- -- if method == v_top then - local delta = height - parent.height + local delta = height - getfield(parent,"height") if trace_margindata then report_margindata("top aligned by %p",delta) end @@ -616,22 +659,23 @@ local function inject(parent,head,candidate) shift = shift + delta offset = offset + delta end - box.shift = shift - box.width = 0 + setfield(box,"shift",shift) + setfield(box,"width",0) if not head then head = box - elseif head.id == whatsit_code and head.subtype == localpar_code then + elseif getid(head) == whatsit_code and getsubtype(head) == localpar_code then -- experimental - if head.dir == "TRT" then - box.list = hpack_nodes(concat_nodes{new_kern(candidate.hsize),box.list,new_kern(-candidate.hsize)}) + if getfield(head,"dir") == "TRT" then + local list = hpack_nodes(linked_nodes(new_kern(candidate.hsize),getlist(box),new_kern(-candidate.hsize))) + setfield(box,"list",list) end insert_node_after(head,head,box) else - head.prev = box - box.next = head + setfield(head,"prev",box) + setfield(box,"next",head) head = box end - box[a_margindata] = nofstatus + setattr(box,a_margindata,nofstatus) if trace_margindata then report_margindata("injected, location %a, shift %p",location,shift) end @@ -656,12 +700,12 @@ local function flushinline(parent,head) local current = head local done = false local continue = false - local room, don, con + local room, don, con, list while current and nofinlined > 0 do - local id = current.id + local id = getid(current) if id == whatsit_code then - if current.subtype == userdefined_code and current.user_id == inline_mark then - local n = current.value + if getsubtype(current) == userdefined_code and getfield(current,"user_id") == inline_mark then + local n = getfield(current,"value") local candidate = inlinestore[n] if candidate then -- no vpack, as we want to realign inlinestore[n] = nil @@ -674,11 +718,12 @@ local function flushinline(parent,head) end elseif id == hlist_code or id == vlist_code then -- optional (but sometimes needed) - current.list, don, con = flushinline(current,current.list) + list, don, con = flushinline(current,getlist(current)) + setfield(current,"list",list) continue = continue or con done = done or don end - current = current.next + current = getnext(current) end return head, done, continue end @@ -686,7 +731,7 @@ end local a_linenumber = attributes.private('linenumber') local function flushed(scope,parent) -- current is hlist - local head = parent.list + local head = getlist(parent) local done = false local continue = false local room, con, don @@ -702,7 +747,7 @@ local function flushed(scope,parent) -- current is hlist done = true continue = continue or con nofstored = nofstored - 1 - registertogether(parent,room) + registertogether(tonode(parent),room) -- !! tonode else break end @@ -711,17 +756,18 @@ local function flushed(scope,parent) -- current is hlist end if nofinlined > 0 then if done then - parent.list = head + setfield(parent,"list",head) end head, don, con = flushinline(parent,head) continue = continue or con done = done or don end if done then - local a = head[a_linenumber] -- hack .. we need a more decent critical attribute inheritance mechanism - parent.list = hpack_nodes(head,parent.width,"exactly") + local a = getattr(head,a_linenumber) -- hack .. we need a more decent critical attribute inheritance mechanism + local l = hpack_nodes(head,getfield(parent,"width"),"exactly") + setfield(parent,"list",l) if a then - parent.list[a_linenumber] = a + setattr(l,a_linenumber,a) end -- resetstacked() end @@ -736,14 +782,15 @@ local function handler(scope,head,group) if trace_margindata then report_margindata("flushing stage one, stored %s, scope %s, delayed %s, group %a",nofstored,scope,nofdelayed,group) end + head = tonut(head) local current = head local done = false while current do - local id = current.id - if (id == vlist_code or id == hlist_code) and not current[a_margindata] then + local id = getid(current) + if (id == vlist_code or id == hlist_code) and not getattr(current,a_margindata) then local don, continue = flushed(scope,current) if don then - current[a_margindata] = 0 -- signal to prevent duplicate processing + setattr(current,a_margindata,0) -- signal to prevent duplicate processing if continue then markovershoot(current) end @@ -753,12 +800,12 @@ local function handler(scope,head,group) done = true end end - current = current.next + current = getnext(current) end -- if done then resetstacked() -- why doesn't done work ok here? -- end - return head, done + return tonode(head), done else return head, false end @@ -811,11 +858,11 @@ local function finalhandler(head) local current = head local done = false while current do - local id = current.id + local id = getid(current) if id == hlist_code then - local a = current[a_margindata] + local a = getattr(current,a_margindata) if not a or a == 0 then - finalhandler(current.list) + finalhandler(getlist(current)) elseif realigned(current,a) then done = true if nofdelayed == 0 then @@ -823,9 +870,9 @@ local function finalhandler(head) end end elseif id == vlist_code then - finalhandler(current.list) + finalhandler(getlist(current)) end - current = current.next + current = getnext(current) end return head, done else @@ -838,7 +885,10 @@ function margins.finalhandler(head) -- if trace_margindata then -- report_margindata("flushing stage two, instore: %s, delayed: %s",nofstored,nofdelayed) -- end - return finalhandler(head) +head = tonut(head) +local head, done = finalhandler(head) +head = tonode(head) + return head, done else return head, false end @@ -877,3 +927,5 @@ statistics.register("margin data", function() return nil end end) + +commands.savemargindata = margins.save |