typo-rep.lmt /size: 4055 b    last modification: 2025-02-21 11:03
1if not modules then modules = { } end modules ['typo-rep'] = {
2    version   = 1.001,
3    comment   = "companion to node-ini.mkiv",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9-- This was rather boring to program (more of the same) but I could
10-- endure it by listening to a couple cd's by The Scene and The Lau
11-- on the squeezebox on my desk.
12
13local next, type, tonumber = next, type, tonumber
14
15local trace_stripping = false  trackers.register("nodes.stripping",  function(v) trace_stripping = v end)
16                               trackers.register("fonts.stripping",  function(v) trace_stripping = v end)
17
18local report_stripping = logs.reporter("fonts","stripping")
19
20local nodes           = nodes
21local enableaction    = nodes.tasks.enableaction
22
23local nuts            = nodes.nuts
24
25local getnext         = nuts.getnext
26local getchar         = nuts.getchar
27local isglyph         = nuts.isglyph
28
29local getattr         = nuts.getattr
30
31local remove_node     = nuts.remove
32local replace_node    = nuts.replace
33local copy_node       = nuts.copy
34
35local nodecodes       = nodes.nodecodes
36
37local chardata        = characters.data
38local collected       = false
39
40local texsetattribute = tex.setattribute
41
42local a_stripping     <const> = attributes.private("stripping")
43local unsetvalue      <const> = attributes.unsetvalue
44local v_reset         <const> = interfaces.variables.reset
45
46-- todo: other namespace -> typesetters
47
48nodes.stripping  = nodes.stripping  or { } local stripping  = nodes.stripping
49stripping.glyphs = stripping.glyphs or { } local glyphs     = stripping.glyphs
50
51local function initialize()
52    for k, v in next, chardata do
53        if v.category == "cf" and not v.visible and not glyphs[k] then
54            glyphs[k] = true
55        end
56    end
57    initialize = nil
58end
59
60local function process(what,head,current,char)
61    if what == true then
62        if trace_stripping then
63            report_stripping("deleting %C from text",char)
64        end
65        head, current = remove_node(head,current,true)
66    elseif type(what) == "function" then
67        head, current = what(head,current)
68        current = getnext(current)
69        if trace_stripping then
70            report_stripping("processing %C in text",char)
71        end
72    elseif what then  -- assume node
73        head, current = replace_node(head,current,copy_node(what))
74        current = getnext(current)
75        if trace_stripping then
76            report_stripping("replacing %C in text",char)
77        end
78    end
79    return head, current
80end
81
82function nodes.handlers.stripping(head) -- use loop
83    local current = head
84    while current do
85        local char, id = isglyph(current)
86        if char then
87            -- it's more efficient to keep track of what needs to be kept
88            local todo = getattr(current,a_stripping)
89            if todo == 1 then
90                local what = glyphs[char]
91                if what then
92                    head, current = process(what,head,current,char)
93                else -- handling of spacing etc has to be done elsewhere
94                    current = getnext(current)
95                end
96            else
97                current = getnext(current)
98            end
99        else
100            current = getnext(current)
101        end
102    end
103    return head
104end
105
106local enabled = false
107
108function stripping.set(n) -- number or 'reset'
109    if n == v_reset then
110        n = unsetvalue
111    else
112        n = tonumber(n)
113        if n then
114            if not enabled then
115                if initialize then initialize() end
116                enableaction("processors","nodes.handlers.stripping")
117                enabled = true
118            end
119        else
120            n = unsetvalue
121        end
122    end
123    texsetattribute(a_stripping,n)
124end
125
126-- interface
127
128interfaces.implement {
129    name      = "setcharacterstripping",
130    public    = true,
131    protected = true,
132    actions   = stripping.set,
133    arguments = "optional"
134}
135