summaryrefslogtreecommitdiff
path: root/tex/context/base/supp-box.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/supp-box.lua')
-rw-r--r--tex/context/base/supp-box.lua353
1 files changed, 244 insertions, 109 deletions
diff --git a/tex/context/base/supp-box.lua b/tex/context/base/supp-box.lua
index 27078f46f..7cc71a891 100644
--- a/tex/context/base/supp-box.lua
+++ b/tex/context/base/supp-box.lua
@@ -8,13 +8,16 @@ if not modules then modules = { } end modules ['supp-box'] = {
-- this is preliminary code, use insert_before etc
+local lpegmatch = lpeg.match
+
local report_hyphenation = logs.reporter("languages","hyphenation")
local tex = tex
local context = context
-local commands = commands
local nodes = nodes
+local implement = interfaces.implement
+
local splitstring = string.split
local nodecodes = nodes.nodecodes
@@ -26,110 +29,217 @@ local glue_code = nodecodes.glue
local kern_code = nodecodes.kern
local glyph_code = nodecodes.glyph
-local new_penalty = nodes.pool.penalty
-local new_hlist = nodes.pool.hlist
-local new_glue = nodes.pool.glue
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
-local free_node = nodes.free
-local copy_list = nodes.copy_list
-local copy_node = nodes.copy
-local find_tail = nodes.tail
+local getfield = nuts.getfield
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local getid = nuts.getid
+local getlist = nuts.getlist
+local getattribute = nuts.getattribute
+local getbox = nuts.getbox
+
+local setfield = nuts.setfield
+local setbox = nuts.setbox
+
+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 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 texsetbox = tex.setbox
-local texgetbox = tex.getbox
local texget = tex.get
+local texgetbox = tex.getbox
-local function hyphenatedlist(list)
- while list do
- local id, next, prev = list.id, list.next, list.prev
+local function hyphenatedlist(head,usecolor)
+ local current = head and tonut(head)
+ while current do
+ local id = getid(current)
+ local next = getnext(current)
+ local prev = getprev(current)
if id == disc_code then
- local hyphen = list.pre
- if hyphen then
- local penalty = new_penalty(-500)
- hyphen.next, penalty.prev = penalty, hyphen
- prev.next, next.prev = hyphen, penalty
- penalty.next, hyphen.prev = next, prev
- list.pre = nil
- free_node(list)
+ local pre = getfield(current,"pre")
+ local post = getfield(current,"post")
+ local replace = getfield(current,"replace")
+ 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
+ setlistcolor(pre,"darkmagenta")
+ setlistcolor(post,"darkcyan")
+ elseif pre then
+ setlistcolor(pre,"darkyellow")
+ elseif post then
+ setlistcolor(post,"darkyellow")
+ end
+ if replace then
+ flush_list(replace)
+ setfield(current,"replace",nil)
+ end
+ -- setfield(current,"replace",new_rule(65536)) -- new_kern(65536*2))
+ setfield(current,"next",nil)
+ setfield(current,"prev",nil)
+ local list = link_nodes (
+ pre and new_penalty(10000),
+ pre,
+ current,
+ post,
+ post and new_penalty(10000)
+ )
+ local tail = find_tail(list)
+ if prev then
+ setfield(prev,"next",list)
+ setfield(list,"prev",prev)
+ end
+ if next then
+ setfield(tail,"next",next)
+ setfield(next,"prev",tail)
+ end
+ -- free_node(current)
elseif id == vlist_code or id == hlist_code then
- hyphenatedlist(list.list)
+ hyphenatedlist(getlist(current))
end
- list = next
+ current = next
end
end
-commands.hyphenatedlist = hyphenatedlist
+implement {
+ name = "hyphenatedlist",
+ arguments = { "integer", "boolean" },
+ actions = function(n,color)
+ local b = texgetbox(n)
+ if b then
+ hyphenatedlist(b.list,color)
+ end
+ end
+}
-function commands.showhyphenatedinlist(list)
- report_hyphenation("show: %s",nodes.listtoutf(list,false,true))
-end
+-- local function hyphenatedhack(head,pre)
+-- pre = tonut(pre)
+-- for n in traverse_id(disc_code,tonut(head)) do
+-- local hyphen = getfield(n,"pre")
+-- if hyphen then
+-- flush_list(hyphen)
+-- end
+-- setfield(n,"pre",copy_list(pre))
+-- end
+-- end
+--
+-- commands.hyphenatedhack = hyphenatedhack
local function checkedlist(list)
if type(list) == "number" then
- return texgetbox(list).list
+ return getlist(getbox(tonut(list)))
else
- return list
+ return tonut(list)
end
end
-local function applytochars(list,what,nested)
- local doaction = context[what or "ruledhbox"]
- local noaction = context
- local current = checkedlist(list)
+implement {
+ name = "showhyphenatedinlist",
+ arguments = "integer",
+ actions = function(box)
+ report_hyphenation("show: %s",listtoutf(checkedlist(n),false,true))
+ end
+}
+
+local function applytochars(current,doaction,noaction,nested)
while current do
- local id = current.id
+ local id = getid(current)
if nested and (id == hlist_code or id == vlist_code) then
context.beginhbox()
- applytochars(current.list,what,nested)
+ applytochars(getlist(current),doaction,noaction,nested)
context.endhbox()
elseif id ~= glyph_code then
- noaction(copy_node(current))
+ noaction(tonode(copy_node(current)))
else
- doaction(copy_node(current))
+ doaction(tonode(copy_node(current)))
end
- current = current.next
+ current = getnext(current)
end
end
-local function applytowords(list,what,nested)
- local doaction = context[what or "ruledhbox"]
- local noaction = context
- local current = checkedlist(list)
+local function applytowords(current,doaction,noaction,nested)
local start
while current do
- local id = current.id
+ local id = getid(current)
if id == glue_code then
if start then
- doaction(copy_list(start,current))
+ doaction(tonode(copy_list(start,current)))
start = nil
end
- noaction(copy_node(current))
+ noaction(tonode(copy_node(current)))
elseif nested and (id == hlist_code or id == vlist_code) then
context.beginhbox()
- applytowords(current.list,what,nested)
+ applytowords(getlist(current),doaction,noaction,nested)
context.egroup()
elseif not start then
start = current
end
- current = current.next
+ current = getnext(current)
end
if start then
- doaction(copy_list(start))
+ doaction(tonode(copy_list(start)))
end
end
-commands.applytochars = applytochars
-commands.applytowords = applytowords
+local methods = {
+ char = applytochars,
+ characters = applytochars,
+ word = applytowords,
+ words = applytowords,
+}
+
+implement {
+ name = "applytobox",
+ arguments = {
+ {
+ { "box", "integer" },
+ { "command" },
+ { "method" },
+ { "nested", "boolean" },
+ }
+ },
+ actions = function(specification)
+ local list = checkedlist(specification.box)
+ local action = methods[specification.method or "char"]
+ if list and action then
+ action(list,context[specification.command or "ruledhbox"],context,specification.nested)
+ end
+ end
+}
local split_char = lpeg.Ct(lpeg.C(1)^0)
local split_word = lpeg.tsplitat(lpeg.patterns.space)
local split_line = lpeg.tsplitat(lpeg.patterns.eol)
-function commands.processsplit(str,command,how,spaced)
- how = how or "word"
- if how == "char" then
- local words = lpeg.match(split_char,str)
+local function processsplit(specification)
+ local str = specification.data or ""
+ local command = specification.command or "ruledhbox"
+ local method = specification.method or "word"
+ local spaced = specification.spaced
+ if method == "char" or method == "character" then
+ local words = lpegmatch(split_char,str)
for i=1,#words do
local word = words[i]
if word == " " then
@@ -142,8 +252,8 @@ function commands.processsplit(str,command,how,spaced)
context(word)
end
end
- elseif how == "word" then
- local words = lpeg.match(split_word,str)
+ elseif method == "word" then
+ local words = lpegmatch(split_word,str)
for i=1,#words do
local word = words[i]
if spaced and i > 1 then
@@ -155,8 +265,8 @@ function commands.processsplit(str,command,how,spaced)
context(word)
end
end
- elseif how == "line" then
- local words = lpeg.match(split_line,str)
+ elseif method == "line" then
+ local words = lpegmatch(split_line,str)
for i=1,#words do
local word = words[i]
if spaced and i > 1 then
@@ -173,63 +283,88 @@ function commands.processsplit(str,command,how,spaced)
end
end
+implement {
+ name = "processsplit",
+ actions = processsplit,
+ arguments = {
+ {
+ { "data" },
+ { "command" },
+ { "method" },
+ { "spaced", "boolean" },
+ }
+ }
+}
+
local a_vboxtohboxseparator = attributes.private("vboxtohboxseparator")
-function commands.vboxlisttohbox(original,target,inbetween)
- local current = texgetbox(original).list
- local head = nil
- local tail = nil
- while current do
- local id = current.id
- local next = current.next
- if id == hlist_code then
- local list = current.list
- if head then
- if inbetween > 0 then
- local n = new_glue(0,0,inbetween)
- tail.next = n
- n.prev = tail
- tail = n
- end
- tail.next = list
- list.prev = tail
- else
- head = list
- end
- tail = find_tail(list)
- -- remove last separator
- if tail.id == hlist_code and tail[a_vboxtohboxseparator] == 1 then
- local temp = tail
- local prev = tail.prev
- if next then
- local list = tail.list
- prev.next = list
- list.prev = prev
- tail.list = nil
- tail = find_tail(list)
+implement {
+ name = "vboxlisttohbox",
+ arguments = { "integer", "integer", "dimen" },
+ actions = function(original,target,inbetween)
+ local current = getlist(getbox(original))
+ local head = nil
+ local tail = nil
+ while current do
+ local id = getid(current)
+ local next = getnext(current)
+ if id == hlist_code then
+ local list = getlist(current)
+ if head then
+ if inbetween > 0 then
+ local n = new_glue(0,0,inbetween)
+ setfield(tail,"next",n)
+ setfield(n,"prev",tail)
+ tail = n
+ end
+ setfield(tail,"next",list)
+ setfield(list,"prev",tail)
else
- tail = prev
+ head = list
end
- free_node(temp)
+ tail = find_tail(list)
+ -- remove last separator
+ if getid(tail) == hlist_code and getattribute(tail,a_vboxtohboxseparator) == 1 then
+ local temp = tail
+ local prev = getprev(tail)
+ if next then
+ local list = getlist(tail)
+ setfield(prev,"next",list)
+ setfield(list,"prev",prev)
+ setfield(tail,"list",nil)
+ tail = find_tail(list)
+ else
+ tail = prev
+ end
+ free_node(temp)
+ end
+ -- done
+ setfield(tail,"next",nil)
+ setfield(current,"list",nil)
end
- -- done
- tail.next = nil
- current.list = nil
+ current = next
end
- current = next
+ local result = new_hlist()
+ setfield(result,"list",head)
+ setbox(target,result)
end
- local result = new_hlist()
- result.list = head
- texsetbox(target,result)
-end
+}
-function commands.hboxtovbox(original)
- local b = texgetbox(original)
- local factor = texget("baselineskip").width / texget("hsize")
- b.depth = 0
- b.height = b.width * factor
-end
+implement {
+ name = "hboxtovbox",
+ 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)
+ end
+}
-function commands.boxtostring(n)
- context.puretext(nodes.toutf(tex.box[n].list)) -- helper is defined later
-end
+implement {
+ name = "boxtostring",
+ arguments = "integer",
+ actions = function(n)
+ context.puretext(nodes.toutf(texgetbox(n).list)) -- helper is defined later
+ end
+}