summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/supp-box.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkiv/supp-box.lua')
-rw-r--r--tex/context/base/mkiv/supp-box.lua364
1 files changed, 280 insertions, 84 deletions
diff --git a/tex/context/base/mkiv/supp-box.lua b/tex/context/base/mkiv/supp-box.lua
index d3a4f57e5..b9bf0ccf0 100644
--- a/tex/context/base/mkiv/supp-box.lua
+++ b/tex/context/base/mkiv/supp-box.lua
@@ -12,66 +12,68 @@ local lpegmatch = lpeg.match
local report_hyphenation = logs.reporter("languages","hyphenation")
-local tex = tex
-local context = context
-local nodes = nodes
-
-local implement = interfaces.implement
-
-local splitstring = string.split
-
-local nodecodes = nodes.nodecodes
-
-local disc_code = nodecodes.disc
-local hlist_code = nodecodes.hlist
-local vlist_code = nodecodes.vlist
-local glue_code = nodecodes.glue
-local kern_code = nodecodes.kern
-local glyph_code = nodecodes.glyph
-
-local nuts = nodes.nuts
-local tonut = nuts.tonut
-local tonode = nuts.tonode
-
-local getfield = nuts.getfield
-local getnext = nuts.getnext
-local getprev = nuts.getprev
-local getdisc = nuts.getdisc
-local getid = nuts.getid
-local getlist = nuts.getlist
-local getattribute = nuts.getattribute
-local getbox = nuts.getbox
-
-local setfield = nuts.setfield
-local setlink = nuts.setlink
-local setboth = nuts.setboth
-local setnext = nuts.setnext
-local setbox = nuts.setbox
-local setlist = nuts.setlist
-
-local free_node = nuts.free
-local flush_list = nuts.flush_list
-local copy_node = nuts.copy
-local copy_list = nuts.copy_list
-local find_tail = nuts.tail
-local traverse_id = nuts.traverse_id
-local link_nodes = nuts.linked
-local dimensions = nuts.dimensions
-
-local listtoutf = nodes.listtoutf
-
-local nodepool = nuts.pool
-local new_penalty = nodepool.penalty
-local new_hlist = nodepool.hlist
-local new_glue = nodepool.glue
-local new_rule = nodepool.rule
-local new_kern = nodepool.kern
-
-local setlistcolor = nodes.tracers.colors.setlist
-
-local texget = tex.get
-local texgetbox = tex.getbox
-local texsetdimen = tex.setdimen
+local tex = tex
+local context = context
+local nodes = nodes
+
+local implement = interfaces.implement
+
+local nodecodes = nodes.nodecodes
+
+local disc_code = nodecodes.disc
+local hlist_code = nodecodes.hlist
+local vlist_code = nodecodes.vlist
+local glue_code = nodecodes.glue
+local glyph_code = nodecodes.glyph
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+
+local getfield = nuts.getfield
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getdisc = nuts.getdisc
+local getid = nuts.getid
+local getlist = nuts.getlist
+local getattribute = nuts.getattribute
+local getbox = nuts.getbox
+local getdir = nuts.getdir
+local getwidth = nuts.getwidth
+local takebox = nuts.takebox
+
+local setfield = nuts.setfield
+local setlink = nuts.setlink
+local setboth = nuts.setboth
+local setnext = nuts.setnext
+local setbox = nuts.setbox
+local setlist = nuts.setlist
+local setdisc = nuts.setdisc
+local setwidth = nuts.setwidth
+local setheight = nuts.setheight
+local setdepth = nuts.setdepth
+
+local flush_node = nuts.flush_node
+local flush_list = nuts.flush_list
+local copy_node = nuts.copy
+local copy_list = nuts.copy_list
+local find_tail = nuts.tail
+local traverse_id = nuts.traverse_id
+local list_dimensions = nuts.dimensions
+local hpack = nuts.hpack
+
+local listtoutf = nodes.listtoutf
+
+local nodepool = nuts.pool
+local new_penalty = nodepool.penalty
+local new_hlist = nodepool.hlist
+local new_glue = nodepool.glue
+
+local setlistcolor = nodes.tracers.colors.setlist
+
+local texget = tex.get
+local texgetbox = tex.getbox
+local texsetdimen = tex.setdimen
local function hyphenatedlist(head,usecolor)
local current = head and tonut(head)
@@ -81,12 +83,6 @@ local function hyphenatedlist(head,usecolor)
local prev = getprev(current)
if id == disc_code then
local pre, post, replace = getdisc(current)
- if pre then
- setfield(current,"pre",nil)
- end
- if post then
- setfield(current,"post",nil)
- end
if not usecolor then
-- nothing fancy done
elseif pre and post then
@@ -99,25 +95,33 @@ local function hyphenatedlist(head,usecolor)
end
if replace then
flush_list(replace)
- setfield(current,"replace",nil)
end
- -- setfield(current,"replace",new_rule(65536)) -- new_kern(65536*2))
+ setdisc(current)
setboth(current)
- local list = link_nodes (
+-- local list = setlink (
+-- pre and new_penalty(10000),
+-- pre,
+-- current,
+-- post,
+-- post and new_penalty(10000)
+-- )
+-- local tail = find_tail(list)
+-- if prev then
+-- setlink(prev,list)
+-- end
+-- if next then
+-- setlink(tail,next)
+-- end
+ setlink (
+ prev, -- there had better be one
pre and new_penalty(10000),
pre,
current,
post,
- post and new_penalty(10000)
+ post and new_penalty(10000),
+ next
)
- local tail = find_tail(list)
- if prev then
- setlink(prev,list)
- end
- if next then
- setlink(tail,next)
- end
- -- free_node(current)
+ -- flush_node(current)
elseif id == vlist_code or id == hlist_code then
hyphenatedlist(getlist(current))
end
@@ -335,7 +339,7 @@ implement {
else
tail = prev
end
- free_node(temp)
+ flush_node(temp)
end
-- done
setnext(tail)
@@ -354,9 +358,9 @@ implement {
arguments = "integer",
actions = function(n)
local b = getbox(n)
- local factor = texget("baselineskip").width / texget("hsize")
- setfield(b,"depth",0)
- setfield(b,"height",getfield(b,"width") * factor)
+ local factor = texget("baselineskip",false) / texget("hsize")
+ setdepth(b,0)
+ setheight(b,getwidth(b) * factor)
end
}
@@ -372,7 +376,7 @@ local function getnaturaldimensions(n)
local w, h, d = 0, 0, 0
local l = getlist(getbox(n))
if l then
- w, h, d = dimensions(l)
+ w, h, d = list_dimensions(l)
end
texsetdimen("lastnaturalboxwd",w)
texsetdimen("lastnaturalboxht",h)
@@ -395,13 +399,42 @@ interfaces.implement {
end
}
+interfaces.implement {
+ name = "getnaturalwd",
+ arguments = "integer",
+ actions = function(n)
+ local w, h, d = 0, 0, 0
+ local l = getlist(getbox(n))
+ if l then
+ w, h, d = list_dimensions(l)
+ end
+ context("\\dimexpr%i\\scaledpoint\\relax",w)
+ end
+}
+
+local function setboxtonaturalwd(n)
+ local old = takebox(n)
+ local new = hpack(getlist(old))
+ setlist(old,nil)
+ flush_node(old)
+ setbox(n,new)
+end
+
+interfaces.implement {
+ name = "setnaturalwd",
+ arguments = "integer",
+ actions = setboxtonaturalwd
+}
+
+nodes.setboxtonaturalwd = setboxtonaturalwd
+
local function firstdirinbox(n)
local b = getbox(n)
if b then
local l = getlist(b)
if l then
for h in traverse_id(hlist_code,l) do
- return getfield(h,"dir")
+ return getdir(h)
end
end
end
@@ -418,3 +451,166 @@ interfaces.implement {
doifelse(firstdirinbox(n) == "TRT")
end
}
+
+-- new (handy for mp) .. might move to its own module
+
+do
+
+ local flush_list = nodes.flush_list
+ local copy_list = nodes.copy_list
+ local takebox = nodes.takebox
+ local texsetbox = tex.setbox
+
+ local new_hlist = nodes.pool.hlist
+
+ local boxes = { }
+ nodes.boxes = boxes
+ local cache = table.setmetatableindex("table")
+ local report = logs.reporter("boxes","cache")
+ local trace = false
+
+ trackers.register("nodes.boxes",function(v) trace = v end)
+
+ function boxes.save(category,name,box)
+ name = tonumber(name) or name
+ local b = takebox(box)
+ if trace then
+ report("category %a, name %a, %s (%s)",category,name,"save",b and "content" or "empty")
+ end
+ cache[category][name] = b or false
+ end
+
+ function boxes.found(category,name)
+ name = tonumber(name) or name
+ return cache[category][name] and true or false
+ end
+
+ function boxes.direct(category,name,copy)
+ name = tonumber(name) or name
+ local c = cache[category]
+ local b = c[name]
+ if not b then
+ -- do nothing, maybe trace
+ elseif copy then
+ b = copy_list(b)
+ else
+ c[name] = false
+ end
+ if trace then
+ report("category %a, name %a, %s (%s)",category,name,"direct",b and "content" or "empty")
+ end
+ return b or nil
+ end
+
+ function boxes.restore(category,name,box,copy)
+ name = tonumber(name) or name
+ local c = cache[category]
+ local b = takebox(box)
+ if b then
+ flush_list(b)
+ end
+ local b = c[name]
+ if not b then
+ -- do nothing, maybe trace
+ elseif copy then
+ b = copy_list(b)
+ else
+ c[name] = false
+ end
+ if trace then
+ report("category %a, name %a, %s (%s)",category,name,"restore",b and "content" or "empty")
+ end
+ texsetbox(box,b or nil)
+ end
+
+ local getwhd = nodes.getwhd
+
+ function boxes.dimensions(category,name)
+ name = tonumber(name) or name
+ local b = cache[category][name]
+ if b then
+ return getwhd(b)
+ else
+ return 0, 0, 0
+ end
+ end
+
+ function boxes.reset(category,name)
+ name = tonumber(name) or name
+ local c = cache[category]
+ if name and name ~= "" then
+ local b = c[name]
+ if b then
+ flush_list(b)
+ c[name] = false
+ end
+ if trace then
+ report("category %a, name %a, reset",category,name)
+ end
+ else
+ for k, b in next, c do
+ if b then
+ flush_list(b)
+ end
+ end
+ cache[category] = { }
+ if trace then
+ report("category %a, reset",category)
+ end
+ end
+ end
+
+ implement {
+ name = "putboxincache",
+ arguments = { "string", "string", "integer" },
+ actions = boxes.save,
+ }
+
+ implement {
+ name = "getboxfromcache",
+ arguments = { "string", "string", "integer" },
+ actions = boxes.restore,
+ }
+
+ implement {
+ name = "directboxfromcache",
+ arguments = { "string", "string" },
+ actions = { boxes.direct, context },
+ -- actions = function(category,name) local b = boxes.direct(category,name) if b then context(b) end end,
+ }
+
+ implement {
+ name = "directcopyboxfromcache",
+ arguments = { "string", "string", true },
+ actions = { boxes.direct, context },
+ -- actions = function(category,name) local b = boxes.direct(category,name,true) if b then context(b) end end,
+ }
+
+ implement {
+ name = "copyboxfromcache",
+ arguments = { "string", "string", "integer", true },
+ actions = boxes.restore,
+ }
+
+ implement {
+ name = "doifelseboxincache",
+ arguments = { "string", "string" },
+ actions = { boxes.found, doifelse },
+ }
+
+ implement {
+ name = "resetboxesincache",
+ arguments = { "string" },
+ actions = boxes.reset,
+ }
+
+ implement {
+ name = "lastlinewidth",
+ actions = function()
+ local head = tex.lists.page_head
+ -- list dimensions returns 3 value but we take the first
+ context(head and list_dimensions(getlist(find_tail(tonut(tex.lists.page_head)))) or 0)
+ end
+ }
+
+end