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