1if not modules then modules = { } end modules ['node-aux'] = {
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
10
11local type, tostring = type, tostring
12
13local nodes = nodes
14local context = context
15
16local utfvalues = utf.values
17
18local nodecodes = nodes.nodecodes
19
20local glyph_code = nodecodes.glyph
21local hlist_code = nodecodes.hlist
22local vlist_code = nodecodes.vlist
23local attribute_code = nodecodes.attribute
24local par_code = nodecodes.par
25
26local nuts = nodes.nuts
27local tonut = nuts.tonut
28local tonode = nuts.tonode
29local vianuts = nuts.vianuts
30
31local getbox = nuts.getbox
32local getnext = nuts.getnext
33local getid = nuts.getid
34local getsubtype = nuts.getsubtype
35local getlist = nuts.getlist
36local getattr = nuts.getattr
37local getboth = nuts.getboth
38local getprev = nuts.getprev
39local getwidth = nuts.getwidth
40local setwidth = nuts.setwidth
41local getboxglue = nuts.getboxglue
42local setboxglue = nuts.setboxglue
43
44local setfield = nuts.setfield
45local setattr = nuts.setattr
46local setlink = nuts.setlink
47local setlist = nuts.setlist
48local setnext = nuts.setnext
49local setprev = nuts.setprev
50local setattrlist = nuts.setattrlist
51
52local traversers = nuts.traversers
53local nextnode = traversers.node
54local nextglyph = traversers.glyph
55
56local flushnode = nuts.flush
57local flushlist = nuts.flushlist
58local hpack_nodes = nuts.hpack
59local vpack_nodes = nuts.vpack
60local unsetattribute = nuts.unsetattribute
61
62
63
64local copy_node = nuts.copy
65local find_tail = nuts.tail
66local getbox = nuts.getbox
67local count = nuts.count
68local isglyph = nuts.isglyph
69
70local nodepool = nuts.pool
71local new_glue = nodepool.glue
72local new_glyph = nodepool.glyph
73
74local unsetvalue = attributes.unsetvalue
75
76local current_font = font.current
77
78local texsetbox = tex.setbox
79
80local report_error = logs.reporter("node-aux:error")
81
82local function takebox(id)
83 local box = getbox(id)
84 if box then
85 local list = getlist(box)
86 setlist(box,nil)
87 local copy = copy_node(box)
88 if list then
89 setlist(copy,list)
90 end
91 texsetbox(id,false)
92 return copy
93 end
94end
95
96function nodes.takebox(id)
97 local b = takebox(id)
98 if b then
99 return tonode(b)
100 end
101end
102
103if not nuts.migratebox then
104
105 local setpre = nuts.setpre
106 local setpost = nuts.setpost
107 local getpre = nuts.getpre
108 local getpost = nuts.getpost
109
110 function nuts.migratebox(source,target)
111 setpre(target,getpre(source))
112 setpost(target,getpost(source))
113 setpre(source)
114 setpost(source)
115 end
116
117end
118
119local splitbox = tex.splitbox
120nodes.splitbox = splitbox
121
122function nuts.splitbox(id,height)
123 return tonut(splitbox(id,height))
124end
125
126
127
128
129
130function nuts.takelist(n)
131 local l = getlist(n)
132 setlist(n)
133 flushnode(n)
134 return l
135end
136
137nuts.takebox = takebox
138tex.takebox = nodes.takebox
139
140
141
142local function repackhlist(list,...)
143 local temp, b = hpack_nodes(list,...)
144 list = getlist(temp)
145 setlist(temp)
146 flushnode(temp)
147 return list, b
148end
149
150nuts.repackhlist = repackhlist
151
152function nodes.repackhlist(list,...)
153 local list, b = repackhlist(tonut(list),...)
154 return tonode(list), b
155end
156
157local function setattributes(head,attr,value)
158 for n, id in nextnode, head do
159 setattr(n,attr,value)
160 if id == hlist_node or id == vlist_node then
161 setattributes(getlist(n),attr,value)
162 end
163 end
164end
165
166local function setunsetattributes(head,attr,value)
167 for n, id in nextnode, head do
168 if not getattr(n,attr) then
169 setattr(n,attr,value)
170 end
171 if id == hlist_code or id == vlist_code then
172 setunsetattributes(getlist(n),attr,value)
173 end
174 end
175end
176
177local function unsetattributes(head,attr)
178 for n, id in nextnode, head do
179 setattr(n,attr,unsetvalue)
180 if id == hlist_code or id == vlist_code then
181 unsetattributes(getlist(n),attr)
182 end
183 end
184end
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208local function tonodes(str,fnt,attr)
209 if not str or str == "" then
210 return
211 end
212 local head, tail, space, fnt, template = nil, nil, nil, nil, nil
213 if not fnt then
214 fnt = current_font()
215 elseif type(fnt) ~= "number" and getid(fnt) == glyph_code then
216 fnt, template = nil, tonut(fnt)
217 end
218 for s in utfvalues(str) do
219 local n
220 if s == 32 then
221 if space then
222 n = copy_node(space)
223 elseif fonts then
224 local parameters = fonts.hashes.identifiers[fnt].parameters
225 space = new_glue(parameters.space,parameters.spacestretch,parameters.spaceshrink)
226 n = space
227 end
228 elseif template then
229 n = copy_node(template)
230 setvalue(n,"char",s)
231 else
232 n = new_glyph(fnt,s)
233 end
234 if attr then
235 setattrlist(n,attr)
236 end
237 if head then
238 setlink(tail,n)
239 else
240 head = n
241 end
242 tail = n
243 end
244 return head, tail
245end
246
247nuts.tonodes = tonodes
248
249nodes.tonodes = function(str,fnt,attr)
250 local head, tail = tonodes(str,fnt,attr)
251 return tonode(head), tonode(tail)
252end
253
254local function link(list,currentfont,currentattr,head,tail)
255 for i=1,#list do
256 local n = list[i]
257 if n then
258 local tn = type(n)
259 if tn == "string" then
260 if #tn > 0 then
261 if not currentfont then
262 currentfont = current_font()
263 end
264 local h, t = tonodes(n,currentfont,currentattr)
265 if not h then
266
267 elseif not head then
268 head, tail = h, t
269 else
270 setnext(tail,h)
271 setprev(h,t)
272 tail = t
273 end
274 end
275 elseif tn == "table" then
276 if #tn > 0 then
277 if not currentfont then
278 currentfont = current_font()
279 end
280 head, tail = link(n,currentfont,currentattr,head,tail)
281 end
282 elseif not head then
283 head = n
284 tail = find_tail(n)
285 elseif getid(n) == attribute_code then
286
287 report_error("weird node type in list at index %s:",i)
288 for i=1,#list do
289 local l = list[i]
290 report_error("%3i: %s %S",i,getid(l) == attribute_code and "!" or ">",l)
291 end
292 os.exit()
293 else
294 setlink(tail,n)
295 if getnext(n) then
296 tail = find_tail(n)
297 else
298 tail = n
299 end
300 end
301 else
302
303 end
304 end
305 return head, tail
306end
307
308nuts.link = link
309
310nodes.link = function(list,currentfont,currentattr,head,tail)
311 local head, tail = link(list,currentfont,currentattr,tonut(head),tonut(tail))
312 return tonode(head), tonode(tail)
313end
314
315local function locate(start,wantedid,wantedsubtype)
316 for n, id, subtype in nextnode, start do
317 if id == wantedid then
318 if not wantedsubtype or subtype == wantedsubtype then
319 return n
320 end
321 elseif id == hlist_code or id == vlist_code then
322 local found = locate(getlist(n),wantedid,wantedsubtype)
323 if found then
324 return found
325 end
326 end
327 end
328end
329
330nuts.locate = locate
331
332function nodes.locate(start,wantedid,wantedsubtype)
333 local found = locate(tonut(start),wantedid,wantedsubtype)
334 return found and tonode(found)
335end
336
337local function rehpack(n,width)
338 local head = getlist(n)
339 local size = width or getwidth(n)
340 local temp = hpack_nodes(head,size,"exactly")
341 setwidth(n,size)
342 local set, order, sign = getboxglue(temp)
343 setboxglue(n,set,order,sign)
344 setlist(temp)
345 flushnode(temp)
346 return n
347end
348
349nuts.rehpack = rehpack
350
351function nodes.rehpack(n,...)
352 rehpack(tonut(n),...)
353end
354
355do
356
357 local parcodes = nodes.parcodes
358 local hmodepar_code = parcodes.hmodepar
359 local vmodepar_code = parcodes.vmodepar
360
361 local getnest = tex.getnest
362 local getsubtype = nuts.getsubtype
363
364 function nuts.setparproperty(action,...)
365 local tail = tonut(getnest().tail)
366 while tail do
367 if getid(tail) == par_code then
368 local s = getsubtype(tail)
369 if s == hmodepar_code or s == vmodepar_code then
370 return action(tail,...)
371 else
372
373 end
374 end
375 tail = getprev(tail)
376 end
377 end
378
379 local startofpar = nuts.startofpar
380
381 function nodes.startofpar(n)
382 return startofpar(tonut(n))
383 end
384
385end
386
387function nodes.hpack(h,...) return tonode(hpack_nodes(tonut(h),...)) end
388function nodes.vpack(h,...) return tonode(vpack_nodes(tonut(h),...)) end
389
390
391
392local report_slide = logs.reporter("nodes", "slide")
393
394function nuts.checkslide(head,banner)
395 local c = head
396 local x = nil
397 local b = false
398 while c do
399 local p, n = getboth(c)
400 if p and p ~= x then
401 b = true
402 end
403 x = c
404 c = n
405 end
406 if b then
407 report_slide("")
408 report_slide(banner or "?")
409 report_slide("")
410 c = head
411 x = nil
412 while c do
413 local p, n = getboth(c)
414 report_slide("%s %s",(p and p ~= x and "!") or " ",tostring(tonode(c)))
415 x = c
416 c = getnext(c)
417 end
418 report_slide("")
419 nuts.show(head)
420 report_slide("")
421 nuts.slide(head)
422 end
423end
424 |