summaryrefslogtreecommitdiff
path: root/tex/context/base/typo-rep.lua
blob: 95b801e2e7c473f04aa528aa36d9d45b37cd678c (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
133
134
135
136
137
138
139
140
141
142
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 tasks           = nodes.tasks

local nuts            = nodes.nuts
local tonut           = nuts.tonut
local tonode          = nuts.tonode

local getnext         = nuts.getnext
local getchar         = nuts.getchar
local getid           = nuts.getid
local getattr         = nuts.getid

local setattr         = nuts.setattr

local delete_node     = nuts.delete
local replace_node    = nuts.replace
local copy_node       = nuts.copy

local nodecodes       = nodes.nodecodes
local glyph_code      = nodecodes.glyph

local chardata        = characters.data
local collected       = false
local fontdata        = fonts.hashes.identifiers

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 v.visible ~= "yes" then
            if not glyphs[k]  then
                glyphs[k] = true
            end
        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 = delete_node(head,current)
    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)
    head = tonut(head)
    local current, done = head, false
    while current do
        if getid(current) == glyph_code 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 char = getchar(current)
                local what = glyphs[char]
                if what then
                    head, current = process(what,head,current,char)
                    done = true
                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 tonode(head), done
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
                tasks.enableaction("processors","nodes.handlers.stripping")
                enabled = true
            end
        else
            n = unsetvalue
        end
    end
    texsetattribute(a_stripping,n)
end

-- why not in task-ini?

tasks.appendaction("processors","fonts","nodes.handlers.stripping",nil,"nodes.handlers.characters")
tasks.disableaction("processors","nodes.handlers.stripping")

-- interface

commands.setcharacterstripping = stripping.set