diff options
Diffstat (limited to 'tex/context/base/spac-ver.lua')
-rw-r--r-- | tex/context/base/spac-ver.lua | 951 |
1 files changed, 693 insertions, 258 deletions
diff --git a/tex/context/base/spac-ver.lua b/tex/context/base/spac-ver.lua index 0035c4119..d1cf09e17 100644 --- a/tex/context/base/spac-ver.lua +++ b/tex/context/base/spac-ver.lua @@ -8,10 +8,16 @@ if not modules then modules = { } end modules ['spac-ver'] = { -- we also need to call the spacer for inserts! --- todo: directly set skips +-- somehow lists still don't always have proper prev nodes so i need to +-- check all of the luatex code some day .. maybe i should replece the +-- whole mvl handler by lua code .. why not + +-- todo: use lua nodes with lua data (>0.79) +-- see ** can go when 0.79 -- this code dates from the beginning and is kind of experimental; it --- will be optimized and improved soon +-- will be optimized and improved soon .. it's way too complex now but +-- dates from less possibilities -- -- the collapser will be redone with user nodes; also, we might get make -- parskip into an attribute and appy it explicitly thereby getting rid @@ -32,14 +38,20 @@ local formatters = string.formatters local P, C, R, S, Cc = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cc -local nodes, node, trackers, attributes, context, commands, tex = nodes, node, trackers, attributes, context, commands, tex +local nodes = nodes +local node = node +local trackers = trackers +local attributes = attributes +local context = context +local tex = tex local texlists = tex.lists local texgetdimen = tex.getdimen +local texsetdimen = tex.setdimen local texnest = tex.nest -local texgetbox = tex.getbox local variables = interfaces.variables +local implement = interfaces.implement -- vertical space handler @@ -49,11 +61,12 @@ local trace_page_builder = false trackers.register("builders.page", fun local trace_collect_vspacing = false trackers.register("vspacing.collect", function(v) trace_collect_vspacing = v end) local trace_vspacing = false trackers.register("vspacing.spacing", function(v) trace_vspacing = v end) local trace_vsnapping = false trackers.register("vspacing.snapping", function(v) trace_vsnapping = v end) -local trace_vpacking = false trackers.register("vspacing.packing", function(v) trace_vpacking = v end) +local trace_specials = false trackers.register("vspacing.specials", function(v) trace_specials = v end) local report_vspacing = logs.reporter("vspacing","spacing") local report_collapser = logs.reporter("vspacing","collapsing") local report_snapper = logs.reporter("vspacing","snapping") +local report_specials = logs.reporter("vspacing","specials") local report_page_builder = logs.reporter("builders","page") local a_skipcategory = attributes.private('skipcategory') @@ -63,27 +76,46 @@ local a_skiporder = attributes.private('skiporder') local a_snapmethod = attributes.private('snapmethod') local a_snapvbox = attributes.private('snapvbox') -local find_node_tail = node.tail -local free_node = node.free -local free_node_list = node.flush_list -local copy_node = node.copy -local traverse_nodes = node.traverse -local traverse_nodes_id = node.traverse_id -local insert_node_before = node.insert_before -local insert_node_after = node.insert_after -local remove_node = nodes.remove -local count_nodes = nodes.count -local nodeidstostring = nodes.idstostring -local hpack_node = node.hpack -local vpack_node = node.vpack -local writable_spec = nodes.writable_spec +local nuts = nodes.nuts +local tonode = nuts.tonode +local tonut = nuts.tonut +local ntostring = nuts.tostring + +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 getbox = nuts.getbox + +local find_node_tail = nuts.tail +local free_node = nuts.free +local free_node_list = nuts.flush_list +local copy_node = nuts.copy +local traverse_nodes = nuts.traverse +local traverse_nodes_id = nuts.traverse_id +local insert_node_before = nuts.insert_before +local insert_node_after = nuts.insert_after +local remove_node = nuts.remove +local count_nodes = nuts.count +local hpack_node = nuts.hpack +local vpack_node = nuts.vpack +local writable_spec = nuts.writable_spec +local nodereference = nuts.reference + local listtoutf = nodes.listtoutf +local nodeidstostring = nodes.idstostring -local nodepool = nodes.pool +local nodepool = nuts.pool local new_penalty = nodepool.penalty local new_kern = nodepool.kern local new_rule = nodepool.rule +local new_glue = nodepool.glue local new_gluespec = nodepool.gluespec local nodecodes = nodes.nodecodes @@ -103,8 +135,8 @@ builders.vspacing = vspacing local vspacingdata = vspacing.data or { } vspacing.data = vspacingdata -vspacingdata.snapmethods = vspacingdata.snapmethods or { } -local snapmethods = vspacingdata.snapmethods --maybe some older code can go +local snapmethods = vspacingdata.snapmethods or { } +vspacingdata.snapmethods = snapmethods storage.register("builders/vspacing/data/snapmethods", snapmethods, "builders.vspacing.data.snapmethods") @@ -114,11 +146,13 @@ local default = { strut = true, hfraction = 1, dfraction = 1, + bfraction = 0.25, } local fractions = { minheight = "hfraction", maxheight = "hfraction", mindepth = "dfraction", maxdepth = "dfraction", + box = "bfraction", top = "tlines", bottom = "blines", } @@ -179,28 +213,26 @@ end -- local rule_id = nodecodes.rule -- local vlist_id = nodecodes.vlist -- function nodes.makevtop(n) --- if n.id == vlist_id then --- local list = n.list --- local height = (list and list.id <= rule_id and list.height) or 0 --- n.depth = n.depth - height + n.height --- n.height = height +-- if getid(n) == vlist_id then +-- local list = getlist(n) +-- local height = (list and getid(list) <= rule_id and getfield(list,"height")) or 0 +-- setfield(n,"depth",getfield(n,"depth") - height + getfield(n,"height") +-- setfield(n,"height",height -- end -- end -local reference = nodes.reference - local function validvbox(parentid,list) if parentid == hlist_code then - local id = list.id + local id = getid(list) if id == whatsit_code then -- check for initial par subtype - list = list.next + list = getnext(list) if not next then return nil end end local done = nil for n in traverse_nodes(list) do - local id = n.id + local id = getid(n) if id == vlist_code or id == hlist_code then if done then return nil @@ -214,9 +246,9 @@ local function validvbox(parentid,list) end end if done then - local id = done.id + local id = getid(done) if id == hlist_code then - return validvbox(id,done.list) + return validvbox(id,getlist(done)) end end return done -- only one vbox @@ -226,19 +258,19 @@ end local function already_done(parentid,list,a_snapmethod) -- todo: done when only boxes and all snapped -- problem: any snapped vbox ends up in a line if list and parentid == hlist_code then - local id = list.id + local id = getid(list) if id == whatsit_code then -- check for initial par subtype - list = list.next + list = getnext(list) if not next then return false end end --~ local i = 0 for n in traverse_nodes(list) do - local id = n.id ---~ i = i + 1 print(i,nodecodes[id],n[a_snapmethod]) + local id = getid(n) +--~ i = i + 1 print(i,nodecodes[id],getattr(n,a_snapmethod)) if id == hlist_code or id == vlist_code then - local a = n[a_snapmethod] + local a = getattr(n,a_snapmethod) if not a then -- return true -- not snapped at all elseif a == 0 then @@ -276,11 +308,11 @@ end -- check variables.none etc local function snap_hlist(where,current,method,height,depth) -- method.strut is default - local list = current.list + local list = getlist(current) local t = trace_vsnapping and { } if t then t[#t+1] = formatters["list content: %s"](listtoutf(list)) - t[#t+1] = formatters["parent id: %s"](reference(current)) + t[#t+1] = formatters["parent id: %s"](nodereference(current)) t[#t+1] = formatters["snap method: %s"](method.name) t[#t+1] = formatters["specification: %s"](method.specification) end @@ -312,26 +344,58 @@ local function snap_hlist(where,current,method,height,depth) -- method.strut is t[#t+1] = formatters["auto: snapht %p snapdp %p"](snapht,snapdp) end end - local h, d = height or current.height, depth or current.depth - local hr, dr, ch, cd = method.hfraction or 1, method.dfraction or 1, h, d - local tlines, blines = method.tlines or 1, method.blines or 1 - local done, plusht, plusdp = false, snapht, snapdp + + local h = (method.noheight and 0) or height or getfield(current,"height") + local d = (method.nodepth and 0) or depth or getfield(current,"depth") + local hr = method.hfraction or 1 + local dr = method.dfraction or 1 + local br = method.bfraction or 0 + local ch = h + local cd = d + local tlines = method.tlines or 1 + local blines = method.blines or 1 + local done = false + local plusht = snapht + local plusdp = snapdp local snaphtdp = snapht + snapdp - if method.none then + if method.box then + local br = 1 - br + if br < 0 then + br = 0 + elseif br > 1 then + br = 1 + end + local n = ceiled((h+d-br*snapht-br*snapdp)/snaphtdp) + local x = n * snaphtdp - h - d + plusht = h + x / 2 + plusdp = d + x / 2 + elseif method.max then + local n = ceiled((h+d)/snaphtdp) + local x = n * snaphtdp - h - d + plusht = h + x / 2 + plusdp = d + x / 2 + elseif method.min then + local n = floored((h+d)/snaphtdp) + local x = n * snaphtdp - h - d + plusht = h + x / 2 + plusdp = d + x / 2 + elseif method.none then plusht, plusdp = 0, 0 if t then t[#t+1] = "none: plusht 0pt plusdp 0pt" end end if method.halfline then -- extra halfline - plusht, plusdp = plusht + snaphtdp/2, plusdp + snaphtdp/2 + plusht = plusht + snaphtdp/2 + plusdp = plusdp + snaphtdp/2 if t then t[#t+1] = formatters["halfline: plusht %p plusdp %p"](plusht,plusdp) end end if method.line then -- extra line - plusht, plusdp = plusht + snaphtdp, plusdp + snaphtdp + plusht = plusht + snaphtdp + plusdp = plusdp + snaphtdp if t then t[#t+1] = formatters["line: plusht %p plusdp %p"](plusht,plusdp) end @@ -339,22 +403,22 @@ local function snap_hlist(where,current,method,height,depth) -- method.strut is if method.first then local thebox = current - local id = thebox.id + local id = getid(thebox) if id == hlist_code then - thebox = validvbox(id,thebox.list) - id = thebox and thebox.id + thebox = validvbox(id,getlist(thebox)) + id = thebox and getid(thebox) end if thebox and id == vlist_code then - local list = thebox.list + local list = getlist(thebox) local lh, ld for n in traverse_nodes_id(hlist_code,list) do - lh = n.height - ld = n.depth + lh = getfield(n,"height") + ld = getfield(n,"depth") break end if lh then - local ht = thebox.height - local dp = thebox.depth + local ht = getfield(thebox,"height") + local dp = getfield(thebox,"depth") if t then t[#t+1] = formatters["first line: height %p depth %p"](lh,ld) t[#t+1] = formatters["dimensions: height %p depth %p"](ht,dp) @@ -362,9 +426,9 @@ local function snap_hlist(where,current,method,height,depth) -- method.strut is local delta = h - lh ch, cd = lh, delta + d h, d = ch, cd - local shifted = hpack_node(current.list) - shifted.shift = delta - current.list = shifted + local shifted = hpack_node(getlist(current)) + setfield(shifted,"shift",delta) + setfield(current,"list",shifted) done = true if t then t[#t+1] = formatters["first: height %p depth %p shift %p"](ch,cd,delta) @@ -377,20 +441,21 @@ local function snap_hlist(where,current,method,height,depth) -- method.strut is end elseif method.last then local thebox = current - local id = thebox.id + local id = getid(thebox) if id == hlist_code then - thebox = validvbox(id,thebox.list) - id = thebox and thebox.id + thebox = validvbox(id,getlist(thebox)) + id = thebox and getid(thebox) end if thebox and id == vlist_code then - local list, lh, ld = thebox.list + local list = getlist(thebox) + local lh, ld for n in traverse_nodes_id(hlist_code,list) do - lh = n.height - ld = n.depth + lh = getfield(n,"height") + ld = getfield(n,"depth") end if lh then - local ht = thebox.height - local dp = thebox.depth + local ht = getfield(thebox,"height") + local dp = getfield(thebox,"depth") if t then t[#t+1] = formatters["last line: height %p depth %p" ](lh,ld) t[#t+1] = formatters["dimensions: height %p depth %p"](ht,dp) @@ -398,9 +463,9 @@ local function snap_hlist(where,current,method,height,depth) -- method.strut is local delta = d - ld cd, ch = ld, delta + h h, d = ch, cd - local shifted = hpack_node(current.list) - shifted.shift = delta - current.list = shifted + local shifted = hpack_node(getlist(current)) + setfield(shifted,"shift",delta) + setfield(current,"list",shifted) done = true if t then t[#t+1] = formatters["last: height %p depth %p shift %p"](ch,cd,delta) @@ -461,25 +526,25 @@ local function snap_hlist(where,current,method,height,depth) -- method.strut is if offset then -- we need to set the attr if t then - t[#t+1] = formatters["before offset: %p (width %p height %p depth %p)"](offset,current.width,current.height,current.depth) + t[#t+1] = formatters["before offset: %p (width %p height %p depth %p)"](offset,getfield(current,"width"),getfield(current,"height"),getfield(current,"depth")) end - local shifted = hpack_node(current.list) - shifted.shift = offset - current.list = shifted + local shifted = hpack_node(getlist(current)) + setfield(shifted,"shift",offset) + setfield(current,"list",shifted) if t then - t[#t+1] = formatters["after offset: %p (width %p height %p depth %p)"](offset,current.width,current.height,current.depth) + t[#t+1] = formatters["after offset: %p (width %p height %p depth %p)"](offset,getfield(current,"width"),getfield(current,"height"),getfield(current,"depth")) end - shifted[a_snapmethod] = 0 - current[a_snapmethod] = 0 + setattr(shifted,a_snapmethod,0) + setattr(current,a_snapmethod,0) end if not height then - current.height = ch + setfield(current,"height",ch) if t then t[#t+1] = formatters["forced height: %p"](ch) end end if not depth then - current.depth = cd + setfield(current,"depth",cd) if t then t[#t+1] = formatters["forced depth: %p"](cd) end @@ -492,18 +557,24 @@ local function snap_hlist(where,current,method,height,depth) -- method.strut is t[#t+1] = formatters["final height: %p -> %p"](h,ch) t[#t+1] = formatters["final depth: %p -> %p"](d,cd) end +-- todo: +-- +-- if h < 0 or d < 0 then +-- h = 0 +-- d = 0 +-- end if t then - report_snapper("trace: %s type %s\n\t%\n\tt",where,nodecodes[current.id],t) + report_snapper("trace: %s type %s\n\t%\n\tt",where,nodecodes[getid(current)],t) end return h, d, ch, cd, lines end local function snap_topskip(current,method) - local spec = current.spec - local w = spec.width + local spec = getfield(current,"spec") + local w = getfield(spec,"width") local wd = w - if spec.writable then - spec.width = 0 + if getfield(spec,"writable") then + setfield(spec,"width",0) wd = 0 end return w, wd @@ -518,14 +589,15 @@ local categories = allocate { [5] = 'disable', [6] = 'nowhite', [7] = 'goback', - [8] = 'together' + [8] = 'together', -- not used (?) + [9] = 'overlay', } vspacing.categories = categories function vspacing.tocategories(str) local t = { } - for s in gmatch(str,"[^, ]") do + for s in gmatch(str,"[^, ]") do -- use lpeg instead local n = tonumber(s) if n then t[categories[n]] = true @@ -536,7 +608,7 @@ function vspacing.tocategories(str) return t end -function vspacing.tocategory(str) +function vspacing.tocategory(str) -- can be optimized if type(str) == "string" then return set.tonumber(vspacing.tocategories(str)) else @@ -567,15 +639,15 @@ do -- todo: interface.variables -- This will change: just node.write and we can store the values in skips which -- then obeys grouping - local fixedblankskip = context.fixedblankskip - local flexibleblankskip = context.flexibleblankskip - local setblankcategory = context.setblankcategory - local setblankorder = context.setblankorder - local setblankpenalty = context.setblankpenalty - local setblankhandling = context.setblankhandling - local flushblankhandling = context.flushblankhandling - local addpredefinedblankskip = context.addpredefinedblankskip - local addaskedblankskip = context.addaskedblankskip + local ctx_fixedblankskip = context.fixedblankskip + local ctx_flexibleblankskip = context.flexibleblankskip + local ctx_setblankcategory = context.setblankcategory + local ctx_setblankorder = context.setblankorder + local ctx_setblankpenalty = context.setblankpenalty + ----- ctx_setblankhandling = context.setblankhandling + local ctx_flushblankhandling = context.flushblankhandling + local ctx_addpredefinedblankskip = context.addpredefinedblankskip + local ctx_addaskedblankskip = context.addaskedblankskip local function analyze(str,oldcategory) -- we could use shorter names for s in gmatch(str,"([^ ,]+)") do @@ -587,35 +659,35 @@ do -- todo: interface.variables if mk then category = analyze(mk,category) elseif keyword == k_fixed then - fixedblankskip() + ctx_fixedblankskip() elseif keyword == k_flexible then - flexibleblankskip() + ctx_flexibleblankskip() elseif keyword == k_category then local category = tonumber(detail) if category then - setblankcategory(category) + ctx_setblankcategory(category) if category ~= oldcategory then - flushblankhandling() + ctx_flushblankhandling() oldcategory = category end end elseif keyword == k_order and detail then local order = tonumber(detail) if order then - setblankorder(order) + ctx_setblankorder(order) end elseif keyword == k_penalty and detail then local penalty = tonumber(detail) if penalty then - setblankpenalty(penalty) + ctx_setblankpenalty(penalty) end else amount = tonumber(amount) or 1 local sk = skip[keyword] if sk then - addpredefinedblankskip(amount,keyword) + ctx_addpredefinedblankskip(amount,keyword) else -- no check - addaskedblankskip(amount,keyword) + ctx_addaskedblankskip(amount,keyword) end end end @@ -623,22 +695,22 @@ do -- todo: interface.variables return category end - local pushlogger = context.pushlogger - local startblankhandling = context.startblankhandling - local stopblankhandling = context.stopblankhandling - local poplogger = context.poplogger + local ctx_pushlogger = context.pushlogger + local ctx_startblankhandling = context.startblankhandling + local ctx_stopblankhandling = context.stopblankhandling + local ctx_poplogger = context.poplogger function vspacing.analyze(str) if trace_vspacing then - pushlogger(report_vspacing) - startblankhandling() + ctx_pushlogger(report_vspacing) + ctx_startblankhandling() analyze(str,1) - stopblankhandling() - poplogger() + ctx_stopblankhandling() + ctx_poplogger() else - startblankhandling() + ctx_startblankhandling() analyze(str,1) - stopblankhandling() + ctx_stopblankhandling() end end @@ -664,18 +736,18 @@ local trace_list, tracing_info, before, after = { }, false, "", "" local function nodes_to_string(head) local current, t = head, { } while current do - local id = current.id + local id = getid(current) local ty = nodecodes[id] if id == penalty_code then - t[#t+1] = formatters["%s:%s"](ty,current.penalty) + t[#t+1] = formatters["%s:%s"](ty,getfield(current,"penalty")) elseif id == glue_code then -- or id == kern_code then -- to be tested t[#t+1] = formatters["%s:%p"](ty,current) elseif id == kern_code then - t[#t+1] = formatters["%s:%p"](ty,current.kern) + t[#t+1] = formatters["%s:%p"](ty,getfield(current,"kern")) else t[#t+1] = ty end - current = current.next + current = getnext(current) end return concat(t," + ") end @@ -699,7 +771,7 @@ local function trace_info(message, where, what) end local function trace_node(what) - local nt = nodecodes[what.id] + local nt = nodecodes[getid(what)] local tl = trace_list[#trace_list] if tl and tl[1] == "node" then trace_list[#trace_list] = { "node", formatters["%s + %s"](tl[2],nt) } @@ -709,8 +781,8 @@ local function trace_node(what) end local function trace_done(str,data) - if data.id == penalty_code then - trace_list[#trace_list+1] = { "penalty", formatters["%s | %s"](str,data.penalty) } + if getid(data) == penalty_code then + trace_list[#trace_list+1] = { "penalty", formatters["%s | %s"](str,getfield(data,"penalty")) } else trace_list[#trace_list+1] = { "glue", formatters["%s | %p"](str,data) } end @@ -748,22 +820,32 @@ local belowdisplayshortskip_code = skipcodes.belowdisplayshortskip local topskip_code = skipcodes.topskip local splittopskip_code = skipcodes.splittopskip +-- local function free_glue_node(n) +-- free_node(n) +-- local s = getfield(n,"spec") +-- if s then +-- free_node(s) +-- end +-- end + local free_glue_node = free_node +local free_glue_spec = function() end +----- free_glue_spec = free_node -- can be enabled in in 0.73 (so for the moment we leak due to old luatex engine issues) function vspacing.snapbox(n,how) local sv = snapmethods[how] if sv then - local box = texgetbox(n) - local list = box.list + local box = getbox(n) + local list = getlist(box) if list then - local s = list[a_snapmethod] + local s = getattr(list,a_snapmethod) if s == 0 then if trace_vsnapping then -- report_snapper("box list not snapped, already done") end else - local ht = box.height - local dp = box.depth + local ht = getfield(box,"height") + local dp = getfield(box,"depth") if false then -- todo: already_done -- assume that the box is already snapped if trace_vsnapping then @@ -772,14 +854,14 @@ function vspacing.snapbox(n,how) end else local h, d, ch, cd, lines = snap_hlist("box",box,sv,ht,dp) - box.height= ch - box.depth = cd + setfield(box,"height",ch) + setfield(box,"depth",cd) if trace_vsnapping then report_snapper("box list snapped from (%p,%p) to (%p,%p) using method %a (%s) for %a (%s lines): %s", h,d,ch,cd,sv.name,sv.specification,"direct",lines,listtoutf(list)) end - box[a_snapmethod] = 0 -- - list[a_snapmethod] = 0 -- yes or no + setattr(box,a_snapmethod,0) -- + setattr(list,a_snapmethod,0) -- yes or no end end end @@ -801,8 +883,10 @@ local w, h, d = 0, 0, 0 ----- w, h, d = 100*65536, 65536, 65536 local function forced_skip(head,current,width,where,trace) - if head == current and head.subtype == baselineskip_code then - width = width - head.spec.width + if head == current then + if getsubtype(head) == baselineskip_code then + width = width - getfield(getfield(head,"spec"),"width") + end end if width == 0 then -- do nothing @@ -825,62 +909,270 @@ end -- penalty only works well when before skip -local discard, largest, force, penalty, add, disable, nowhite, goback, together = 0, 1, 2, 3, 4, 5, 6, 7, 8 -- move into function when upvalue 60 issue +local discard = 0 +local largest = 1 +local force = 2 +local penalty = 3 +local add = 4 +local disable = 5 +local nowhite = 6 +local goback = 7 +local together = 8 -- not used (?) +local overlay = 9 -- [whatsits][hlist][glue][glue][penalty] local special_penalty_min = 32250 local special_penalty_max = 35000 +local special_penalty_xxx = 0 + +-- this is rather messy and complex: we want to make sure that successive +-- header don't break but also make sure that we have at least a decent +-- break when we have succesive ones (often when testing) + +-- todo: mark headers as such so that we can recognize them + +local specialmethods = { } +local specialmethod = 1 -local function specialpenalty(start,penalty) - -- nodes.showsimplelist(texlists.page_head,1) - local current = find_node_tail(texlists.page_head) +local properties = nodes.properties.data + +specialmethods[1] = function(pagehead,pagetail,start,penalty) + -- + if not pagehead or penalty < special_penalty_min or penalty > special_penalty_max then + return + end + local current = pagetail + -- + -- nodes.showsimplelist(pagehead,0) + -- + if trace_specials then + report_specials("checking penalty %a",penalty) + end while current do - local id = current.id - if id == glue_code then - current = current.prev - elseif id == penalty_code then - local p = current.penalty - if p == penalty then - if trace_vspacing then - report_vspacing("overloading penalty %a",p) + local id = getid(current) + if id == penalty_code then + local p = properties[current] + if p then + local p = p.special_penalty + if not p then + if trace_specials then + report_specials(" regular penalty, continue") + end + elseif p == penalty then + if trace_specials then + report_specials(" context penalty %a, same level, overloading",p) + end + return special_penalty_xxx + elseif p > special_penalty_min and p < special_penalty_max then + if penalty < p then + if trace_specials then + report_specials(" context penalty %a, lower level, overloading",p) + end + return special_penalty_xxx + else + if trace_specials then + report_specials(" context penalty %a, higher level, quitting",p) + end + return + end + elseif trace_specials then + report_specials(" context penalty %a, higher level, continue",p) end - return current - elseif p >= 10000 then - current = current.prev else - break + local p = getfield(current,"penalty") + if p < 10000 then + -- assume some other mechanism kicks in so we seem to have content + if trace_specials then + report_specials(" regular penalty %a, quitting",p) + end + break + else + if trace_specials then + report_specials(" regular penalty %a, continue",p) + end + end + end + end + current = getprev(current) + end + -- none found, so no reson to be special + if trace_specials then + if pagetail then + report_specials(" context penalty, discarding, nothing special") + else + report_specials(" context penalty, discarding, nothing preceding") + end + end + return special_penalty_xxx +end + +-- specialmethods[2] : always put something before and use that as to-be-changed +-- +-- we could inject a vadjust to force a recalculation .. a mess +-- +-- So, the next is far from robust and okay but for the moment this overlaying +-- has to do. Always test this with the examples in spec-ver.mkvi! + +local function check_experimental_overlay(head,current) + local p = nil + local c = current + local n = nil + + -- setfield(head,"prev",nil) -- till we have 0.79 ** + + local function overlay(p,n,mvl) + local p_ht = getfield(p,"height") + local p_dp = getfield(p,"depth") + local n_ht = getfield(n,"height") + local skips = 0 + -- + -- We deal with this at the tex end .. we don't see spacing .. enabling this code + -- is probably harmless btu then we need to test it. + -- + local c = getnext(p) + while c and c ~= n do + local id = getid(c) + if id == glue_code then + skips = skips + getfield(getfield(c,"glue_spec"),"width") + elseif id == kern_code then + skips = skips + getfield(c,"kern") end + c = getnext(c) + end + -- + local delta = n_ht + skips + p_dp + texsetdimen("global","d_spac_overlay",-delta) -- for tracing + local k = new_kern(-delta) + if n_ht > p_ht then + -- we should adapt pagetotal ! (need a hook for that) .. now we have the wrong pagebreak + setfield(p,"height",n_ht) + end + insert_node_before(head,n,k) + if p == head then + head = k + end + if trace_vspacing then + report_vspacing("overlaying, prev height: %p, prev depth: %p, next height: %p, skips: %p, move up: %p",p_ht,p_dp,n_ht,skips,delta) + end + return remove_node(head,current,true) + end + + -- goto next line + while c do + local id = getid(c) + if id == glue_code or id == penalty_code or id == kern_code then + -- skip (actually, remove) + c = getnext(c) + elseif id == hlist_code then + n = c + break else - current = current.prev + break + end + end + if n then + -- we have a next line, goto prev line + c = current + while c do + local id = getid(c) + if id == glue_code or id == penalty_code then + c = getprev(c) + elseif id == hlist_code then + p = c + break + else + break + end + end + if not p then + if a_snapmethod == a_snapvbox then + -- quit, we're not on the mvl + else + local c = tonut(texlists.page_head) + while c and c ~= n do + local id = getid(c) + if id == hlist_code then + p = c + end + c = getnext(c) + end + if p and p ~= n then + return overlay(p,n,true) + end + end + elseif p ~= n then + return overlay(p,n,false) end end + -- in fact, we could try again later ... so then no remove (a few tries) + return remove_node(head, current, true) end +-- This will be replaced after 0.80+ when we have a more robust look-back and +-- can look at the bigger picture. + +-- todo: look back and when a special is there before a list is seen penalty keep ut + +-- we now look back a lot, way too often + local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also pass tail if trace then reset_tracing(head) end local current, oldhead = head, head local glue_order, glue_data, force_glue = 0, nil, false - local penalty_order, penalty_data, natural_penalty = 0, nil, nil + local penalty_order, penalty_data, natural_penalty, special_penalty = 0, nil, nil, nil local parskip, ignore_parskip, ignore_following, ignore_whitespace, keep_together = nil, false, false, false, false -- -- todo: keep_together: between headers -- + local pagehead = nil + local pagetail = nil + + local function getpagelist() + if not pagehead then + pagehead = texlists.page_head + if pagehead then + pagehead = tonut(texlists.page_head) + pagetail = find_node_tail(pagehead) -- no texlists.page_tail yet-- no texlists.page_tail yet + end + end + end + -- local function flush(why) if penalty_data then local p = new_penalty(penalty_data) if trace then trace_done("flushed due to " .. why,p) end - head = insert_node_before(head,current,p) + if penalty_data >= 10000 then -- or whatever threshold? + local prev = getprev(current) + if getid(prev) == glue_code then -- maybe go back more, or maybe even push back before any glue + -- tricky case: spacing/grid-007.tex: glue penalty glue + head = insert_node_before(head,prev,p) + else + head = insert_node_before(head,current,p) + end + else + head = insert_node_before(head,current,p) + end +-- if penalty_data > special_penalty_min and penalty_data < special_penalty_max then + local props = properties[p] + if props then + props.special_penalty = special_penalty or penalty_data + else + properties[p] = { + special_penalty = special_penalty or penalty_data + } + end +-- end end if glue_data then - local spec = glue_data.spec + local spec = getfield(glue_data,"spec") if force_glue then if trace then trace_done("flushed due to " .. why,glue_data) end - head = forced_skip(head,current,spec.width,"before",trace) + head = forced_skip(head,current,getfield(spec,"width"),"before",trace) free_glue_node(glue_data) - elseif spec.writable then + elseif getfield(spec,"writable") then if trace then trace_done("flushed due to " .. why,glue_data) end head = insert_node_before(head,current,glue_data) else @@ -892,6 +1184,26 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also penalty_order, penalty_data, natural_penalty = 0, nil, nil parskip, ignore_parskip, ignore_following, ignore_whitespace = nil, false, false, false end + -- + +-- quick hack, can be done nicer +-- local nobreakfound = nil +-- local function checknobreak() +-- local pagehead, pagetail = getpagelist() +-- local current = pagetail +-- while current do +-- local id = getid(current) +-- if id == hlist_code or id == vlist_code then +-- return false +-- elseif id == penalty_code then +-- return getfield(current,"penalty") >= 10000 +-- end +-- current = getprev(current) +-- end +-- return false +-- end + + -- if trace_vsnapping then report_snapper("global ht/dp = %p/%p, local ht/dp = %p/%p", texgetdimen("globalbodyfontstrutheight"), texgetdimen("globalbodyfontstrutdepth"), @@ -899,13 +1211,19 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also ) end if trace then trace_info("start analyzing",where,what) end + +-- local headprev = getprev(head) + while current do - local id = current.id + local id = getid(current) if id == hlist_code or id == vlist_code then +-- if nobreakfound == nil then +-- nobreakfound = false +-- end -- needs checking, why so many calls if snap then - local list = current.list - local s = current[a_snapmethod] + local list = getlist(current) + local s = getattr(current,a_snapmethod) if not s then -- if trace_vsnapping then -- report_snapper("mvl list not snapped") @@ -919,8 +1237,8 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also if sv then -- check if already snapped if list and already_done(id,list,a_snapmethod) then - local ht = current.height - local dp = current.depth + local ht = getfield(current,"height") + local dp = getfield(current,"depth") -- assume that the box is already snapped if trace_vsnapping then report_snapper("mvl list already snapped at (%p,%p): %s",ht,dp,listtoutf(list)) @@ -935,40 +1253,60 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also elseif trace_vsnapping then report_snapper("mvl %a not snapped due to unknown snap specification: %s",nodecodes[id],listtoutf(list)) end - current[a_snapmethod] = 0 + setattr(current,a_snapmethod,0) end else -- end -- tex.prevdepth = 0 flush("list") - current = current.next + current = getnext(current) elseif id == penalty_code then - -- natural_penalty = current.penalty + -- natural_penalty = getfield(current,"penalty") -- if trace then trace_done("removed penalty",current) end -- head, current = remove_node(head, current, true) - current = current.next + +-- if nobreakfound == nil then +-- nobreakfound = checknobreak() +-- end +-- if nobreakfound and getfield(current,"penalty") <= 10000 then +-- -- if trace then +-- trace_done("removed penalty",current) +-- -- end +-- head, current = remove_node(head, current, true) +-- end + + current = getnext(current) elseif id == kern_code then - if snap and trace_vsnapping and current.kern ~= 0 then - report_snapper("kern of %p kept",current.kern) + if snap and trace_vsnapping and getfield(current,"kern") ~= 0 then + report_snapper("kern of %p kept",getfield(current,"kern")) end flush("kern") - current = current.next + current = getnext(current) elseif id == glue_code then - local subtype = current.subtype + local subtype = getsubtype(current) if subtype == userskip_code then - local sc = current[a_skipcategory] -- has no default, no unset (yet) - local so = current[a_skiporder] or 1 -- has 1 default, no unset (yet) - local sp = current[a_skippenalty] -- has no default, no unset (yet) + local sc = getattr(current,a_skipcategory) -- has no default, no unset (yet) + local so = getattr(current,a_skiporder) or 1 -- has 1 default, no unset (yet) + local sp = getattr(current,a_skippenalty) -- has no default, no unset (yet) if sp and sc == penalty then + if where == "page" then + getpagelist() + local p = specialmethods[specialmethod](pagehead,pagetail,current,sp) + if p then + if trace then + trace_skip("previous special penalty %a is changed to %a using method %a",sp,p,specialmethod) + end + special_penalty = sp + sp = p + end -if where == "page" and sp >= special_penalty_min and sp <= special_penalty_max then - local previousspecial = specialpenalty(current,sp) - if previousspecial then - previousspecial.penalty = 0 - sp = 0 - end -end +-- else +-- if nobreakfound == nil then +-- nobreakfound = checknobreak() +-- end + + end if not penalty_data then penalty_data = sp elseif penalty_order < so then @@ -977,43 +1315,52 @@ end penalty_data = sp end if trace then trace_skip("penalty in skip",sc,so,sp,current) end + +-- if nobreakfound then +-- penalty_data = 10000 +-- if trace then +-- trace_skip("nobreak found before penalty in skip",sc,so,sp,current) +-- end +-- end + head, current = remove_node(head, current, true) elseif not sc then -- if not sc then if glue_data then if trace then trace_done("flush",glue_data) end head = insert_node_before(head,current,glue_data) if trace then trace_natural("natural",current) end - current = current.next + current = getnext(current) else -- not look back across head --- todo: prev can be whatsit (latelua) - local previous = current.prev - if previous and previous.id == glue_code and previous.subtype == userskip_code then - local ps = previous.spec - if ps.writable then - local cs = current.spec - if cs.writable and ps.stretch_order == 0 and ps.shrink_order == 0 and cs.stretch_order == 0 and cs.shrink_order == 0 then - local pw, pp, pm = ps.width, ps.stretch, ps.shrink - local cw, cp, cm = cs.width, cs.stretch, cs.shrink + -- todo: prev can be whatsit (latelua) + local previous = getprev(current) + if previous and getid(previous) == glue_code and getsubtype(previous) == userskip_code then + local ps = getfield(previous,"spec") + if getfield(ps,"writable") then + local cs = getfield(current,"spec") + if getfield(cs,"writable") and getfield(ps,"stretch_order") == 0 and getfield(ps,"shrink_order") == 0 and getfield(cs,"stretch_order") == 0 and getfield(cs,"shrink_order") == 0 then + local pw, pp, pm = getfield(ps,"width"), getfield(ps,"stretch"), getfield(ps,"shrink") + local cw, cp, cm = getfield(cs,"width"), getfield(cs,"stretch"), getfield(cs,"shrink") -- ps = writable_spec(previous) -- no writable needed here -- ps.width, ps.stretch, ps.shrink = pw + cw, pp + cp, pm + cm - previous.spec = new_gluespec(pw + cw, pp + cp, pm + cm) -- else topskip can disappear + free_glue_spec(ps) + setfield(previous,"spec",new_gluespec(pw + cw, pp + cp, pm + cm)) -- else topskip can disappear if trace then trace_natural("removed",current) end head, current = remove_node(head, current, true) -- current = previous if trace then trace_natural("collapsed",previous) end - -- current = current.next + -- current = getnext(current) else if trace then trace_natural("filler",current) end - current = current.next + current = getnext(current) end else if trace then trace_natural("natural (no prev spec)",current) end - current = current.next + current = getnext(current) end else if trace then trace_natural("natural (no prev)",current) end - current = current.next + current = getnext(current) end end glue_order, glue_data = 0, nil @@ -1031,6 +1378,12 @@ end elseif sc == discard then if trace then trace_skip("discard",sc,so,sp,current) end head, current = remove_node(head, current, true) + elseif sc == overlay then + -- todo (overlay following line over previous + if trace then trace_skip("overlay",sc,so,sp,current) end + -- beware: head can actually be after the affected nodes as + -- we look back ... some day head will the real head + head, current = check_experimental_overlay(head,current,a_snapmethod) elseif ignore_following then if trace then trace_skip("disabled",sc,so,sp,current) end head, current = remove_node(head, current, true) @@ -1046,12 +1399,12 @@ end elseif glue_order == so then -- is now exclusive, maybe support goback as combi, else why a set if sc == largest then - local cs, gs = current.spec, glue_data.spec - local cw, gw = cs.width, gs.width + local cs, gs = getfield(current,"spec"), getfield(glue_data,"spec") + local cw, gw = getfield(cs,"width"), getfield(gs,"width") if cw > gw then if trace then trace_skip("largest",sc,so,sp,current) end free_glue_node(glue_data) -- also free spec - head, current, glue_data = remove_node(head, current) + head, current, glue_data = remove_node(head,current) else if trace then trace_skip("remove smallest",sc,so,sp,current) end head, current = remove_node(head, current, true) @@ -1059,7 +1412,7 @@ end elseif sc == goback then if trace then trace_skip("goback",sc,so,sp,current) end free_glue_node(glue_data) -- also free spec - head, current, glue_data = remove_node(head, current) + head, current, glue_data = remove_node(head,current) elseif sc == force then -- last one counts, some day we can provide an accumulator and largest etc -- but not now @@ -1073,11 +1426,11 @@ end head, current = remove_node(head, current, true) elseif sc == add then if trace then trace_skip("add",sc,so,sp,current) end - -- local old, new = glue_data.spec, current.spec - local old, new = writable_spec(glue_data), current.spec - old.width = old.width + new.width - old.stretch = old.stretch + new.stretch - old.shrink = old.shrink + new.shrink + -- local old, new = glue_data.spec, getfield(current,"spec") + local old, new = writable_spec(glue_data), getfield(current,"spec") + setfield(old,"width",getfield(old,"width") + getfield(new,"width")) + setfield(old,"stretch",getfield(old,"stretch") + getfield(new,"stretch")) + setfield(old,"shrink",getfield(old,"shrink") + getfield(new,"shrink")) -- toto: order head, current = remove_node(head, current, true) else @@ -1093,12 +1446,13 @@ end end elseif subtype == lineskip_code then if snap then - local s = current[a_snapmethod] + local s = getattr(current,a_snapmethod) if s and s ~= 0 then - current[a_snapmethod] = 0 - if current.spec.writable then + setattr(current,a_snapmethod,0) + local spec = getfield(current,"spec") + if getfield(spec,"writable") then local spec = writable_spec(current) - spec.width = 0 + setfield(spec,"width",0) if trace_vsnapping then report_snapper("lineskip set to zero") end @@ -1111,15 +1465,16 @@ end if trace then trace_skip("lineskip",sc,so,sp,current) end flush("lineskip") end - current = current.next + current = getnext(current) elseif subtype == baselineskip_code then if snap then - local s = current[a_snapmethod] + local s = getattr(current,a_snapmethod) if s and s ~= 0 then - current[a_snapmethod] = 0 - if current.spec.writable then + setattr(current,a_snapmethod,0) + local spec = getfield(current,"spec") + if getfield(spec,"writable") then local spec = writable_spec(current) - spec.width = 0 + setfield(spec,"width",0) if trace_vsnapping then report_snapper("baselineskip set to zero") end @@ -1132,17 +1487,17 @@ end if trace then trace_skip("baselineskip",sc,so,sp,current) end flush("baselineskip") end - current = current.next + current = getnext(current) elseif subtype == parskip_code then -- parskip always comes later if ignore_whitespace then if trace then trace_natural("ignored parskip",current) end head, current = remove_node(head, current, true) elseif glue_data then - local ps = current.spec - local gs = glue_data.spec - if ps.writable and gs.writable and ps.width > gs.width then - glue_data.spec = copy_node(ps) + local ps = getfield(current,"spec") + local gs = getfield(glue_data,"spec") + if getfield(ps,"writable") and getfield(gs,"writable") and getfield(ps,"width") > getfield(gs,"width") then + setfield(glue_data,"spec",copy_node(ps)) if trace then trace_natural("taking parskip",current) end else if trace then trace_natural("removed parskip",current) end @@ -1154,9 +1509,9 @@ end end elseif subtype == topskip_code or subtype == splittopskip_code then if snap then - local s = current[a_snapmethod] + local s = getattr(current,a_snapmethod) if s and s ~= 0 then - current[a_snapmethod] = 0 + setattr(current,a_snapmethod,0) local sv = snapmethods[s] local w, cw = snap_topskip(current,sv) if trace_vsnapping then @@ -1170,46 +1525,46 @@ end if trace then trace_skip("topskip",sc,so,sp,current) end flush("topskip") end - current = current.next + current = getnext(current) elseif subtype == abovedisplayskip_code then -- if trace then trace_skip("above display skip (normal)",sc,so,sp,current) end flush("above display skip (normal)") - current = current.next + current = getnext(current) -- elseif subtype == belowdisplayskip_code then -- if trace then trace_skip("below display skip (normal)",sc,so,sp,current) end flush("below display skip (normal)") - current = current.next - -- + current = getnext(current) + -- elseif subtype == abovedisplayshortskip_code then -- if trace then trace_skip("above display skip (short)",sc,so,sp,current) end flush("above display skip (short)") - current = current.next + current = getnext(current) -- elseif subtype == belowdisplayshortskip_code then -- if trace then trace_skip("below display skip (short)",sc,so,sp,current) end flush("below display skip (short)") - current = current.next + current = getnext(current) -- else -- other glue if snap and trace_vsnapping then - local spec = current.spec - if spec.writable and spec.width ~= 0 then - report_snapper("glue %p of type %a kept",current.spec.width,skipcodes[subtype]) - -- spec.width = 0 + local spec = getfield(current,"spec") + if getfield(spec,"writable") and getfield(spec,"width") ~= 0 then + report_snapper("glue %p of type %a kept",getfield(spec,"width"),skipcodes[subtype]) + -- setfield(spec,"width",0) end end - if trace then trace_skip(formatter["glue of type %a"](subtype),sc,so,sp,current) end + if trace then trace_skip(formatters["glue of type %a"](subtype),sc,so,sp,current) end flush("some glue") - current = current.next + current = getnext(current) end else - flush("something else") - current = current.next + flush(formatters["node with id %a"](id)) + current = getnext(current) end end if trace then trace_info("stop analyzing",where,what) end @@ -1225,17 +1580,28 @@ end local p = new_penalty(penalty_data) if trace then trace_done("result",p) end head, tail = insert_node_after(head,tail,p) + -- if penalty_data > special_penalty_min and penalty_data < special_penalty_max then + local props = properties[p] + if props then + props.special_penalty = special_penalty or penalty_data + else + properties[p] = { + special_penalty = special_penalty or penalty_data + } + end + -- end end if glue_data then if not tail then tail = find_node_tail(head) end if trace then trace_done("result",glue_data) end if force_glue then - head, tail = forced_skip(head,tail,glue_data.spec.width,"after",trace) + local spec = getfield(glue_data,"spec") + head, tail = forced_skip(head,tail,getfield(spec,"width"),"after",trace) free_glue_node(glue_data) else head, tail = insert_node_after(head,tail,glue_data) end -texnest[texnest.ptr].prevdepth = 0 -- appending to the list bypasses tex's prevdepth handler + texnest[texnest.ptr].prevdepth = 0 -- appending to the list bypasses tex's prevdepth handler end if trace then if glue_data or penalty_data then @@ -1243,9 +1609,16 @@ texnest[texnest.ptr].prevdepth = 0 -- appending to the list bypasses tex's prevd end show_tracing(head) if oldhead ~= head then - trace_info("head has been changed from %a to %a",nodecodes[oldhead.id],nodecodes[head.id]) + trace_info("head has been changed from %a to %a",nodecodes[getid(oldhead)],nodecodes[getid(head)]) end end + +-- if headprev then +-- setprev(head,headprev) +-- setnext(headprev,head) +-- end +-- print("C HEAD",tonode(head)) + return head, true end @@ -1271,16 +1644,17 @@ end function vspacing.pagehandler(newhead,where) -- local newhead = texlists.contrib_head if newhead then + newhead = tonut(newhead) local newtail = find_node_tail(newhead) -- best pass that tail, known anyway local flush = false stackhack = true -- todo: only when grid snapping once enabled -- todo: fast check if head = tail for n in traverse_nodes(newhead) do -- we could just look for glue nodes - local id = n.id + local id = getid(n) if id ~= glue_code then flush = true - elseif n.subtype == userskip_code then - if n[a_skipcategory] then + elseif getsubtype(n) == userskip_code then + if getattr(n,a_skipcategory) then stackhack = true else flush = true @@ -1292,35 +1666,36 @@ function vspacing.pagehandler(newhead,where) if flush then if stackhead then if trace_collect_vspacing then report("appending %s nodes to stack (final): %s",newhead) end - stacktail.next = newhead - newhead.prev = stacktail + setfield(stacktail,"next",newhead) + setfield(newhead,"prev",stacktail) newhead = stackhead stackhead, stacktail = nil, nil end if stackhack then stackhack = false if trace_collect_vspacing then report("processing %s nodes: %s",newhead) end - -- texlists.contrib_head = collapser(newhead,"page",where,trace_page_vspacing,true,a_snapmethod) - newhead = collapser(newhead,"page",where,trace_page_vspacing,true,a_snapmethod) + -- texlists.contrib_head = collapser(newhead,"page",where,trace_page_vspacing,true,a_snapmethod) + newhead = collapser(newhead,"page",where,trace_page_vspacing,true,a_snapmethod) else if trace_collect_vspacing then report("flushing %s nodes: %s",newhead) end -- texlists.contrib_head = newhead end + return tonode(newhead) else if stackhead then if trace_collect_vspacing then report("appending %s nodes to stack (intermediate): %s",newhead) end - stacktail.next = newhead - newhead.prev = stacktail + setfield(stacktail,"next",newhead) + setfield(newhead,"prev",stacktail) else if trace_collect_vspacing then report("storing %s nodes in stack (initial): %s",newhead) end stackhead = newhead end stacktail = newtail -- texlists.contrib_head = nil - newhead = nil + -- newhead = nil end end - return newhead + return nil end local ignore = table.tohash { @@ -1330,18 +1705,27 @@ local ignore = table.tohash { } function vspacing.vboxhandler(head,where) - if head and not ignore[where] and head.next then - head = collapser(head,"vbox",where,trace_vbox_vspacing,true,a_snapvbox) -- todo: local snapper + if head and not ignore[where] then + local h = tonut(head) + if getnext(h) then -- what if a one liner and snapping? + h = collapser(h,"vbox",where,trace_vbox_vspacing,true,a_snapvbox) -- todo: local snapper + return tonode(h) + end end return head end -function vspacing.collapsevbox(n) -- for boxes but using global a_snapmethod - local box = texgetbox(n) +function vspacing.collapsevbox(n,aslist) -- for boxes but using global a_snapmethod + local box = getbox(n) if box then - local list = box.list + local list = getlist(box) if list then - box.list = vpack_node(collapser(list,"snapper","vbox",trace_vbox_vspacing,true,a_snapmethod)) + list = collapser(list,"snapper","vbox",trace_vbox_vspacing,true,a_snapmethod) + if aslist then + setfield(box,"list",list) -- beware, dimensions of box are wrong now + else + setfield(box,"list",vpack_node(list)) + end end end end @@ -1352,14 +1736,65 @@ end local outer = texnest[0] function vspacing.resetprevdepth() - outer.prevdepth = 0 + if texlists.hold_head then + outer.prevdepth = 0 + end end -- interface -commands.vspacing = vspacing.analyze -commands.vspacingsetamount = vspacing.setskip -commands.vspacingdefine = vspacing.setmap -commands.vspacingcollapse = vspacing.collapsevbox -commands.vspacingsnap = vspacing.snapbox -commands.resetprevdepth = vspacing.resetprevdepth +implement { + name = "vspacing", + actions = vspacing.analyze, + scope = "private", + arguments = "string" +} + +implement { + name = "resetprevdepth", + actions = vspacing.resetprevdepth, + scope = "private" +} + +implement { + name = "vspacingsetamount", + actions = vspacing.setskip, + scope = "private", + arguments = "string", +} + +implement { + name = "vspacingdefine", + actions = vspacing.setmap, + scope = "private", + arguments = { "string", "string" } +} + +implement { + name = "vspacingcollapse", + actions = vspacing.collapsevbox, + scope = "private", + arguments = "integer" +} + +implement { + name = "vspacingcollapseonly", + actions = vspacing.collapsevbox, + scope = "private", + arguments = { "integer", true } +} + +implement { + name = "vspacingsnap", + actions = vspacing.snapbox, + scope = "private", + arguments = { "integer", "integer" } +} + +implement { + name = "definesnapmethod", + actions = vspacing.definesnapmethod, + scope = "private", + arguments = { "string", "string" } +} + |