if not modules then modules = { } end modules ['lang-dis'] = { version = 1.001, comment = "companion to lang-ini.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" } local concat = table.concat local nodes = nodes local tasks = nodes.tasks local nuts = nodes.nuts local nodepool = nuts.pool local tonode = nuts.tonode local tonut = nuts.tonut local getfield = nuts.getfield local setfield = nuts.setfield local getnext = nuts.getnext local getprev = nuts.getprev local getid = nuts.getid local getfont = nuts.getfont local getattr = nuts.getattr local getsubtype = nuts.getsubtype local setsubtype = nuts.setsubtype local getchar = nuts.getchar local getdisc = nuts.getdisc local setdisc = nuts.setdisc local isglyph = nuts.isglyph local copy_node = nuts.copy local free_node = nuts.free local remove_node = nuts.remove local traverse_id = nuts.traverse_id local traverse_nodes = nuts.traverse local nodecodes = nodes.nodecodes local disccodes = nodes.disccodes local disc_code = nodecodes.disc local glyph_code = nodecodes.glyph local discretionary_code = disccodes.discretionary local a_visualize = attributes.private("visualizediscretionary") local setattribute = tex.setattribute local getlanguagedata = languages.getdata local check_regular = true local expanders = { [disccodes.discretionary] = function(d,template) -- \discretionary return template end, [disccodes.explicit] = function(d,template) -- \- local pre, post, replace = getdisc(d) local done = false if pre then local char = isglyph(pre) if char and char <= 0 then done = true pre = nil end end if post then local char = isglyph(post) if char and char <= 0 then done = true post = nil end end if done then setdisc(d,pre,post,replace,discretionary_code,tex.exhyphenpenalty) end return template end, [disccodes.automatic] = function(d,template) -- following a - : the pre and post chars are already appended and set -- so we have pre=preex and post=postex .. however, the previous -- hyphen is already injected ... downside: the font handler sees this -- so this is another argument for doing a hyphenation pass in context local pre, post, replace = getdisc(d) if pre then -- we have a preex characters and want that one to replace the -- character in front which is the trigger if not template then -- can there be font kerns already? template = getprev(d) if template and getid(template) ~= glyph_code then template = getnext(d) if template and getid(template) ~= glyph_code then template = nil end end end if template then local pseudohead = getprev(template) if pseudohead then while template ~= d do pseudohead, template, removed = remove_node(pseudohead,template) -- free old replace ? replace = removed -- break ? end else -- can't happen end setdisc(d,pre,post,replace,discretionary_code,tex.hyphenpenalty) else -- print("lone regular discretionary ignored") end else setdisc(d,pre,post,replace,discretionary_code,tex.hyphenpenalty) end return template end, [disccodes.regular] = function(d,template) if check_regular then -- simple if not template then -- can there be font kerns already? template = getprev(d) if template and getid(template) ~= glyph_code then template = getnext(d) if template and getid(template) ~= glyph_code then template = nil end end end if template then local language = template and getfield(template,"lang") local data = getlanguagedata(language) local prechar = data.prehyphenchar local postchar = data.posthyphenchar local pre, post, replace = getdisc(d) -- pre can be set local done = false if prechar and prechar > 0 then done = true pre = copy_node(template) setchar(pre,prechar) end if postchar and postchar > 0 then done = true post = copy_node(template) setchar(post,postchar) end if done then setdisc(d,pre,post,replace,discretionary_code,tex.hyphenpenalty) end else -- print("lone regular discretionary ignored") end return template else -- maybe also set penalty here setsubtype(d,discretionary_code) end end, [disccodes.first] = function() -- forget about them end, [disccodes.second] = function() -- forget about them end, } languages.expanders = expanders function languages.expand(d,template,subtype) if not subtype then subtype = getsubtype(d) end if subtype ~= discretionary_code then return expanders[subtype](d,template) end end local setlistcolor = nodes.tracers.colors.setlist function languages.visualizediscretionaries(head) for d in traverse_id(disc_code,tonut(head)) do if getattr(d,a_visualize) then local pre, post, replace = getdisc(d) if pre then setlistcolor(pre,"darkred") end if post then setlistcolor(post,"darkgreen") end if replace then setlistcolor(replace,"darkblue") end end end end local enabled = false function languages.showdiscretionaries(v) if v == false then setattribute(a_visualize,unsetvalue) else -- also nil if not enabled then nodes.tasks.enableaction("processors","languages.visualizediscretionaries") enabled = true end setattribute(a_visualize,1) end end interfaces.implement { name = "showdiscretionaries", actions = languages.showdiscretionaries } local toutf = nodes.listtoutf function languages.serializediscretionary(d) -- will move to tracer local pre, post, replace = getdisc(d) return string.formatters["{%s}{%s}{%s}"]( pre and toutf(pre) or "", post and toutf(post) or "", replace and toutf(replace) or "" ) end