summaryrefslogtreecommitdiff
path: root/tex/context/base/page-mix.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/page-mix.lua')
-rw-r--r--tex/context/base/page-mix.lua590
1 files changed, 397 insertions, 193 deletions
diff --git a/tex/context/base/page-mix.lua b/tex/context/base/page-mix.lua
index 7d13d9e4e..61a4f944d 100644
--- a/tex/context/base/page-mix.lua
+++ b/tex/context/base/page-mix.lua
@@ -13,48 +13,81 @@ if not modules then modules = { } end modules ["page-mix"] = {
-- local trackers, logs, storage = trackers, logs, storage
-- local number, table = number, table
+local next, type = next, type
local concat = table.concat
-
-local nodecodes = nodes.nodecodes
-local gluecodes = nodes.gluecodes
-local nodepool = nodes.pool
-
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
-local kern_code = nodecodes.kern
-local glue_code = nodecodes.glue
-local penalty_code = nodecodes.penalty
-local insert_code = nodecodes.ins
-local mark_code = nodecodes.mark
-
-local new_hlist = nodepool.hlist
-local new_vlist = nodepool.vlist
-local new_glue = nodepool.glue
-
-local hpack = node.hpack
-local vpack = node.vpack
-local freenode = node.free
-local concatnodes = nodes.concat
-
-local texgetbox = tex.getbox
-local texsetbox = tex.setbox
-local texgetskip = tex.getskip
-
-local points = number.points
-
-local settings_to_hash = utilities.parsers.settings_to_hash
-
-local variables = interfaces.variables
-local v_yes = variables.yes
-local v_global = variables["global"]
-local v_local = variables["local"]
-local v_columns = variables.columns
+local ceil, floor = math.ceil, math.floor
local trace_state = false trackers.register("mixedcolumns.trace", function(v) trace_state = v end)
local trace_detail = false trackers.register("mixedcolumns.detail", function(v) trace_detail = v end)
local report_state = logs.reporter("mixed columns")
+local nodecodes = nodes.nodecodes
+local gluecodes = nodes.gluecodes
+
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local kern_code = nodecodes.kern
+local glue_code = nodecodes.glue
+local penalty_code = nodecodes.penalty
+local insert_code = nodecodes.ins
+local mark_code = nodecodes.mark
+local rule_code = nodecodes.rule
+
+local topskip_code = gluecodes.topskip
+local lineskip_code = gluecodes.lineskip
+local baselineskip_code = gluecodes.baselineskip
+local userskip_code = gluecodes.userskip
+
+local nuts = nodes.nuts
+local tonode = nuts.tonode
+local nodetostring = nuts.tostring
+local listtoutf = nodes.listtoutf
+
+local hpack = nuts.hpack
+local vpack = nuts.vpack
+local freenode = nuts.free
+local concatnodes = nuts.concat
+local slidenodes = nuts.slide -- ok here as we mess with prev links intermediately
+local traversenodes = nuts.traverse
+
+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 getsubtype = nuts.getsubtype
+local getbox = nuts.getbox
+local setbox = nuts.setbox
+local getskip = nuts.getskip
+local getattribute = nuts.getattribute
+
+local nodepool = nuts.pool
+
+local new_hlist = nodepool.hlist
+local new_vlist = nodepool.vlist
+local new_glue = nodepool.glue
+
+local points = number.points
+
+local settings_to_hash = utilities.parsers.settings_to_hash
+
+local variables = interfaces.variables
+local v_yes = variables.yes
+local v_global = variables["global"]
+local v_local = variables["local"]
+local v_columns = variables.columns
+local v_fixed = variables.fixed
+local v_auto = variables.auto
+local v_none = variables.none
+local v_more = variables.more
+local v_less = variables.less
+local v_halfline = variables.halfline
+
+local context = context
+local implement = interfaces.implement
+
pagebuilders = pagebuilders or { }
pagebuilders.mixedcolumns = pagebuilders.mixedcolumns or { }
local mixedcolumns = pagebuilders.mixedcolumns
@@ -77,13 +110,13 @@ local function collectinserts(result,nxt,nxtid)
local inserts, currentskips, nextskips, inserttotal = { }, 0, 0, 0
while nxt do
if nxtid == insert_code then
- inserttotal = inserttotal + nxt.height + nxt.depth
- local s = nxt.subtype
+ inserttotal = inserttotal + getfield(nxt,"height") + getfield(nxt,"depth")
+ local s = getsubtype(nxt)
local c = inserts[s]
if not c then
c = { }
inserts[s] = c
- local width = texgetskip(s).width
+ local width = getfield(getskip(s),"width")
if not result.inserts[s] then
currentskips = currentskips + width
end
@@ -100,9 +133,9 @@ local function collectinserts(result,nxt,nxtid)
else
break
end
- nxt = nxt.next
+ nxt = getnext(nxt)
if nxt then
- nxtid = nxt.id
+ nxtid = getid(nxt)
else
break
end
@@ -128,30 +161,30 @@ end
local function discardtopglue(current,discarded)
local size = 0
while current do
- local id = current.id
+ local id = getid(current)
if id == glue_code then
- size = size + current.spec.width
+ size = size + getfield(getfield(current,"spec"),"width")
discarded[#discarded+1] = current
- current = current.next
+ current = getnext(current)
elseif id == penalty_code then
- if current.penalty == forcedbreak then
+ if getfield(current,"penalty") == forcedbreak then
discarded[#discarded+1] = current
- current = current.next
- while current and current.id == glue_code do
- size = size + current.spec.width
+ current = getnext(current)
+ while current and getid(current) == glue_code do
+ size = size + getfield(getfield(current,"spec"),"width")
discarded[#discarded+1] = current
- current = current.next
+ current = getnext(current)
end
else
discarded[#discarded+1] = current
- current = current.next
+ current = getnext(current)
end
else
break
end
end
if current then
- current.prev = nil
+ setfield(current,"prev",nil) -- prevent look back
end
return current, size
end
@@ -162,13 +195,13 @@ local function stripbottomglue(results,discarded)
local r = results[i]
local t = r.tail
while t and t ~= r.head do
- local prev = t.prev
+ local prev = getprev(t)
if not prev then
break
end
- local id = t.id
+ local id = getid(t)
if id == penalty_code then
- if t.penalty == forcedbreak then
+ if getfield(t,"penalty") == forcedbreak then
break
else
discarded[#discarded+1] = t
@@ -177,7 +210,7 @@ local function stripbottomglue(results,discarded)
end
elseif id == glue_code then
discarded[#discarded+1] = t
- local width = t.spec.width
+ local width = getfield(getfield(t,"spec"),"width")
if trace_state then
report_state("columns %s, discarded bottom glue %p",i,width)
end
@@ -195,51 +228,52 @@ local function stripbottomglue(results,discarded)
return height
end
-local function setsplit(specification) -- a rather large function
+local function preparesplit(specification) -- a rather large function
local box = specification.box
if not box then
report_state("fatal error, no box")
return
end
- local list = texgetbox(box)
+ local list = getbox(box)
if not list then
report_state("fatal error, no list")
return
end
- local head = list.head or specification.originalhead
+ local head = getlist(list) or specification.originalhead
if not head then
report_state("fatal error, no head")
return
end
- local discarded = { }
- local originalhead = head
- local originalwidth = specification.originalwidth or list.width
- local originalheight = specification.originalheight or list.height
- local current = head
- local skipped = 0
- local height = 0
- local depth = 0
- local skip = 0
- local splitmethod = specification.splitmethod or false
+ slidenodes(head) -- we can have set prev's to nil to prevent backtracking
+ local discarded = { }
+ local originalhead = head
+ local originalwidth = specification.originalwidth or getfield(list,"width")
+ local originalheight = specification.originalheight or getfield(list,"height")
+ local current = head
+ local skipped = 0
+ local height = 0
+ local depth = 0
+ local skip = 0
+ local splitmethod = specification.splitmethod or false
if splitmethod == v_none then
splitmethod = false
end
- local options = settings_to_hash(specification.option or "")
+ local options = settings_to_hash(specification.option or "")
local stripbottom = specification.alternative == v_local
- local cycle = specification.cycle or 1
- local nofcolumns = specification.nofcolumns or 1
+ local cycle = specification.cycle or 1
+ local nofcolumns = specification.nofcolumns or 1
if nofcolumns == 0 then
nofcolumns = 1
end
local preheight = specification.preheight or 0
- local extra = specification.extra or 0
+ local extra = specification.extra or 0
local maxheight = specification.maxheight
- local optimal = originalheight/nofcolumns
+ local optimal = originalheight/nofcolumns
if specification.balance ~= v_yes then
optimal = maxheight
end
- local target = optimal + extra
- local overflow = target > maxheight - preheight
+ local target = optimal + extra
+ local overflow = target > maxheight - preheight
local threshold = specification.threshold or 0
if overflow then
target = maxheight - preheight
@@ -267,33 +301,73 @@ local function setsplit(specification) -- a rather large function
local rest = nil
local lastlocked = nil
local lastcurrent = nil
+ local lastcontent = nil
local backtracked = false
if trace_state then
report_state("setting collector to column %s",column)
end
+ local function unlock(penalty)
+ if lastlocked then
+ if trace_state then
+ report_state("penalty %s, unlocking in column %s",penalty or "-",column)
+ end
+ lastlocked = nil
+ end
+ lastcurrent = nil
+ lastcontent = nil
+ end
+
+ local function lock(penalty,current)
+ if trace_state then
+ report_state("penalty %s, locking in column %s",penalty,column)
+ end
+ lastlocked = penalty
+ lastcurrent = current or lastcurrent
+ lastcontent = nil
+ end
+
local function backtrack(start)
local current = start
-- first skip over glue and penalty
while current do
- local id = current.id
- if id == glue_code or id == penalty_code then
- current = current.prev
+ local id = getid(current)
+ if id == glue_code then
+ if trace_state then
+ report_state("backtracking over %s in column %s","glue",column)
+ end
+ current = getprev(current)
+ elseif id == penalty_code then
+ if trace_state then
+ report_state("backtracking over %s in column %s","penalty",column)
+ end
+ current = getprev(current)
else
break
end
end
-- then skip over content
while current do
- local id = current.id
- if id == glue_code or id == penalty_code then
+ local id = getid(current)
+ if id == glue_code then
+ if trace_state then
+ report_state("quitting at %s in column %s","glue",column)
+ end
+ break
+ elseif id == penalty_code then
+ if trace_state then
+ report_state("quitting at %s in column %s","penalty",column)
+ end
break
else
- current = current.prev
+ current = getprev(current)
end
end
if not current then
+ if trace_state then
+ report_state("no effective backtracking in column %s",column)
+ end
current = start
end
return current
@@ -310,7 +384,12 @@ local function setsplit(specification) -- a rather large function
backtracked = true
end
lastcurrent = nil
- lastlocked = nil
+ if lastlocked then
+ if trace_state then
+ report_state("unlocking in column %s",column)
+ end
+ lastlocked = nil
+ end
end
if head == lasthead then
if trace_state then
@@ -324,7 +403,7 @@ local function setsplit(specification) -- a rather large function
if current == head then
result.tail = head
else
- result.tail = current.prev
+ result.tail = getprev(current)
end
result.height = height
result.depth = depth
@@ -344,6 +423,9 @@ local function setsplit(specification) -- a rather large function
report_state("setting collector to column %s",column)
end
current, skipped = discardtopglue(current,discarded)
+ if trace_detail and skipped ~= 0 then
+ report_state("check > column 1, discarded %p",skipped)
+ end
head = current
return true, skipped
end
@@ -352,6 +434,7 @@ local function setsplit(specification) -- a rather large function
local function checked(advance,where,locked)
local total = skip + height + depth + advance
local delta = total - target
+-- - 65536*3
local state = "same"
local okay = false
local skipped = 0
@@ -366,7 +449,7 @@ local function setsplit(specification) -- a rather large function
end
end
if trace_detail then
- report_state("%-7s > column %s, delta %p, threshold %p, advance %p, total %p, target %p, discarded %p => %a (height %p, depth %p, skip %p)",
+ report_state("%-7s > column %s, delta %p, threshold %p, advance %p, total %p, target %p => %a (height %p, depth %p, skip %p)",
where,curcol,delta,threshold,advance,total,target,state,skipped,height,depth,skip)
end
return state, skipped
@@ -387,7 +470,7 @@ local function setsplit(specification) -- a rather large function
head = current
local function process_skip(current,nxt)
- local advance = current.spec.width
+ local advance = getfield(getfield(current,"spec"),"width")
if advance ~= 0 then
local state, skipped = checked(advance,"glue")
if trace_state then
@@ -401,17 +484,28 @@ local function setsplit(specification) -- a rather large function
end
height = height + depth + skip
depth = 0
+if advance < 0 then
+ height = height + advance
+ skip = 0
+ if height < 0 then
+ height = 0
+ end
+else
skip = height > 0 and advance or 0
+end
if trace_state then
report_state("%-7s > column %s, height %p, depth %p, skip %p","glue",column,height,depth,skip)
end
else
-- what else? ignore? treat as valid as usual?
end
+ if lastcontent then
+ unlock()
+ end
end
local function process_kern(current,nxt)
- local advance = current.kern
+ local advance = getfield(current,"kern")
if advance ~= 0 then
local state, skipped = checked(advance,"kern")
if trace_state then
@@ -434,25 +528,28 @@ local function setsplit(specification) -- a rather large function
local function process_rule(current,nxt)
-- simple variant of h|vlist
- local advance = current.height -- + current.depth
- local state, skipped = checked(advance+currentskips,"rule")
- if trace_state then
- report_state("%-7s > column %s, state %a, rule, advance %p, height %p","line",column,state,advance,inserttotal,height)
- if skipped ~= 0 then
- report_state("%-7s > column %s, discarded %p","rule",column,skipped)
+ local advance = getfield(current,"height") -- + getfield(current,"depth")
+ if advance ~= 0 then
+ local state, skipped = checked(advance,"rule")
+ if trace_state then
+ report_state("%-7s > column %s, state %a, rule, advance %p, height %p","rule",column,state,advance,inserttotal,height)
+ if skipped ~= 0 then
+ report_state("%-7s > column %s, discarded %p","rule",column,skipped)
+ end
end
+ if state == "quit" then
+ return true
+ end
+ height = height + depth + skip + advance
+ -- if state == "next" then
+ -- height = height + nextskips
+ -- else
+ -- height = height + currentskips
+ -- end
+ depth = getfield(current,"depth")
+ skip = 0
end
- if state == "quit" then
- return true
- end
- height = height + depth + skip + advance
- if state == "next" then
- height = height + nextskips
- else
- height = height + currentskips
- end
- depth = current.depth
- skip = 0
+ lastcontent = current
end
-- okay, here we could do some badness like magic but we want something
@@ -462,12 +559,11 @@ local function setsplit(specification) -- a rather large function
-- [chapter] [penalty] [section] [penalty] [first line]
local function process_penalty(current,nxt)
- local penalty = current.penalty
+ local penalty = getfield(current,"penalty")
if penalty == 0 then
- lastlocked = nil
- lastcurrent = nil
+ unlock(penalty)
elseif penalty == forcedbreak then
- local needed = current[a_checkedbreak]
+ local needed = getattribute(current,a_checkedbreak)
local proceed = not needed or needed == 0
if not proceed then
local available = target - height
@@ -477,8 +573,7 @@ local function setsplit(specification) -- a rather large function
end
end
if proceed then
- lastlocked = nil
- lastcurrent = nil
+ unlock(penalty)
local okay, skipped = gotonext()
if okay then
if trace_state then
@@ -499,28 +594,26 @@ local function setsplit(specification) -- a rather large function
end
elseif penalty < 0 then
-- we don't care too much
- lastlocked = nil
- lastcurrent = nil
+ unlock(penalty)
elseif penalty >= 10000 then
if not lastcurrent then
- lastcurrent = current
- lastlocked = penalty
+ lock(penalty,current)
elseif penalty > lastlocked then
- lastlocked = penalty
+ lock(penalty)
end
else
- lastlocked = nil
- lastcurrent = nil
+ unlock(penalty)
end
end
local function process_list(current,nxt)
- local nxtid = nxt and nxt.id
+ local nxtid = nxt and getid(nxt)
line = line + 1
local inserts, currentskips, nextskips, inserttotal = nil, 0, 0, 0
- local advance = current.height -- + current.depth
+ local advance = getfield(current,"height")
+-- + getfield(current,"depth") -- when > strutdp
if trace_state then
- report_state("%-7s > column %s, content: %s","line",column,listtoutf(current.list,true,true))
+ report_state("%-7s > column %s, content: %s","line",column,listtoutf(getlist(current),true,true))
end
if nxt and (nxtid == insert_code or nxtid == mark_code) then
nxt, inserts, localskips, insertskips, inserttotal = collectinserts(result,nxt,nxtid)
@@ -541,7 +634,7 @@ local function setsplit(specification) -- a rather large function
else
height = height + currentskips
end
- depth = current.depth
+ depth = getfield(current,"depth")
skip = 0
if inserts then
-- so we already collect them ... makes backtracking tricky ... alternatively
@@ -551,12 +644,15 @@ local function setsplit(specification) -- a rather large function
if trace_state then
report_state("%-7s > column %s, height %p, depth %p, skip %p","line",column,height,depth,skip)
end
+ lastcontent = current
end
+local kept = head
+
while current do
- local id = current.id
- local nxt = current.next
+ local id = getid(current)
+ local nxt = getnext(current)
backtracked = false
@@ -602,14 +698,16 @@ local function setsplit(specification) -- a rather large function
if not current then
if trace_state then
- report_state("nilling rest")
+ report_state("nothing left")
end
- rest = nil
- elseif rest == lasthead then
+ -- needs well defined case
+ -- rest = nil
+ elseif rest == lasthead then
if trace_state then
- report_state("nilling rest as rest is lasthead")
+ report_state("rest equals lasthead")
end
- rest = nil
+ -- test case: x\index{AB} \index{AA}x \blank \placeindex
+ -- makes line disappear: rest = nil
end
if stripbottom then
@@ -629,24 +727,26 @@ local function setsplit(specification) -- a rather large function
specification.overflow = overflow
specification.discarded = discarded
- texgetbox(specification.box).list = nil
+ setfield(getbox(specification.box),"list",nil)
return specification
end
-function mixedcolumns.finalize(result)
+local function finalize(result)
if result then
- local results = result.results
- for i=1,result.nofcolumns do
+ local results = result.results
+ local columns = result.nofcolumns
+ local maxtotal = 0
+ for i=1,columns do
local r = results[i]
local h = r.head
if h then
- h.prev = nil
+ setfield(h,"prev",nil)
local t = r.tail
if t then
- t.next = nil
+ setfield(t,"next",nil)
else
- h.next = nil
+ setfield(h,"next",nil)
r.tail = h
end
for c, list in next, r.inserts do
@@ -655,16 +755,26 @@ function mixedcolumns.finalize(result)
local l = list[i]
local h = new_hlist()
t[i] = h
- h.head = l.head
- h.height = l.height
- h.depth = l.depth
- l.head = nil
+ setfield(h,"list",getfield(l,"head"))
+ setfield(h,"height",getfield(l,"height"))
+ setfield(h,"depth",getfield(l,"depth"))
+ setfield(l,"head",nil)
end
- t[1].prev = nil -- needs checking
- t[#t].next = nil -- needs checking
+ setfield(t[1],"prev",nil) -- needs checking
+ setfield(t[#t],"next",nil) -- needs checking
r.inserts[c] = t
end
end
+ local total = r.height + r.depth
+ if total > maxtotal then
+ maxtotal = total
+ end
+ r.total = total
+ end
+ result.maxtotal = maxtotal
+ for i=1,columns do
+ local r = results[i]
+ r.extra = maxtotal - r.total
end
end
end
@@ -679,12 +789,12 @@ local function report_deltas(result,str)
report_state("%s, cycles %s, deltas % | t",str,result.cycle or 1,t)
end
-function mixedcolumns.setsplit(specification)
+local function setsplit(specification)
splitruns = splitruns + 1
if trace_state then
report_state("split run %s",splitruns)
end
- local result = setsplit(specification)
+ local result = preparesplit(specification)
if result then
if result.overflow then
if trace_state then
@@ -697,7 +807,7 @@ function mixedcolumns.setsplit(specification)
local cycles = specification.cycles or 100
while result.rest and cycle <= cycles do
specification.extra = cycle * step
- result = setsplit(specification) or result
+ result = preparesplit(specification) or result
if trace_state then
report_state("cycle: %s.%s, original height %p, total height %p",
splitruns,cycle,result.originalheight,result.nofcolumns*result.targetheight)
@@ -719,7 +829,7 @@ function mixedcolumns.setsplit(specification)
end
end
-function mixedcolumns.getsplit(result,n)
+local function getsplit(result,n)
if not result then
report_state("flush, column %s, no result",n)
return
@@ -733,17 +843,18 @@ function mixedcolumns.getsplit(result,n)
return new_glue(result.originalwidth)
end
- h.prev = nil -- move up
+ setfield(h,"prev",nil) -- move up
local strutht = result.strutht
local strutdp = result.strutdp
local lineheight = strutht + strutdp
+ local isglobal = result.alternative == v_global
local v = new_vlist()
- v.head = h
+ setfield(v,"list",h)
-- local v = vpack(h,"exactly",height)
- if result.alternative == v_global then -- option
+ if isglobal then -- option
result.height = result.maxheight
end
@@ -751,24 +862,69 @@ function mixedcolumns.getsplit(result,n)
local dp = 0
local wd = result.originalwidth
- local grid = result.grid
+ local grid = result.grid
+ local internalgrid = result.internalgrid
+ local httolerance = .25
+ local dptolerance = .50
+ local lineheight = internalgrid == v_halfline and lineheight/2 or lineheight
+
+ local function amount(r,s,t)
+ local l = ceil((r-t)/lineheight)
+ local a = lineheight * l
+ if a > s then
+ return a - s
+ else
+ return s
+ end
+ end
if grid then
- ht = lineheight * math.ceil(result.height/lineheight) - strutdp
- dp = strutdp
+ -- print(n,result.maxtotal,r.total,r.extra)
+ if isglobal then
+ local rh = r.height
+ -- ht = (lineheight * ceil(result.height/lineheight) - strutdp
+ ht = amount(rh,strutdp,0)
+ dp = strutdp
+ else
+ -- natural dimensions
+ local rh = r.height
+ local rd = r.depth
+ if rh > ht then
+ ht = amount(rh,strutdp,httolerance*strutht)
+ end
+ if rd > dp then
+ dp = amount(rd,strutht,dptolerance*strutdp)
+ end
+ -- forced dimensions
+ local rh = result.height or 0
+ local rd = result.depth or 0
+ if rh > ht then
+ ht = amount(rh,strutdp,httolerance*strutht)
+ end
+ if rd > dp then
+ dp = amount(rd,strutht,dptolerance*strutdp)
+ end
+ -- always one line at least
+ if ht < strutht then
+ ht = strutht
+ end
+ if dp < strutdp then
+ dp = strutdp
+ end
+ end
else
ht = result.height
dp = result.depth
end
- v.width = wd
- v.height = ht
- v.depth = dp
+ setfield(v,"width",wd)
+ setfield(v,"height",ht)
+ setfield(v,"depth",dp)
if trace_state then
- local id = h.id
+ local id = getid(h)
if id == hlist_code then
- report_state("flush, column %s, grid %a, width %p, height %p, depth %p, %s: %s",n,grid,wd,ht,dp,"top line",nodes.toutf(h.list))
+ report_state("flush, column %s, grid %a, width %p, height %p, depth %p, %s: %s",n,grid,wd,ht,dp,"top line",listtoutf(getlist(h)))
else
report_state("flush, column %s, grid %a, width %p, height %p, depth %p, %s: %s",n,grid,wd,ht,dp,"head node",nodecodes[id])
end
@@ -777,27 +933,27 @@ function mixedcolumns.getsplit(result,n)
for c, list in next, r.inserts do
local l = concatnodes(list)
local b = vpack(l) -- multiple arguments, todo: fastvpack
- -- texsetbox("global",c,b)
- texsetbox(c,b)
+ -- setbox("global",c,b)
+ setbox(c,b)
r.inserts[c] = nil
end
return v
end
-function mixedcolumns.getrest(result)
+local function getrest(result)
local rest = result and result.rest
result.rest = nil -- to be sure
return rest
end
-function mixedcolumns.getlist(result)
+local function getlist(result)
local originalhead = result and result.originalhead
result.originalhead = nil -- to be sure
return originalhead
end
-function mixedcolumns.cleanup(result)
+local function cleanup(result)
local discarded = result.discarded
for i=1,#discarded do
freenode(discarded[i])
@@ -805,52 +961,100 @@ function mixedcolumns.cleanup(result)
result.discarded = { }
end
+mixedcolumns.setsplit = setsplit
+mixedcolumns.getsplit = getsplit
+mixedcolumns.finalize = finalize
+mixedcolumns.getrest = getrest
+mixedcolumns.getlist = getlist
+mixedcolumns.cleanup = cleanup
+
-- interface --
local result
-function commands.mixsetsplit(specification)
- if result then
- for k, v in next, specification do
- result[k] = v
+implement {
+ name = "mixsetsplit",
+ actions = function(specification)
+ if result then
+ for k, v in next, specification do
+ result[k] = v
+ end
+ result = setsplit(result)
+ else
+ result = setsplit(specification)
end
- result = mixedcolumns.setsplit(result)
- else
- result = mixedcolumns.setsplit(specification)
- end
-end
+ end,
+ arguments = {
+ {
+ { "box", "integer" },
+ { "nofcolumns", "integer" },
+ { "maxheight", "dimen" },
+ { "step", "dimen" },
+ { "cycles", "integer" },
+ { "preheight", "dimen" },
+ { "prebox", "integer" },
+ { "strutht", "dimen" },
+ { "strutdp", "dimen" },
+ { "threshold", "dimen" },
+ { "splitmethod" },
+ { "balance" },
+ { "alternative" },
+ { "internalgrid" },
+ { "grid", "boolean" },
+ }
+ }
+}
-function commands.mixgetsplit(n)
- if result then
- context(mixedcolumns.getsplit(result,n))
- end
-end
+implement {
+ name = "mixgetsplit",
+ arguments = "integer",
+ actions = function(n)
+ if result then
+ context(tonode(getsplit(result,n)))
+ end
+ end,
+}
-function commands.mixfinalize()
- if result then
- mixedcolumns.finalize(result)
+implement {
+ name = "mixfinalize",
+ actions = function()
+ if result then
+ finalize(result)
+ end
end
-end
+}
-function commands.mixflushrest()
- if result then
- context(mixedcolumns.getrest(result))
+implement {
+ name = "mixflushrest",
+ actions = function()
+ if result then
+ context(tonode(getrest(result)))
+ end
end
-end
+}
-function commands.mixflushlist()
- if result then
- context(mixedcolumns.getlist(result))
+implement {
+ name = "mixflushlist",
+ actions = function()
+ if result then
+ context(tonode(getlist(result)))
+ end
end
-end
+}
-function commands.mixstate()
- context(result and result.rest and 1 or 0)
-end
+implement {
+ name = "mixstate",
+ actions = function()
+ context(result and result.rest and 1 or 0)
+ end
+}
-function commands.mixcleanup()
- if result then
- mixedcolumns.cleanup(result)
- result = nil
+implement {
+ name = "mixcleanup",
+ actions = function()
+ if result then
+ cleanup(result)
+ result = nil
+ end
end
-end
+}