summaryrefslogtreecommitdiff
path: root/tex/context/base/typo-drp.lua
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/typo-drp.lua')
-rw-r--r--tex/context/base/typo-drp.lua308
1 files changed, 261 insertions, 47 deletions
diff --git a/tex/context/base/typo-drp.lua b/tex/context/base/typo-drp.lua
index b3f840ae1..57818d62f 100644
--- a/tex/context/base/typo-drp.lua
+++ b/tex/context/base/typo-drp.lua
@@ -11,9 +11,7 @@ if not modules then modules = { } end modules ['typo-drp'] = {
local tonumber, type, next = tonumber, type, next
local ceil = math.ceil
-
-local utfbyte = utf.byte
-local utfchar = utf.char
+local settings_to_hash = utilities.parsers.settings_to_hash
local trace_initials = false trackers.register("typesetters.initials", function(v) trace_initials = v end)
local report_initials = logs.reporter("nodes","initials")
@@ -49,10 +47,17 @@ local new_kern = nodepool.kern
local insert_before = nuts.insert_before
local insert_after = nuts.insert_after
+local remove_node = nuts.remove
+local traverse_id = nuts.traverse_id
+local traverse = nuts.traverse
+local free_node = nuts.free
local variables = interfaces.variables
local v_default = variables.default
local v_margin = variables.margin
+local v_auto = variables.auto
+local v_first = variables.first
+local v_last = variables.last
local texget = tex.get
local texsetattribute = tex.setattribute
@@ -60,7 +65,8 @@ local unsetvalue = attributes.unsetvalue
local glyph_code = nodecodes.glyph
local hlist_code = nodecodes.hlist
-local kern_node = nodecodes.kern
+local glue_code = nodecodes.glue
+local kern_code = nodecodes.kern
local whatsit_code = nodecodes.whatsit
local localpar_code = whatsitcodes.localpar
@@ -72,6 +78,8 @@ local a_color = attributes.private('color')
local a_transparency = attributes.private('transparency')
local a_colorspace = attributes.private('colormodel')
+local category = characters.category
+
local settings = nil
function initials.set(specification)
@@ -100,6 +108,99 @@ commands.setinitial = initials.set
-- todo: prevent linebreak .. but normally a initial ends up at the top of
-- a page so this has a low priority
+-- actions[v_default] = function(head,setting)
+-- local done = false
+-- if getid(head) == whatsit_code and getsubtype(head) == localpar_code then
+-- -- begin of par
+-- local first = getnext(head)
+-- -- parbox .. needs to be set at 0
+-- if first and getid(first) == hlist_code then
+-- first = getnext(first)
+-- end
+-- -- we need to skip over kerns and glues (signals)
+-- while first and getid(first) ~= glyph_code do
+-- first = getnext(first)
+-- end
+-- if first and getid(first) == glyph_code then
+-- local char = getchar(first)
+-- local prev = getprev(first)
+-- local next = getnext(first)
+-- -- if getid(prev) == hlist_code then
+-- -- -- set the width to 0
+-- -- end
+-- if next and getid(next) == kern_code then
+-- setfield(next,"kern",0)
+-- end
+-- if setting.font then
+-- setfield(first,"font",setting.font)
+-- end
+-- if setting.dynamic > 0 then
+-- setattr(first,0,setting.dynamic)
+-- end
+-- -- can be a helper
+-- local ma = setting.ma or 0
+-- local ca = setting.ca
+-- local ta = setting.ta
+-- if ca and ca > 0 then
+-- setattr(first,a_colorspace,ma == 0 and 1 or ma)
+-- setattr(first,a_color,ca)
+-- end
+-- if ta and ta > 0 then
+-- setattr(first,a_transparency,ta)
+-- end
+-- --
+-- local width = getfield(first,"width")
+-- local height = getfield(first,"height")
+-- local depth = getfield(first,"depth")
+-- local distance = setting.distance or 0
+-- local voffset = setting.voffset or 0
+-- local hoffset = setting.hoffset or 0
+-- local parindent = tex.parindent
+-- local baseline = texget("baselineskip").width
+-- local lines = tonumber(setting.n) or 0
+-- --
+-- setfield(first,"xoffset",- width - hoffset - distance - parindent)
+-- setfield(first,"yoffset",- voffset) -- no longer - height here
+-- -- We pack so that successive handling cannot touch the dropped cap. Packaging
+-- -- in a hlist is also needed because we cannot locally adapt e.g. parindent (not
+-- -- yet stored in with localpar).
+-- setfield(first,"prev",nil)
+-- setfield(first,"next",nil)
+-- local h = hpack_nodes(first)
+-- setfield(h,"width",0)
+-- setfield(h,"height",0)
+-- setfield(h,"depth",0)
+-- setfield(prev,"next",h)
+-- setfield(next,"prev",h)
+-- setfield(h,"next",next)
+-- setfield(h,"prev",prev)
+-- first = h
+-- -- end of packaging
+-- if setting.location == v_margin then
+-- -- okay
+-- else
+-- if lines == 0 then -- safeguard, not too precise
+-- lines = ceil((height+voffset) / baseline)
+-- end
+-- -- We cannot set parshape yet ... when we can I'll add a slope
+-- -- option (positive and negative, in emwidth).
+-- local hangafter = - lines
+-- local hangindent = width + distance + parindent
+-- if trace_initials then
+-- report_initials("setting hangafter to %i and hangindent to %p",hangafter,hangindent)
+-- end
+-- tex.hangafter = hangafter
+-- tex.hangindent = hangindent
+-- if parindent ~= 0 then
+-- insert_after(first,first,new_kern(-parindent))
+-- end
+-- end
+-- done = true
+-- end
+-- end
+-- return head, done
+-- end
+
actions[v_default] = function(head,setting)
local done = false
if getid(head) == whatsit_code and getsubtype(head) == localpar_code then
@@ -114,60 +215,173 @@ actions[v_default] = function(head,setting)
first = getnext(first)
end
if first and getid(first) == glyph_code then
- local char = getchar(first)
- local prev = getprev(first)
- local next = getnext(first)
- -- if getid(prev) == hlist_code then
- -- -- set the width to 0
- -- end
- if next and getid(next) == kern_node then
- setfield(next,"kern",0)
- end
- if setting.font then
- setfield(first,"font",setting.font)
- end
- if setting.dynamic > 0 then
- setattr(first,0,setting.dynamic)
- end
- -- can be a helper
- local ma = setting.ma or 0
- local ca = setting.ca
- local ta = setting.ta
- if ca and ca > 0 then
- setattr(first,a_colorspace,ma == 0 and 1 or ma)
- setattr(first,a_color,ca)
- end
- if ta and ta > 0 then
- setattr(first,a_transparency,ta)
- end
- --
- local width = getfield(first,"width")
- local height = getfield(first,"height")
- local depth = getfield(first,"depth")
+
+-- show(head,8,"one")
+
+ local ma = setting.ma or 0
+ local ca = setting.ca
+ local ta = setting.ta
+ local last = first
local distance = setting.distance or 0
local voffset = setting.voffset or 0
local hoffset = setting.hoffset or 0
local parindent = tex.parindent
local baseline = texget("baselineskip").width
local lines = tonumber(setting.n) or 0
+ local dynamic = setting.dynamic
+ local font = setting.font
+ local method = settings_to_hash(setting.method)
+ local length = tonumber(setting.m) or 1
+ --
+ -- 1 char | n chars | skip first quote | ignore punct | keep punct
--
- setfield(first,"xoffset",- width - hoffset - distance - parindent)
- setfield(first,"yoffset",- voffset) -- no longer - height here
+ if method[v_auto] then
+ local char = getchar(first)
+ local kind = category(char)
+ if kind == "po" or kind == "pi" then
+ if method[v_first] then
+ -- remove quote etc before initial
+ local next = getnext(first)
+ if not next then
+ -- don't start with a quote or so
+ return head, false
+ end
+ last = nil
+ for current in traverse_id(glyph_code,next) do
+ head, first = remove_node(head,first,true)
+ first = current
+ last = first
+ break
+ end
+ if not last then
+ -- no following glyph or so
+ return head, false
+ end
+ else
+ -- keep quote etc with initial
+ local next = getnext(first)
+ if not next then
+ -- don't start with a quote or so
+ return head, false
+ end
+ for current in traverse_id(glyph_code,next) do
+ last = current
+ break
+ end
+ if last == first then
+ return head, false
+ end
+ end
+ elseif kind == "pf" then
+ -- error: final quote
+ else
+ -- okay
+ end
+ local next = getnext(first)
+ if next then
+ for current in traverse_id(glyph_code,next) do
+ local char = getchar(current)
+ local kind = category(char)
+ if kind == "po" then
+ if method[v_last] then
+ -- remove period etc after initial
+ remove_node(head,current,true)
+ else
+ -- keep period etc with initial
+ last = current
+ end
+ end
+ break
+ end
+ end
+ else
+ for current in traverse_id(glyph_code,first) do
+ last = current
+ if length <= 1 then
+ break
+ else
+ length = length - 1
+ end
+ end
+ end
+ local current = first
+ while true do
+ local id = getid(current)
+ if id == kern_code then
+ setfield(current,"kern",0)
+ elseif id == glyph_code then
+ local next = getnext(current)
+ if font then
+ setfield(current,"font",font)
+ end
+ if dynamic > 0 then
+ setattr(current,0,dynamic)
+ end
+ -- can be a helper
+ if ca and ca > 0 then
+ setattr(current,a_colorspace,ma == 0 and 1 or ma)
+ setattr(current,a_color,ca)
+ end
+ if ta and ta > 0 then
+ setattr(current,a_transparency,ta)
+ end
+ --
+ end
+ if current == last then
+ break
+ else
+ current = getnext(current)
+ end
+ end
-- We pack so that successive handling cannot touch the dropped cap. Packaging
-- in a hlist is also needed because we cannot locally adapt e.g. parindent (not
-- yet stored in with localpar).
+ local prev = getprev(first)
+ local next = getnext(last)
+ --
setfield(first,"prev",nil)
- setfield(first,"next",nil)
- local h = hpack_nodes(first)
- setfield(h,"width",0)
- setfield(h,"height",0)
- setfield(h,"depth",0)
- setfield(prev,"next",h)
- setfield(next,"prev",h)
- setfield(h,"next",next)
- setfield(h,"prev",prev)
- first = h
- -- end of packaging
+ setfield(last,"next",nil)
+ local dropper = hpack_nodes(first)
+ local width = getfield(dropper,"width")
+ local height = getfield(dropper,"height")
+ local depth = getfield(dropper,"depth")
+ setfield(dropper,"width",0)
+ setfield(dropper,"height",0)
+ setfield(dropper,"depth",0)
+ --
+ setfield(prev,"next",dropper)
+ if next then
+ setfield(next,"prev",dropper)
+ end
+ setfield(dropper,"next",next)
+ setfield(dropper,"prev",prev)
+ --
+ if next then
+ local current = next
+ while current do
+ local id = getid(current)
+ if id == glue_code or id == kern_code then
+ local next = getnext(current)
+ -- remove_node(current,current,true) -- created an invalid next link and dangling remains
+ remove_node(head,current,true)
+ current = next
+ else
+ break
+ end
+ end
+ end
+ --
+ local hoffset = width + hoffset + distance + parindent
+ for current in traverse_id(glyph_code,first) do
+ setfield(current,"xoffset",- hoffset )
+ setfield(current,"yoffset",- voffset) -- no longer - height here
+ if current == last then
+ break
+ end
+ end
+ --
+ first = dropper
+ --
if setting.location == v_margin then
-- okay
else