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