summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/typo-ovl.lua
blob: 6f836551dbcbc1294e1c64684647d4844501ecf6 (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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
if not modules then modules = { } end modules ['typo-ovl'] = {
    version   = 1.001,
    comment   = "companion to typo-ovl.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

-- This is dubious code. If you needed it your source is probably bad. We only used
-- in when we had to mark bad content but when cleaning up some project code I decided
-- that it is easier to maintain in the distribution then in a project style. After all,
-- we have hardly any private code. For convenience I hooked it into the existing
-- replacement module (as it used the same code anyway). I did some cleanup.

local next, type = next, type

local context      = context

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

local nodecodes    = nodes.nodecodes
local glyph_code   = nodecodes.glyph
local disc_code    = nodecodes.disc

local getnext      = nuts.getnext
local getid        = nuts.getid
local getdisc      = nuts.getdisc
local getattr      = nuts.getattr
local setattr      = nuts.setattr
local getattrlist  = nuts.getattrlist
local setattrlist  = nuts.setattrlist
local getfield     = nuts.getfield
local setfont      = nuts.setfont

local unsetvalue   = attributes.unsetvalue
local prvattribute = attributes.private

local texgetbox    = tex.getbox
local currentfont  = font.current

local a_overloads  = attributes.private("overloads")
local n_overloads  = 0
local t_overloads  = { }

local overloaded   = { }

local function markasoverload(a)
    local n = prvattribute(a)
    if n then
        overloaded[n] = a
    end
end

attributes.markasoverload = markasoverload

markasoverload("color")
markasoverload("colormodel")
markasoverload("transparency")
markasoverload("case")
markasoverload("negative")
markasoverload("effect")
markasoverload("ruled")
markasoverload("shifted")
markasoverload("kernchars")
markasoverload("kern")
markasoverload("noligature")
markasoverload("viewerlayer")

local function tooverloads(n)
    local current = tonut(n)
    local a = getattrlist(current)
    local s = { }
    while a do
        local n = getfield(a,"number")
        local o = overloaded[n]
        if o then
            local v = getfield(a,"value")
            if v ~= unsetvalue then
                s[n] = v
             -- print(o,n,v)
            end
        end
        a = getnext(a)
    end
    return s
end

attributes.tooverloads = tooverloads

function attributes.applyoverloads(specification,start,stop)
    local current   = tonut(start)
    local processor = specification.processor
    local overloads = specification.processor or getattr(current,a_overloads)
    if overloads and overloads ~= unsetvalue then
        overloads = t_overloads[overloads]
        if not overloads then
            return
        end
    else
        return
    end

    local last    = stop and tonut(stop)
    local oldlist = nil
    local newlist = nil
    local newfont = overloads.font

    local function apply()
        local a = getattrlist(current)
        if a == oldlist then
            setattrlist(current,newlist)
        else
            oldlist = getattrlist(current)
            for k, v in next, overloads do
                if type(v) == "number" then
                    setattr(current,k,v)
                else
                    -- can be: ["font"] = number
                end
            end
            newlist = current -- getattrlist(current)
        end
        if newfont then
            setfont(current,newfont)
        end
    end

    while current do
        local id = getid(current)
        if id == glyph_code then
            apply()
        elseif id == disc_code then
            apply()
            if pre then
                while pre do
                    if getid(pre) == glyph_code then
                        apply()
                    end
                    pre = getnext(pre)
                end
            end
            if post then
                while post do
                    if getid(post) == glyph_code then
                        apply()
                    end
                    post = getnext(post)
                end
            end
            if replace then
                while replace do
                    if getid(replace) == glyph_code then
                        apply()
                    end
                    replace = getnext(replace)
                end
            end
        end
        if current == last then
            break
        end
        current = getnext(current)
    end
end

-- we assume the same highlight so we're global

interfaces.implement {
    name      = "overloadsattribute",
    arguments = { "string", "integer", "integer" },
    actions   = function(name,font,box)
        local samplebox = texgetbox(box)
        local sample    = samplebox and samplebox.list
        local overloads = sample and tooverloads(sample)
        if overloads then
            overloads.font = font > 0 and font or false
            n_overloads = n_overloads + 1
            t_overloads[n_overloads] = overloads
            t_overloads[name] = overloads
            context(n_overloads)
        else
            context(unsetvalue)
        end
    end
}