math-noa.lua /size: 87 Kb    last modification: 2021-10-28 13:50
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
math-noa
'
]
=
{
2
version
=
1
.
001
,
3
optimize
=
true
,
4
comment
=
"
companion to math-ini.mkiv
"
,
5
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
6
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
7
license
=
"
see context related readme files
"
8
}
9 10
-- beware: this is experimental code and there will be a more generic (attribute value
11
-- driven) interface too but for the moment this is ok (sometime in 2015-2016 i will
12
-- start cleaning up as by then the bigger picture is clear and code has been used for
13
-- years; the main handlers will get some extensions)
14
--
15
-- we will also make dedicated processors (faster)
16
--
17
-- beware: names will change as we wil make noads.xxx.handler i.e. xxx
18
-- subnamespaces
19 20
-- 20D6 -> 2190
21
-- 20D7 -> 2192
22 23
-- todo: most is mathchar_code so we can have simple dedicated loops
24 25
-- nota bene: uunderdelimiter uoverdelimiter etc are radicals (we have 5 types)
26 27
local
next
,
tonumber
=
next
,
tonumber
28
local
utfchar
,
utfbyte
=
utf
.
char
,
utf
.
byte
29
local
formatters
,
gmatch
=
string
.
formatters
,
string
.
gmatch
30
local
sortedhash
=
table
.
sortedhash
31
local
insert
,
remove
=
table
.
insert
,
table
.
remove
32
local
div
,
round
=
math
.
div
,
math
.
round
33
local
bor
,
band
=
bit32
.
bor
,
bit32
.
band
34 35
local
fonts
=
fonts
36
local
nodes
=
nodes
37
local
node
=
node
38
local
mathematics
=
mathematics
39
local
context
=
context
40 41
local
otf
=
fonts
.
handlers
.
otf
42
local
otffeatures
=
fonts
.
constructors
.
features
.
otf
43
local
registerotffeature
=
otffeatures
.
register
44 45
local
privateattribute
=
attributes
.
private
46
local
registertracker
=
trackers
.
register
47
local
registerdirective
=
directives
.
register
48
local
logreporter
=
logs
.
reporter
49
local
setmetatableindex
=
table
.
setmetatableindex
50 51
local
colortracers
=
nodes
.
tracers
.
colors
52 53
local
trace_remapping
=
false
registertracker
(
"
math.remapping
"
,
function
(
v
)
trace_remapping
=
v
end
)
54
local
trace_processing
=
false
registertracker
(
"
math.processing
"
,
function
(
v
)
trace_processing
=
v
end
)
55
local
trace_analyzing
=
false
registertracker
(
"
math.analyzing
"
,
function
(
v
)
trace_analyzing
=
v
end
)
56
local
trace_normalizing
=
false
registertracker
(
"
math.normalizing
"
,
function
(
v
)
trace_normalizing
=
v
end
)
57
local
trace_collapsing
=
false
registertracker
(
"
math.collapsing
"
,
function
(
v
)
trace_collapsing
=
v
end
)
58
local
trace_fixing
=
false
registertracker
(
"
math.fixing
"
,
function
(
v
)
trace_fixing
=
v
end
)
59
local
trace_patching
=
false
registertracker
(
"
math.patching
"
,
function
(
v
)
trace_patching
=
v
end
)
60
local
trace_goodies
=
false
registertracker
(
"
math.goodies
"
,
function
(
v
)
trace_goodies
=
v
end
)
61
local
trace_variants
=
false
registertracker
(
"
math.variants
"
,
function
(
v
)
trace_variants
=
v
end
)
62
local
trace_alternates
=
false
registertracker
(
"
math.alternates
"
,
function
(
v
)
trace_alternates
=
v
end
)
63
local
trace_italics
=
false
registertracker
(
"
math.italics
"
,
function
(
v
)
trace_italics
=
v
end
)
64
local
trace_kernpairs
=
false
registertracker
(
"
math.kernpairs
"
,
function
(
v
)
trace_kernpairs
=
v
end
)
65
local
trace_domains
=
false
registertracker
(
"
math.domains
"
,
function
(
v
)
trace_domains
=
v
end
)
66
local
trace_families
=
false
registertracker
(
"
math.families
"
,
function
(
v
)
trace_families
=
v
end
)
67
local
trace_fences
=
false
registertracker
(
"
math.fences
"
,
function
(
v
)
trace_fences
=
v
end
)
68
local
trace_unstacking
=
false
registertracker
(
"
math.unstack
"
,
function
(
v
)
trace_unstacking
=
v
end
)
69 70
local
check_coverage
=
true
registerdirective
(
"
math.checkcoverage
"
,
function
(
v
)
check_coverage
=
v
end
)
71 72
local
report_processing
=
logreporter
(
"
mathematics
"
,
"
processing
"
)
73
local
report_remapping
=
logreporter
(
"
mathematics
"
,
"
remapping
"
)
74
local
report_normalizing
=
logreporter
(
"
mathematics
"
,
"
normalizing
"
)
75
local
report_collapsing
=
logreporter
(
"
mathematics
"
,
"
collapsing
"
)
76
local
report_fixing
=
logreporter
(
"
mathematics
"
,
"
fixing
"
)
77
local
report_patching
=
logreporter
(
"
mathematics
"
,
"
patching
"
)
78
local
report_goodies
=
logreporter
(
"
mathematics
"
,
"
goodies
"
)
79
local
report_variants
=
logreporter
(
"
mathematics
"
,
"
variants
"
)
80
local
report_alternates
=
logreporter
(
"
mathematics
"
,
"
alternates
"
)
81
local
report_italics
=
logreporter
(
"
mathematics
"
,
"
italics
"
)
82
local
report_kernpairs
=
logreporter
(
"
mathematics
"
,
"
kernpairs
"
)
83
local
report_domains
=
logreporter
(
"
mathematics
"
,
"
domains
"
)
84
local
report_families
=
logreporter
(
"
mathematics
"
,
"
families
"
)
85
local
report_fences
=
logreporter
(
"
mathematics
"
,
"
fences
"
)
86
local
report_unstacking
=
logreporter
(
"
mathematics
"
,
"
unstack
"
)
87 88
local
a_mathrendering
=
privateattribute
(
"
mathrendering
"
)
89
local
a_exportstatus
=
privateattribute
(
"
exportstatus
"
)
90 91
local
nuts
=
nodes
.
nuts
92
local
nodepool
=
nuts
.
pool
93
local
tonut
=
nuts
.
tonut
94
local
nutstring
=
nuts
.
tostring
95 96
local
setfield
=
nuts
.
setfield
97
local
setlink
=
nuts
.
setlink
98
local
setlist
=
nuts
.
setlist
99
local
setnext
=
nuts
.
setnext
100
local
setprev
=
nuts
.
setprev
101
local
setchar
=
nuts
.
setchar
102
local
setfam
=
nuts
.
setfam
103
local
setsubtype
=
nuts
.
setsubtype
104
local
setattr
=
nuts
.
setattr
105
local
setattrlist
=
nuts
.
setattrlist
106
local
setwidth
=
nuts
.
setwidth
107
local
setheight
=
nuts
.
setheight
108
local
setdepth
=
nuts
.
setdepth
109 110
local
getfield
=
nuts
.
getfield
111
local
getnext
=
nuts
.
getnext
112
local
getprev
=
nuts
.
getprev
113
local
getboth
=
nuts
.
getboth
114
local
getid
=
nuts
.
getid
115
local
getsubtype
=
nuts
.
getsubtype
116
local
getchar
=
nuts
.
getchar
117
local
getfont
=
nuts
.
getfont
118
local
getfam
=
nuts
.
getfam
119
local
getattr
=
nuts
.
getattr
120
local
getlist
=
nuts
.
getlist
121
local
getwidth
=
nuts
.
getwidth
122
local
getheight
=
nuts
.
getheight
123
local
getdepth
=
nuts
.
getdepth
124 125
local
getnucleus
=
nuts
.
getnucleus
126
local
getsub
=
nuts
.
getsub
127
local
getsup
=
nuts
.
getsup
128
local
getsubpre
=
nuts
.
getsubpre
129
local
getsuppre
=
nuts
.
getsuppre
130 131
local
setnucleus
=
nuts
.
setnucleus
132
local
setsub
=
nuts
.
setsub
133
local
setsup
=
nuts
.
setsup
134
local
setsubpre
=
nuts
.
setsubpre
135
local
setsuppre
=
nuts
.
setsuppre
136 137
local
flushnode
=
nuts
.
flush
138
local
copy_node
=
nuts
.
copy
139
local
slide_nodes
=
nuts
.
slide
140
local
set_visual
=
nuts
.
setvisual
141 142
local
mlisttohlist
=
nuts
.
mlisttohlist
143 144
local
new_kern
=
nodepool
.
kern
145
local
new_submlist
=
nodepool
.
submlist
146
local
new_noad
=
nodepool
.
noad
147
local
new_delimiter
=
nodepool
.
delimiter
148
local
new_fence
=
nodepool
.
fence
149 150
local
fonthashes
=
fonts
.
hashes
151
local
fontdata
=
fonthashes
.
identifiers
152
local
fontcharacters
=
fonthashes
.
characters
153
local
fontitalics
=
fonthashes
.
italics
154 155
local
variables
=
interfaces
.
variables
156
local
texsetattribute
=
tex
.
setattribute
157
local
texgetattribute
=
tex
.
getattribute
158
local
getfontoffamily
=
tex
.
getfontoffamily
159
local
unsetvalue
=
attributes
.
unsetvalue
160
local
implement
=
interfaces
.
implement
161 162
local
v_reset
=
variables
.
reset
163 164
local
chardata
=
characters
.
data
165 166
noads
=
noads
or
{
}
-- todo: only here
167
local
noads
=
noads
168 169
noads
.
processors
=
noads
.
processors
or
{
}
170
local
processors
=
noads
.
processors
171 172
noads
.
handlers
=
noads
.
handlers
or
{
}
173
local
handlers
=
noads
.
handlers
174 175
local
tasks
=
nodes
.
tasks
176
local
enableaction
=
tasks
.
enableaction
177
local
setaction
=
tasks
.
setaction
178 179
local
nodecodes
=
nodes
.
nodecodes
180
local
noadcodes
=
nodes
.
noadcodes
181
local
fencecodes
=
nodes
.
fencecodes
182 183
local
ordnoad_code
=
noadcodes
.
ord
184
local
opdisplaylimitsnoad_code
=
noadcodes
.
opdisplaylimits
185
local
oplimitsnoad_code
=
noadcodes
.
oplimits
186
local
opnolimitsnoad_code
=
noadcodes
.
opnolimits
187
local
binnoad_code
=
noadcodes
.
bin
188
local
relnode_code
=
noadcodes
.
rel
189
local
opennoad_code
=
noadcodes
.
open
190
local
closenoad_code
=
noadcodes
.
close
191
local
punctnoad_code
=
noadcodes
.
punct
192
local
innernoad_code
=
noadcodes
.
inner
193
local
undernoad_code
=
noadcodes
.
under
194
local
overnoad_code
=
noadcodes
.
over
195
local
vcenternoad_code
=
noadcodes
.
vcenter
196
local
ordlimitsnoad_code
=
noadcodes
.
ordlimits
or
oplimitsnoad_code
197 198
local
noad_code
=
nodecodes
.
noad
-- attr nucleus sub sup
199
local
accent_code
=
nodecodes
.
accent
-- attr nucleus sub sup accent
200
local
radical_code
=
nodecodes
.
radical
-- attr nucleus sub sup left degree
201
local
fraction_code
=
nodecodes
.
fraction
-- attr nucleus sub sup left right
202
local
subbox_code
=
nodecodes
.
subbox
-- attr list
203
local
submlist_code
=
nodecodes
.
submlist
-- attr list
204
local
mathchar_code
=
nodecodes
.
mathchar
-- attr fam char
205
local
mathtextchar_code
=
nodecodes
.
mathtextchar
-- attr fam char
206
local
delimiter_code
=
nodecodes
.
delimiter
-- attr small_fam small_char large_fam large_char
207
----- style_code = nodecodes.style -- attr style
208
----- parameter_code = nodecodes.parameter -- attr style
209
local
math_choice
=
nodecodes
.
choice
-- attr display text script scriptscript
210
local
fence_code
=
nodecodes
.
fence
-- attr subtype
211 212
local
leftfence_code
=
fencecodes
.
left
213
local
middlefence_code
=
fencecodes
.
middle
214
local
rightfence_code
=
fencecodes
.
right
215 216
-- local mathclasses = mathematics.classes
217
-- local fenceclasses = {
218
-- [leftfence_code] = mathclasses.open,
219
-- [middlefence_code] = mathclasses.middle,
220
-- [rightfence_code] = mathclasses.close,
221
-- }
222 223
-- this initial stuff is tricky as we can have removed and new nodes with the same address
224
-- the only way out is a free-per-page list of nodes (not bad anyway)
225 226
-- local gf = getfield local gt = setmetatableindex("number") getfield = function(n,f) gt[f] = gt[f] + 1 return gf(n,f) end mathematics.GETFIELD = gt
227
-- local sf = setfield local st = setmetatableindex("number") setfield = function(n,f,v) st[f] = st[f] + 1 sf(n,f,v) end mathematics.SETFIELD = st
228 229
local
function
process
(
start
,
what
,
n
,
parent
)
230 231
if
n
then
232
n
=
n
+
1
233
else
234
n
=
0
235
end
236
--
237
local
initial
=
start
238
--
239
slide_nodes
(
start
)
-- we still miss a prev in noads -- fences test code
240
--
241
while
start
do
242
local
id
=
getid
(
start
)
243
if
trace_processing
then
244
if
id
=
=
noad_code
then
245
report_processing
(
"
%w%S, class %a
"
,
n
*
2
,
nutstring
(
start
)
,
noadcodes
[
getsubtype
(
start
)
]
)
246
elseif
id
=
=
mathchar_code
then
247
local
char
=
getchar
(
start
)
248
local
font
=
getfont
(
start
)
249
local
fam
=
getfam
(
start
)
250
report_processing
(
"
%w%S, family %a, font %a, char %a, shape %c
"
,
n
*
2
,
nutstring
(
start
)
,
fam
,
font
,
char
,
char
)
251
else
252
report_processing
(
"
%w%S
"
,
n
*
2
,
nutstring
(
start
)
)
253
end
254
end
255
local
proc
=
what
[
id
]
256
if
proc
then
257
-- report_processing("start processing")
258
local
done
,
newstart
,
newinitial
=
proc
(
start
,
what
,
n
,
parent
)
-- prev is bugged: or getprev(start)
259
if
newinitial
then
260
initial
=
newinitial
-- temp hack .. we will make all return head
261
if
newstart
then
262
start
=
newstart
263
-- report_processing("stop processing (new start)")
264
else
265
-- report_processing("quit processing (done)")
266
break
267
end
268
else
269
if
newstart
then
270
start
=
newstart
271
-- report_processing("stop processing (new start)")
272
else
273
-- report_processing("stop processing")
274
end
275
end
276
elseif
id
=
=
noad_code
then
277
-- single characters are like this
278
local
noad
=
getnucleus
(
start
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
279
noad
=
getsup
(
start
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
280
noad
=
getsub
(
start
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
281
if
getsubpre
then
282
noad
=
getsuppre
(
start
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
283
noad
=
getsubpre
(
start
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
284
end
285
elseif
id
=
=
mathchar_code
or
id
=
=
mathtextchar_code
or
id
=
=
delimiter_code
then
286
break
287
elseif
id
=
=
subbox_code
or
id
=
=
submlist_code
then
288
local
noad
=
getlist
(
start
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list (not getlist !)
289
elseif
id
=
=
fraction_code
then
290
local
noad
=
getfield
(
start
,
"
num
"
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
291
noad
=
getfield
(
start
,
"
denom
"
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
292
noad
=
getfield
(
start
,
"
left
"
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- delimiter
293
noad
=
getfield
(
start
,
"
right
"
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- delimiter
294
elseif
id
=
=
math_choice
then
295
local
noad
=
getfield
(
start
,
"
display
"
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
296
noad
=
getfield
(
start
,
"
text
"
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
297
noad
=
getfield
(
start
,
"
script
"
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
298
noad
=
getfield
(
start
,
"
scriptscript
"
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
299
elseif
id
=
=
fence_code
then
300
local
noad
=
getfield
(
start
,
"
delim
"
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- delimiter
301
elseif
id
=
=
radical_code
then
302
local
noad
=
getnucleus
(
start
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
303
noad
=
getsup
(
start
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
304
noad
=
getsub
(
start
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
305
if
getsubpre
then
306
noad
=
getsuppre
(
start
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
307
noad
=
getsubpre
(
start
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
308
end
309
noad
=
getfield
(
start
,
"
left
"
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- delimiter
310
noad
=
getfield
(
start
,
"
degree
"
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
311
elseif
id
=
=
accent_code
then
312
local
noad
=
getnucleus
(
start
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
313
noad
=
getsup
(
start
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
314
noad
=
getsub
(
start
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
315
if
getsubpre
then
316
noad
=
getsuppre
(
start
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
317
noad
=
getsubpre
(
start
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
318
end
319
noad
=
getfield
(
start
,
"
accent
"
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
320
noad
=
getfield
(
start
,
"
bot_accent
"
)
if
noad
then
process
(
noad
,
what
,
n
,
start
)
end
-- list
321
-- elseif id == style_code then
322
-- -- has a next
323
-- elseif id == parameter_code then
324
-- -- has a next
325
-- else
326
-- -- glue, penalty, etc
327
end
328
start
=
getnext
(
start
)
329
end
330
if
not
parent
then
331
return
initial
-- only first level -- for now
332
end
333
end
334 335
local
function
processnested
(
current
,
what
,
n
)
336
local
noad
=
nil
337
local
id
=
getid
(
current
)
338
if
id
=
=
noad_code
then
339
noad
=
getnucleus
(
current
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
340
noad
=
getsup
(
current
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
341
noad
=
getsub
(
current
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
342
if
getsubpre
then
343
noad
=
getsuppre
(
current
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
344
noad
=
getsubpre
(
current
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
345
end
346
elseif
id
=
=
subbox_code
or
id
=
=
submlist_code
then
347
noad
=
getlist
(
current
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list (not getlist !)
348
elseif
id
=
=
fraction_code
then
349
noad
=
getfield
(
current
,
"
num
"
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
350
noad
=
getfield
(
current
,
"
denom
"
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
351
noad
=
getfield
(
current
,
"
left
"
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- delimiter
352
noad
=
getfield
(
current
,
"
right
"
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- delimiter
353
elseif
id
=
=
math_choice
then
354
noad
=
getfield
(
current
,
"
display
"
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
355
noad
=
getfield
(
current
,
"
text
"
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
356
noad
=
getfield
(
current
,
"
script
"
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
357
noad
=
getfield
(
current
,
"
scriptscript
"
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
358
elseif
id
=
=
fence_code
then
359
noad
=
getfield
(
current
,
"
delim
"
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- delimiter
360
elseif
id
=
=
radical_code
then
361
noad
=
getnucleus
(
current
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
362
noad
=
getsup
(
current
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
363
noad
=
getsub
(
current
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
364
if
getsubpre
then
365
noad
=
getsuppre
(
current
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
366
noad
=
getsubpre
(
current
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
367
end
368
noad
=
getfield
(
current
,
"
left
"
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- delimiter
369
noad
=
getfield
(
current
,
"
degree
"
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
370
elseif
id
=
=
accent_code
then
371
noad
=
getnucleus
(
current
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
372
noad
=
getsup
(
current
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
373
noad
=
getsub
(
current
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
374
if
getsubpre
then
375
noad
=
getsuppre
(
current
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
376
noad
=
getsubpre
(
current
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
377
end
378
noad
=
getfield
(
current
,
"
accent
"
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
379
noad
=
getfield
(
current
,
"
bot_accent
"
)
if
noad
then
process
(
noad
,
what
,
n
,
current
)
end
-- list
380
end
381
end
382 383
local
function
processstep
(
current
,
process
,
n
,
id
)
384
local
noad
=
nil
385
local
id
=
id
or
getid
(
current
)
386
if
id
=
=
noad_code
then
387
noad
=
getnucleus
(
current
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
388
noad
=
getsup
(
current
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
389
noad
=
getsub
(
current
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
390
if
getsubpre
then
391
noad
=
getsuppre
(
current
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
392
noad
=
getsubpre
(
current
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
393
end
394
elseif
id
=
=
subbox_code
or
id
=
=
submlist_code
then
395
noad
=
getlist
(
current
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list (not getlist !)
396
elseif
id
=
=
fraction_code
then
397
noad
=
getfield
(
current
,
"
num
"
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
398
noad
=
getfield
(
current
,
"
denom
"
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
399
noad
=
getfield
(
current
,
"
left
"
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- delimiter
400
noad
=
getfield
(
current
,
"
right
"
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- delimiter
401
elseif
id
=
=
math_choice
then
402
noad
=
getfield
(
current
,
"
display
"
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
403
noad
=
getfield
(
current
,
"
text
"
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
404
noad
=
getfield
(
current
,
"
script
"
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
405
noad
=
getfield
(
current
,
"
scriptscript
"
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
406
elseif
id
=
=
fence_code
then
407
noad
=
getfield
(
current
,
"
delim
"
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- delimiter
408
elseif
id
=
=
radical_code
then
409
noad
=
getnucleus
(
current
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
410
noad
=
getsup
(
current
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
411
noad
=
getsub
(
current
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
412
if
getsubpre
then
413
noad
=
getsuppre
(
current
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
414
noad
=
getsubpre
(
current
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
415
end
416
noad
=
getfield
(
current
,
"
left
"
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- delimiter
417
noad
=
getfield
(
current
,
"
degree
"
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
418
elseif
id
=
=
accent_code
then
419
noad
=
getnucleus
(
current
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
420
noad
=
getsup
(
current
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
421
noad
=
getsub
(
current
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
422
if
getsubpre
then
423
noad
=
getsuppre
(
current
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
424
noad
=
getsubpre
(
current
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
425
end
426
noad
=
getfield
(
current
,
"
accent
"
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
427
noad
=
getfield
(
current
,
"
bot_accent
"
)
if
noad
then
process
(
noad
,
n
,
current
)
end
-- list
428
end
429
end
430 431
local
function
processnoads
(
head
,
actions
,
banner
)
432
if
trace_processing
then
433
report_processing
(
"
start %a
"
,
banner
)
434
head
=
process
(
head
,
actions
)
435
report_processing
(
"
stop %a
"
,
banner
)
436
else
437
head
=
process
(
head
,
actions
)
438
end
439
return
head
440
end
441 442
noads
.
process
=
processnoads
443
noads
.
processnested
=
processnested
444
noads
.
processouter
=
process
445 446
-- experiment (when not present fall back to fam 0) -- needs documentation
447 448
local
unknowns
=
{
}
449
local
checked
=
{
}
-- simple case
450
local
tracked
=
false
trackers
.
register
(
"
fonts.missing
"
,
function
(
v
)
tracked
=
v
end
)
451
local
cached
=
setmetatableindex
(
"
table
"
)
-- complex case
452 453
local
function
errorchar
(
font
,
char
)
454
local
done
=
unknowns
[
char
]
455
if
done
then
456
unknowns
[
char
]
=
done
+
1
457
else
458
unknowns
[
char
]
=
1
459
end
460
if
tracked
then
461
-- slower as we check each font too and we always replace as math has
462
-- more demands than text
463
local
fake
=
cached
[
font
]
[
char
]
464
if
fake
then
465
return
fake
466
else
467
local
kind
,
fake
=
fonts
.
checkers
.
placeholder
(
font
,
char
)
468
if
not
fake
or
kind
~
=
"
char
"
then
-- Also check for "with" here?
469
fake
=
0x3F
470
end
471
cached
[
font
]
[
char
]
=
fake
472
return
fake
473
end
474
else
475
-- only simple checking, report at the end so one should take
476
-- action anyway ... we can miss a few checks but that is ok
477
-- as there is at least one reported
478
if
not
checked
[
char
]
then
479
if
trace_normalizing
then
480
report_normalizing
(
"
character %C is not available
"
,
char
)
481
end
482
checked
[
char
]
=
true
483
end
484
return
0x3F
485
end
486
end
487 488
-- 0-2 regular
489
-- 3-5 bold
490
-- 6-8 pseudobold
491 492
-- this could best be integrated in the remapper, and if we run into problems, we
493
-- might as well do this
494 495
do
496 497
local
families
=
{
}
498
local
a_mathfamily
=
privateattribute
(
"
mathfamily
"
)
499
local
boldmap
=
mathematics
.
boldmap
500 501
local
familymap
=
{
[
0
]
=
502
"
regular
"
,
503
"
regular
"
,
504
"
regular
"
,
505
"
bold
"
,
506
"
bold
"
,
507
"
bold
"
,
508
"
pseudobold
"
,
509
"
pseudobold
"
,
510
"
pseudobold
"
,
511
}
512 513
families
[
fraction_code
]
=
function
(
pointer
,
what
,
n
,
parent
)
514
local
a
=
getattr
(
pointer
,
a_mathfamily
)
515
if
a
and
a
>
=
0
then
516
if
a
>
0
then
517
setattr
(
pointer
,
a_mathfamily
,
0
)
518
if
a
>
5
then
519
a
=
a
-
3
520
end
521
end
522
setfam
(
pointer
,
a
)
523
end
524
processnested
(
pointer
,
families
,
n
+
1
)
525
end
526 527
families
[
noad_code
]
=
function
(
pointer
,
what
,
n
,
parent
)
528
local
a
=
getattr
(
pointer
,
a_mathfamily
)
529
if
a
and
a
>
=
0
then
530
if
a
>
0
then
531
setattr
(
pointer
,
a_mathfamily
,
0
)
532
if
a
>
5
then
533
a
=
a
-
3
534
end
535
end
536
setfam
(
pointer
,
a
)
537
end
538
processnested
(
pointer
,
families
,
n
+
1
)
539
end
540 541
families
[
mathchar_code
]
=
function
(
pointer
)
542
if
getfam
(
pointer
)
=
=
0
then
543
local
a
=
getattr
(
pointer
,
a_mathfamily
)
544
if
a
and
a
>
0
then
545
setattr
(
pointer
,
a_mathfamily
,
0
)
546
if
a
>
5
then
547
local
char
=
getchar
(
pointer
)
548
local
bold
=
boldmap
[
char
]
549
local
newa
=
a
-
3
550
if
not
bold
then
551
if
trace_families
then
552
report_families
(
"
no bold replacement for %C, family %s with remap %s becomes %s with remap %s
"
,
char
,
a
,
familymap
[
a
]
,
newa
,
familymap
[
newa
]
)
553
end
554
setfam
(
pointer
,
newa
)
555
elseif
not
fontcharacters
[
getfontoffamily
(
newa
)
]
[
bold
]
then
556
if
trace_families
then
557
report_families
(
"
no bold character for %C, family %s with remap %s becomes %s with remap %s
"
,
char
,
a
,
familymap
[
a
]
,
newa
,
familymap
[
newa
]
)
558
end
559
if
newa
>
3
then
560
setfam
(
pointer
,
newa
-3
)
561
end
562
else
563
setattr
(
pointer
,
a_exportstatus
,
char
)
564
setchar
(
pointer
,
bold
)
565
if
trace_families
then
566
report_families
(
"
replacing %C by bold %C, family %s with remap %s becomes %s with remap %s
"
,
char
,
bold
,
a
,
familymap
[
a
]
,
newa
,
familymap
[
newa
]
)
567
end
568
setfam
(
pointer
,
newa
)
569
end
570
else
571
local
char
=
getchar
(
pointer
)
572
if
not
fontcharacters
[
getfontoffamily
(
a
)
]
[
char
]
then
573
if
trace_families
then
574
report_families
(
"
no bold replacement for %C
"
,
char
)
575
end
576
else
577
if
trace_families
then
578
report_families
(
"
family of %C becomes %s with remap %s
"
,
char
,
a
,
familymap
[
a
]
)
579
end
580
setfam
(
pointer
,
a
)
581
end
582
end
583
end
584
end
585
end
586
families
[
delimiter_code
]
=
function
(
pointer
)
587
if
getfield
(
pointer
,
"
small_fam
"
)
=
=
0
then
588
local
a
=
getattr
(
pointer
,
a_mathfamily
)
589
if
a
and
a
>
0
then
590
setattr
(
pointer
,
a_mathfamily
,
0
)
591
if
a
>
5
then
592
-- no bold delimiters in unicode
593
a
=
a
-
3
594
end
595
local
char
=
getfield
(
pointer
,
"
small_char
"
)
596
local
okay
=
fontcharacters
[
getfontoffamily
(
a
)
]
[
char
]
597
if
okay
then
598
setfield
(
pointer
,
"
small_fam
"
,
a
)
599
elseif
a
>
2
then
600
setfield
(
pointer
,
"
small_fam
"
,
a
-3
)
601
end
602
local
char
=
getfield
(
pointer
,
"
large_char
"
)
603
local
okay
=
fontcharacters
[
getfontoffamily
(
a
)
]
[
char
]
604
if
okay
then
605
setfield
(
pointer
,
"
large_fam
"
,
a
)
606
elseif
a
>
2
then
607
setfield
(
pointer
,
"
large_fam
"
,
a
-3
)
608
end
609
else
610
setfield
(
pointer
,
"
small_fam
"
,
0
)
611
setfield
(
pointer
,
"
large_fam
"
,
0
)
612
end
613
end
614
end
615 616
-- will become:
617 618
-- families[delimiter_code] = function(pointer)
619
-- if getfam(pointer) == 0 then
620
-- local a = getattr(pointer,a_mathfamily)
621
-- if a and a > 0 then
622
-- setattr(pointer,a_mathfamily,0)
623
-- if a > 5 then
624
-- -- no bold delimiters in unicode
625
-- a = a - 3
626
-- end
627
-- local char = getchar(pointer)
628
-- local okay = fontcharacters[getfontoffamily(a)][char]
629
-- if okay then
630
-- setfam(pointer,a)
631
-- elseif a > 2 then
632
-- setfam(pointer,a-3)
633
-- end
634
-- else
635
-- setfam(pointer,0)
636
-- end
637
-- end
638
-- end
639 640
families
[
mathtextchar_code
]
=
families
[
mathchar_code
]
641 642
function
handlers
.
families
(
head
,
style
,
penalties
)
643
processnoads
(
head
,
families
,
"
families
"
)
644
return
true
-- not needed
645
end
646 647
end
648 649
-- character remapping
650 651
do
652 653
local
a_mathalphabet
=
privateattribute
(
"
mathalphabet
"
)
654
local
a_mathgreek
=
privateattribute
(
"
mathgreek
"
)
655 656
local
relocate
=
{
}
657 658
local
remapalphabets
=
mathematics
.
remapalphabets
659
local
fallbackstyleattr
=
mathematics
.
fallbackstyleattr
660
local
setnodecolor
=
colortracers
.
set
661 662
local
function
report_remap
(
tag
,
id
,
old
,
new
,
extra
)
663
report_remapping
(
"
remapping %s in font (%s,%s) from %C to %C%s
"
,
664
tag
,
id
,
fontdata
[
id
]
.
properties
.
fontname
or
"
"
,
old
,
new
,
extra
)
665
end
666 667
local
function
checked
(
pointer
)
668
local
char
=
getchar
(
pointer
)
669
local
font
=
getfont
(
pointer
)
670
local
data
=
fontcharacters
[
font
]
671
if
not
data
[
char
]
then
672
local
specials
=
characters
.
data
[
char
]
.
specials
673
if
specials
and
(
specials
[
1
]
=
=
"
char
"
or
specials
[
1
]
=
=
"
font
"
)
then
674
local
newchar
=
specials
[
#
specials
]
675
if
trace_remapping
then
676
report_remap
(
"
fallback
"
,
font
,
char
,
newchar
)
677
end
678
if
trace_analyzing
then
679
setnodecolor
(
pointer
,
"
font:isol
"
)
680
end
681
setattr
(
pointer
,
a_exportstatus
,
char
)
-- testcase: exponentiale
682
setchar
(
pointer
,
newchar
)
683
return
true
684
end
685
end
686
end
687 688
relocate
[
mathchar_code
]
=
function
(
pointer
)
689
local
g
=
getattr
(
pointer
,
a_mathgreek
)
or
0
690
local
a
=
getattr
(
pointer
,
a_mathalphabet
)
or
0
691
local
char
=
getchar
(
pointer
)
692
local
font
=
getfont
(
pointer
)
693
local
characters
=
fontcharacters
[
font
]
694
if
a
>
0
or
g
>
0
then
695
if
a
>
0
then
696
setattr
(
pointer
,
a_mathgreek
,
0
)
697
end
698
if
g
>
0
then
699
setattr
(
pointer
,
a_mathalphabet
,
0
)
700
end
701
local
newchar
=
remapalphabets
(
char
,
a
,
g
)
702
if
newchar
then
703
local
newchardata
=
characters
[
newchar
]
704
if
newchardata
then
705
if
trace_remapping
then
706
report_remap
(
"
char
"
,
font
,
char
,
newchar
,
newchardata
.
commands
and
"
(virtual)
"
or
"
"
)
707
end
708
if
trace_analyzing
then
709
setnodecolor
(
pointer
,
"
font:isol
"
)
710
end
711
setchar
(
pointer
,
newchar
)
712
return
true
713
else
714
local
fallback
=
fallbackstyleattr
(
a
)
715
if
fallback
then
716
local
newchar
=
remapalphabets
(
char
,
fallback
,
g
)
717
if
newchar
then
718
if
characters
[
newchar
]
then
719
if
trace_remapping
then
720
report_remap
(
"
char
"
,
font
,
char
,
newchar
,
"
(fallback remapping used)
"
)
721
end
722
if
trace_analyzing
then
723
setnodecolor
(
pointer
,
"
font:isol
"
)
724
end
725
setchar
(
pointer
,
newchar
)
726
return
true
727
elseif
trace_remapping
then
728
report_remap
(
"
char
"
,
font
,
char
,
newchar
,
"
fails (no fallback character)
"
)
729
end
730
elseif
trace_remapping
then
731
report_remap
(
"
char
"
,
font
,
char
,
newchar
,
"
fails (no fallback remap character)
"
)
732
end
733
elseif
trace_remapping
then
734
report_remap
(
"
char
"
,
font
,
char
,
newchar
,
"
fails (no fallback style)
"
)
735
end
736
end
737
elseif
trace_remapping
then
738
local
chardata
=
characters
[
char
]
739
if
chardata
and
chardata
.
commands
then
740
report_remap
(
"
char
"
,
font
,
char
,
char
,
"
(virtual)
"
)
741
end
742
end
743
end
744
if
not
characters
[
char
]
then
745
setchar
(
pointer
,
errorchar
(
font
,
char
)
)
746
end
747
if
trace_analyzing
then
748
setnodecolor
(
pointer
,
"
font:medi
"
)
749
end
750
if
check_coverage
then
751
return
checked
(
pointer
)
752
end
753
end
754 755
relocate
[
mathtextchar_code
]
=
function
(
pointer
)
756
if
trace_analyzing
then
757
setnodecolor
(
pointer
,
"
font:init
"
)
758
end
759
end
760 761
relocate
[
delimiter_code
]
=
function
(
pointer
)
762
if
trace_analyzing
then
763
setnodecolor
(
pointer
,
"
font:fina
"
)
764
end
765
end
766 767
function
handlers
.
relocate
(
head
,
style
,
penalties
)
768
processnoads
(
head
,
relocate
,
"
relocate
"
)
769
return
true
-- not needed
770
end
771 772
end
773 774
-- rendering (beware, not exported)
775 776
do
777 778
local
render
=
{
}
779 780
local
rendersets
=
mathematics
.
renderings
.
numbers
or
{
}
-- store
781 782
render
[
mathchar_code
]
=
function
(
pointer
)
783
local
attr
=
getattr
(
pointer
,
a_mathrendering
)
784
if
attr
and
attr
>
0
then
785
local
char
=
getchar
(
pointer
)
786
local
renderset
=
rendersets
[
attr
]
787
if
renderset
then
788
local
newchar
=
renderset
[
char
]
789
if
newchar
then
790
local
font
=
getfont
(
pointer
)
791
local
characters
=
fontcharacters
[
font
]
792
if
characters
and
characters
[
newchar
]
then
793
setchar
(
pointer
,
newchar
)
794
setattr
(
pointer
,
a_exportstatus
,
char
)
795
end
796
end
797
end
798
end
799
end
800 801
function
handlers
.
render
(
head
,
style
,
penalties
)
802
processnoads
(
head
,
render
,
"
render
"
)
803
return
true
-- not needed
804
end
805 806
end
807 808
-- some resize options (this works ok because the content is
809
-- empty and no larger next will be forced)
810
--
811
-- beware: we don't use \delcode but \Udelcode and as such have
812
-- no large_fam; also, we need to check for subtype and/or
813
-- small_fam not being 0 because \. sits in 0,0 by default
814
--
815
-- todo: just replace the character by an ord noad
816
-- and remove the right delimiter as well
817 818
do
819 820
local
a_mathsize
=
privateattribute
(
"
mathsize
"
)
-- this might move into other fence code
821
local
resize
=
{
}
822 823
resize
[
fence_code
]
=
function
(
pointer
)
824
local
subtype
=
getsubtype
(
pointer
)
825
if
subtype
=
=
leftfence_code
or
subtype
=
=
rightfence_code
then
826
local
a
=
getattr
(
pointer
,
a_mathsize
)
827
if
a
and
a
>
0
then
828
local
method
=
div
(
a
,
100
)
829
local
size
=
a
%
100
830
setattr
(
pointer
,
a_mathsize
,
0
)
831
local
delimiter
=
getfield
(
pointer
,
"
delim
"
)
832
local
chr
=
getchar
(
delimiter
)
833
if
chr
>
0
then
834
local
fam
=
getfam
(
delimiter
)
835
local
id
=
getfontoffamily
(
fam
)
836
if
id
>
0
then
837
local
data
=
fontdata
[
id
]
838
local
char
=
mathematics
.
big
(
data
,
chr
,
size
,
method
)
839
local
ht
=
getheight
(
pointer
)
840
local
dp
=
getdepth
(
pointer
)
841
if
ht
=
=
1
or
dp
=
=
1
then
-- 1 scaled point is a signal
842
local
chardata
=
data
.
characters
[
char
]
843
if
ht
=
=
1
then
844
setheight
(
pointer
,
chardata
.
height
)
845
end
846
if
dp
=
=
1
then
847
setdepth
(
pointer
,
chardata
.
depth
)
848
end
849
end
850
if
trace_fences
then
851
report_fences
(
"
replacing %C by %C using method %a and size %a
"
,
chr
,
char
,
method
,
size
)
852
end
853
setchar
(
delimiter
,
char
)
854
end
855
end
856
end
857
end
858
end
859 860
function
handlers
.
resize
(
head
,
style
,
penalties
)
861
processnoads
(
head
,
resize
,
"
resize
"
)
862
return
true
-- not needed
863
end
864 865
end
866 867
-- still not perfect:
868 869
do
870 871
local
a_autofence
=
privateattribute
(
"
mathautofence
"
)
872
local
autofences
=
{
}
873
local
dummyfencechar
=
0x2E
874 875
local
function
makefence
(
what
,
char
)
876
local
d
=
new_delimiter
(
)
-- todo: attr
877
local
f
=
new_fence
(
)
-- todo: attr
878
if
char
then
879
local
sym
=
getnucleus
(
char
)
880
local
chr
=
getchar
(
sym
)
881
local
fam
=
getfam
(
sym
)
882
if
chr
=
=
dummyfencechar
then
883
chr
=
0
884
end
885
setchar
(
d
,
chr
)
886
setfam
(
d
,
fam
)
887
flushnode
(
sym
)
888
end
889
setattrlist
(
d
,
char
)
890
setattrlist
(
f
,
char
)
891
setsubtype
(
f
,
what
)
892
setfield
(
f
,
"
delim
"
,
d
)
893
setfield
(
f
,
"
class
"
,
-1
)
-- tex itself does this, so not fenceclasses[what]
894
return
f
895
end
896 897
local
function
show
(
where
,
pointer
)
898
print
(
"
"
)
899
local
i
=
0
900
for
n
in
nuts
.
traverse
(
pointer
)
do
901
i
=
i
+
1
902
print
(
i
,
where
,
nuts
.
tonode
(
n
)
)
903
end
904
print
(
"
"
)
905
end
906 907
local
function
makelist
(
middle
,
noad
,
f_o
,
o_next
,
c_prev
,
f_c
)
908
-- report_fences(
909
-- "middle %s, noad %s, open %s, opennext %s, closeprev %s, close %s",
910
-- middle or "?",
911
-- noad or "?",
912
-- f_o or "?",
913
-- o_next or "?",
914
-- c_prev or "?",
915
-- f_c or "?"
916
-- )
917
local
list
=
new_submlist
(
)
918
setsubtype
(
noad
,
innernoad_code
)
919
setnucleus
(
noad
,
list
)
920
setlist
(
list
,
f_o
)
921
setlink
(
f_o
,
o_next
)
-- prev of list is nil
922
setlink
(
c_prev
,
f_c
)
-- next of list is nil
923
-- show("list",f_o)
924
if
middle
and
next
(
middle
)
then
925
local
prev
=
f_o
926
local
current
=
o_next
927
while
current
~
=
f_c
do
928
local
midl
=
middle
[
current
]
929
local
next
=
getnext
(
current
)
930
if
midl
then
931
local
fence
=
makefence
(
middlefence_code
,
current
)
932
setnucleus
(
current
)
933
flushnode
(
current
)
934
middle
[
current
]
=
nil
935
-- replace_node
936
setlink
(
prev
,
fence
,
next
)
937
prev
=
fence
938
else
939
prev
=
current
940
end
941
current
=
next
942
end
943
end
944
return
noad
945
end
946 947
-- relinking is now somewhat overdone
948 949
local
function
convert_both
(
open
,
close
,
middle
)
950
local
o_next
=
getnext
(
open
)
951
if
o_next
=
=
close
then
952
return
close
953
else
954
local
c_prev
,
c_next
=
getboth
(
close
)
955
local
f_o
=
makefence
(
leftfence_code
,
open
)
956
local
f_c
=
makefence
(
rightfence_code
,
close
)
957
makelist
(
middle
,
open
,
f_o
,
o_next
,
c_prev
,
f_c
)
958
setnucleus
(
close
)
959
flushnode
(
close
)
960
-- open is now a list
961
setlink
(
open
,
c_next
)
962
return
open
963
end
964
end
965 966
local
function
convert_open
(
open
,
last
,
middle
)
-- last is really last (final case)
967
local
f_o
=
makefence
(
leftfence_code
,
open
)
968
local
f_c
=
makefence
(
rightfence_code
)
969
local
o_next
=
getnext
(
open
)
970
makelist
(
middle
,
open
,
f_o
,
o_next
,
last
,
nil
)
971
-- open is now a list
972
setlink
(
open
,
l_next
)
973
return
open
974
end
975 976
local
function
convert_close
(
first
,
close
,
middle
)
977
local
f_o
=
makefence
(
leftfence_code
)
978
local
f_c
=
makefence
(
rightfence_code
,
close
)
979
local
c_prev
=
getprev
(
close
)
980
local
f_next
=
getnext
(
first
)
981
makelist
(
middle
,
close
,
f_o
,
f_next
,
c_prev
,
f_c
)
982
-- close is now a list
983
if
c_prev
~
=
first
then
984
setlink
(
first
,
close
)
985
end
986
return
close
987
end
988 989
local
stacks
=
setmetatableindex
(
"
table
"
)
990 991
-- 1=open 2=close 3=middle 4=both
992 993
local
function
processfences
(
pointer
,
n
,
parent
)
994
local
current
=
pointer
995
local
last
=
pointer
996
local
start
=
pointer
997
local
done
=
false
998
local
initial
=
pointer
999
local
stack
=
nil
1000
local
middle
=
nil
-- todo: use properties
1001
while
current
do
1002
-- show("before",pointer)
1003
local
id
=
getid
(
current
)
1004
if
id
=
=
noad_code
then
1005
local
a
=
getattr
(
current
,
a_autofence
)
1006
if
a
and
a
>
0
then
1007
local
stack
=
stacks
[
n
]
1008
setattr
(
current
,
a_autofence
,
0
)
-- hm, better use a property
1009
local
level
=
#
stack
1010
if
a
=
=
1
then
1011
if
trace_fences
then
1012
report_fences
(
"
%2i: level %i, handling %s, action %s
"
,
n
,
level
,
"
open
"
,
"
open
"
)
1013
end
1014
insert
(
stack
,
current
)
1015
elseif
a
=
=
2
then
1016
local
open
=
remove
(
stack
)
1017
if
open
then
1018
if
trace_fences
then
1019
report_fences
(
"
%2i: level %i, handling %s, action %s
"
,
n
,
level
,
"
close
"
,
"
both
"
)
1020
end
1021
current
=
convert_both
(
open
,
current
,
middle
)
1022
elseif
current
=
=
start
then
1023
if
trace_fences
then
1024
report_fences
(
"
%2i: level %i, handling %s, action %s
"
,
n
,
level
,
"
close
"
,
"
skip
"
)
1025
end
1026
else
1027
if
trace_fences
then
1028
report_fences
(
"
%2i: level %i, handling %s, action %s
"
,
n
,
level
,
"
close
"
,
"
close
"
)
1029
end
1030
current
=
convert_close
(
initial
,
current
,
middle
)
1031
if
not
parent
then
1032
initial
=
current
1033
end
1034
end
1035
elseif
a
=
=
3
then
1036
if
trace_fences
then
1037
report_fences
(
"
%2i: level %i, handling %s, action %s
"
,
n
,
level
,
"
middle
"
,
"
middle
"
)
1038
end
1039
if
middle
then
1040
middle
[
current
]
=
last
1041
else
1042
middle
=
{
[
current
]
=
last
}
1043
end
1044
elseif
a
=
=
4
then
1045
if
not
stack
or
#
stack
=
=
0
then
1046
if
trace_fences
then
1047
report_fences
(
"
%2i: level %i, handling %s, action %s
"
,
n
,
level
,
"
both
"
,
"
open
"
)
1048
end
1049
insert
(
stack
,
current
)
1050
else
1051
local
open
=
remove
(
stack
)
1052
if
open
then
1053
if
trace_fences
then
1054
report_fences
(
"
%2i: level %i, handling %s, action %s
"
,
n
,
level
,
"
both
"
,
"
both
"
)
1055
end
1056
current
=
convert_both
(
open
,
current
,
middle
)
1057
elseif
current
=
=
start
then
1058
if
trace_fences
then
1059
report_fences
(
"
%2i: level %i, handling %s, action %s
"
,
n
,
level
,
"
both
"
,
"
skip
"
)
1060
end
1061
else
1062
if
trace_fences
then
1063
report_fences
(
"
%2i: level %i, handling %s, action %s
"
,
n
,
level
,
"
both
"
,
"
close
"
)
1064
end
1065
current
=
convert_close
(
initial
,
current
,
middle
)
1066
if
not
parent
then
1067
initial
=
current
1068
end
1069
end
1070
end
1071
end
1072
done
=
true
1073
else
1074
processstep
(
current
,
processfences
,
n
+
1
,
id
)
1075
end
1076
else
1077
-- next at current level
1078
processstep
(
current
,
processfences
,
n
,
id
)
1079
end
1080
-- show("after",pointer)
1081
last
=
current
1082
current
=
getnext
(
current
)
1083
end
1084
if
done
then
1085
local
stack
=
stacks
[
n
]
1086
local
s
=
#
stack
1087
if
s
>
0
then
1088
for
i
=
1
,
s
do
1089
local
open
=
remove
(
stack
)
1090
if
trace_fences
then
1091
report_fences
(
"
%2i: level %i, handling %s, action %s
"
,
n
,
#
stack
,
"
flush
"
,
"
open
"
)
1092
end
1093
last
=
convert_open
(
open
,
last
,
middle
)
1094
end
1095
-- show("done",pointer)
1096
end
1097
end
1098
end
1099 1100
-- we can have a first changed node .. an option is to have a leading dummy node in math
1101
-- lists like the par node as it can save a lot of mess
1102 1103
local
enabled
=
false
1104 1105
implement
{
1106
name
=
"
enableautofences
"
,
1107
onlyonce
=
true
,
1108
actions
=
function
(
)
1109
enableaction
(
"
math
"
,
"
noads.handlers.autofences
"
)
1110
enabled
=
true
1111
end
1112
}
1113 1114
function
handlers
.
autofences
(
head
,
style
,
penalties
)
1115
if
enabled
then
-- tex.modes.c_math_fences_auto
1116
-- inspect(nodes.totree(head))
1117
processfences
(
head
,
1
)
1118
-- inspect(nodes.totree(head))
1119
end
1120
end
1121 1122
end
1123 1124
-- normalize scripts
1125 1126
do
1127 1128
local
unscript
=
{
}
noads
.
processors
.
unscript
=
unscript
1129
local
superscripts
=
characters
.
superscripts
1130
local
subscripts
=
characters
.
subscripts
1131
local
fractions
=
characters
.
fractions
1132
local
replaced
=
{
}
1133 1134
local
function
replace
(
pointer
,
what
,
n
,
parent
)
1135
pointer
=
parent
-- we're following the parent list (chars trigger this)
1136
local
next
=
getnext
(
pointer
)
1137
local
start_super
,
stop_super
,
start_sub
,
stop_sub
1138
local
mode
=
"
unset
"
1139
while
next
and
getid
(
next
)
=
=
noad_code
do
1140
local
nextnucleus
=
getnucleus
(
next
)
1141
if
nextnucleus
and
getid
(
nextnucleus
)
=
=
mathchar_code
and
not
getsub
(
next
)
and
not
getsup
(
next
)
then
1142
local
char
=
getchar
(
nextnucleus
)
1143
local
s
=
superscripts
[
char
]
1144
if
s
then
1145
if
not
start_super
then
1146
start_super
=
next
1147
mode
=
"
super
"
1148
elseif
mode
=
=
"
sub
"
then
1149
break
1150
end
1151
stop_super
=
next
1152
next
=
getnext
(
next
)
1153
setchar
(
nextnucleus
,
s
)
1154
replaced
[
char
]
=
(
replaced
[
char
]
or
0
)
+
1
1155
if
trace_normalizing
then
1156
report_normalizing
(
"
superscript %C becomes %C
"
,
char
,
s
)
1157
end
1158
else
1159
local
s
=
subscripts
[
char
]
1160
if
s
then
1161
if
not
start_sub
then
1162
start_sub
=
next
1163
mode
=
"
sub
"
1164
elseif
mode
=
=
"
super
"
then
1165
break
1166
end
1167
stop_sub
=
next
1168
next
=
getnext
(
next
)
1169
setchar
(
nextnucleus
,
s
)
1170
replaced
[
char
]
=
(
replaced
[
char
]
or
0
)
+
1
1171
if
trace_normalizing
then
1172
report_normalizing
(
"
subscript %C becomes %C
"
,
char
,
s
)
1173
end
1174
else
1175
break
1176
end
1177
end
1178
else
1179
break
1180
end
1181
end
1182
if
start_super
then
1183
if
start_super
=
=
stop_super
then
1184
setsup
(
pointer
,
getnucleus
(
start_super
)
)
1185
else
1186
local
list
=
new_submlist
(
)
-- todo attr
1187
setlist
(
list
,
start_super
)
1188
setsup
(
pointer
,
list
)
1189
end
1190
if
mode
=
=
"
super
"
then
1191
setnext
(
pointer
,
getnext
(
stop_super
)
)
1192
end
1193
setnext
(
stop_super
)
1194
end
1195
if
start_sub
then
1196 1197
-- if mode == "sub" then
1198
-- local sup = getsup(pointer)
1199
-- if sup and not getsub(pointer) then
1200
-- local nxt = getnext(pointer)
1201
-- local new = new_noad(pointer)
1202
-- setnucleus(new,new_submlist())
1203
-- setlink(pointer,new,nxt)
1204
-- pointer = new
1205
-- end
1206
-- end
1207 1208
if
start_sub
=
=
stop_sub
then
1209
setsub
(
pointer
,
getnucleus
(
start_sub
)
)
1210
else
1211
local
list
=
new_submlist
(
)
-- todo attr
1212
setlist
(
list
,
start_sub
)
1213
setsub
(
pointer
,
list
)
1214
end
1215
if
mode
=
=
"
sub
"
then
1216
setnext
(
pointer
,
getnext
(
stop_sub
)
)
1217
end
1218
setnext
(
stop_sub
)
1219
end
1220
-- we could return stop
1221
end
1222 1223
unscript
[
mathchar_code
]
=
replace
-- not noads as we need to recurse
1224 1225
function
handlers
.
unscript
(
head
,
style
,
penalties
)
1226
processnoads
(
head
,
unscript
,
"
unscript
"
)
1227
return
true
-- not needed
1228
end
1229 1230
end
1231 1232
do
1233 1234
local
unstack
=
{
}
noads
.
processors
.
unstack
=
unstack
1235
local
enabled
=
false
1236
local
a_unstack
=
privateattribute
(
"
mathunstack
"
)
1237 1238
unstack
[
noad_code
]
=
function
(
pointer
)
1239
if
getattr
(
pointer
,
a_unstack
)
then
1240
local
sup
=
getsup
(
pointer
)
1241
local
sub
=
getsub
(
pointer
)
1242
if
sup
and
sub
then
1243
-- if trace_unstacking then
1244
-- report_unstacking() -- todo ... what to show ...
1245
-- end
1246
local
nxt
=
getnext
(
pointer
)
1247
local
new
=
new_noad
(
pointer
)
1248
setnucleus
(
new
,
new_submlist
(
)
)
1249
setsub
(
pointer
)
1250
setsub
(
new
,
sub
)
1251
setlink
(
pointer
,
new
,
nxt
)
1252
end
1253
end
1254
end
1255 1256
function
handlers
.
unstack
(
head
,
style
,
penalties
)
1257
if
enabled
then
1258
processnoads
(
head
,
unstack
,
"
unstack
"
)
1259
return
true
-- not needed
1260
end
1261
end
1262 1263
implement
{
1264
name
=
"
enablescriptunstacking
"
,
1265
onlyonce
=
true
,
1266
actions
=
function
(
)
1267
enableaction
(
"
math
"
,
"
noads.handlers.unstack
"
)
1268
enabled
=
true
1269
end
1270
}
1271 1272
end
1273 1274
do
1275 1276
local
function
collected
(
list
)
1277
if
list
and
next
(
list
)
then
1278
local
n
,
t
=
0
,
{
}
1279
for
k
,
v
in
sortedhash
(
list
)
do
1280
n
=
n
+
1
1281
t
[
n
]
=
formatters
[
"
%C
"
]
(
k
)
1282
end
1283
return
formatters
[
"
% t (n=%s)
"
]
(
t
,
n
)
1284
end
1285
end
1286 1287
statistics
.
register
(
"
math script replacements
"
,
function
(
)
1288
return
collected
(
replaced
)
1289
end
)
1290 1291
statistics
.
register
(
"
unknown math characters
"
,
function
(
)
1292
return
collected
(
unknowns
)
1293
end
)
1294 1295
end
1296 1297
-- math alternates: (in xits lgf: $ABC$ $\cal ABC$ $\mathalternate{cal}\cal ABC$)
1298
-- math alternates: (in lucidaot lgf: $ABC \mathalternate{italic} ABC$)
1299 1300
-- todo: set alternate for specific symbols
1301
-- todo: no need to do this when already loaded
1302
-- todo: use a fonts.hashes.mathalternates
1303 1304
do
1305 1306
local
last
=
0
1307 1308
local
known
=
setmetatableindex
(
function
(
t
,
k
)
1309
local
v
=
bor
(
0
,
2
^
last
)
1310
t
[
k
]
=
v
1311
last
=
last
+
1
1312
return
v
1313
end
)
1314 1315
local
defaults
=
{
1316
dotless
=
{
feature
=
'
dtls
'
,
value
=
1
,
comment
=
"
Mathematical Dotless Forms
"
}
,
1317
-- zero = { feature = 'zero', value = 1, comment = "Slashed or Dotted Zero" }, -- in no math font (yet)
1318
}
1319 1320
local
function
initializemathalternates
(
tfmdata
)
1321
local
goodies
=
tfmdata
.
goodies
1322
local
autolist
=
defaults
-- table.copy(defaults)
1323 1324
local
function
setthem
(
newalternates
)
1325
local
resources
=
tfmdata
.
resources
-- was tfmdata.shared
1326
local
mathalternates
=
resources
.
mathalternates
1327
local
alternates
,
attributes
,
registered
,
presets
1328
if
mathalternates
then
1329
alternates
=
mathalternates
.
alternates
1330
attributes
=
mathalternates
.
attributes
1331
registered
=
mathalternates
.
registered
1332
else
1333
alternates
,
attributes
,
registered
=
{
}
,
{
}
,
{
}
1334
mathalternates
=
{
1335
attributes
=
attributes
,
1336
alternates
=
alternates
,
1337
registered
=
registered
,
1338
presets
=
{
}
,
1339
resets
=
{
}
,
1340
hashes
=
setmetatableindex
(
"
table
"
)
1341
}
1342
resources
.
mathalternates
=
mathalternates
1343
end
1344
--
1345
for
name
,
data
in
sortedhash
(
newalternates
)
do
1346
if
alternates
[
name
]
then
1347
-- ignore
1348
else
1349
local
attr
=
known
[
name
]
1350
attributes
[
attr
]
=
data
1351
alternates
[
name
]
=
attr
1352
registered
[
#
registered
+
1
]
=
attr
1353
end
1354
end
1355
end
1356 1357
if
goodies
then
1358
local
done
=
{
}
1359
for
i
=
1
,
#
goodies
do
1360
-- first one counts
1361
-- we can consider sharing the attributes ... todo (only once scan)
1362
local
mathgoodies
=
goodies
[
i
]
.
mathematics
1363
local
alternates
=
mathgoodies
and
mathgoodies
.
alternates
1364
if
alternates
then
1365
if
trace_goodies
then
1366
report_goodies
(
"
loading alternates for font %a
"
,
tfmdata
.
properties
.
name
)
1367
end
1368
for
k
,
v
in
next
,
autolist
do
1369
if
not
alternates
[
k
]
then
1370
alternates
[
k
]
=
v
1371
end
1372
end
1373
setthem
(
alternates
)
1374
return
1375
end
1376
end
1377
end
1378 1379
if
trace_goodies
then
1380
report_goodies
(
"
loading default alternates for font %a
"
,
tfmdata
.
properties
.
name
)
1381
end
1382
setthem
(
autolist
)
1383 1384
end
1385 1386
registerotffeature
{
1387
name
=
"
mathalternates
"
,
1388
description
=
"
additional math alternative shapes
"
,
1389
initializers
=
{
1390
base
=
initializemathalternates
,
1391
node
=
initializemathalternates
,
1392
}
1393
}
1394 1395
-- local getalternate = otf.getalternate (runtime new method so ...)
1396 1397
-- todo: not shared but copies ... one never knows
1398 1399
local
a_mathalternate
=
privateattribute
(
"
mathalternate
"
)
1400
local
alternate
=
{
}
-- processors.alternate = alternate
1401
local
fontdata
=
fonts
.
hashes
.
identifiers
1402
local
fontresources
=
fonts
.
hashes
.
resources
1403 1404
local
function
getalternate
(
fam
,
tag
,
current
)
1405
local
resources
=
fontresources
[
getfontoffamily
(
fam
)
]
1406
local
attribute
=
unsetvalue
1407
if
resources
then
1408
local
mathalternates
=
resources
.
mathalternates
1409
if
mathalternates
then
1410
local
presets
=
mathalternates
.
presets
1411
if
presets
then
1412
local
resets
=
mathalternates
.
resets
1413
attribute
=
presets
[
tag
]
1414
if
not
attribute
then
1415
attribute
=
0
1416
local
alternates
=
mathalternates
.
alternates
1417
for
s
in
gmatch
(
tag
,
"
[^, ]+
"
)
do
1418
if
s
=
=
v_reset
then
1419
resets
[
tag
]
=
true
1420
current
=
unsetvalue
1421
else
1422
local
a
=
alternates
[
s
]
-- or known[s]
1423
if
a
then
1424
attribute
=
bor
(
attribute
,
a
)
1425
end
1426
end
1427
end
1428
if
attribute
=
=
0
then
1429
attribute
=
unsetvalue
1430
end
1431
presets
[
tag
]
=
attribute
1432
elseif
resets
[
tag
]
then
1433
current
=
unsetvalue
1434
end
1435
end
1436
end
1437
end
1438
if
attribute
>
0
and
current
and
current
>
0
then
1439
return
bor
(
current
,
attribute
)
1440
else
1441
return
attribute
1442
end
1443
end
1444 1445
local
function
presetalternate
(
fam
,
tag
)
1446
texsetattribute
(
a_mathalternate
,
getalternate
(
fam
,
tag
)
)
1447
end
1448 1449
implement
{
1450
name
=
"
presetmathalternate
"
,
1451
actions
=
presetalternate
,
1452
arguments
=
{
"
integer
"
,
"
string
"
}
1453
}
1454 1455
local
function
setalternate
(
fam
,
tag
)
1456
local
a
=
texgetattribute
(
a_mathalternate
)
1457
local
v
=
getalternate
(
fam
,
tag
,
a
)
1458
texsetattribute
(
a_mathalternate
,
v
)
1459
end
1460 1461
implement
{
1462
name
=
"
setmathalternate
"
,
1463
actions
=
setalternate
,
1464
arguments
=
{
"
integer
"
,
"
string
"
}
1465
}
1466 1467
alternate
[
mathchar_code
]
=
function
(
pointer
)
-- slow
1468
local
a
=
getattr
(
pointer
,
a_mathalternate
)
1469
if
a
and
a
>
0
then
1470
setattr
(
pointer
,
a_mathalternate
,
0
)
1471
local
fontid
=
getfont
(
pointer
)
1472
local
resources
=
fontresources
[
fontid
]
1473
if
resources
then
1474
local
mathalternates
=
resources
.
mathalternates
1475
if
mathalternates
then
1476
local
attributes
=
mathalternates
.
attributes
1477
local
registered
=
mathalternates
.
registered
1478
local
hashes
=
mathalternates
.
hashes
1479
for
i
=
1
,
#
registered
do
1480
local
r
=
registered
[
i
]
1481
if
band
(
a
,
r
)
~
=
0
then
1482
local
char
=
getchar
(
pointer
)
1483
local
alt
=
hashes
[
i
]
[
char
]
1484
if
alt
=
=
nil
then
1485
local
what
=
attributes
[
r
]
1486
alt
=
otf
.
getalternate
(
fontdata
[
fontid
]
,
char
,
what
.
feature
,
what
.
value
)
or
false
1487
if
alt
=
=
char
then
1488
alt
=
false
1489
end
1490
hashes
[
i
]
[
char
]
=
alt
1491
end
1492
if
alt
then
1493
if
trace_alternates
then
1494
local
what
=
attributes
[
r
]
1495
report_alternates
(
"
alternate %a, value %a, replacing glyph %U by glyph %U
"
,
1496
tostring
(
what
.
feature
)
,
tostring
(
what
.
value
)
,
getchar
(
pointer
)
,
alt
)
1497
end
1498
setchar
(
pointer
,
alt
)
1499
break
1500
end
1501
end
1502
end
1503
end
1504
end
1505
end
1506
end
1507 1508
function
handlers
.
alternates
(
head
,
style
,
penalties
)
1509
processnoads
(
head
,
alternate
,
"
alternate
"
)
1510
return
true
-- not needed
1511
end
1512 1513
end
1514 1515
-- italics: we assume that only characters matter
1516
--
1517
-- = we check for correction first because accessing nodes is slower
1518
-- = the actual glyph is not that important (we can control it with numbers)
1519 1520
-- Italic correction in luatex math is (was) a mess. There are all kind of assumptions based on
1521
-- old fonts and new fonts. Eventually there should be a flag that can signal to ignore all
1522
-- those heuristics. We want to deal with it ourselves also in the perspective of mixed math
1523
-- and text. Also, for a while in context we had to deal with a mix of virtual math fonts and
1524
-- real ones.
1525 1526
-- in opentype the italic correction of a limop is added to the width and luatex does
1527
-- some juggling that we want to avoid but we need to do something here (in fact, we could
1528
-- better fix the width of the character)
1529 1530
do
1531 1532
local
a_mathitalics
=
privateattribute
(
"
mathitalics
"
)
1533 1534
local
italics
=
{
}
1535
local
default_factor
=
1
/
20
1536 1537
local
setcolor
=
colortracers
.
set
1538
local
resetcolor
=
colortracers
.
reset
1539
local
italic_kern
=
new_kern
1540 1541
local
c_positive_d
=
"
trace:dg
"
1542
local
c_negative_d
=
"
trace:dr
"
1543 1544
local
function
insert_kern
(
current
,
kern
)
1545
local
sub
=
new_submlist
(
)
-- todo: attr
1546
local
noad
=
new_noad
(
)
-- todo: attr
1547
setlist
(
sub
,
kern
)
1548
setnext
(
kern
,
noad
)
1549
setnucleus
(
noad
,
current
)
1550
return
sub
1551
end
1552 1553
registertracker
(
"
math.italics.visualize
"
,
function
(
v
)
1554
if
v
then
1555
italic_kern
=
function
(
k
)
1556
local
n
=
new_kern
(
k
)
-- todo: attr
1557
set_visual
(
n
,
"
italic
"
)
1558
return
n
1559
end
1560
else
1561
italic_kern
=
new_kern
1562
end
1563
end
)
1564 1565
local
function
getcorrection
(
method
,
font
,
char
)
-- -- or character.italic -- (this one is for tex)
1566 1567
local
visual
=
chardata
[
char
]
.
visual
1568 1569
if
method
=
=
1
then
1570
-- check on state
1571
local
italics
=
fontitalics
[
font
]
1572
if
italics
then
1573
local
character
=
fontcharacters
[
font
]
[
char
]
1574
if
character
then
1575
local
correction
=
character
.
italic
1576
if
correction
and
correction
~
=
0
then
1577
return
correction
,
visual
1578
end
1579
end
1580
end
1581
elseif
method
=
=
2
then
1582
-- no check
1583
local
character
=
fontcharacters
[
font
]
[
char
]
1584
if
character
then
1585
local
correction
=
character
.
italic
1586
if
correction
and
correction
~
=
0
then
1587
return
correction
,
visual
1588
end
1589
end
1590
elseif
method
=
=
3
then
1591
-- check on visual
1592
if
visual
=
=
"
it
"
or
visual
=
=
"
bi
"
then
1593
local
character
=
fontcharacters
[
font
]
[
char
]
1594
if
character
then
1595
local
correction
=
character
.
italic
1596
if
correction
and
correction
~
=
0
then
1597
return
correction
,
visual
1598
end
1599
end
1600
end
1601
elseif
method
=
=
4
then
1602
-- combination of 1 and 3
1603
local
italics
=
fontitalics
[
font
]
1604
if
italics
and
(
visual
=
=
"
it
"
or
visual
=
=
"
bi
"
)
then
1605
local
character
=
fontcharacters
[
font
]
[
char
]
1606
if
character
then
1607
local
correction
=
character
.
italic
1608
if
correction
and
correction
~
=
0
then
1609
return
correction
,
visual
1610
end
1611
end
1612
end
1613
end
1614 1615
end
1616 1617
italics
[
mathchar_code
]
=
function
(
pointer
,
what
,
n
,
parent
)
1618
local
method
=
getattr
(
pointer
,
a_mathitalics
)
1619
if
method
and
method
>
0
and
method
<
100
then
1620
local
char
=
getchar
(
pointer
)
1621
local
font
=
getfont
(
pointer
)
1622
local
correction
,
visual
=
getcorrection
(
method
,
font
,
char
)
1623
if
correction
and
correction
~
=
0
then
1624
local
next_noad
=
getnext
(
parent
)
1625
if
not
next_noad
then
1626
if
n
=
=
1
then
1627
-- only at the outer level .. will become an option (always,endonly,none)
1628
if
trace_italics
then
1629
report_italics
(
"
method %a, flagging italic correction %p between %C and end math
"
,
method
,
correction
,
char
)
1630
end
1631
if
correction
>
0
then
1632
correction
=
correction
+
100
1633
else
1634
correction
=
correction
-
100
1635
end
1636
correction
=
round
(
correction
)
1637
setattr
(
pointer
,
a_mathitalics
,
correction
)
1638
setattr
(
parent
,
a_mathitalics
,
correction
)
1639
return
-- so no reset later on
1640
end
1641
end
1642
end
1643
end
1644
setattr
(
pointer
,
a_mathitalics
,
unsetvalue
)
1645
end
1646 1647
function
handlers
.
italics
(
head
,
style
,
penalties
)
1648
processnoads
(
head
,
italics
,
"
italics
"
)
1649
return
true
-- not needed
1650
end
1651 1652
local
enable
=
function
(
)
1653
enableaction
(
"
math
"
,
"
noads.handlers.italics
"
)
1654
if
trace_italics
then
1655
report_italics
(
"
enabling math italics
"
)
1656
end
1657
-- we enable math (unless already enabled elsewhere)
1658
typesetters
.
italics
.
enablemath
(
)
1659
enable
=
false
1660
end
1661 1662
-- best do this only on math mode (less overhead)
1663 1664
function
mathematics
.
setitalics
(
name
)
1665
if
enable
then
1666
enable
(
)
1667
end
1668
texsetattribute
(
a_mathitalics
,
name
and
name
~
=
v_reset
and
tonumber
(
name
)
or
unsetvalue
)
-- maybe also v_none
1669
end
1670 1671
function
mathematics
.
getitalics
(
name
)
1672
if
enable
then
1673
enable
(
)
1674
end
1675
context
(
name
and
name
~
=
v_reset
and
tonumber
(
name
)
or
unsetvalue
)
1676
end
1677 1678
function
mathematics
.
resetitalics
(
)
1679
texsetattribute
(
a_mathitalics
,
unsetvalue
)
1680
end
1681 1682
implement
{
1683
name
=
"
initializemathitalics
"
,
1684
actions
=
enable
,
1685
onlyonce
=
true
,
1686
}
1687 1688
implement
{
1689
name
=
"
setmathitalics
"
,
1690
actions
=
mathematics
.
setitalics
,
1691
arguments
=
"
string
"
,
1692
}
1693 1694
implement
{
1695
name
=
"
getmathitalics
"
,
1696
actions
=
mathematics
.
getitalics
,
1697
arguments
=
"
string
"
,
1698
}
1699 1700
implement
{
1701
name
=
"
resetmathitalics
"
,
1702
actions
=
mathematics
.
resetitalics
1703
}
1704 1705
end
1706 1707
do
1708 1709
-- math kerns (experiment) in goodies:
1710
--
1711
-- mathematics = {
1712
-- kernpairs = {
1713
-- [0x1D44E] = {
1714
-- [0x1D44F] = 400, -- 𝑎𝑏
1715
-- }
1716
-- },
1717
-- }
1718 1719
local
a_kernpairs
=
privateattribute
(
"
mathkernpairs
"
)
1720
local
kernpairs
=
{
}
1721 1722
local
function
enable
(
)
1723
enableaction
(
"
math
"
,
"
noads.handlers.kernpairs
"
)
1724
if
trace_kernpairs
then
1725
report_kernpairs
(
"
enabling math kern pairs
"
)
1726
end
1727
enable
=
false
1728
end
1729 1730
implement
{
1731
name
=
"
initializemathkernpairs
"
,
1732
actions
=
enable
,
1733
onlyonce
=
true
,
1734
}
1735 1736
local
hash
=
setmetatableindex
(
function
(
t
,
font
)
1737
local
g
=
fontdata
[
font
]
.
goodies
1738
local
m
=
g
and
g
[
1
]
and
g
[
1
]
.
mathematics
1739
local
k
=
m
and
m
.
kernpairs
1740
t
[
font
]
=
k
1741
return
k
1742
end
)
1743 1744
-- no correction after prime because that moved to a superscript
1745 1746
kernpairs
[
mathchar_code
]
=
function
(
pointer
,
what
,
n
,
parent
)
1747
if
getattr
(
pointer
,
a_kernpairs
)
=
=
1
then
1748
local
font
=
getfont
(
pointer
)
1749
local
list
=
hash
[
font
]
1750
if
list
then
1751
local
first
=
getchar
(
pointer
)
1752
local
found
=
list
[
first
]
1753
if
found
then
1754
local
next
=
getnext
(
parent
)
1755
if
next
and
getid
(
next
)
=
=
noad_code
then
1756
pointer
=
getnucleus
(
next
)
1757
if
pointer
then
1758
if
getfont
(
pointer
)
=
=
font
then
1759
local
second
=
getchar
(
pointer
)
1760
local
kern
=
found
[
second
]
1761
if
kern
then
1762
kern
=
kern
*
fonts
.
hashes
.
parameters
[
font
]
.
hfactor
1763
if
trace_kernpairs
then
1764
report_kernpairs
(
"
adding %p kerning between %C and %C
"
,
kern
,
first
,
second
)
1765
end
1766
setlink
(
parent
,
new_kern
(
kern
)
,
getnext
(
parent
)
)
-- todo: attr
1767
end
1768
end
1769
end
1770
end
1771
end
1772
end
1773
end
1774
end
1775 1776
function
handlers
.
kernpairs
(
head
,
style
,
penalties
)
1777
processnoads
(
head
,
kernpairs
,
"
kernpairs
"
)
1778
return
true
-- not needed
1779
end
1780 1781
end
1782 1783
-- primes and such
1784 1785
do
1786 1787
-- is validpair stil needed?
1788 1789
local
a_mathcollapsing
=
privateattribute
(
"
mathcollapsing
"
)
1790
local
collapse
=
{
}
1791
local
mathlists
=
characters
.
mathlists
1792
local
validpair
=
{
1793
[
ordnoad_code
]
=
true
,
1794
[
opdisplaylimitsnoad_code
]
=
true
,
1795
[
oplimitsnoad_code
]
=
true
,
1796
[
opnolimitsnoad_code
]
=
true
,
1797
[
binnoad_code
]
=
true
,
-- new
1798
[
relnode_code
]
=
true
,
1799
[
opennoad_code
]
=
true
,
-- new
1800
[
closenoad_code
]
=
true
,
-- new
1801
[
punctnoad_code
]
=
true
,
-- new
1802
[
innernoad_code
]
=
false
,
1803
[
undernoad_code
]
=
false
,
1804
[
overnoad_code
]
=
false
,
1805
[
vcenternoad_code
]
=
false
,
1806
[
ordlimitsnoad_code
]
=
true
,
1807
}
1808 1809
local
reported
=
setmetatableindex
(
"
table
"
)
1810 1811
collapse
[
mathchar_code
]
=
function
(
pointer
,
what
,
n
,
parent
)
1812 1813
if
parent
and
mathlists
[
getchar
(
pointer
)
]
then
1814
local
found
,
last
,
lucleus
,
lsup
,
lsub
,
category
1815
local
tree
=
mathlists
1816
local
current
=
parent
1817
while
current
and
validpair
[
getsubtype
(
current
)
]
do
1818
local
nucleus
=
getnucleus
(
current
)
-- == pointer
1819
local
sub
=
getsub
(
current
)
1820
local
sup
=
getsup
(
current
)
1821
local
char
=
getchar
(
nucleus
)
1822
if
char
then
1823
local
match
=
tree
[
char
]
1824
if
match
then
1825
local
method
=
getattr
(
current
,
a_mathcollapsing
)
1826
if
method
and
method
>
0
and
method
<
=
3
then
1827
local
specials
=
match
.
specials
1828
local
mathlist
=
match
.
mathlist
1829
local
ligature
1830
if
method
=
=
1
then
1831
ligature
=
specials
1832
elseif
method
=
=
2
then
1833
ligature
=
specials
or
mathlist
1834
else
-- 3
1835
ligature
=
mathlist
or
specials
1836
end
1837
if
ligature
then
1838
category
=
mathlist
and
"
mathlist
"
or
"
specials
"
1839
found
=
ligature
1840
last
=
current
1841
lucleus
=
nucleus
1842
lsup
=
sup
1843
lsub
=
sub
1844
end
1845
tree
=
match
1846
if
sub
or
sup
then
1847
break
1848
else
1849
current
=
getnext
(
current
)
1850
end
1851
else
1852
break
1853
end
1854
else
1855
break
1856
end
1857
else
1858
break
1859
end
1860
end
1861
if
found
and
last
and
lucleus
then
1862
local
id
=
getfont
(
lucleus
)
1863
local
characters
=
fontcharacters
[
id
]
1864
local
replace
=
characters
and
characters
[
found
]
1865
if
not
replace
then
1866
if
not
reported
[
id
]
[
found
]
then
1867
reported
[
id
]
[
found
]
=
true
1868
report_collapsing
(
"
%s ligature %C from %s
"
,
"
ignoring
"
,
found
,
category
)
1869
end
1870
elseif
trace_collapsing
then
1871
report_collapsing
(
"
%s ligature %C from %s
"
,
"
creating
"
,
found
,
category
)
1872
end
1873
setchar
(
pointer
,
found
)
1874
local
l
=
getnext
(
last
)
1875
local
c
=
getnext
(
parent
)
1876
if
lsub
then
1877
setsub
(
parent
,
lsub
)
1878
setsub
(
last
)
1879
end
1880
if
lsup
then
1881
setsup
(
parent
,
lsup
)
1882
setsup
(
last
)
1883
end
1884
while
c
~
=
l
do
1885
local
n
=
getnext
(
c
)
1886
flushnode
(
c
)
1887
c
=
n
1888
end
1889
setlink
(
parent
,
l
)
1890
end
1891
end
1892
end
1893 1894
function
noads
.
handlers
.
collapse
(
head
,
style
,
penalties
)
1895
processnoads
(
head
,
collapse
,
"
collapse
"
)
1896
return
true
-- not needed
1897
end
1898 1899
local
enable
=
function
(
)
1900
enableaction
(
"
math
"
,
"
noads.handlers.collapse
"
)
1901
if
trace_collapsing
then
1902
report_collapsing
(
"
enabling math collapsing
"
)
1903
end
1904
enable
=
false
1905
end
1906 1907
implement
{
1908
name
=
"
initializemathcollapsing
"
,
1909
actions
=
enable
,
1910
onlyonce
=
true
,
1911
}
1912 1913
end
1914 1915
do
1916
-- inner under over vcenter
1917 1918
local
fixscripts
=
{
}
1919
local
movesub
=
{
1920
-- primes
1921
[
0x2032
]
=
0xFE932
,
1922
[
0x2033
]
=
0xFE933
,
1923
[
0x2034
]
=
0xFE934
,
1924
[
0x2057
]
=
0xFE957
,
1925
-- reverse primes
1926
[
0x2035
]
=
0xFE935
,
1927
[
0x2036
]
=
0xFE936
,
1928
[
0x2037
]
=
0xFE937
,
1929
}
1930 1931
mathematics
.
virtualize
(
movesub
)
1932 1933
local
function
fixsupscript
(
parent
,
current
,
current_char
,
new_char
)
1934
if
new_char
~
=
current_char
and
new_char
~
=
true
then
1935
setchar
(
current
,
new_char
)
1936
if
trace_fixing
then
1937
report_fixing
(
"
fixing subscript, replacing superscript %U by %U
"
,
current_char
,
new_char
)
1938
end
1939
else
1940
if
trace_fixing
then
1941
report_fixing
(
"
fixing subscript, superscript %U
"
,
current_char
)
1942
end
1943
end
1944
setfield
(
parent
,
"
options
"
,
0x08
+
0x22
)
1945
end
1946 1947
-- local function movesubscript(parent,current_nucleus,oldchar,newchar)
1948
-- local prev = getprev(parent)
1949
-- if prev and getid(prev) == noad_code then
1950
-- local psup = getsup(prev)
1951
-- local psub = getsub(prev)
1952
-- if not psup and not psub then
1953
-- fixsupscript(prev,current_nucleus,oldchar,newchar)
1954
-- local nucleus = getnucleus(parent)
1955
-- local sub = getsub(parent)
1956
-- setsup(prev,nucleus)
1957
-- setsub(prev,sub)
1958
-- local dummy = copy_node(nucleus)
1959
-- setchar(dummy,0)
1960
-- setnucleus(parent,dummy)
1961
-- setsub(parent)
1962
-- elseif not psup then
1963
-- fixsupscript(prev,current_nucleus,oldchar,newchar)
1964
-- local nucleus = getnucleus(parent)
1965
-- setsup(prev,nucleus)
1966
-- local dummy = copy_node(nucleus)
1967
-- setchar(dummy,0)
1968
-- setnucleus(parent,dummy)
1969
-- end
1970
-- end
1971
-- end
1972 1973
local
function
move_none_none
(
parent
,
prev
,
nuc
,
oldchar
,
newchar
)
1974
fixsupscript
(
prev
,
nuc
,
oldchar
,
newchar
)
1975
local
sub
=
getsub
(
parent
)
1976
setsup
(
prev
,
nuc
)
1977
setsub
(
prev
,
sub
)
1978
local
dummy
=
copy_node
(
nuc
)
1979
setchar
(
dummy
,
0
)
1980
setnucleus
(
parent
,
dummy
)
1981
setsub
(
parent
)
1982
end
1983 1984
local
function
move_none_psub
(
parent
,
prev
,
nuc
,
oldchar
,
newchar
)
1985
fixsupscript
(
prev
,
nuc
,
oldchar
,
newchar
)
1986
setsup
(
prev
,
nuc
)
1987
local
dummy
=
copy_node
(
nuc
)
1988
setchar
(
dummy
,
0
)
1989
setnucleus
(
parent
,
dummy
)
1990
end
1991 1992
fixscripts
[
mathchar_code
]
=
function
(
pointer
,
what
,
n
,
parent
,
nested
)
-- todo: switch to turn in on and off
1993
if
parent
then
1994
local
oldchar
=
getchar
(
pointer
)
1995
local
newchar
=
movesub
[
oldchar
]
1996
if
newchar
then
1997
local
nuc
=
getnucleus
(
parent
)
1998
if
pointer
=
=
nuc
then
1999
local
sub
=
getsub
(
pointer
)
2000
local
sup
=
getsup
(
pointer
)
2001
if
sub
then
2002
if
sup
then
2003
-- print("[char] sub sup")
2004
else
2005
-- print("[char] sub ---")
2006
end
2007
elseif
sup
then
2008
-- print("[char] --- sup")
2009
else
2010
local
prev
=
getprev
(
parent
)
2011
if
prev
and
getid
(
prev
)
=
=
noad_code
then
2012
local
psub
=
getsub
(
prev
)
2013
local
psup
=
getsup
(
prev
)
2014
if
psub
then
2015
if
psup
then
2016
-- print("sub sup [char] --- ---")
2017
else
2018
-- print("sub --- [char] --- ---")
2019
move_none_psub
(
parent
,
prev
,
nuc
,
oldchar
,
newchar
)
2020
end
2021
elseif
psup
then
2022
-- print("--- sup [char] --- ---")
2023
else
2024
-- print("[char] --- ---")
2025
move_none_none
(
parent
,
prev
,
nuc
,
oldchar
,
newchar
)
2026
end
2027
else
2028
-- print("no prev [char]")
2029
end
2030
end
2031
else
2032
-- print("[char]")
2033
end
2034
end
2035
end
2036
end
2037 2038
function
noads
.
handlers
.
fixscripts
(
head
,
style
,
penalties
)
2039
processnoads
(
head
,
fixscripts
,
"
fixscripts
"
)
2040
return
true
-- not needed
2041
end
2042 2043
end
2044 2045
-- variants
2046 2047
do
2048 2049
local
variants
=
{
}
2050
local
validvariants
=
{
-- fast check on valid
2051
[
0x2229
]
=
0xFE00
,
[
0x222A
]
=
0xFE00
,
2052
[
0x2268
]
=
0xFE00
,
[
0x2269
]
=
0xFE00
,
2053
[
0x2272
]
=
0xFE00
,
[
0x2273
]
=
0xFE00
,
2054
[
0x228A
]
=
0xFE00
,
[
0x228B
]
=
0xFE00
,
2055
[
0x2293
]
=
0xFE00
,
[
0x2294
]
=
0xFE00
,
2056
[
0x2295
]
=
0xFE00
,
2057
[
0x2297
]
=
0xFE00
,
2058
[
0x229C
]
=
0xFE00
,
2059
[
0x22DA
]
=
0xFE00
,
[
0x22DB
]
=
0xFE00
,
2060
[
0x2A3C
]
=
0xFE00
,
[
0x2A3D
]
=
0xFE00
,
2061
[
0x2A9D
]
=
0xFE00
,
[
0x2A9E
]
=
0xFE00
,
2062
[
0x2AAC
]
=
0xFE00
,
[
0x2AAD
]
=
0xFE00
,
2063
[
0x2ACB
]
=
0xFE00
,
[
0x2ACC
]
=
0xFE00
,
2064
}
2065 2066
variants
[
mathchar_code
]
=
function
(
pointer
,
what
,
n
,
parent
)
-- also set export value
2067
local
char
=
getchar
(
pointer
)
2068
local
selector
=
validvariants
[
char
]
2069
if
selector
then
2070
local
next
=
getnext
(
parent
)
2071
if
next
and
getid
(
next
)
=
=
noad_code
then
2072
local
nucleus
=
getnucleus
(
next
)
2073
if
nucleus
and
getid
(
nucleus
)
=
=
mathchar_code
and
getchar
(
nucleus
)
=
=
selector
then
2074
local
variant
2075
local
tfmdata
=
fontdata
[
getfont
(
pointer
)
]
2076
local
mathvariants
=
tfmdata
.
resources
.
variants
-- and variantdata
2077
if
mathvariants
then
2078
mathvariants
=
mathvariants
[
selector
]
2079
if
mathvariants
then
2080
variant
=
mathvariants
[
char
]
2081
end
2082
end
2083
if
variant
then
2084
setchar
(
pointer
,
variant
)
2085
setattr
(
pointer
,
a_exportstatus
,
char
)
-- we don't export the variant as it's visual markup
2086
if
trace_variants
then
2087
report_variants
(
"
variant (%U,%U) replaced by %U
"
,
char
,
selector
,
variant
)
2088
end
2089
else
2090
if
trace_variants
then
2091
report_variants
(
"
no variant (%U,%U)
"
,
char
,
selector
)
2092
end
2093
end
2094
setprev
(
next
,
pointer
)
2095
setnext
(
parent
,
getnext
(
next
)
)
2096
flushnode
(
next
)
2097
end
2098
end
2099
end
2100
end
2101 2102
function
handlers
.
variants
(
head
,
style
,
penalties
)
2103
processnoads
(
head
,
variants
,
"
unicode variant
"
)
2104
return
true
-- not needed
2105
end
2106 2107
end
2108 2109
-- for manuals
2110 2111
do
2112 2113
local
classes
=
{
}
2114
local
colors
=
{
2115
[
relnode_code
]
=
"
trace:dr
"
,
2116
[
ordnoad_code
]
=
"
trace:db
"
,
2117
[
binnoad_code
]
=
"
trace:dg
"
,
2118
[
opennoad_code
]
=
"
trace:dm
"
,
2119
[
closenoad_code
]
=
"
trace:dm
"
,
2120
[
punctnoad_code
]
=
"
trace:dc
"
,
2121
-- [opdisplaylimitsnoad_code] = "",
2122
-- [oplimitsnoad_code] = "",
2123
-- [opnolimitsnoad_code] = "",
2124
-- [ordlimitsnoad_code] = "",
2125
-- [innernoad_code = "",
2126
-- [undernoad_code] = "",
2127
-- [overnoad_code] = "",
2128
-- [vcenternoad_code] = "",
2129
}
2130 2131
local
setcolor
=
colortracers
.
set
2132
local
resetcolor
=
colortracers
.
reset
2133 2134
classes
[
mathchar_code
]
=
function
(
pointer
,
what
,
n
,
parent
)
2135
local
color
=
colors
[
getsubtype
(
parent
)
]
2136
if
color
then
2137
setcolor
(
pointer
,
color
)
2138
else
2139
resetcolor
(
pointer
)
2140
end
2141
end
2142 2143
function
handlers
.
classes
(
head
,
style
,
penalties
)
2144
processnoads
(
head
,
classes
,
"
classes
"
)
2145
return
true
-- not needed
2146
end
2147 2148
registertracker
(
"
math.classes
"
,
function
(
v
)
2149
setaction
(
"
math
"
,
"
noads.handlers.classes
"
,
v
)
2150
end
)
2151 2152
end
2153 2154
-- experimental
2155 2156
do
2157 2158
-- mathematics.registerdomain {
2159
-- name = "foo",
2160
-- parents = { "bar" },
2161
-- characters = {
2162
-- [0x123] = { char = 0x234, class = binary },
2163
-- },
2164
-- }
2165 2166
local
domains
=
{
}
2167
local
categories
=
{
}
2168
local
numbers
=
{
}
2169
local
a_mathdomain
=
privateattribute
(
"
mathdomain
"
)
2170
mathematics
.
domains
=
categories
2171
local
permitted
=
{
2172
ordinary
=
ordnoad_code
,
2173
binary
=
binnoad_code
,
2174
relation
=
relnode_code
,
2175
punctuation
=
punctnoad_code
,
2176
inner
=
innernoad_code
,
2177
}
2178 2179
function
mathematics
.
registerdomain
(
data
)
2180
local
name
=
data
.
name
2181
if
not
name
then
2182
return
2183
end
2184
local
attr
=
#
numbers
+
1
2185
categories
[
name
]
=
data
2186
numbers
[
attr
]
=
data
2187
data
.
attribute
=
attr
2188
-- we delay hashing
2189
return
attr
2190
end
2191 2192
local
enable
2193 2194
enable
=
function
(
)
2195
enableaction
(
"
math
"
,
"
noads.handlers.domains
"
)
2196
if
trace_domains
then
2197
report_domains
(
"
enabling math domains
"
)
2198
end
2199
enable
=
false
2200
end
2201 2202
function
mathematics
.
setdomain
(
name
)
2203
if
enable
then
2204
enable
(
)
2205
end
2206
local
data
=
name
and
name
~
=
v_reset
and
categories
[
name
]
2207
texsetattribute
(
a_mathdomain
,
data
and
data
.
attribute
or
unsetvalue
)
2208
end
2209 2210
function
mathematics
.
getdomain
(
name
)
2211
if
enable
then
2212
enable
(
)
2213
end
2214
local
data
=
name
and
name
~
=
v_reset
and
categories
[
name
]
2215
context
(
data
and
data
.
attribute
or
unsetvalue
)
2216
end
2217 2218
implement
{
2219
name
=
"
initializemathdomain
"
,
2220
actions
=
enable
,
2221
onlyonce
=
true
,
2222
}
2223 2224
implement
{
2225
name
=
"
setmathdomain
"
,
2226
arguments
=
"
string
"
,
2227
actions
=
mathematics
.
setdomain
,
2228
}
2229 2230
implement
{
2231
name
=
"
getmathdomain
"
,
2232
arguments
=
"
string
"
,
2233
actions
=
mathematics
.
getdomain
,
2234
}
2235 2236
local
function
makehash
(
data
)
2237
local
hash
=
{
}
2238
local
parents
=
data
.
parents
2239
if
parents
then
2240
local
function
merge
(
name
)
2241
if
name
then
2242
local
c
=
categories
[
name
]
2243
if
c
then
2244
local
hash
=
c
.
hash
2245
if
not
hash
then
2246
hash
=
makehash
(
c
)
2247
end
2248
for
k
,
v
in
next
,
hash
do
2249
hash
[
k
]
=
v
2250
end
2251
end
2252
end
2253
end
2254
if
type
(
parents
)
=
=
"
string
"
then
2255
merge
(
parents
)
2256
elseif
type
(
parents
)
=
=
"
table
"
then
2257
for
i
=
1
,
#
parents
do
2258
merge
(
parents
[
i
]
)
2259
end
2260
end
2261
end
2262
local
characters
=
data
.
characters
2263
if
characters
then
2264
for
k
,
v
in
next
,
characters
do
2265
-- local chr = n.char
2266
local
cls
=
v
.
class
2267
if
cls
then
2268
v
.
code
=
permitted
[
cls
]
2269
else
2270
-- invalid class
2271
end
2272
hash
[
k
]
=
v
2273
end
2274
end
2275
data
.
hash
=
hash
2276
return
hash
2277
end
2278 2279
domains
[
mathchar_code
]
=
function
(
pointer
,
what
,
n
,
parent
)
2280
local
attr
=
getattr
(
pointer
,
a_mathdomain
)
2281
if
attr
then
2282
local
domain
=
numbers
[
attr
]
2283
if
domain
then
2284
local
hash
=
domain
.
hash
2285
if
not
hash
then
2286
hash
=
makehash
(
domain
)
2287
end
2288
local
char
=
getchar
(
pointer
)
2289
local
okay
=
hash
[
char
]
2290
if
okay
then
2291
local
chr
=
okay
.
char
2292
local
cls
=
okay
.
code
2293
if
chr
and
chr
~
=
char
then
2294
setchar
(
pointer
,
chr
)
2295
end
2296
if
cls
and
cls
~
=
getsubtype
(
parent
)
then
2297
setsubtype
(
parent
,
cls
)
2298
end
2299
end
2300
end
2301
end
2302
end
2303 2304
function
handlers
.
domains
(
head
,
style
,
penalties
)
2305
processnoads
(
head
,
domains
,
"
domains
"
)
2306
return
true
-- not needed
2307
end
2308 2309
end
2310 2311
-- just for me
2312 2313
function
handlers
.
showtree
(
head
,
style
,
penalties
)
2314
inspect
(
nodes
.
totree
(
tonut
(
head
)
)
)
2315
end
2316 2317
registertracker
(
"
math.showtree
"
,
function
(
v
)
2318
setaction
(
"
math
"
,
"
noads.handlers.showtree
"
,
v
)
2319
end
)
2320 2321
-- also for me
2322 2323
do
2324 2325
local
applyvisuals
=
nuts
.
applyvisuals
2326
local
visual
=
false
2327 2328
function
handlers
.
makeup
(
head
)
2329
applyvisuals
(
head
,
visual
)
2330
end
2331 2332
registertracker
(
"
math.makeup
"
,
function
(
v
)
2333
visual
=
v
2334
setaction
(
"
math
"
,
"
noads.handlers.makeup
"
,
v
)
2335
end
)
2336 2337
end
2338 2339
-- the normal builder
2340 2341
do
2342 2343
local
force_penalties
=
false
2344 2345
-- registertracker("math.penalties",function(v)
2346
-- force_penalties = v
2347
-- end)
2348 2349
function
builders
.
kernel
.
mlisttohlist
(
head
,
style
,
penalties
)
2350
return
mlisttohlist
(
head
,
style
,
force_penalties
or
penalties
)
2351
end
2352 2353
implement
{
2354
name
=
"
setmathpenalties
"
,
2355
arguments
=
"
integer
"
,
2356
actions
=
function
(
p
)
2357
force_penalties
=
p
>
0
2358
end
,
2359
}
2360 2361
end
2362 2363
local
actions
=
tasks
.
actions
(
"
math
"
)
-- head, style, penalties
2364 2365
local
starttiming
,
stoptiming
=
statistics
.
starttiming
,
statistics
.
stoptiming
2366 2367
function
processors
.
mlisttohlist
(
head
,
style
,
penalties
)
2368
starttiming
(
noads
)
2369
head
=
actions
(
head
,
style
,
penalties
)
2370
stoptiming
(
noads
)
2371
return
head
2372
end
2373 2374
callbacks
.
register
(
'
mlist_to_hlist
'
,
processors
.
mlisttohlist
,
"
preprocessing math list
"
)
2375 2376
-- tracing
2377 2378
statistics
.
register
(
"
math processing time
"
,
function
(
)
2379
return
statistics
.
elapsedseconds
(
noads
)
2380
end
)
2381