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 leaders_code = gluecodes.leaders
44
45local fontkern_code = kerncodes.fontkern
46
47local variables = interfaces.variables
48
49local privateattributes = attributes.private
50
51local a_runningtext = privateattributes('runningtext')
52
53local v_yes = variables.yes
54local v_all = variables.all
55
56local function striprange(first,last)
57 if first and last then
58 if first == last then
59 return first, last
60 end
61 while first and first ~= last do
62 local id = getid(first)
63 if id == glyph_code or id == disc_code or id == dir_code or id == boundary_code then
64 break
65 else
66 first = getnext(first)
67 end
68 end
69 if not first then
70 return nil, nil
71 elseif first == last then
72 return first, last
73 end
74 while last and last ~= first do
75 local id = getid(last)
76 if id == glyph_code or id == disc_code or id == dir_code or id == boundary_code then
77 break
78 else
79 local prev = getprev(last)
80 if prev then
81 last = prev
82 else
83 break
84 end
85 end
86 end
87 if not last then
88 return nil, nil
89 end
90 end
91 return first, last
92end
93
94nuts.striprange = striprange
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116local function processwords(attribute,data,flush,head,parent,skip)
117 local n = head
118 if n then
119 local f, l, a, d, i, class
120 local continue, leaders, done, strip, level = false, false, false, true, -1
121 while n do
122 local id = getid(n)
123 if id == glyph_code or id == rule_code or (id == hlist_code and getattr(n,a_runningtext))
124or id == disc_code or id == boundary_code
125 then
126 local aa = getattr(n,attribute)
127 if aa and aa ~= skip then
128 if aa == a then
129 if not f then
130 f = n
131 end
132 l = n
133 else
134
135 local newlevel, newclass = floor(aa/1000), aa%1000
136
137 if f then
138 if class == newclass then
139 head, done = flush(head,f,l,d,level,parent,false), true
140 else
141 head, done = flush(head,f,l,d,level,parent,strip), true
142 end
143 end
144 f, l, a = n, n, aa
145 level, class = newlevel, newclass
146 d = data[class]
147 if d then
148 local c = d.continue
149 leaders = c == v_all
150 continue = leaders or c == v_yes
151 else
152 continue = true
153 end
154 end
155 else
156 if f then
157 head, done = flush(head,f,l,d,level,parent,strip), true
158 end
159 f, l, a = nil, nil, nil
160 end
161 if id == hlist_code then
162 local list = getlist(n)
163 if list then
164 setlist(n,(processwords(attribute,data,flush,list,n,aa)))
165 end
166 end
167
168
169
170
171 elseif id == kern_code and getsubtype(n) == fontkern_code then
172 if f then
173 l = n
174 end
175 elseif id == math_code then
176
177
178 if f then
179 head, done = flush(head,f,l,d,level,parent,strip), true
180 f, l, a = nil, nil, nil
181 end
182 elseif id == hlist_code or id == vlist_code then
183 if f then
184 head, done = flush(head,f,l,d,level,parent,strip), true
185 f, l, a = nil, nil, nil
186 end
187 local list = getlist(n)
188 if list then
189 setlist(n,(processwords(attribute,data,flush,list,n,skip)))
190 end
191 elseif id == dir_code then
192 if f then
193 l = n
194 end
195 elseif f then
196 if continue then
197 if id == penalty_code then
198 l = n
199
200
201 elseif id == glue_code then
202
203 local subtype = getsubtype(n)
204 if getattr(n,attribute) and (subtype == userskip_code or subtype == spaceskip_code or subtype == xspaceskip_code or (leaders and subtype >= leaders_code)) then
205 l = n
206 else
207 head, done = flush(head,f,l,d,level,parent,strip), true
208 f, l, a = nil, nil, nil
209 end
210 end
211 else
212 head, done = flush(head,f,l,d,level,parent,strip), true
213 f, l, a = nil, nil, nil
214 end
215 end
216 n = getnext(n)
217 end
218 if f then
219 head, done = flush(head,f,l,d,level,parent,strip), true
220 end
221 return head, true
222 else
223 return head, false
224 end
225end
226
227nuts.processwords = function(attribute,data,flush,head,parent)
228 return processwords(attribute,data,flush,head,parent)
229end
230
231
232
233
234local function processranges(attribute,flush,head,parent,depth,skip)
235 local n = head
236 if n then
237 local f, l, a
238 local done = false
239 while n do
240 local id = getid(n)
241 if id == glyph_code or id == rule_code then
242 local aa = getattr(n,attribute)
243
244 if aa then
245 if aa == a then
246 if not f then
247 f = n
248 end
249 l = n
250 else
251 if f then
252 head, done = flush(head,f,l,a,parent,depth), true
253 end
254 f, l, a = n, n, aa
255 end
256 else
257 if f then
258 head, done = flush(head,f,l,a,parent,depth), true
259 end
260 f, l, a = nil, nil, nil
261 end
262 elseif id == disc_code or id == boundary_code then
263 if f then
264 l = n
265 else
266
267 end
268 elseif id == kern_code and getsubtype(n) == fontkern_code then
269 if f then
270 l = n
271 end
272
273 elseif id == glue_code then
274
275 elseif id == hlist_code or id == vlist_code then
276 local aa = getattr(n,attribute)
277
278 if aa then
279 if aa == a then
280 if not f then
281 f = n
282 end
283 l = n
284 else
285 if f then
286 head, done = flush(head,f,l,a,parent,depth), true
287 end
288 f, l, a = n, n, aa
289 end
290 else
291 if f then
292 head, done = flush(head,f,l,a,parent,depth), true
293 end
294 f, l, a = nil, nil, nil
295 end
296 local list = getlist(n)
297 if list then
298 setlist(n,(processranges(attribute,flush,list,n,depth+1,aa)))
299 end
300 end
301 n = getnext(n)
302 end
303 if f then
304 head, done = flush(head,f,l,a,parent,depth), true
305 end
306 return head, done
307 else
308 return head, false
309 end
310end
311
312nuts.processranges = function(attribute,flush,head,parent)
313 return processranges(attribute,flush,head,parent,0)
314end
315 |