1if 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
9local floor = math.floor
10
11local attributes = attributes
12local nodes = nodes
13
14local nuts = nodes.nuts
15
16local getnext = nuts.getnext
17local getprev = nuts.getprev
18local getid = nuts.getid
19local getattr = nuts.getattr
20local getattrs = nuts.getattrs
21local getsubtype = nuts.getsubtype
22local getlist = nuts.getlist
23local setlist = nuts.setlist
24
25local nodecodes = nodes.nodecodes
26local gluecodes = nodes.gluecodes
27local kerncodes = nodes.kerncodes
28
29local glyph_code <const> = nodecodes.glyph
30local disc_code <const> = nodecodes.disc
31local rule_code <const> = nodecodes.rule
32local boundary_code <const> = nodecodes.boundary
33local dir_code <const> = nodecodes.dir
34local math_code <const> = nodecodes.math
35local glue_code <const> = nodecodes.glue
36local penalty_code <const> = nodecodes.penalty
37local kern_code <const> = nodecodes.kern
38local hlist_code <const> = nodecodes.hlist
39local vlist_code <const> = nodecodes.vlist
40
41local userskip_code <const> = gluecodes.userskip
42local spaceskip_code <const> = gluecodes.spaceskip
43local xspaceskip_code <const> = gluecodes.xspaceskip
44local intermathkip_code <const> = gluecodes.intermathskip
45local leaders_code <const> = gluecodes.leaders
46local rightfillskip_code <const> = gluecodes.rightparfillskip
47local righthangskip_code <const> = gluecodes.righthangskip
48
49local fontkern_code <const> = kerncodes.fontkern
50local mathshapekern_code <const> = kerncodes.mathshapekern
51local rightmathslackkern_code <const> = kerncodes.rightmathslackkern
52
53local a_runningtext <const> = attributes.private('runningtext')
54
55local v_yes <const> = interfaces.variables.yes
56local v_all <const> = interfaces.variables.all
57
58local function striprange(first,last)
59 if first and last then
60 if first == last then
61 return first, last
62 end
63 while first and first ~= last do
64 local id = getid(first)
65 if id == glyph_code or id == disc_code or id == dir_code or id == boundary_code then
66 break
67 else
68 first = getnext(first)
69 end
70 end
71 if not first then
72 return nil, nil
73 elseif first == last then
74 return first, last
75 end
76 while last and last ~= first do
77 local id = getid(last)
78 if id == glyph_code or id == disc_code or id == dir_code or id == boundary_code then
79 break
80 else
81 local prev = getprev(last)
82 if prev then
83 last = prev
84 else
85 break
86 end
87 end
88 end
89 if not last then
90 return nil, nil
91 end
92 end
93 return first, last
94end
95
96nuts.striprange = striprange
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118local maxlevel = 1
119
120local ignore = table.setmetatableindex("number")
121
122local function processtricky(attribute,data,flush,head,parent)
123 local n = head
124 if n then
125 local f, l, a, d
126 while n do
127 local id = getid(n)
128 local aa, ra = getattrs(n,attribute,a_runningtext)
129 if id == glyph_code
130
131
132
133 or id == hlist_code
134 or id == vlist_code
135 then
136 if aa and ignore[aa] > 0 then
137 aa = nil
138 end
139 if not aa then
140 if f then
141 head = flush(head,f,l,data[a],1,parent,false)
142 end
143 f, l, a = nil, nil, nil
144 elseif aa == a then
145 if not f then
146 f = n
147 end
148 l = n
149 else
150 if f then
151 head = flush(head,f,l,data[a],1,parent,false)
152 end
153 f, l, a = n, n, aa
154 end
155 if id == hlist_code or id == vlist_code then
156 local list = getlist(n)
157 if list then
158 if a then
159 ignore[a] = ignore[a] + 1
160 end
161 setlist(n,processtricky(attribute,data,flush,list,n))
162 if a then
163 ignore[a] = ignore[a] - 1
164 end
165 end
166 end
167 end
168 n = getnext(n)
169 end
170 if f then
171 head = flush(head,f,l,data[a],1,parent,false)
172 end
173 end
174 return head
175end
176
177local function processwords(nesting,attribute,data,flush,head,parent,skip)
178 local n = head
179 if n then
180 local f, l, a, d, class
181 local continue, leaders, strip, level = false, false, true, -1
182 while n do
183 local id = getid(n)
184 local aa, ra = getattrs(n,attribute,a_runningtext)
185 if ra and ra < 0 then
186 processtricky(attribute,data,flush,head,parent)
187 elseif id == glyph_code
188 or id == disc_code
189 or id == rule_code
190 or id == boundary_code
191 or (ra and id == hlist_code and ra > 0)
192 then
193
194 local dd, ll
195 if aa then
196 dd = data[aa]
197 ll = dd.level or 1
198 if nesting == 1 and ll > maxlevel then
199 maxlevel = ll
200 end
201 if ll == nesting then
202
203 else
204 while true do
205 local nestingvalue = dd.nestingvalue
206 if nestingvalue then
207 dd = dd.nestingdata
208 ll = dd.level
209 if ll == nesting then
210 aa = nestingvalue
211 break
212 end
213 else
214
215 aa = nil
216 dd = nil
217 break
218 end
219 end
220 end
221 end
222
223 if aa and aa ~= skip then
224 if aa == a then
225 if not f then
226 f = n
227 end
228 l = n
229 else
230 if f then
231 if class == aa then
232 head = flush(head,f,l,d,level,parent,false)
233 else
234 head = flush(head,f,l,d,level,parent,strip)
235 end
236 end
237 f, l, a = n, n, aa
238 d = dd
239 class = aa
240 if d then
241 continue = d.continue
242 level = d.level or 1
243 leaders = continue == v_all
244 continue = leaders or continue == v_yes
245 else
246 continue = true
247 level = 1
248 leaders = false
249 end
250 end
251 else
252 if f then
253 head = flush(head,f,l,d,level,parent,strip)
254 end
255 f, l, a = nil, nil, nil
256 end
257 if id == hlist_code then
258 local list = getlist(n)
259 if list then
260 setlist(n,processwords(nesting,attribute,data,flush,list,n,aa))
261 end
262 end
263 goto next
264
265
266
267
268
269 elseif id == kern_code then
270 local subtype = getsubtype(n)
271 if subtype == fontkern_code then
272
273 if f then
274 l = n
275 end
276 goto next
277 else
278 goto rest
279 end
280 elseif id == math_code then
281
282
283 if f then
284 head = flush(head,f,l,d,level,parent,strip)
285 f, l, a = nil, nil, nil
286 end
287 goto next
288 elseif id == hlist_code or id == vlist_code then
289 if f then
290 head = flush(head,f,l,d,level,parent,strip)
291 f, l, a = nil, nil, nil
292 end
293 local list = getlist(n)
294 if list then
295 setlist(n,processwords(nesting,attribute,data,flush,list,n,skip))
296 end
297 goto next
298 elseif id == dir_code then
299 if f then
300 l = n
301 end
302 goto next
303 end
304 ::rest::
305 if f then
306 if continue then
307 if id == penalty_code then
308 l = n
309 goto next
310
311
312
313 elseif id == glue_code then
314
315 local subtype = getsubtype(n)
316 if getattr(n,attribute) and (subtype == userskip_code or subtype == spaceskip_code or subtype == xspaceskip_code or subtype == intermathkip_code or (leaders and subtype >= leaders_code)) then
317 l = n
318 else
319 head = flush(head,f,l,d,level,parent,strip)
320 f, l, a = nil, nil, nil
321 end
322 end
323 else
324 head = flush(head,f,l,d,level,parent,strip)
325 f, l, a = nil, nil, nil
326 end
327 end
328 ::next::
329 n = getnext(n)
330 end
331 if f then
332 head = flush(head,f,l,d,level,parent,strip)
333 end
334 end
335 return head
336end
337
338nuts.processwords = function(attribute,data,flush,head,parent)
339
340 maxlevel = 1
341 head = processwords(1,attribute,data,flush,head,parent)
342 for i=2,maxlevel do
343
344 head = processwords(i,attribute,data,flush,head,parent)
345 end
346 return head
347end
348
349
350
351
352local function processranges(attribute,flush,head,parent,depth,skip)
353 local n = head
354 if n then
355 local f, l, a
356 while n do
357 local id = getid(n)
358 if id == glyph_code or id == rule_code then
359 local aa = getattr(n,attribute)
360
361 if aa then
362 if aa == a then
363 if not f then
364 f = n
365 end
366 l = n
367 else
368 if f then
369 head = flush(head,f,l,a,parent,depth)
370 end
371 f, l, a = n, n, aa
372 end
373 else
374 if f then
375 head = flush(head,f,l,a,parent,depth)
376 end
377 f, l, a = nil, nil, nil
378 end
379 elseif id == disc_code or id == boundary_code then
380 if f then
381 l = n
382 else
383
384 end
385 elseif id == kern_code then
386 if getsubtype(n) == fontkern_code then
387 if f then
388 l = n
389 end
390 end
391
392 elseif id == glue_code then
393
394
395
396
397 elseif id == hlist_code or id == vlist_code then
398 local aa = getattr(n,attribute)
399
400 if aa then
401 if aa == a then
402 if not f then
403 f = n
404 end
405 l = n
406 else
407 if f then
408 head = flush(head,f,l,a,parent,depth), true
409 end
410 f, l, a = n, n, aa
411 end
412 else
413 if f then
414 head = flush(head,f,l,a,parent,depth), true
415 end
416 f, l, a = nil, nil, nil
417 end
418 local list = getlist(n)
419 if list then
420 setlist(n,processranges(attribute,flush,list,n,depth+1,aa))
421 end
422 end
423 n = getnext(n)
424 end
425 if f then
426 head = flush(head,f,l,a,parent,depth)
427 end
428 end
429 return head
430end
431
432nuts.processranges = function(attribute,flush,head,parent)
433 return processranges(attribute,flush,head,parent,0)
434end
435 |