node-scn.lua /size: 11 Kb    last modification: 2020-07-01 14:35
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
node-scn
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to node-ini.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
local
floor
=
math
.
floor
10 11
local
attributes
=
attributes
12
local
nodes
=
nodes
13 14
local
nuts
=
nodes
.
nuts
15 16
local
getnext
=
nuts
.
getnext
17
local
getprev
=
nuts
.
getprev
18
local
getid
=
nuts
.
getid
19
local
getattr
=
nuts
.
getattr
20
local
getsubtype
=
nuts
.
getsubtype
21
local
getlist
=
nuts
.
getlist
22
local
setlist
=
nuts
.
setlist
23 24
local
end_of_math
=
nuts
.
end_of_math
25 26
local
nodecodes
=
nodes
.
nodecodes
27
local
leadercodes
=
nodes
.
leadercodes
28
local
gluecodes
=
nodes
.
gluecodes
29
local
kerncodes
=
nodes
.
kerncodes
30 31
local
glyph_code
=
nodecodes
.
glyph
32
local
disc_code
=
nodecodes
.
disc
33
local
rule_code
=
nodecodes
.
rule
34
local
boundary_code
=
nodecodes
.
boundary
35
local
dir_code
=
nodecodes
.
dir
36
local
math_code
=
nodecodes
.
math
37
local
glue_code
=
nodecodes
.
glue
38
local
penalty_code
=
nodecodes
.
penalty
39
local
kern_code
=
nodecodes
.
kern
40
local
hlist_code
=
nodecodes
.
hlist
41
local
vlist_code
=
nodecodes
.
vlist
42 43
local
userskip_code
=
gluecodes
.
userskip
44
local
spaceskip_code
=
gluecodes
.
spaceskip
45
local
xspaceskip_code
=
gluecodes
.
xspaceskip
46 47
local
leaders_code
=
leadercodes
.
leaders
48 49
local
fontkern_code
=
kerncodes
.
fontkern
50 51
local
variables
=
interfaces
.
variables
52 53
local
privateattributes
=
attributes
.
private
54 55
local
a_runningtext
=
privateattributes
(
'
runningtext
'
)
56 57
local
v_yes
=
variables
.
yes
58
local
v_all
=
variables
.
all
59 60
local
function
striprange
(
first
,
last
)
-- todo: dir
61
if
first
and
last
then
-- just to be sure
62
if
first
=
=
last
then
63
return
first
,
last
64
end
65
while
first
and
first
~
=
last
do
66
local
id
=
getid
(
first
)
67
if
id
=
=
glyph_code
or
id
=
=
disc_code
or
id
=
=
dir_code
or
id
=
=
boundary_code
then
-- or id == rule_code
68
break
69
else
70
first
=
getnext
(
first
)
71
end
72
end
73
if
not
first
then
74
return
nil
,
nil
75
elseif
first
=
=
last
then
76
return
first
,
last
77
end
78
while
last
and
last
~
=
first
do
79
local
id
=
getid
(
last
)
80
if
id
=
=
glyph_code
or
id
=
=
disc_code
or
id
=
=
dir_code
or
id
=
=
boundary_code
then
-- or id == rule_code
81
break
82
else
83
local
prev
=
getprev
(
last
)
-- luatex < 0.70 has italic correction kern not prev'd
84
if
prev
then
85
last
=
prev
86
else
87
break
88
end
89
end
90
end
91
if
not
last
then
92
return
nil
,
nil
93
end
94
end
95
return
first
,
last
96
end
97 98
nuts
.
striprange
=
striprange
99 100
-- todo: order and maybe other dimensions
101 102
-- we can use this one elsewhere too
103
--
104
-- todo: functions: word, sentence
105
--
106
-- glyph rule unset whatsit glue margin_kern kern math disc
107 108
-- we assume {glyphruns} and no funny extra kerning, ok, maybe we need
109
-- a dummy character as start and end; anyway we only collect glyphs
110
--
111
-- this one needs to take layers into account (i.e. we need a list of
112
-- critical attributes)
113 114
-- omkeren class en level -> scheelt functie call in analyze
115 116
-- todo: switching inside math
117 118
-- handlers
119 120
local
function
processwords
(
attribute
,
data
,
flush
,
head
,
parent
,
skip
)
-- we have hlistdir and local dir
121
local
n
=
head
122
if
n
then
123
local
f
,
l
,
a
,
d
,
i
,
class
124
local
continue
,
leaders
,
done
,
strip
,
level
=
false
,
false
,
false
,
true
,
-1
125
while
n
do
126
local
id
=
getid
(
n
)
127
if
id
=
=
glyph_code
or
id
=
=
rule_code
or
(
id
=
=
hlist_code
and
getattr
(
n
,
a_runningtext
)
)
then
128
local
aa
=
getattr
(
n
,
attribute
)
129
if
aa
and
aa
~
=
skip
then
130
if
aa
=
=
a
then
131
if
not
f
then
-- ?
132
f
=
n
133
end
134
l
=
n
135
else
136
-- possible extensions: when in same class then keep spanning
137
local
newlevel
,
newclass
=
floor
(
aa
/
1000
)
,
aa
%
1000
-- will be configurable
138
-- strip = not continue or level == 1 -- 0
139
if
f
then
140
if
class
=
=
newclass
then
-- and newlevel > level then
141
head
,
done
=
flush
(
head
,
f
,
l
,
d
,
level
,
parent
,
false
)
,
true
142
else
143
head
,
done
=
flush
(
head
,
f
,
l
,
d
,
level
,
parent
,
strip
)
,
true
144
end
145
end
146
f
,
l
,
a
=
n
,
n
,
aa
147
level
,
class
=
newlevel
,
newclass
148
d
=
data
[
class
]
149
if
d
then
150
local
c
=
d
.
continue
151
leaders
=
c
=
=
v_all
152
continue
=
leaders
or
c
=
=
v_yes
153
else
154
continue
=
true
155
end
156
end
157
else
158
if
f
then
159
head
,
done
=
flush
(
head
,
f
,
l
,
d
,
level
,
parent
,
strip
)
,
true
160
end
161
f
,
l
,
a
=
nil
,
nil
,
nil
162
end
163
if
id
=
=
hlist_code
then
164
local
list
=
getlist
(
n
)
165
if
list
then
166
setlist
(
n
,
(
processwords
(
attribute
,
data
,
flush
,
list
,
n
,
aa
)
)
)
-- watch ()
167
end
168
end
169
elseif
id
=
=
disc_code
or
id
=
=
boundary_code
then
170
if
f
then
171
l
=
n
172
end
173
elseif
id
=
=
kern_code
and
getsubtype
(
n
)
=
=
fontkern_code
then
174
if
f
then
175
l
=
n
176
end
177
elseif
id
=
=
math_code
then
178
-- otherwise not consistent: a $b$ c vs a $b+c$ d etc
179
-- we need a special (optional) go over math variant
180
if
f
then
181
head
,
done
=
flush
(
head
,
f
,
l
,
d
,
level
,
parent
,
strip
)
,
true
182
f
,
l
,
a
=
nil
,
nil
,
nil
183
end
184
elseif
id
=
=
hlist_code
or
id
=
=
vlist_code
then
185
if
f
then
186
head
,
done
=
flush
(
head
,
f
,
l
,
d
,
level
,
parent
,
strip
)
,
true
187
f
,
l
,
a
=
nil
,
nil
,
nil
188
end
189
local
list
=
getlist
(
n
)
190
if
list
then
191
setlist
(
n
,
(
processwords
(
attribute
,
data
,
flush
,
list
,
n
,
skip
)
)
)
-- watch ()
192
end
193
elseif
id
=
=
dir_code
then
-- only changes in dir, we assume proper boundaries
194
if
f
then
195
l
=
n
196
end
197
elseif
f
then
198
if
continue
then
199
if
id
=
=
penalty_code
then
200
l
=
n
201
-- elseif id == kern_code then
202
-- l = n
203
elseif
id
=
=
glue_code
then
204
-- catch \underbar{a} \underbar{a} (subtype test is needed)
205
local
subtype
=
getsubtype
(
n
)
206
if
getattr
(
n
,
attribute
)
and
(
subtype
=
=
userskip_code
or
subtype
=
=
spaceskip_code
or
subtype
=
=
xspaceskip_code
or
(
leaders
and
subtype
>
=
leaders_code
)
)
then
207
l
=
n
208
else
209
head
,
done
=
flush
(
head
,
f
,
l
,
d
,
level
,
parent
,
strip
)
,
true
210
f
,
l
,
a
=
nil
,
nil
,
nil
211
end
212
end
213
else
214
head
,
done
=
flush
(
head
,
f
,
l
,
d
,
level
,
parent
,
strip
)
,
true
215
f
,
l
,
a
=
nil
,
nil
,
nil
216
end
217
end
218
n
=
getnext
(
n
)
219
end
220
if
f
then
221
head
,
done
=
flush
(
head
,
f
,
l
,
d
,
level
,
parent
,
strip
)
,
true
222
end
223
return
head
,
true
-- todo: done
224
else
225
return
head
,
false
226
end
227
end
228 229
nuts
.
processwords
=
function
(
attribute
,
data
,
flush
,
head
,
parent
)
-- we have hlistdir and local dir
230
return
processwords
(
attribute
,
data
,
flush
,
head
,
parent
)
231
end
232 233
-- works on lines !
234
-- todo: stack because skip can change when nested
235 236
local
function
processranges
(
attribute
,
flush
,
head
,
parent
,
depth
,
skip
)
237
local
n
=
head
238
if
n
then
239
local
f
,
l
,
a
240
local
done
=
false
241
while
n
do
242
local
id
=
getid
(
n
)
243
if
id
=
=
glyph_code
or
id
=
=
rule_code
then
244
local
aa
=
getattr
(
n
,
attribute
)
245
-- if aa and (not skip or aa ~= skip) then
246
if
aa
then
247
if
aa
=
=
a
then
248
if
not
f
then
249
f
=
n
250
end
251
l
=
n
252
else
253
if
f
then
254
head
,
done
=
flush
(
head
,
f
,
l
,
a
,
parent
,
depth
)
,
true
255
end
256
f
,
l
,
a
=
n
,
n
,
aa
257
end
258
else
259
if
f
then
260
head
,
done
=
flush
(
head
,
f
,
l
,
a
,
parent
,
depth
)
,
true
261
end
262
f
,
l
,
a
=
nil
,
nil
,
nil
263
end
264
elseif
id
=
=
disc_code
or
id
=
=
boundary_code
then
265
if
f
then
266
l
=
n
267
else
268
-- weird
269
end
270
elseif
id
=
=
kern_code
and
getsubtype
(
n
)
=
=
fontkern_code
then
271
if
f
then
272
l
=
n
273
end
274
-- elseif id == penalty_code then
275
elseif
id
=
=
glue_code
then
276
-- todo: leaders
277
elseif
id
=
=
hlist_code
or
id
=
=
vlist_code
then
278
local
aa
=
getattr
(
n
,
attribute
)
279
-- if aa and (not skip or aa ~= skip) then
280
if
aa
then
281
if
aa
=
=
a
then
282
if
not
f
then
283
f
=
n
284
end
285
l
=
n
286
else
287
if
f
then
288
head
,
done
=
flush
(
head
,
f
,
l
,
a
,
parent
,
depth
)
,
true
289
end
290
f
,
l
,
a
=
n
,
n
,
aa
291
end
292
else
293
if
f
then
294
head
,
done
=
flush
(
head
,
f
,
l
,
a
,
parent
,
depth
)
,
true
295
end
296
f
,
l
,
a
=
nil
,
nil
,
nil
297
end
298
local
list
=
getlist
(
n
)
299
if
list
then
300
setlist
(
n
,
(
processranges
(
attribute
,
flush
,
list
,
n
,
depth
+
1
,
aa
)
)
)
301
end
302
end
303
n
=
getnext
(
n
)
304
end
305
if
f
then
306
head
,
done
=
flush
(
head
,
f
,
l
,
a
,
parent
,
depth
)
,
true
307
end
308
return
head
,
done
309
else
310
return
head
,
false
311
end
312
end
313 314
nuts
.
processranges
=
function
(
attribute
,
flush
,
head
,
parent
)
-- we have hlistdir and local dir
315
return
processranges
(
attribute
,
flush
,
head
,
parent
,
0
)
316
end
317