1if not modules then modules = { } end modules ['node-nut'] = {
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
11
12
13
14local type, rawget = type, rawget
15
16local nodes = nodes
17local direct = node.direct
18
19local fastcopy = table.fastcopy
20
21local nodecodes = nodes.nodecodes
22local hlist_code <const> = nodecodes.hlist
23local vlist_code <const> = nodecodes.vlist
24local glyph_code <const> = nodecodes.glyph
25
26local tonode = direct.tonode
27local tonut = direct.todirect
28
29local isnode = direct.isnode
30local isnut = direct.isdirect
31local isdirect = direct.isdirect
32
33local d_remove_node = direct.remove
34local d_flushnode = direct.flushnode
35local d_getnext = direct.getnext
36local d_getprev = direct.getprev
37local d_getid = direct.getid
38local d_getlist = direct.getlist
39local d_find_tail = direct.tail
40local d_insertafter = direct.insertafter
41local d_insertbefore = direct.insertbefore
42local d_slide = direct.slide
43local d_traverse = direct.traverse
44local d_setlink = direct.setlink
45local d_getboth = direct.getboth
46
47local nuts = {
48 addmargins = direct.addmargins,
49 addxoffset = direct.addxoffset,
50 addxymargins = direct.addxymargins,
51 addyoffset = direct.addyoffset,
52 append = direct.append,
53 appendaftertail = direct.appendaftertail,
54 checkdiscretionaries = direct.checkdiscretionaries,
55 collapsing = direct.collapsing,
56 copy = direct.copy,
57 copylist = direct.copylist,
58 copynode = direct.copy,
59 copyonly = direct.copyonly,
60 count = direct.count,
61 currentattributes = direct.currentattributes,
62 delete = direct.delete,
63 dimensions = direct.dimensions,
64 effectiveglue = direct.effectiveglue,
65 beginofmath = direct.beginofmath,
66 endofmath = direct.endofmath,
67 exchange = direct.exchange,
68 findattribute = direct.findattribute,
69 findattributerange = direct.findattributerange,
70 findnode = direct.findnode,
71 firstchar = direct.firstchar,
72 firstglyph = direct.firstglyph,
73 firstglyphnode = direct.firstglyphnode,
74 firstitalicglyph = direct.firstitalicglyph,
75 flattendiscretionaries = direct.flattendiscretionaries,
76 flattenleaders = direct.flattenleaders,
77 flush = d_flushnode,
78 flushlist = direct.flushlist,
79 flushnode = d_flushnode,
80 free = direct.free,
81 freeze = direct.freeze,
82 getanchors = direct.getanchors,
83 getattr = direct.getattribute,
84 getattribute = direct.getattribute,
85 getattributelist = direct.getattributelist,
86 getattributes = direct.getattributes,
87 getattrlist = direct.getattributelist,
88 getattrs = direct.getattributes,
89 getboth = d_getboth,
90 getbottom = direct.getbottom,
91 getbottomdelimiter = direct.getbottomdelimiter,
92 getbox = direct.getbox,
93 getboxglue = direct.getglue,
94 getchar = direct.getchar,
95 getchardict = direct.getchardict,
96 getcharspec = direct.getcharspec,
97 getchoice = direct.getchoice,
98 getclass = direct.getclass,
99 getcornerkerns = direct.getcornerkerns,
100 getdata = direct.getdata,
101 getdegree = direct.getdegree,
102 getdelimiter = direct.getdelimiter,
103 getdenominator = direct.getdenominator,
104 getdepth = direct.getdepth,
105 getdir = direct.getdir,
106 getdirection = direct.getdirection,
107 getdisc = direct.getdisc,
108 getdiscpart = direct.getdiscpart,
109 getdiscretionary = direct.getdisc,
110 getexcept = direct.getexcept,
111 getexpansion = direct.getexpansion,
112 getfam = direct.getfam,
113 getfield = direct.getfield,
114 getfont = direct.getfont,
115 getgeometry = direct.getgeometry,
116 getglue = direct.getglue,
117 getglyphdata = direct.getglyphdata,
118 getglyphdimensions = direct.getglyphdimensions,
119 getheight = direct.getheight,
120 getid = d_getid,
121 getidsubtype = direct.getidsubtype,
122 getindex = direct.getindex,
123 getinputfields = direct.getinputfields,
124 getkern = direct.getkern,
125 getkerndimension = direct.getkerndimension,
126 getlang = direct.getlanguage,
127 getlanguage = direct.getlanguage,
128 getleader = direct.getleader,
129 getleftdelimiter = direct.getleftdelimiter,
130 getlist = d_getlist,
131 getlistdimensions = direct.getlistdimensions,
132 getmiddle = direct.getdelimiter,
133 getmiddledelimiter = direct.getdelimiter,
134 getmvllist = direct.getmvllist,
135 getnext = d_getnext,
136 getnormalizedline = direct.getnormalizedline,
137 getnucleus = direct.getnucleus,
138 getnumerator = direct.getnumerator,
139 getoffsets = direct.getoffsets,
140 getoptions = direct.getoptions,
141 getorientation = direct.getorientation,
142 getparstate = direct.getparstate,
143 getpenalty = direct.getpenalty,
144 getpost = direct.getpost,
145 getpre = direct.getpre,
146 getprev = d_getprev,
147 getprime = direct.getprime,
148 getreplace = direct.getreplace,
149 getrightdelimiter = direct.getrightdelimiter,
150 getruledata = direct.getdata,
151 getruledimensions = direct.getruledimensions,
152 getscale = direct.getscale,
153 getscales = direct.getscales,
154 getscript = direct.getscript,
155 getscripts = direct.getscripts,
156 getshift = direct.getshift,
157 getslant = direct.getslant,
158 getspeciallist = direct.getspeciallist,
159 getstate = direct.getstate,
160 getsub = direct.getsub,
161 getsubpre = direct.getsubpre,
162 getsubtype = direct.getsubtype,
163 getsup = direct.getsup,
164 getsuppre = direct.getsuppre,
165 getsurround = direct.getkern,
166 gettop = direct.gettop,
167 gettopdelimiter = direct.gettopdelimiter,
168 gettotal = direct.gettotal,
169 getusedattributes = direct.getusedattributes,
170 getvalue = direct.getdata,
171 getweight = direct.getweight,
172 getwhd = direct.getwhd,
173 getwidth = direct.getwidth,
174 getwordrange = direct.getwordrange,
175 getxscale = direct.getxscale,
176 getxyscales = direct.getxyscales,
177 getyscale = direct.getyscale,
178 gluetostring = direct.gluetostring,
179 hasattribute = direct.hasattribute,
180 hasdimensions = direct.hasdimensions,
181 hasdiscoption = direct.hasdiscoption,
182 hasfield = direct.hasfield,
183 hasgeometry = direct.hasgeometry,
184 hasglyph = direct.hasglyph,
185 hasglyphoption = direct.hasglyphoption,
186 hpack = direct.hpack,
187 hyphenating = direct.hyphenating,
188 ignoremathskip = direct.ignoremathskip,
189 insertafter = d_insertafter,
190 insertbefore = d_insertbefore,
191 isboth = direct.isboth,
192 ischar = direct.ischar,
193 isdirect = isdirect,
194 isglyph = direct.isglyph,
195 isitalicglyph = direct.isitalicglyph,
196 isnext = direct.isnext,
197 isnextchar = direct.isnextchar,
198 isnextglyph = direct.isnextglyph,
199 isnode = isnode,
200 isnut = isdirect,
201 isprev = direct.isprev,
202 isprevchar = direct.isprevchar,
203 isprevglyph = direct.isprevglyph,
204 issimilarglyph = direct.issimilarglyph,
205 iszeroglue = direct.iszeroglue,
206 kerning = direct.kerning,
207 lastnode = direct.lastnode,
208 length = direct.length,
209 ligaturing = direct.ligaturing,
210 makextensible = direct.makextensible,
211 migrate = direct.migrate,
212 mlisttohlist = direct.mlisttohlist,
213 naturalhsize = direct.naturalhsize,
214 naturalwidth = direct.naturalwidth,
215 new = direct.new,
216 newcontinuationatom = direct.newcontinuationatom,
217 newmathglyph = direct.newmathglyph,
218 patchattributes = direct.patchattributes,
219 patchparshape = direct.patchparshape,
220 prependbeforehead = direct.prependbeforehead,
221 protectglyph = direct.protectglyph,
222 protectglyphs = direct.protectglyphs,
223 protectglyphsnone = direct.protectglyphsnone,
224 protrusionskippable = direct.protrusionskippable,
225 rangedimensions = direct.rangedimensions,
226 remove = d_remove_node,
227 removefromlist = direct.removefromlist,
228 repack = direct.repack,
229 reverse = direct.reverse,
230 serialized = direct.serialized,
231 setanchors = direct.setanchors,
232 setattr = direct.setattribute,
233 setattribute = direct.setattribute,
234 setattributelist = direct.setattributelist,
235 setattributes = direct.setattributes,
236 setattrlist = direct.setattributelist,
237 setattrs = direct.setattributes,
238 setboth = direct.setboth,
239 setbottom = direct.setbottom,
240 setbox = direct.setbox,
241 setboxglue = direct.setglue,
242 setchar = direct.setchar,
243 setchardict = direct.setchardict,
244 setchoice = direct.setchoice,
245 setclass = direct.setclass,
246 setdata = direct.setdata,
247 setdegree = direct.setdegree,
248 setdelimiter = direct.setdelimiter,
249 setdenominator = direct.setdenominator,
250 setdepth = direct.setdepth,
251 setdir = direct.setdir,
252 setdirection = direct.setdirection,
253 setdisc = direct.setdisc,
254 setdiscpart = direct.setdiscpart,
255 setdiscretionary = direct.setdisc,
256 setexcept = direct.setexcept,
257 setexpansion = direct.setexpansion,
258 setfam = direct.setfam,
259 setfield = direct.setfield,
260 setfont = direct.setfont,
261 setgeometry = direct.setgeometry,
262 setglue = direct.setglue,
263 setglyphdata = direct.setglyphdata,
264 setheight = direct.setheight,
265 setinputfields = direct.setinputfields,
266 setkern = direct.setkern,
267 setlang = direct.setlanguage,
268 setlanguage = direct.setlanguage,
269 setleader = direct.setleader,
270 setleftdelimiter = direct.setleftdelimiter,
271 setlink = d_setlink,
272 setlist = direct.setlist,
273 setmvllist = direct.setmvllist,
274 setmiddledelimiter = direct.setdelimiter,
275 setnext = direct.setnext,
276 setnucleus = direct.setnucleus,
277 setnumerator = direct.setnumerator,
278 setoffsets = direct.setoffsets,
279 setoptions = direct.setoptions,
280 setorientation = direct.setorientation,
281 setpenalty = direct.setpenalty,
282 setpost = direct.setpost,
283 setpre = direct.setpre,
284 setprev = direct.setprev,
285 setprime = direct.setprime,
286 setreplace = direct.setreplace,
287 setrightdelimiter = direct.setrightdelimiter,
288 setruledata = direct.setdata,
289 setruledimensions = direct.setruledimensions,
290 setscale = direct.setscale or direct.setscales,
291 setscales = direct.setscales,
292 setscript = direct.setscript,
293 setscripts = direct.setscripts,
294 setshift = direct.setshift,
295 setslant = direct.setslant,
296 setspeciallist = direct.setspeciallist,
297 setsplit = direct.setsplit,
298 setstate = direct.setstate,
299 setsub = direct.setsub,
300 setsubpre = direct.setsubpre,
301 setsubtype = direct.setsubtype,
302 setsup = direct.setsup,
303 setsuppre = direct.setsuppre,
304 setsurround = direct.setkern,
305 settop = direct.settop,
306 setvalue = direct.setdata,
307 setweight = direct.setweight,
308 setwhd = direct.setwhd,
309 setwidth = direct.setwidth,
310 show = direct.show,
311 slide = d_slide,
312 softenhyphens = direct.softenhyphens,
313 startofpar = direct.startofpar,
314 tail = d_find_tail,
315 takeattr = direct.unsetattribute,
316 tonode = tonode,
317 tonut = tonut,
318 tostring = direct.tostring,
319 traverse = d_traverse,
320 traversechar = direct.traversechar,
321 traversecontent = direct.traversecontent,
322 traverseglyph = direct.traverseglyph,
323 traverseid = direct.traverseid,
324 traverseitalic = direct.traverseitalic,
325 traverseleader = direct.traverseleader,
326 traverselist = direct.traverselist,
327 unprotectglyph = direct.unprotectglyph,
328 unprotectglyphs = direct.unprotectglyphs,
329 unsetattribute = direct.unsetattribute,
330 unsetattributes = direct.unsetattributes,
331 usedlist = direct.usedlist,
332 usesfont = direct.usesfont,
333 verticalbreak = direct.verticalbreak,
334 vpack = direct.vpack,
335 write = direct.write,
336 xscaled = direct.xscaled,
337 yscaled = direct.yscaled,
338
339 updatetopmarks = direct.updatetopmarks,
340 updatemarks = direct.updatemarks,
341 updatefirstmarks = direct.updatefirstmarks,
342 updatefirstandbotmark = direct.updatefirstandbotmark,
343}
344
345nodes.nuts = nuts
346
347nodes.isnode = isnode
348nodes.isdirect = isnut
349nodes.isnut = isnut
350
351nodes.tonode = tonode
352nodes.tonut = tonut
353
354function nuts.delete(head,current)
355 return d_remove_node(head,current,true)
356end
357
358function nuts.replace(head,current,new)
359 if not new then
360 head, current, new = false, head, current
361 end
362 local prev, next = d_getboth(current)
363 if prev or next then
364 d_setlink(prev,new,next)
365 end
366 if head then
367 if head == current then
368 head = new
369 end
370 d_flushnode(current)
371 return head, new
372 else
373 d_flushnode(current)
374 return new
375 end
376end
377
378local function countall(stack,flat)
379 local n = 0
380 while stack do
381 local id = d_getid(stack)
382 if not flat and id == hlist_code or id == vlist_code then
383 local list = d_getlist(stack)
384 if list then
385 n = n + 1 + countall(list)
386 else
387 n = n + 1
388 end
389 else
390 n = n + 1
391 end
392 stack = d_getnext(stack)
393 end
394 return n
395end
396
397nuts.countall = countall
398
399function nodes.countall(stack,flat)
400 return countall(tonut(stack),flat)
401end
402
403function nuts.append(head,current,...)
404 for i=1,select("#",...) do
405 head, current = d_insertafter(head,current,(select(i,...)))
406 end
407 return head, current
408end
409
410function nuts.prepend(head,current,...)
411 for i=1,select("#",...) do
412 head, current = d_insertbefore(head,current,(select(i,...)))
413 end
414 return head, current
415end
416
417function nuts.linked(...)
418 local head, last
419 for i=1,select("#",...) do
420 local next = select(i,...)
421 if next then
422 if head then
423 d_setlink(last,next)
424 else
425 head = next
426 end
427 last = d_find_tail(next)
428 end
429 end
430 return head
431end
432
433function nuts.concat(list)
434 local head, tail
435 for i=1,#list do
436 local li = list[i]
437 if li then
438 if head then
439 d_setlink(tail,li)
440 else
441 head = li
442 end
443 tail = d_slide(li)
444 end
445 end
446 return head, tail
447end
448
449function nuts.reference(n)
450 return n or "<none>"
451end
452
453function nuts.vianuts (f) return function(n,...) return tonode(f(tonut (n),...)) end end
454function nuts.vianodes(f) return function(n,...) return tonut (f(tonode(n),...)) end end
455
456nodes.vianuts = nuts.vianuts
457nodes.vianodes = nuts.vianodes
458
459function nodes.insertlistafter(h,c,n)
460 local t = n_tail(n)
461 if c then
462 local cn = n_getnext(c)
463 if cn then
464
465 n_setfield(t,"next",cn)
466 n_setfield(cn,"prev",t)
467 else
468 n_setfield(t,"next",nil)
469 end
470 n_setfield(c,"next",n)
471 n_setfield(n,"prev",c)
472 return h, n
473 end
474 return n, t
475end
476
477function nuts.insertlistafter(h,c,n)
478 local t = d_tail(n)
479 if c then
480 local cn = d_getnext(c)
481 if cn then
482 d_setlink(t,cn)
483 else
484 d_setnext(t)
485 end
486 d_setlink(c,n)
487 return h, n
488 end
489 return n, t
490end
491
492
493
494
495
496local report = logs.reporter("sliding")
497
498local function message(detail,head,current,previous)
499 report("error: %s, current: %s:%s, previous: %s:%s, list: %s, text: %s",
500 detail,
501 nodecodes[d_getid(current)],
502 current,
503 nodecodes[d_getid(previous)],
504 previous,
505 nodes.idstostring(head),
506 nodes.listtoutf(head)
507 )
508 utilities.debugger.showtraceback(report)
509end
510
511local function warn()
512 report()
513 report("warning: the slide tracer is enabled")
514 report()
515 warn = false
516end
517
518local function tracedslide(head)
519 if head then
520 if warn then
521 warn()
522 end
523 local next = d_getnext(head)
524 if next then
525 local prev = head
526 for n in d_traverse(next) do
527 local p = d_getprev(n)
528 if not p then
529 message("unset",head,n,prev)
530
531 elseif p ~= prev then
532 message("wrong",head,n,prev)
533
534 end
535 prev = n
536 end
537 end
538 return d_slide(head)
539 end
540end
541
542local function nestedtracedslide(head,level)
543 if head then
544 if warn then
545 warn()
546 end
547 local id = d_getid(head)
548 local next = d_getnext(head)
549 if next then
550 report("%whead:%s",level or 0,nodecodes[id])
551 local prev = head
552 for n in d_traverse(next) do
553 local p = d_getprev(n)
554 if not p then
555 message("unset",head,n,prev)
556
557 elseif p ~= prev then
558 message("wrong",head,n,prev)
559
560 end
561 prev = n
562 local id = d_getid(n)
563 if id == hlist_code or id == vlist_code then
564 nestedtracedslide(d_getlist(n),(level or 0) + 1)
565 end
566 end
567 elseif id == hlist_code or id == vlist_code then
568 report("%wlist:%s",level or 0,nodecodes[id])
569 nestedtracedslide(d_getlist(head),(level or 0) + 1)
570 end
571
572 end
573end
574
575local function untracedslide(head)
576 if head then
577 if warn then
578 warn()
579 end
580 local next = d_getnext(head)
581 if next then
582 local prev = head
583 for n in d_traverse(next) do
584 local p = d_getprev(n)
585 if not p then
586 return "unset", d_getid(n)
587 elseif p ~= prev then
588 return "wrong", d_getid(n)
589 end
590 prev = n
591 end
592 end
593 return d_slide(head)
594 end
595end
596
597nuts.tracedslide = tracedslide
598nuts.untracedslide = untracedslide
599nuts.nestedtracedslide = nestedtracedslide
600
601
602
603local propertydata = direct.getpropertiestable(true)
604
605local getattr = nuts.getattr
606local setattr = nuts.setattr
607
608nodes.properties = {
609 data = propertydata,
610}
611
612
613
614
615function nuts.getprop(n,k)
616 local p = propertydata[n]
617 if p then
618 if k then
619 return p[k]
620 else
621 return p
622 end
623 end
624end
625
626function nuts.rawprop(n,k)
627 local p = rawget(propertydata,n)
628 if p then
629 if k then
630 return p[k]
631 else
632 return p
633 end
634 end
635end
636
637function nuts.setprop(n,k,v)
638 local p = propertydata[n]
639 if p then
640 p[k] = v
641 else
642 propertydata[n] = { [k] = v }
643 end
644end
645
646function nuts.theprop(n)
647 local p = propertydata[n]
648 if not p then
649 p = { }
650 propertydata[n] = p
651 end
652 return p
653end
654
655
656function nuts.isdone(n,k)
657 local p = propertydata[n]
658 if not p then
659 propertydata[n] = { [k] = true }
660 return false
661 end
662 local v = p[k]
663 if v == nil then
664 propertydata[n] = { [k] = true }
665 return false
666 end
667 return v
668end
669
670function nuts.copy_properties(source,target,what)
671 local newprops = propertydata[source]
672 if not newprops then
673
674 return
675 end
676 if what then
677
678 newprops = rawget(source,what)
679 if newprops then
680 newprops = fastcopy(newprops)
681 local p = rawget(propertydata,target)
682 if p then
683 p[what] = newprops
684 else
685 propertydata[target] = {
686 [what] = newprops,
687 }
688 end
689 end
690 else
691
692 newprops = fastcopy(newprops)
693 propertydata[target] = newprops
694 end
695 return newprops
696end
697 |