1 if 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
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89local type, rawget = type, rawget
90
91local nodes = nodes
92local direct = node.direct
93
94local fastcopy = table.fastcopy
95
96local nodecodes = nodes.nodecodes
97local hlist_code = nodecodes.hlist
98local vlist_code = nodecodes.vlist
99local glyph_code = nodecodes.glyph
100
101local nuts = nodes.nuts or { }
102nodes.nuts = nuts
103
104nodes.isnode = direct.isnode or function() return true end
105nodes.isdirect = direct.isdirect or function() return false end
106nodes.isnut = nodes.isdirect
107
108
109
110local tonode = direct.tonode or function(n) return n end
111local tonut = direct.todirect or function(n) return n end
112
113nuts.tonode = tonode
114nuts.tonut = tonut
115
116nodes.tonode = tonode
117nodes.tonut = tonut
118
119
120
121local nuts = nodes.nuts
122
123nuts.checkdiscretionaries = direct.check_discretionaries
124nuts.copy = direct.copy
125nuts.copynode = direct.copy
126nuts.copyonly = direct.copy_only or direct.copy
127nuts.copylist = direct.copy_list
128nuts.count = direct.count
129nuts.currentattribute = direct.current_attr
130nuts.currentattr = direct.current_attr
131nuts.delete = direct.delete
132nuts.dimensions = direct.dimensions
133nuts.endofmath = direct.end_of_math
134nuts.findattribute = direct.find_attribute
135nuts.firstglyph = direct.first_glyph
136nuts.flattendiscretionaries = direct.flatten_discretionaries
137nuts.flush = direct.flush_node
138nuts.flushlist = direct.flush_list
139nuts.flushnode = direct.flush_node
140nuts.free = direct.free
141nuts.getsynctexfields = direct.get_synctex_fields
142nuts.hasattribute = direct.has_attribute
143nuts.hasfield = direct.has_field
144nuts.hasglyph = direct.has_glyph or direct.first_glyph
145nuts.hpack = direct.hpack
146nuts.insertafter = direct.insert_after
147nuts.insertbefore = direct.insert_before
148nuts.isdirect = direct.is_direct
149nuts.isnode = direct.is_node
150nuts.isnut = direct.is_direct
151nuts.kerning = direct.kerning
152nuts.hyphenating = direct.hyphenating
153nuts.lastnode = direct.last_node
154nuts.length = direct.length
155nuts.ligaturing = direct.ligaturing
156nuts.new = direct.new
157nuts.protectglyph = direct.protect_glyph
158nuts.protectglyphs = direct.protect_glyphs
159nuts.protrusionskippable = direct.protrusion_skippable
160nuts.rangedimensions = direct.rangedimensions
161nuts.setattribute = direct.set_attribute
162nuts.setsynctexfields = direct.set_synctex_fields
163nuts.slide = direct.slide
164nuts.tail = direct.tail
165nuts.tostring = direct.tostring
166nuts.traverse = direct.traverse
167nuts.traversechar = direct.traverse_char
168nuts.traverseglyph = direct.traverse_glyph
169nuts.traverseid = direct.traverse_id
170nuts.traverselist = direct.traverse_list
171nuts.unprotectglyph = direct.unprotect_glyph
172nuts.unprotectglyphs = direct.unprotect_glyphs
173nuts.unsetattribute = direct.unset_attribute
174nuts.unsetattribute = direct.unset_attribute
175nuts.usedlist = direct.usedlist
176nuts.usesfont = direct.uses_font
177nuts.vpack = direct.vpack
178nuts.write = direct.write
179nuts.mlisttohlist = direct.mlist_to_hlist
180nuts.hasdimensions = direct.has_dimensions
181nuts.startofpar = direct.start_of_par
182nuts.migrate = direct.migrate
183
184if not nuts.mlisttohlist then
185
186 local n_mlisttohlist = node.mlist_to_hlist
187
188 function nuts.mlisttohlist(head,...)
189 if head then
190 local head = n_mlisttohlist(tonode(head),...)
191 if head then
192 return tonut(head)
193 end
194 end
195 end
196
197end
198
199if not nuts.hasdimensions then
200
201 local getwhd = direct.getwhd
202
203 function nuts.hasdimensions(n)
204 local wd, ht, dp = getwhd(n)
205 return wd ~= 0 or (ht + dp) ~= 0
206 end
207
208end
209
210local getfield = direct.getfield
211local setfield = direct.setfield
212
213nuts.getfield = getfield
214nuts.setfield = setfield
215
216nuts.getnext = direct.getnext
217nuts.setnext = direct.setnext
218
219nuts.getid = direct.getid
220
221nuts.getprev = direct.getprev
222nuts.setprev = direct.setprev
223
224local getattribute = direct.get_attribute
225local setattribute = direct.set_attribute
226local unsetattribute = direct.unset_attribute
227
228nuts.getattr = getattribute
229nuts.setattr = setattribute
230nuts.takeattr = unsetattribute
231
232nuts.getattribute = getattribute
233nuts.setattribute = setattribute
234nuts.unsetattribute = unsetattribute
235
236nuts.iszeroglue = direct.is_zero_glue
237nuts.effectiveglue = direct.effective_glue
238
239nuts.getglue = direct.getglue
240nuts.setglue = direct.setglue
241nuts.getboxglue = direct.getglue
242nuts.setboxglue = direct.setglue
243
244nuts.getdisc = direct.getdisc
245nuts.setdisc = direct.setdisc
246nuts.getdiscretionary = direct.getdisc
247nuts.setdiscretionary = direct.setdisc
248
249nuts.getpre = direct.getpre
250nuts.setpre = direct.setpre
251nuts.getpost = direct.getpost
252nuts.setpost = direct.setpost
253nuts.getreplace = direct.getreplace
254nuts.setreplace = direct.setreplace
255
256local getdata = direct.getdata
257local setdata = direct.setdata
258
259nuts.getdata = getdata
260nuts.setdata = setdata
261nuts.getvalue = getdata
262nuts.setvalue = setdata
263
264nuts.getexpansion = direct.getexpansion
265nuts.setexpansion = direct.setexpansion
266
267nuts.getwhd = direct.getwhd
268nuts.setwhd = direct.setwhd
269nuts.getwidth = direct.getwidth
270nuts.setwidth = direct.setwidth
271nuts.getheight = direct.getheight
272nuts.setheight = direct.setheight
273nuts.getdepth = direct.getdepth
274nuts.setdepth = direct.setdepth
275nuts.getshift = direct.getshift
276nuts.setshift = direct.setshift
277nuts.gettotal = direct.gettotal
278
279
280
281nuts.getorientation = direct.getorientation or function() end
282nuts.setorientation = direct.setorientation or function() end
283
284nuts.getglyphdata = direct.getglyphdata or getattribute
285nuts.setglyphdata = direct.setglyphdata or function(n,d) setattribute(n,0,d) end
286
287nuts.getruledata = direct.getglyphdata and getdata or function(n) return getfield(n,"transform") end
288nuts.setruledata = direct.setglyphdata and setdata or function(n,d) return setfield(n,"transform",d) end
289
290
291
292nuts.getoptions = direct.getoptions or function() return 0 end
293nuts.setoptions = direct.setoptions or function() end
294
295
296
297nuts.getnucleus = direct.getnucleus
298nuts.setnucleus = direct.setnucleus
299nuts.getsup = direct.getsup
300nuts.setsup = direct.setsup
301nuts.getsub = direct.getsub
302nuts.setsub = direct.setsub
303nuts.getsuppre = direct.getsuppre
304nuts.setsuppre = direct.setsuppre
305nuts.getsubpre = direct.getsubpre
306nuts.setsubpre = direct.setsubpre
307
308nuts.getchar = direct.getchar
309nuts.setchar = direct.setchar
310nuts.getfont = direct.getfont
311nuts.setfont = direct.setfont
312nuts.getfam = direct.getfam
313nuts.setfam = direct.setfam
314
315nuts.getboth = direct.getboth
316nuts.setboth = direct.setboth
317nuts.setlink = direct.setlink
318nuts.exchange = direct.exchange
319nuts.reverse = direct.reverse
320nuts.setsplit = direct.setsplit
321
322nuts.getlist = direct.getlist
323nuts.setlist = direct.setlist
324nuts.getleader = direct.getleader
325nuts.setleader = direct.setleader
326nuts.getcomponents = direct.getcomponents
327nuts.setcomponents = direct.setcomponents
328
329nuts.getsubtype = direct.getsubtype
330nuts.setsubtype = direct.setsubtype
331
332nuts.getlang = direct.getlang
333nuts.setlang = direct.setlang
334nuts.getlanguage = direct.getlang
335nuts.setlanguage = direct.setlang
336
337nuts.getattrlist = direct.getattributelist
338nuts.setattrlist = direct.setattributelist
339nuts.getattributelist = direct.getattributelist
340nuts.setattributelist = direct.setattributelist
341
342nuts.getoffsets = direct.getoffsets
343nuts.setoffsets = direct.setoffsets
344
345nuts.getkern = direct.getkern
346nuts.setkern = direct.setkern
347
348nuts.getdir = direct.getdir
349nuts.setdir = direct.setdir
350
351nuts.getdirection = direct.getdirection
352nuts.setdirection = direct.setdirection
353
354nuts.getpenalty = direct.getpenalty
355nuts.setpenalty = direct.setpenalty
356
357nuts.getbox = direct.getbox
358nuts.setbox = direct.setbox
359
360nuts.ischar = direct.is_char
361nuts.isglyph = direct.is_glyph
362
363local d_remove_node = direct.remove
364local d_flushnode = direct.flush_node
365local d_getnext = direct.getnext
366local d_getprev = direct.getprev
367local d_getid = direct.getid
368local d_getlist = direct.getlist
369local d_find_tail = direct.tail
370local d_insertafter = direct.insert_after
371local d_insertbefore = direct.insert_before
372local d_slide = direct.slide
373local d_traverse = direct.traverse
374local d_setlink = direct.setlink
375local d_setboth = direct.setboth
376local d_getboth = direct.getboth
377
378local remove = function(head,current,free_too)
379 if current then
380 local h, c = d_remove_node(head,current)
381 if free_too then
382 d_flushnode(current)
383 return h, c
384 else
385 d_setboth(current)
386 return h, c, current
387 end
388 end
389 return head, current
390end
391
392
393
394if not nuts.startofpar then
395
396 local parcodes = nodes.parcodes
397 local hmodepar_code = parcodes.vmode_par
398 local vmodepar_code = parcodes.hmode_par
399
400 local getsubtype = nuts.getsubtype
401
402 function nuts.startofpar(n)
403 local s = getsubtype(n)
404 return s == hmodepar_code or s == vmodepar_code
405 end
406
407end
408
409
410
411if not nuts.exchange then
412
413 local d_getprev = direct.getprev
414 local d_getnext = direct.getnext
415 local d_setlink = direct.setlink
416
417 function nuts.exchange(head,first,second)
418 if first then
419 if not second then
420 second = d_getnext(first)
421 end
422 if second then
423 d_setlink(d_getprev(first),second,first,d_getnext(second))
424 if first == head then
425 return second
426 end
427 end
428 end
429 return head
430 end
431
432end
433
434
435
436if not nuts.getpre then
437
438 local d_getdisc = direct.getdisc
439 local d_setfield = direct.setfield
440
441 function nuts.getpre (n) local h, _, _, t, _, _ = d_getdisc(n,true) return h, t end
442 function nuts.getpost (n) local _, h, _, _, t, _ = d_getdisc(n,true) return h, t end
443 function nuts.getreplace(n) local _, _, h, _, _, t = d_getdisc(n,true) return h, t end
444
445 function nuts.setpre (n,h) d_setfield(n,"pre", h) end
446 function nuts.setpost (n,h) d_setfield(n,"post", h) end
447 function nuts.setreplace(n,h) d_setfield(n,"replace",h) end
448
449end
450
451if not nuts.gettotal then
452
453 local d_getheight = direct.getheight
454 local d_getdepth = direct.getdepth
455
456 function nuts.gettotal(n)
457 return (d_getheight(n) or 0) + (d_getdepth(n) or 0)
458 end
459
460end
461
462
463
464nuts.getsurround = nuts.getkern
465nuts.setsurround = nuts.setkern
466
467nuts.remove = remove
468
469function nuts.delete(head,current)
470 return remove(head,current,true)
471end
472
473function nuts.replace(head,current,new)
474 if not new then
475 head, current, new = false, head, current
476 end
477 local prev, next = d_getboth(current)
478 if prev or next then
479 d_setlink(prev,new,next)
480 end
481 if head then
482 if head == current then
483 head = new
484 end
485 d_flushnode(current)
486 return head, new
487 else
488 d_flushnode(current)
489 return new
490 end
491end
492
493local function countall(stack,flat)
494 local n = 0
495 while stack do
496 local id = d_getid(stack)
497 if not flat and id == hlist_code or id == vlist_code then
498 local list = d_getlist(stack)
499 if list then
500 n = n + 1 + countall(list)
501 else
502 n = n + 1
503 end
504 else
505 n = n + 1
506 end
507 stack = d_getnext(stack)
508 end
509 return n
510end
511
512nuts.countall = countall
513
514function nodes.countall(stack,flat)
515 return countall(tonut(stack),flat)
516end
517
518function nuts.append(head,current,...)
519 for i=1,select("#",...) do
520 head, current = d_insertafter(head,current,(select(i,...)))
521 end
522 return head, current
523end
524
525function nuts.prepend(head,current,...)
526 for i=1,select("#",...) do
527 head, current = d_insertbefore(head,current,(select(i,...)))
528 end
529 return head, current
530end
531
532function nuts.linked(...)
533 local head, last
534 for i=1,select("#",...) do
535 local next = select(i,...)
536 if next then
537 if head then
538 d_setlink(last,next)
539 else
540 head = next
541 end
542 last = d_find_tail(next)
543 end
544 end
545 return head
546end
547
548function nuts.concat(list)
549 local head, tail
550 for i=1,#list do
551 local li = list[i]
552 if li then
553 if head then
554 d_setlink(tail,li)
555 else
556 head = li
557 end
558 tail = d_slide(li)
559 end
560 end
561 return head, tail
562end
563
564function nuts.reference(n)
565 return n or "<none>"
566end
567
568
569
570
571
572
573
574
575
576function nodes.vianuts (f) return function(n,...) return tonode(f(tonut (n),...)) end end
577function nodes.vianodes(f) return function(n,...) return tonut (f(tonode(n),...)) end end
578
579nuts.vianuts = nodes.vianuts
580nuts.vianodes = nodes.vianodes
581
582function nodes.insertlistafter(h,c,n)
583 local t = n_tail(n)
584 if c then
585 local cn = n_getnext(c)
586 if cn then
587
588 n_setfield(t,"next",cn)
589 n_setfield(cn,"prev",t)
590 else
591 n_setfield(t,"next",nil)
592 end
593 n_setfield(c,"next",n)
594 n_setfield(n,"prev",c)
595 return h, n
596 end
597 return n, t
598end
599
600function nuts.insertlistafter(h,c,n)
601 local t = d_tail(n)
602 if c then
603 local cn = d_getnext(c)
604 if cn then
605 d_setlink(t,cn)
606 else
607 d_setnext(t)
608 end
609 d_setlink(c,n)
610 return h, n
611 end
612 return n, t
613end
614
615
616
617
618
619local report = logs.reporter("sliding")
620
621local function message(detail,head,current,previous)
622 report("error: %s, current: %s:%s, previous: %s:%s, list: %s, text: %s",
623 detail,
624 nodecodes[d_getid(current)],
625 current,
626 nodecodes[d_getid(previous)],
627 previous,
628 nodes.idstostring(head),
629 nodes.listtoutf(head)
630 )
631 utilities.debugger.showtraceback(report)
632end
633
634local function warn()
635 report()
636 report("warning: the slide tracer is enabled")
637 report()
638 warn = false
639end
640
641local function tracedslide(head)
642 if head then
643 if warn then
644 warn()
645 end
646 local next = d_getnext(head)
647 if next then
648 local prev = head
649 for n in d_traverse(next) do
650 local p = d_getprev(n)
651 if not p then
652 message("unset",head,n,prev)
653
654 elseif p ~= prev then
655 message("wrong",head,n,prev)
656
657 end
658 prev = n
659 end
660 end
661 return d_slide(head)
662 end
663end
664
665local function nestedtracedslide(head,level)
666 if head then
667 if warn then
668 warn()
669 end
670 local id = d_getid(head)
671 local next = d_getnext(head)
672 if next then
673 report("%whead:%s",level or 0,nodecodes[id])
674 local prev = head
675 for n in d_traverse(next) do
676 local p = d_getprev(n)
677 if not p then
678 message("unset",head,n,prev)
679
680 elseif p ~= prev then
681 message("wrong",head,n,prev)
682
683 end
684 prev = n
685 local id = d_getid(n)
686 if id == hlist_code or id == vlist_code then
687 nestedtracedslide(d_getlist(n),(level or 0) + 1)
688 end
689 end
690 elseif id == hlist_code or id == vlist_code then
691 report("%wlist:%s",level or 0,nodecodes[id])
692 nestedtracedslide(d_getlist(head),(level or 0) + 1)
693 end
694
695 end
696end
697
698local function untracedslide(head)
699 if head then
700 if warn then
701 warn()
702 end
703 local next = d_getnext(head)
704 if next then
705 local prev = head
706 for n in d_traverse(next) do
707 local p = d_getprev(n)
708 if not p then
709 return "unset", d_getid(n)
710 elseif p ~= prev then
711 return "wrong", d_getid(n)
712 end
713 prev = n
714 end
715 end
716 return d_slide(head)
717 end
718end
719
720nuts.tracedslide = tracedslide
721nuts.untracedslide = untracedslide
722nuts.nestedtracedslide = nestedtracedslide
723
724
725
726local propertydata = direct.get_properties_table(true)
727
728local getattr = nuts.getattr
729local setattr = nuts.setattr
730
731nodes.properties = {
732 data = propertydata,
733}
734
735if direct.set_properties_mode then
736 direct.set_properties_mode(true,true)
737 function direct.set_properties_mode() end
738end
739
740
741
742
743nuts.getprop = function(n,k)
744 local p = propertydata[n]
745 if p then
746 if k then
747 return p[k]
748 else
749 return p
750 end
751 end
752end
753
754nuts.rawprop = function(n,k)
755 local p = rawget(propertydata,n)
756 if p then
757 if k then
758 return p[k]
759 else
760 return p
761 end
762 end
763end
764
765nuts.setprop = function(n,k,v)
766 local p = propertydata[n]
767 if p then
768 p[k] = v
769 else
770 propertydata[n] = { [k] = v }
771 end
772end
773
774nuts.theprop = function(n)
775 local p = propertydata[n]
776 if not p then
777 p = { }
778 propertydata[n] = p
779 end
780 return p
781end
782
783local getstate = direct.getstate
784local setstate = direct.setstate
785
786if not setstate or not getstate then
787
788 setstate = function(n,v)
789 local p = propertydata[n]
790 if p then
791 p.state = v
792 else
793 propertydata[n] = { state = v }
794 end
795 end
796
797 getstate = function(n,v)
798 local p = propertydata[n]
799 if p then
800 if v then
801 return p.state == v
802 else
803 return p.state
804 end
805 else
806 return nil
807 end
808 end
809end
810
811nuts.setstate = setstate
812nuts.getstate = getstate
813
814local getscript = direct.getscript or function(n,v) end
815local setscript = direct.setscript or function(n,v) end
816
817nuts.setscript = setscript
818nuts.getscript = getscript
819
820function nuts.isdone(n,k)
821 local p = propertydata[n]
822 if not p then
823 propertydata[n] = { [k] = true }
824 return false
825 end
826 local v = p[k]
827 if v == nil then
828 propertydata[n] = { [k] = true }
829 return false
830 end
831 return v
832end
833
834function nuts.copy_properties(source,target,what)
835 local newprops = propertydata[source]
836 if not newprops then
837
838 return
839 end
840 if what then
841
842 newprops = rawget(source,what)
843 if newprops then
844 newprops = fastcopy(newprops)
845 local p = rawget(propertydata,target)
846 if p then
847 p[what] = newprops
848 else
849 propertydata[target] = {
850 [what] = newprops,
851 }
852 end
853 end
854 else
855
856 newprops = fastcopy(newprops)
857 propertydata[target] = newprops
858 end
859 return newprops
860end
861 |