typo-ovl.lua /size: 5337 b    last modification: 2020-07-01 14:35
1if not modules then modules = { } end modules ['typo-ovl'] = {
2    version   = 1.001,
3    comment   = "companion to typo-ovl.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 is dubious code. If you needed it your source is probably bad. We only used
10-- in when we had to mark bad content but when cleaning up some project code I decided
11-- that it is easier to maintain in the distribution then in a project style. After all,
12-- we have hardly any private code. For convenience I hooked it into the existing
13-- replacement module (as it used the same code anyway). I did some cleanup.
14
15local next, type = next, type
16
17local context      = context
18
19local nuts         = nodes.nuts
20local tonut        = nodes.tonut
21local tonode       = nodes.tonode
22
23local nodecodes    = nodes.nodecodes
24local glyph_code   = nodecodes.glyph
25local disc_code    = nodecodes.disc
26
27local getnext      = nuts.getnext
28local getid        = nuts.getid
29local getdisc      = nuts.getdisc
30local getattr      = nuts.getattr
31local setattr      = nuts.setattr
32local getattrlist  = nuts.getattrlist
33local setattrlist  = nuts.setattrlist
34local getfield     = nuts.getfield
35local setfont      = nuts.setfont
36
37local nextnode     = nuts.traversers.node
38
39local unsetvalue   = attributes.unsetvalue
40local prvattribute = attributes.private
41
42local texgetbox    = tex.getbox
43local currentfont  = font.current
44
45local a_overloads  = attributes.private("overloads")
46local n_overloads  = 0
47local t_overloads  = { }
48
49local overloaded   = { }
50
51local function markasoverload(a)
52    local n = prvattribute(a)
53    if n then
54        overloaded[n] = a
55    end
56end
57
58attributes.markasoverload = markasoverload
59
60markasoverload("color")
61markasoverload("colormodel")
62markasoverload("transparency")
63markasoverload("case")
64markasoverload("negative")
65markasoverload("effect")
66markasoverload("ruled")
67markasoverload("shifted")
68markasoverload("kernchars")
69markasoverload("kern")
70markasoverload("noligature")
71markasoverload("viewerlayer")
72
73local function tooverloads(n)
74    local current = tonut(n)
75    local a = getattrlist(current)
76    local s = { }
77    while a do
78        local n = getfield(a,"number")
79        local o = overloaded[n]
80        if o then
81            local v = getfield(a,"value")
82            if v ~= unsetvalue then
83                s[n] = v
84             -- print(o,n,v)
85            end
86        end
87        a = getnext(a)
88    end
89    return s
90end
91
92attributes.tooverloads = tooverloads
93
94function attributes.applyoverloads(specification,start,stop)
95    local start     = tonut(start)
96    local processor = specification.processor
97    local overloads = specification.processor or getattr(start,a_overloads)
98    if overloads and overloads ~= unsetvalue then
99        overloads = t_overloads[overloads]
100        if not overloads then
101            return
102        end
103    else
104        return
105    end
106
107    local last    = stop and tonut(stop)
108    local oldlist = nil
109    local newlist = nil
110    local newfont = overloads.font
111
112    local function apply(current)
113        local a = getattrlist(current)
114        if a == oldlist then
115            setattrlist(current,newlist)
116        else
117            oldlist = getattrlist(current)
118            for k, v in next, overloads do
119                if type(v) == "number" then
120                    setattr(current,k,v)
121                else
122                    -- can be: ["font"] = number
123                end
124            end
125            newlist = current -- getattrlist(current)
126        end
127        if newfont then
128            setfont(current,newfont)
129        end
130    end
131
132    for current, id in nextnode, start do
133        if id == glyph_code then
134            apply(current)
135        elseif id == disc_code then
136            apply(current)
137            if pre then
138                while pre do
139                    if getid(pre) == glyph_code then
140                        apply()
141                    end
142                    pre = getnext(pre)
143                end
144            end
145            if post then
146                while post do
147                    if getid(post) == glyph_code then
148                        apply()
149                    end
150                    post = getnext(post)
151                end
152            end
153            if replace then
154                while replace do
155                    if getid(replace) == glyph_code then
156                        apply()
157                    end
158                    replace = getnext(replace)
159                end
160            end
161        end
162        if current == last then
163            break
164        end
165    end
166end
167
168-- we assume the same highlight so we're global
169
170interfaces.implement {
171    name      = "overloadsattribute",
172    arguments = { "string", "integer", "integer" },
173    actions   = function(name,font,box)
174        local samplebox = texgetbox(box)
175        local sample    = samplebox and samplebox.list
176        local overloads = sample and tooverloads(sample)
177        if overloads then
178            overloads.font = font > 0 and font or false
179            n_overloads = n_overloads + 1
180            t_overloads[n_overloads] = overloads
181            t_overloads[name] = overloads
182            context(n_overloads)
183        else
184            context(unsetvalue)
185        end
186    end
187}
188