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 attributelist_code = nodecodes . attributelist
24local localpar_code = nodecodes . localpar
25local ligatureglyph_code = nodes . glyphcodes . ligature
26
27local nuts = nodes . nuts
28local tonut = nuts . tonut
29local tonode = nuts . tonode
30local vianuts = nuts . vianuts
31
32local getbox = nuts . getbox
33local getnext = nuts . getnext
34local getid = nuts . getid
35local getsubtype = nuts . getsubtype
36local getlist = nuts . getlist
37local getattr = nuts . getattr
38local getboth = nuts . getboth
39local getprev = nuts . getprev
40local getwidth = nuts . getwidth
41local setwidth = nuts . setwidth
42local getboxglue = nuts . getboxglue
43local setboxglue = nuts . setboxglue
44
45local setfield = nuts . setfield
46local setattr = nuts . setattr
47local setlink = nuts . setlink
48local setlist = nuts . setlist
49local setnext = nuts . setnext
50local setprev = nuts . setprev
51local setcomponents = nuts . setcomponents
52local setattrlist = nuts . setattrlist
53
54local traversers = nuts . traversers
55local nextnode = traversers . node
56local nextglyph = traversers . glyph
57
58local flush_node = nuts . flush
59local flush_list = nuts . flush_list
60local hpack_nodes = nuts . hpack
61local unset_attribute = nuts . unset_attribute
62local first_glyph = nuts . first_glyph
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 = attributes . unsetvalue
74
75local current_font = font . current
76
77local texsetbox = tex . setbox
78
79local report_error = logs . reporter ( " node-aux:error " )
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99local function takebox ( id )
100 local box = getbox ( id )
101 if box then
102 local list = getlist ( box )
103 setlist ( box , nil )
104 local copy = copy_node ( box )
105 if list then
106 setlist ( copy , list )
107 end
108 texsetbox ( id , false )
109 return copy
110 end
111end
112
113function nodes . takebox ( id )
114 local b = takebox ( id )
115 if b then
116 return tonode ( b )
117 end
118end
119
120local splitbox = tex . splitbox
121nodes . splitbox = splitbox
122
123function nuts . splitbox ( id , height )
124 return tonut ( splitbox ( id , height ) )
125end
126
127
128
129
130
131function nuts . takelist ( n )
132 local l = getlist ( n )
133 setlist ( n )
134 flush_node ( n )
135 return l
136end
137
138nuts . takebox = takebox
139tex . takebox = nodes . takebox
140
141
142
143local function repackhlist ( list , ... )
144 local temp , b = hpack_nodes ( list , ... )
145 list = getlist ( temp )
146 setlist ( temp )
147 flush_node ( temp )
148 return list , b
149end
150
151nuts . repackhlist = repackhlist
152
153function nodes . repackhlist ( list , ... )
154 local list , b = repackhlist ( tonut ( list ) , ... )
155 return tonode ( list ) , b
156end
157
158local function set_attributes ( head , attr , value )
159 for n , id in nextnode , head do
160 setattr ( n , attr , value )
161 if id = = hlist_node or id = = vlist_node then
162 set_attributes ( getlist ( n ) , attr , value )
163 end
164 end
165end
166
167local function set_unset_attributes ( head , attr , value )
168 for n , id in nextnode , head do
169 if not getattr ( n , attr ) then
170 setattr ( n , attr , value )
171 end
172 if id = = hlist_code or id = = vlist_code then
173 set_unset_attributes ( getlist ( n ) , attr , value )
174 end
175 end
176end
177
178local function unset_attributes ( head , attr )
179 for n , id in nextnode , head do
180 setattr ( n , attr , unsetvalue )
181 if id = = hlist_code or id = = vlist_code then
182 unset_attributes ( getlist ( n ) , attr )
183 end
184 end
185end
186
187
188
189nuts . setattribute = nuts . setattr nodes . setattribute = nodes . setattr
190nuts . getattribute = nuts . getattr nodes . getattribute = nodes . getattr
191nuts . unsetattribute = nuts . unset_attribute nodes . unsetattribute = nodes . unset_attribute
192nuts . has_attribute = nuts . has_attribute nodes . has_attribute = nodes . has_attribute
193nuts . firstglyph = nuts . first_glyph nodes . firstglyph = nodes . first_glyph
194
195nuts . setattributes = set_attributes nodes . setattributes = vianuts ( set_attributes )
196nuts . setunsetattributes = set_unset_attributes nodes . setunsetattributes = vianuts ( set_unset_attributes )
197nuts . unsetattributes = unset_attributes nodes . unsetattributes = vianuts ( unset_attributes )
198
199function nuts . firstcharacter ( n , untagged )
200 if untagged then
201 return first_glyph ( n )
202 else
203 for g in nextglyph , n do
204 return g
205 end
206 end
207end
208
209local function firstcharinbox ( n )
210 local l = getlist ( getbox ( n ) )
211 if l then
212 for g , c in nextglyph , l do
213 return c
214 end
215 end
216 return 0
217end
218
219nuts . firstcharinbox = firstcharinbox
220nodes . firstcharinbox = firstcharinbox
221nodes . firstcharacter = vianuts ( firstcharacter )
222
223interfaces . implement {
224 name = " buildtextaccent " ,
225 arguments = " integer " ,
226 actions = function ( n )
227 local char = firstcharinbox ( n )
228 if char > 0 then
229
230 context ( [[ \accent%s\relax ]] , char )
231 end
232 end
233}
234
235
236
237
238local function tonodes ( str , fnt , attr )
239 if not str or str = = " " then
240 return
241 end
242 local head , tail , space , fnt , template = nil , nil , nil , nil , nil
243 if not fnt then
244 fnt = current_font ( )
245 elseif type ( fnt ) ~ = " number " and getid ( fnt ) = = glyph_code then
246 fnt , template = nil , tonut ( fnt )
247 end
248 for s in utfvalues ( str ) do
249 local n
250 if s = = 32 then
251 if space then
252 n = copy_node ( space )
253 elseif fonts then
254 local parameters = fonts . hashes . identifiers [ fnt ] . parameters
255 space = new_glue ( parameters . space , parameters . space_stretch , parameters . space_shrink )
256 n = space
257 end
258 elseif template then
259 n = copy_node ( template )
260 setvalue ( n , " char " , s )
261 else
262 n = new_glyph ( fnt , s )
263 end
264 if attr then
265 setattrlist ( n , attr )
266 end
267 if head then
268 setlink ( tail , n )
269 else
270 head = n
271 end
272 tail = n
273 end
274 return head , tail
275end
276
277nuts . tonodes = tonodes
278
279nodes . tonodes = function ( str , fnt , attr )
280 local head , tail = tonodes ( str , fnt , attr )
281 return tonode ( head ) , tonode ( tail )
282end
283
284local function link ( list , currentfont , currentattr , head , tail )
285 for i = 1 , # list do
286 local n = list [ i ]
287 if n then
288 local tn = type ( n )
289 if tn = = " string " then
290 if # tn > 0 then
291 if not currentfont then
292 currentfont = current_font ( )
293 end
294 local h , t = tonodes ( n , currentfont , currentattr )
295 if not h then
296
297 elseif not head then
298 head , tail = h , t
299 else
300 setnext ( tail , h )
301 setprev ( h , t )
302 tail = t
303 end
304 end
305 elseif tn = = " table " then
306 if # tn > 0 then
307 if not currentfont then
308 currentfont = current_font ( )
309 end
310 head , tail = link ( n , currentfont , currentattr , head , tail )
311 end
312 elseif not head then
313 head = n
314 tail = find_tail ( n )
315 elseif getid ( n ) = = attributelist_code then
316
317 report_error ( " weird node type in list at index %s: " , i )
318 for i = 1 , # list do
319 local l = list [ i ]
320 report_error ( " %3i: %s %S " , i , getid ( l ) = = attributelist_code and " ! " or " > " , l )
321 end
322 os . exit ( )
323 else
324 setlink ( tail , n )
325 if getnext ( n ) then
326 tail = find_tail ( n )
327 else
328 tail = n
329 end
330 end
331 else
332
333 end
334 end
335 return head , tail
336end
337
338nuts . link = link
339
340nodes . link = function ( list , currentfont , currentattr , head , tail )
341 local head , tail = link ( list , currentfont , currentattr , tonut ( head ) , tonut ( tail ) )
342 return tonode ( head ) , tonode ( tail )
343end
344
345local function locate ( start , wantedid , wantedsubtype )
346 for n , id , subtype in nextnode , start do
347 if id = = wantedid then
348 if not wantedsubtype or subtype = = wantedsubtype then
349 return n
350 end
351 elseif id = = hlist_code or id = = vlist_code then
352 local found = locate ( getlist ( n ) , wantedid , wantedsubtype )
353 if found then
354 return found
355 end
356 end
357 end
358end
359
360nuts . locate = locate
361
362function nodes . locate ( start , wantedid , wantedsubtype )
363 local found = locate ( tonut ( start ) , wantedid , wantedsubtype )
364 return found and tonode ( found )
365end
366
367local function rehpack ( n , width )
368 local head = getlist ( n )
369 local size = width or getwidth ( n )
370 local temp = hpack_nodes ( head , size , " exactly " )
371 setwidth ( n , size )
372 local set , order , sign = getboxglue ( temp )
373 setboxglue ( n , set , order , sign )
374 setlist ( temp )
375 flush_node ( temp )
376 return n
377end
378
379nuts . rehpack = rehpack
380
381function nodes . rehpack ( n , ... )
382 rehpack ( tonut ( n ) , ... )
383end
384
385if CONTEXTLMTXMODE > 0 then
386
387 local fastcopy = table . fastcopy
388 local getprop = nuts . getprop
389 local setprop = nuts . setprop
390
391 local function set_components ( base , list )
392 local t = { }
393 local n = 0
394 while list do
395 local char = isglyph ( list )
396 if char then
397 n = n + 1
398 t [ n ] = char
399 end
400 list = getnext ( list )
401 end
402 setprop ( base , " components " , n > 0 and t or false )
403 end
404
405 local function get_components ( base )
406 return getprop ( base , " components " )
407 end
408
409 local function copy_no_components ( base )
410 local copy = copy_node ( base )
411 setprop ( copy , " components " , false )
412 return copy
413 end
414
415 local function copy_only_glyphs ( base )
416 local t = getprop ( base , " components " )
417 if t then
418 return fastcopy ( t )
419 end
420 end
421
422 local function do_count ( t , marks )
423 local n = 0
424 if t then
425 for i = 1 , # t do
426 local c = t [ i ]
427 if type ( c ) = = " table " then
428 n = n + do_count ( t , marks )
429 elseif not marks [ c ] then
430 n = n + 1
431 else
432
433 end
434 end
435 end
436 return n
437 end
438
439
440
441 local done = false
442
443 local function count_components ( base , marks )
444 local char = isglyph ( base )
445 if char then
446 if getsubtype ( base ) = = ligatureglyph_code then
447 if not done then
448 logs . report ( " fonts " , " ! " )
449 logs . report ( " fonts " , " ! check count_components with mkiv ! " )
450 logs . report ( " fonts " , " ! " )
451 done = true
452 end
453 local t = getprop ( base , " components " )
454 if t then
455 return do_count ( t , marks )
456 end
457 elseif not marks [ char ] then
458 return 1
459 end
460 end
461 return 0
462 end
463
464 nuts . set_components = set_components
465 nuts . get_components = get_components
466 nuts . copy_only_glyphs = copy_only_glyphs
467 nuts . copy_no_components = copy_no_components
468 nuts . count_components = count_components
469
470else
471
472 local get_components = node . direct . getcomponents
473 local set_components = node . direct . setcomponents
474
475 local function copy_no_components ( g , copyinjection )
476 local components = get_components ( g )
477 if components then
478 set_components ( g )
479 local n = copy_node ( g )
480 if copyinjection then
481 copyinjection ( n , g )
482 end
483 set_components ( g , components )
484
485 return n
486 else
487 local n = copy_node ( g )
488 if copyinjection then
489 copyinjection ( n , g )
490 end
491 return n
492 end
493 end
494
495 local function copy_only_glyphs ( current )
496 local head = nil
497 local previous = nil
498 for n in nextglyph , current do
499 n = copy_node ( n )
500 if head then
501 setlink ( previous , n )
502 else
503 head = n
504 end
505 previous = n
506 end
507 return head
508 end
509
510
511
512 local function count_components ( start , marks )
513 local char = isglyph ( start )
514 if char then
515 if getsubtype ( start ) = = ligatureglyph_code then
516 local n = 0
517 local components = get_components ( start )
518 while components do
519 n = n + count_components ( components , marks )
520 components = getnext ( components )
521 end
522 return n
523 elseif not marks [ char ] then
524 return 1
525 end
526 end
527 return 0
528 end
529
530 nuts . set_components = set_components
531 nuts . get_components = get_components
532 nuts . copy_only_glyphs = copy_only_glyphs
533 nuts . copy_no_components = copy_no_components
534 nuts . count_components = count_components
535
536end
537
538nuts . setcomponents = function ( ) report_error ( " unsupported: %a " , " setcomponents " ) end
539nuts . getcomponents = function ( ) report_error ( " unsupported: %a " , " getcomponents " ) end
540
541do
542
543 local localparcodes = nodes . localparcodes
544 local hmodepar_code = localparcodes . vmode_par
545 local vmodepar_code = localparcodes . hmode_par
546
547 local getnest = tex . getnest
548 local getsubtype = nuts . getsubtype
549
550 function nuts . setparproperty ( action , ... )
551 local tail = tonut ( getnest ( ) . tail )
552 while tail do
553 if getid ( tail ) = = localpar_code then
554 local s = getsubtype ( tail )
555 if s = = hmodepar_code or s = = vmodepar_code then
556 return action ( tail , ... )
557 else
558
559 end
560 end
561 tail = getprev ( tail )
562 end
563 end
564
565 local getsubtype = nodes . getsubtype
566
567 function nodes . start_of_par ( n )
568 local s = getsubtype ( n )
569 return s = = hmodepar_code or s = = vmodepar_code
570 end
571
572end
573
574
575
576
577do
578
579 local nextnode = traversers . glue
580 local findfail = nuts . tail
581
582 local getid = nuts . getid
583 local getsubtype = nuts . getsubtype
584 local getlist = nuts . getlist
585 local getwidth = nuts . getwidth
586
587 local direct = node . direct
588
589 local nodecodes = nodes . nodecodes
590 local skipcodes = nodes . skipcodes
591
592 local hlist_code = nodecodes . hlist
593 local line_code = nodecodes . line
594
595 local leftskip_code = skipcodes . leftskip
596 local rightskip_code = skipcodes . rightskip
597 local lefthangskip_code = skipcodes . lefthangskip
598 local righthangskip_code = skipcodes . righthangskip
599 local indentskip_code = skipcodes . indentskip
600 local parfillskip_code = skipcodes . parfillskip
601
602 local find_node = direct . find_node or function ( h , t , s )
603 if h then
604 if s then
605 for node , subtype in traversers [ t ] do
606 if s = = subtype then
607 return current
608 end
609 end
610 else
611 for node , subtype in traversers [ t ] do
612 return current , subtype
613 end
614 end
615 end
616 end
617
618 nuts . find_node = find_node
619
620 nodes . getnormalizeline = node . getnormalizeline or function ( ) return 0 end
621 nodes . setnormalizeline = node . setnormalizeline or function ( ) end
622
623 nuts . getnormalizedline = direct . getnormalizedline or function ( h )
624 if getid ( h ) = = hlist_code and getsubtype ( h ) = = line_code then
625 local ls , rs = 0 , 0
626 local lh , rh = 0 , 0
627 local is , ps = 0 , 0
628 local h = getlist ( h )
629 local t = findtail ( h )
630 for n , subtype in nextglue , h do
631 if subtype = = leftskip_code then ls = getwidth ( n )
632 elseif subtype = = rightskip_code then rs = getwidth ( n )
633 elseif subtype = = lefthangskip_code then lh = getwidth ( n )
634 elseif subtype = = righthangskip_code then rh = getwidth ( n )
635 elseif subtype = = indentskip_code then is = getwidth ( n )
636 elseif subtype = = parfillskip_code then ps = getwidth ( n )
637 end
638 end
639 return ls , rs , lh , rh , is , ps , h , t
640 end
641 end
642
643end
644
645if not nodes . count then
646
647 local type = type
648
649 local direct = node . direct
650 local todirect = direct . tovaliddirect
651 local tonode = direct . tonode
652
653 local count = direct . count
654 local length = direct . length
655 local slide = direct . slide
656
657 function node . count ( id , first , last )
658 return count ( id , first and todirect ( first ) , last and todirect ( last ) or nil )
659 end
660
661 function node . length ( first , last )
662 return length ( first and todirect ( first ) , last and todirect ( last ) or nil )
663 end
664
665 function node . slide ( n )
666 if n then
667 n = slide ( todirect ( n ) )
668 if n then
669 return tonode ( n )
670 end
671 end
672 return nil
673 end
674
675 local hyphenating = direct . hyphenating
676 local ligaturing = direct . ligaturing
677 local kerning = direct . kerning
678
679
680
681 function node . hyphenating ( first , last )
682 if first then
683 local h , t = hyphenating ( todirect ( first ) , last and todirect ( last ) or nil )
684 return h and tonode ( h ) or nil , t and tonode ( t ) or nil , true
685 else
686 return nil , false
687 end
688 end
689
690 function node . ligaturing ( first , last )
691 if first then
692 local h , t = ligaturing ( todirect ( first ) , last and todirect ( last ) or nil )
693 return h and tonode ( h ) or nil , t and tonode ( t ) or nil , true
694 else
695 return nil , false
696 end
697 end
698
699 function node . kerning ( first , last )
700 if first then
701 local h , t = kerning ( todirect ( first ) , last and todirect ( last ) or nil )
702 return h and tonode ( h ) or nil , t and tonode ( t ) or nil , true
703 else
704 return nil , false
705 end
706 end
707
708 local protect_glyph = direct . protect_glyph
709 local unprotect_glyph = direct . unprotect_glyph
710 local protect_glyphs = direct . protect_glyphs
711 local unprotect_glyphs = direct . unprotect_glyphs
712
713 function node . protect_glyphs ( first , last )
714 protect_glyphs ( todirect ( first ) , last and todirect ( last ) or nil )
715 end
716
717 function node . unprotect_glyphs ( first , last )
718 unprotect_glyphs ( todirect ( first ) , last and todirect ( last ) or nil )
719 end
720
721 function node . protect_glyph ( first )
722 protect_glyph ( todirect ( first ) )
723 end
724
725 function node . unprotect_glyph ( first )
726 unprotect_glyph ( todirect ( first ) )
727 end
728
729 local flatten_discretionaries = direct . flatten_discretionaries
730 local check_discretionaries = direct . check_discretionaries
731 local check_discretionary = direct . check_discretionary
732
733 function node . flatten_discretionaries ( first )
734 local h , count = flatten_discretionaries ( todirect ( first ) )
735 return tonode ( h ) , count
736 end
737
738 function node . check_discretionaries ( n )
739 check_discretionaries ( todirect ( n ) )
740 end
741
742 function node . check_discretionary ( n )
743 check_discretionary ( todirect ( n ) )
744 end
745
746 local hpack = direct . hpack
747 local vpack = direct . vpack
748 local list_to_hlist = direct . mlist_to_hlist
749
750 function node . hpack ( head , ... )
751 local h , badness = hpack ( head and todirect ( head ) or nil , ... )
752 return tonode ( h ) , badness
753 end
754
755 function node . vpack ( head , ... )
756 local h , badness = vpack ( head and todirect ( head ) or nil , ... )
757 return tonode ( h ) , badness
758 end
759
760 function node . mlist_to_hlist ( head , ... )
761 return tonode ( mlist_to_hlist ( head and todirect ( head ) or nil , ... ) )
762 end
763
764 local end_of_math = direct . end_of_math
765 local find_attribute = direct . find_attribute
766 local first_glyph = direct . first_glyph
767
768 function node . end_of_math ( n )
769 if n then
770 n = end_of_math ( todirect ( n ) )
771 if n then
772 return tonode ( n )
773 end
774 end
775 return nil
776 end
777
778 function node . find_attribute ( n , a )
779 if n then
780 local v , n = find_attribute ( todirect ( n ) , a )
781 if n then
782 return v , tonode ( n )
783 end
784 end
785 return nil
786 end
787
788 function node . first_glyph ( first , last )
789 local n = first_glyph ( todirect ( first ) , last and todirect ( last ) or nil )
790 return n and tonode ( n ) or nil
791 end
792
793 local dimensions = direct . dimensions
794 local rangedimensions = direct . rangedimensions
795 local effective_glue = direct . effective_glue
796
797 function node . dimensions ( a , b , c , d , e )
798 if type ( a ) = = " userdata " then
799 a = todirect ( a )
800 if type ( b ) = = " userdata " then
801 b = todirect ( b )
802 end
803 return dimensions ( a , b )
804 else
805 d = todirect ( d )
806 if type ( e ) = = " userdata " then
807 e = todirect ( e )
808 end
809 return dimensions ( a , b , c , d , e )
810 end
811 return 0 , 0 , 0
812 end
813
814 function node . rangedimensions ( parent , first , last )
815 return rangedimenensions ( todirect ( parent ) , todirect ( first ) , last and todirect ( last ) )
816 end
817
818 function node . effective_glue ( list , parent )
819 return effective_glue ( list and todirect ( list ) or nil , parent and todirect ( parent ) or nil )
820 end
821
822 local uses_font = direct . uses_font
823 local has_glyph = direct . has_glyph
824 local protrusion_skippable = direct . protrusion_skippable
825 local prepend_prevdepth = direct . prepend_prevdepth
826 local make_extensible = direct . make_extensible
827
828 function node . uses_font ( n , f )
829 return uses_font ( todirect ( n ) , f )
830 end
831
832 function node . has_glyph ( n )
833 return has_glyph ( todirect ( n ) )
834 end
835
836 function node . protrusion_skippable ( n )
837 return protrusion_skippable ( todirect ( n ) )
838 end
839
840 function node . prepend_prevdepth ( n )
841 local n , d = prepend_prevdepth ( todirect ( n ) )
842 return tonode ( n ) , d
843 end
844
845 function node . make_extensible ( ... )
846 local n = make_extensible ( ... )
847 return n and tonode ( n ) or nil
848 end
849
850 local last_node = direct . last_node
851
852 function node . last_node ( )
853 local n = last_node ( )
854 return n and tonode ( n ) or nil
855 end
856
857 local is_zero_glue = direct . is_zero_glue
858 local getglue = direct . getglue
859 local setglue = direct . setglue
860
861 function node . is_zero_glue ( n )
862 return is_zero_glue ( todirect ( n ) )
863 end
864
865 function node . get_glue ( n )
866 return get_glue ( todirect ( n ) )
867 end
868
869 function node . set_glue ( n )
870 return set_glue ( todirect ( n ) )
871 end
872
873end
874 |