summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/typo-rep.lua
blob: 2538a014d10591d13ae96bd0755f192a9fc3e50d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
if not modules then modules = { } end modules ['typo-rep'] = {
    version   = 1.001,
    comment   = "companion to node-ini.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

-- This was rather boring to program (more of the same) but I could
-- endure it by listening to a couple cd's by The Scene and The Lau
-- on the squeezebox on my desk.

local next, type, tonumber = next, type, tonumber

local trace_stripping = false  trackers.register("nodes.stripping",  function(v) trace_stripping = v end)
                               trackers.register("fonts.stripping",  function(v) trace_stripping = v end)

local report_stripping = logs.reporter("fonts","stripping")

local nodes           = nodes
local enableaction    = nodes.tasks.enableaction

local nuts            = nodes.nuts

local getnext         = nuts.getnext
local getchar         = nuts.getchar
local isglyph         = nuts.isglyph

local getattr         = nuts.getattr

local remove_node     = nuts.remove
local replace_node    = nuts.replace
local copy_node       = nuts.copy

local nodecodes       = nodes.nodecodes

local chardata        = characters.data
local collected       = false

local a_stripping     = attributes.private("stripping")
local texsetattribute = tex.setattribute
local unsetvalue      = attributes.unsetvalue

local v_reset         = interfaces.variables.reset

-- todo: other namespace -> typesetters

nodes.stripping  = nodes.stripping  or { } local stripping  = nodes.stripping
stripping.glyphs = stripping.glyphs or { } local glyphs     = stripping.glyphs

local function initialize()
    for k, v in next, chardata do
        if v.category == "cf" and not v.visible and not glyphs[k] then
            glyphs[k] = true
        end
    end
    initialize = nil
end

local function process(what,head,current,char)
    if what == true then
        if trace_stripping then
            report_stripping("deleting %C from text",char)
        end
        head, current = remove_node(head,current,true)
    elseif type(what) == "function" then
        head, current = what(head,current)
        current = getnext(current)
        if trace_stripping then
            report_stripping("processing %C in text",char)
        end
    elseif what then  -- assume node
        head, current = replace_node(head,current,copy_node(what))
        current = getnext(current)
        if trace_stripping then
            report_stripping("replacing %C in text",char)
        end
    end
    return head, current
end

function nodes.handlers.stripping(head) -- use loop
    local current = head
    while current do
        local char, id = isglyph(current)
        if char then
            -- it's more efficient to keep track of what needs to be kept
            local todo = getattr(current,a_stripping)
            if todo == 1 then
                local what = glyphs[char]
                if what then
                    head, current = process(what,head,current,char)
                else -- handling of spacing etc has to be done elsewhere
                    current = getnext(current)
                end
            else
                current = getnext(current)
            end
        else
            current = getnext(current)
        end
    end
    return head
end

local enabled = false

function stripping.set(n) -- number or 'reset'
    if n == v_reset then
        n = unsetvalue
    else
        n = tonumber(n)
        if n then
            if not enabled then
                if initialize then initialize() end
                enableaction("processors","nodes.handlers.stripping")
                enabled = true
            end
        else
            n = unsetvalue
        end
    end
    texsetattribute(a_stripping,n)
end

-- interface

interfaces.implement {
    name      = "setcharacterstripping",
    actions   = stripping.set,
    arguments = "string"
}