1if not modules then modules = { } end modules ['node-ali'] = {
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
9local aligncharacter_code = 1
10local mathalign_code = 2
11local mathmatrix_code = 3
12
13local setmetatableindex = table.setmetatableindex
14
15local nuts = nodes.nuts
16local tonut = nuts.tonut
17local tonode = nuts.tonode
18local getwidth = nuts.getwidth
19local setwidth = nuts.setwidth
20local getid = nuts.getid
21local getattr = nuts.getattr
22local setnext = nuts.setnext
23local getnext = nuts.getnext
24local getprev = nuts.getprev
25local getboth = nuts.getboth
26local getglue = nuts.getglue
27local setglue = nuts.setglue
28local getwhd = nuts.getwhd
29local setwhd = nuts.setwhd
30local setpenalty = nuts.setpenalty
31local getlist = nuts.getlist
32local setlist = nuts.setlist
33local getleader = nuts.getleader
34local setattrlist = nuts.setattrlist
35local setprop = nuts.setprop
36local getprop = nuts.getprop
37local getfont = nuts.getfont
38local getchar = nuts.getchar
39local addmargins = nuts.addmargins
40local findtail = nuts.tail
41local hasglyph = nuts.hasglyph
42local getwordrange = nuts.getwordrange
43local dimensions = nuts.rangedimensions
44local flushnode = nuts.flush
45local hpack = nuts.hpack
46local repack = nuts.repack
47local insertbefore = nuts.insertbefore
48local insertafter = nuts.insertafter
49local effectiveglue = nuts.effectiveglue
50
51local newkern = nuts.pool.kern
52local newrule = nuts.pool.rule
53local newglue = nuts.pool.glue
54
55local traversers = nuts.traversers
56local nextrecord = traversers.alignrecord
57local nextunset = traversers.unset
58local nextglyph = traversers.glyph
59local nextglue = traversers.glue
60local nextpenalty = traversers.penalty
61local nextboundary = traversers.boundary
62local nextnode = traversers.node
63local nextlist = traversers.list
64local nextrule = traversers.rule
65
66local nodecodes = nodes.nodecodes
67local glyph_code = nodecodes.glyph
68local glue_code = nodecodes.glue
69local kern_code = nodecodes.kern
70local disc_code = nodecodes.disc
71local unset_code = nodecodes.unset
72local alignrecord_code = nodecodes.alignrecord
73local rule_code = nodecodes.rule
74local temp_code = nodecodes.temp
75
76local spaceskip_code = nodes.gluecodes.spaceskip
77local xspaceskip_code = nodes.gluecodes.xspaceskip
78local intermathskip_code = nodes.gluecodes.intermathskip
79local fontkern_code = nodes.kerncodes.fontkern
80local row_code = nodes.listcodes.alignment
81local cell_code = nodes.listcodes.cell
82local line_code = nodes.listcodes.line
83local linepenalty_code = nodes.penaltycodes.linepanalty
84
85
86
87
88
89
90
91do
92
93
94 local a_alignchar = attributes.private("aligncharacter")
95
96 local method = 2
97 local unislots = fonts.hashes.unislots
98 local chardata = fonts.hashes.characters
99
100 function nodes.handlers.aligncharacter(head,where,callback,attr,preamble)
101 if callback ~= aligncharacter_code then
102
103 elseif where == "preroll" then
104 local attr = getattr(attr,a_alignchar)
105 if attr then
106 local widths = { }
107 local data = { }
108 local rows = 0
109 local cols = 0
110 for col in nextrecord, preamble do
111 cols = cols + 1
112 local w, s = getwidth(col,true)
113 widths[cols] = { col, w, s }
114 end
115
116 for row in nextunset, head do
117 rows = rows + 1
118 local c = 0
119 local d = { }
120 data[rows] = d
121 for col in nextunset, getlist(row) do
122 c = c + 1
123 if widths[c][2] then
124 local list = getlist(col)
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140 local middle = nil
141
142 for g, char, font in nextglyph, list do
143 local unicode = getattr(g,a_alignchar)
144 if unicode then
145 if char == unicode then
146 middle = g
147 elseif unislots[font][char] == unicode then
148 middle = g
149 end
150 end
151 end
152 if middle then
153 local left, right = getwordrange(middle)
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174 d[c] = { col, left, middle, right, 0, 0, getwidth(middle) }
175 else
176 d[c] = false
177 end
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199 else
200 d[c] = false
201 end
202 end
203 end
204
205 for col=1,cols do
206 local maxl = 0
207 local maxr = 0
208 local minm = 0
209 local maxm = 0
210 local colw = widths[col]
211 for row=1,rows do
212 local d = data[row][col]
213 if d then
214 local p = d[1]
215 local l = d[2]
216 local m = d[3]
217 local r = d[4]
218 if m then
219 local lw = l == m and 0 or dimensions(p,l,m)
220 local rw = m == r and 0 or dimensions(p,getnext(m),getnext(r))
221 d[5] = lw
222 d[6] = rw
223 if lw > maxl then
224 maxl = lw
225 end
226 if rw > maxr then
227 maxr = rw
228 end
229 local mw = d[7]
230 if maxm == 0 then
231 minm = mw
232 maxm = mw
233 else
234 if mw > maxm then
235 maxm = mw
236 end
237 if mw < minm then
238 minm = mw
239 end
240 end
241 end
242 end
243 end
244
245 local fixedwidth = colw[3] ~= 0
246
247 local old = colw[2]
248 local new = old
249 for row=1,rows do
250 local d = data[row][col]
251 if d then
252 local p = d[1]
253 local l = d[2]
254 local m = d[3]
255 local r = d[4]
256 if l and m and r then
257 local lw = d[5]
258 local rw = d[6]
259 local mw = d[7]
260 dl = maxl - lw
261 dr = maxr - rw
262 if dl ~= 0 or dr ~= 0 or mw ~= maxm then
263 local lst = getlist(p)
264 local wid = getwidth(p)
265 if dl ~= 0 then
266 local k = newkern(dl)
267 lst = insertbefore(lst,l,k)
268 setattrlist(k,m)
269 setlist(p,lst)
270 wid = wid + dl
271 end
272 if dr ~= 0 then
273 local k = newkern(dr)
274 insertafter(lst,r,k)
275 setattrlist(k,m)
276 wid = wid + dr
277 end
278 if mw ~= maxm then
279 local dw = (maxm - mw)
280 local dx = dw / 2
281 addmargins(m,-dx,-dx)
282 wid = wid + dw
283 end
284 setwidth(p,wid)
285 if wid > new then
286 new = wid
287 end
288 setlist(p,lst)
289
290 if fixedwidth then
291 local l = hpack(h,getwidth(p),"exactly")
292 setglue(p,getglue(l))
293 setlist(l)
294 flushnode(l)
295 else
296 setglue(p)
297 end
298
299 end
300 end
301 end
302 end
303 if new > old then
304 if fixedwidth then
305
306 else
307 setwidth(colw[1],new)
308 end
309 end
310 end
311 end
312 end
313 end
314
315 local enabled = false
316
317 interfaces.implement {
318 name = "enablealignmentcharacter",
319
320 public = true,
321 protected = true,
322 actions = function()
323 if not enabled then
324 nodes.tasks.enableaction("alignments", "nodes.handlers.aligncharacter")
325 enabled = true
326 end
327 end,
328 }
329
330end
331
332
333
334do
335
336 local getdata = nuts.getdata
337 local removenode = nuts.remove
338 local getwhd = nuts.getwhd
339 local getheight = nuts.getheight
340 local getdepth = nuts.getdepth
341 local setheight = nuts.setheight
342 local setdepth = nuts.setdepth
343 local getglue = nuts.getglue
344 local setoffsets = nuts.setoffsets
345 local setsubtype = nuts.setsubtype
346
347 local baselineskip_code = nodes.gluecodes.baselineskip
348 local lineskip_code = nodes.gluecodes.lineskip
349
350 local alignrecord_code = nodecodes.alignrecord
351 local hlist_code = nodecodes.hlist
352 local unset_code = nodecodes.unset
353
354
355 local nextnode = nuts.traversers.node
356
357 local texgetdimen = tex.getdimen
358 local texsetdimen = tex.setdimen
359 local texgetglue = tex.getglue
360 local texget = tex.get
361
362 local leftmarker = tex.boundaries.system("c_math_align_l_marker")
363 local rightmarker = tex.boundaries.system("c_math_align_r_marker")
364
365 local a_location = attributes.system("mathnumberlocation")
366 local a_threshold = attributes.system("mathnumberthreshold")
367
368 local v_first = interfaces.variables.first
369 local v_last = interfaces.variables.last
370 local v_both = interfaces.variables.both
371
372
373
374 local function openup(specification,head)
375 local inbetween = specification.inbetween or 0
376 local height = specification.height or 0
377 local depth = specification.depth or 0
378 local splitmethod = specification.splitmethod or ""
379 local lines = { }
380 for n, id, subtype, list in nextlist, head do
381 lines[#lines+1] = { n, subtype, getwhd(n) }
382 end
383 local noflines = #lines
384 if noflines > 0 then
385 local currentline = 1
386 for n, subtype in nextglue, head do
387
388
389
390 if subtype == baselineskip_code or subtype == lineskip_code then
391 local nextline = currentline + 1
392 local amount, stretch, shrink = getglue(n)
393
394 local prevdp = lines[currentline][5]
395 local nextht = lines[nextline][4]
396
397 local delta = 0
398 if prevdp < depth then
399 setdepth(lines[currentline][1],depth)
400 delta = delta + (depth - prevdp)
401
402 end
403 if nextht < height then
404 setheight(lines[nextline][1],height)
405
406 delta = delta + (height - nextht)
407 end
408
409
410 setsubtype(n,baselineskip_code)
411
412 setglue(n,amount+inbetween-delta,stretch,shrink)
413
414 currentline = nextline
415
416
417
418 end
419 end
420 if splitmethod ~= "" then
421 local currentline = 0
422 for n, subtype in nextpenalty, head do
423 if subtype == linepenalty_code then
424 if l == 1 then
425 if splitmethod == v_both or splitmethod == v_first then
426
427 setpenalty(n, 10000)
428 end
429 elseif l == noflines then
430 if splitmethod == v_both or splitmethod == v_last then
431
432 setpenalty(n, 10000)
433 end
434 end
435 curline = currentline
436 end
437 end
438 end
439 local firstht = lines[1][4]
440 local lastdp = lines[noflines][5]
441 if firstht < height then
442 setheight(lines[1],height)
443 end
444 if lastdp < depth then
445 setdepth(lines[noflines],depth)
446 end
447 end
448 end
449
450 nuts.openup = openup
451
452
453
454
455
456
457
458
459
460
461
462
463
464 local totals = { }
465 local widths = { }
466 local records = { }
467 local deltas = { }
468 local cellwidths = { }
469
470 local a_flushleft <const> = 1
471 local a_centered <const> = 2
472 local a_flushright <const> = 3
473
474 local a_numberright <const> = 1
475 local a_numberleft <const> = 2
476
477 local function first_pass(head,callback,attr,preamble,signal)
478
479 local width = 0
480 local hsize = texget("hsize")
481 local count = 0
482 local overflow = false
483 totals = { }
484 widths = { }
485 records = { }
486 deltas = { }
487 for n in nextrecord, preamble do
488 local wd = getwidth(n)
489 count = count + 1
490 width = width + wd
491 totals [count] = width
492 widths [count] = wd
493 records[count] = n
494 deltas [count] = 0
495 end
496
497 local lindex = 0
498 local rindex = 0
499 local lwidth = 0
500 local rwidth = 0
501 local centered = false
502
503 for row in nextunset, head do
504 local count = 0
505 local anchor = nil
506 local rochan = nil
507
508 for cell in nextunset, getlist(row) do
509 local list = getlist(cell)
510 count = count + 1
511 cellwidths[count] = getwidth(cell)
512 for bound in nextboundary, list do
513 local marker = getdata(bound)
514 if marker == leftmarker then
515 lindex = count
516 anchor = bound
517 rochan = list
518 elseif marker == rightmarker then
519 local n = getnext(bound)
520 if n and getid(n) == hlist_code then
521 local wd, ht, dp = getwhd(n)
522 local lc = getattr(n,a_location)
523 if lc then
524
525
526
527 local packed = (lc >> 8) & 0xF
528 local align = (lc >> 4) & 0xF
529 local location = (lc ) & 0xF
530 local threshold = getattr(n,a_threshold)
531 if location == a_numberright then
532
533 local m = 1
534 local s = align == a_centered and 2 or 1
535 if align == a_flushleft then
536 rwidth = wd
537 elseif align == a_flushright then
538 rwidth = wd
539 elseif wd > lwidth then
540 lwidth = wd
541 rwidth = wd
542 centered = true
543 end
544
545if packed > 0 then
546 setprop(n,"mathalignshift","right")
547 lwidth = 0
548 rwidth = 0
549end
550
551 if totals[count-2] + cellwidths[count-1] + s*wd - s*threshold > hsize then
552 local total = ht + dp
553 setdepth(row,getdepth(row) + total)
554 setoffsets(n,0,-total)
555 local pr = records[count-1]
556 local cw = getwidth(pr)
557 if cw - wd > deltas[count-1] then
558 deltas[count-1] = cw - wd
559 end
560 overflow = true
561 end
562 elseif location == a_numberleft then
563 if align == a_flushleft then
564 lwidth = wd
565 elseif align == a_flushright then
566 lwidth = wd
567 end
568 if signal == 0x80 then
569 lwidth = wd
570 end
571
572if packed > 0 then
573 setprop(n,"mathalignshift","left")
574 lwidth = 0
575 rwidth = 0
576end
577
578 end
579 if location == a_numberleft and anchor then
580 local l, l, n = removenode(list,n)
581 if l ~= list then
582 setlist(cell,l)
583
584 end
585 if signal == 0x80 then
586 setwidth(cell,lwidth)
587 end
588 insertafter(rochan,anchor,n)
589 end
590 end
591 end
592 rindex = count
593 end
594 end
595 end
596 end
597
598 if overflow then
599 if deltas[rindex-1] ~= 0 then
600 setwidth(records[rindex-1],deltas[rindex-1])
601 end
602 end
603
604 for count=1,#records do
605 if count == lindex then
606 if centered and overflow then
607 lwidth = lwidth - texgetdimen("d_math_eqalign_number_distance")
608 end
609 setwidth(records[count],lwidth)
610 elseif count == rindex then
611 setwidth(records[count],rwidth)
612 end
613 end
614 end
615
616 local function second_pass(head,callback,attr,preamble,signal)
617 local done = setmetatableindex("table")
618 local glues = { }
619 local okay = false
620 for row, id, subtype in nextlist, head do
621 if id == hlist_code and subtype == row_code then
622 for cell, id, subtype in nextlist, getlist(row) do
623 if id == hlist_code and subtype == cell_code then
624 for n, s in nextglue, getlist(cell) do
625 if s == intermathskip_code then
626 local e = effectiveglue(n,cell)
627 local g = getglue(n)
628 local f = getfont(n)
629 local a = done[f]
630 local d = a[g]
631 glues[n] = g
632 if not d then
633 a[g] = e
634 elseif d > e then
635 a[g] = e
636 okay = true
637 end
638 end
639 end
640 end
641 end
642 end
643 end
644 if okay then
645 for k, v in next, glues do
646 local g = done[getfont(k)][v]
647 if g then
648 setglue(k,g)
649 setprop(k,"fixedmathalign",true)
650 end
651 end
652 for row, id, subtype in nextlist, head do
653 if id == hlist_code and subtype == row_code then
654 for cell, id, subtype, list in nextlist, getlist(row) do
655 if list and id == hlist_code and subtype == cell_code then
656 local wd = getwidth(cell)
657 repack(cell,wd,"exactly")
658 end
659 end
660 end
661 end
662 end
663 end
664
665 local function third_pass(head,callback,attr,preamble,signal)
666 local inbetween, stretch, shrink = texgetglue("s_strc_math_alignment_inbetween")
667 openup({ inbetween = inbetween }, head)
668 end
669
670
671
672
673
674 function nodes.handlers.mathalignrelocate(head,where,callback,attr,preamble)
675 if callback ~= mathalign_code then
676
677 elseif where == "preroll" then
678 local signal = getattr(attr,a_location)
679 if signal == 0x20 or signal == 0x40 or signal == 0x80 then
680 first_pass(head,callback,attr,preamble,signal)
681 end
682 elseif where == "wrapup" then
683 local signal = getattr(attr,a_location)
684 if signal == 0x40 or signal == 0x80 then
685 second_pass(head,callback,attr,preamble,signal)
686 end
687 if signal then
688 third_pass(head,callback,attr,preamble,signal)
689 end
690 end
691 end
692
693do
694
695 local a_mathalignmentvrule = attributes.private("mathalignmentvrule")
696 local a_mathalignmenthrule = attributes.private("mathalignmenthrule")
697 local a_mathalignmenttop = attributes.private("mathalignmenttop")
698 local a_mathalignmentmid = attributes.private("mathalignmentmid")
699 local a_mathalignmentbot = attributes.private("mathalignmentbot")
700
701 local function hrule_pass(head,attr,preamble)
702 local i = 0
703 for row, id, subtype, list in nextlist, head do
704 if id == hlist_code and subtype == row_code then
705 local height = 0
706 local depth = 0
707 local done = false
708 for cell, id, subtype, list in nextlist, list do
709 if list then
710
711 for n, id, subtype in nextglue, list do
712
713
714 local rule = getleader(n)
715 if rule then
716 local signal = getattr(rule,a_mathalignmenthrule)
717 if signal then
718 local w, h, d = getwhd(n)
719 if h and d then
720 if h > height then
721 height = h
722 end
723 if d > depth then
724 depth = d
725 end
726 done = true
727 end
728 end
729 end
730 end
731 end
732 end
733 if done then
734 setheight(row,height)
735 setdepth(row,depth)
736 end
737 end
738 end
739 end
740
741
742
743
744 local function vrule_pass(head,attr,preamble)
745 for row, id, subtype, list in nextlist, head do
746 if id == hlist_code and subtype == row_code then
747 local prv, nxt = getboth(row)
748 for cell, id, subtype, list in nextlist, list do
749 if list then
750
751 local d = false
752 local h = false
753 for n, id, subtype in nextrule, list do
754 local signal = getattr(n,a_mathalignmentvrule)
755
756 if signal then
757 if not d then
758 if prv then
759 if getattr(prv,a_mathalignmentvrule) == 4 then
760 local p = prv
761 while p do
762 local a = getattr(p,a_mathalignmentvrule)
763 if not a then
764 break
765 elseif a == 2 then
766 if not getprev(p) or getid(getprev(p)) == temp_code then
767 local h = getattr(p,a_mathalignmenttop) or 0
768 nuts.setheight(p,h)
769 end
770 break
771 else
772 p = getprev(p)
773 end
774 end
775 else
776 prv = nil
777 end
778
779
780
781 end
782 if nxt then
783 if getattr(nxt,a_mathalignmentvrule) == 2 then
784 local p = nxt
785 while p do
786 local a = getattr(p,a_mathalignmentvrule)
787 if not a then
788 break
789 elseif a == 4 then
790 if not getnext(p) then
791 local d = getattr(p,a_mathalignmentbot) or 0
792 nuts.setdepth(p,d)
793 end
794 break
795 else
796 p = getnext(p)
797 end
798 end
799 else
800 nxt = nil
801 end
802
803
804
805 end
806 d = prv and -getdepth (prv) or 0
807 h = nxt and -getheight(nxt) or 0
808 d = d - (getattr(prv,a_mathalignmentmid) or 0)
809 end
810 setoffsets(n,nil,nil,d,h)
811 end
812 end
813 end
814 end
815 end
816 end
817 end
818
819 function nodes.handlers.mathmatrixrules(head,where,callback,attr,preamble)
820 if callback ~= mathmatrix_code then
821
822 elseif where == "wrapup" then
823 hrule_pass(head,attr,preamble)
824 vrule_pass(head,attr,preamble)
825 end
826 end
827
828 local enabled = false
829
830 interfaces.implement {
831 name = "enablematrixrules",
832
833 public = true,
834 protected = true,
835 actions = function()
836 if not enabled then
837 nodes.tasks.enableaction("alignments","nodes.handlers.mathmatrixrules")
838 enabled = true
839 end
840 end,
841 }
842
843end
844
845
846
847 local a_ornament = attributes.system("mathmatrixornament")
848
849 local leftornament = tex.boundaries.system("c_math_matrix_ornament_l")
850 local rightornament = tex.boundaries.system("c_math_matrix_ornament_r")
851 local topornament = tex.boundaries.system("c_math_matrix_ornament_t")
852 local bottomornament = tex.boundaries.system("c_math_matrix_ornament_b")
853
854 local verticalline = tex.boundaries.system("c_math_matrix_vl_boundary")
855
856 local left = 0
857 local right = 0
858 local nofcells = 0
859 local found = false
860
861 local lefts = false
862 local rights = false
863 local tops = false
864 local bottoms = false
865
866 local function first_pass(head,callback,attr,preamble,signal)
867 nofcells = 0
868 left = 0
869 right = 0
870 found = false
871 lefts = { }
872 rights = { }
873 tops = { }
874 bottoms = { }
875 for n in nextrecord, preamble do
876 nofcells = nofcells + 1
877 end
878 local cells = { }
879 for row in nextunset, head do
880 local c = 0
881 for cell in nextunset, getlist(row) do
882 local list = getlist(cell)
883 c = c + 1
884 for bound in nextboundary, list do
885 local ornament = getdata(bound)
886 if ornament == verticalline then
887
888 c = c + 1
889 break
890 elseif ornament == leftornament then
891 if c == 1 then
892 local w = getwidth(cell)
893 if w > left then
894 left = w
895 end
896 setwidth(cell,0)
897 cells[c+1] = true
898 cells[c] = true
899 found = true
900 lefts[#lefts+1] = cell
901 end
902 elseif ornament == rightornament then
903 if c == nofcells then
904 local w = getwidth(cell)
905 if w > right then
906 right = w
907 end
908 setwidth(cell,0)
909 cells[c-1] = true
910 cells[c] = true
911 found = true
912 rights[#rights+1] = cell
913 end
914 elseif ornament == topornament then
915 setheight(row,0)
916 setdepth(row,0)
917 found = true
918 tops[#tops+1] = cell
919 elseif ornament == bottomornament then
920 setheight(row,0)
921 setdepth(row,0)
922 found = true
923 bottoms[#bottoms+1] = cell
924 end
925 end
926 end
927 end
928 if next(cells) then
929 local c = 0
930 for n in nextrecord, preamble do
931 c = c + 1
932 if cells[c] then
933 setwidth(n)
934 end
935 end
936 end
937 end
938
939 local function second_pass(box,callback,attr,preamble,signal)
940 if found then
941 local head = getlist(nuts.getbox(box))
942 local leftmargin = texgetdimen("d_math_matrix_margin_l")
943 local rightmargin = texgetdimen("d_math_matrix_margin_r")
944 local topmargin = texgetdimen("d_math_matrix_margin_t")
945 local bottommargin = texgetdimen("d_math_matrix_margin_b")
946 for i=1,#lefts do
947 setoffsets(lefts[i],-(left+leftmargin),0)
948 end
949 for i=1,#rights do
950 setoffsets(rights[i], (rightmargin),0)
951 end
952 for i=1,#tops do
953 setoffsets(tops[i],0,topmargin)
954 end
955 for i=1,#bottoms do
956 setoffsets(bottoms[i],0,-bottommargin)
957 end
958 lefts = false
959 rights = false
960 tops = false
961 bottoms = false
962 texsetdimen("global","d_math_matrix_max_left", left)
963 texsetdimen("global","d_math_matrix_max_right",right)
964 end
965 end
966
967 function nodes.handlers.mathmatrixornaments(head,where,callback,attr,preamble)
968 if callback ~= mathmatrix_code then
969
970 elseif where == "preroll" then
971 first_pass(head,callback,attr,preamble,signal)
972
973
974 end
975 end
976
977 interfaces.implement {
978 name = "shiftmatrixornaments",
979 actions = second_pass,
980 arguments = "integer",
981 }
982
983 local enabled = false
984
985 interfaces.implement {
986 name = "enablemathalignrelocate",
987
988 public = true,
989 protected = true,
990 actions = function()
991 if not enabled then
992 nodes.tasks.enableaction("alignments","nodes.handlers.mathalignrelocate")
993 enabled = true
994 end
995 end,
996 }
997
998 local enabled = false
999
1000 interfaces.implement {
1001 name = "enablematrixornaments",
1002
1003 public = true,
1004 protected = true,
1005 actions = function()
1006 if not enabled then
1007 nodes.tasks.enableaction("alignments","nodes.handlers.mathmatrixornaments")
1008 enabled = true
1009 end
1010 end,
1011 }
1012
1013end
1014
1015
1016
1017local report = logs.reporter("alignment","preamble")
1018local trace trackers.register("alignments.showstates",function(v) trace = v end)
1019
1020function nodes.handlers.showpreamble(head,where,callback,attr,preamble)
1021 if trace then
1022 local c = 0
1023 for n, id in nextnode, preamble do
1024 if id == unset_code or id == alignrecord_code then
1025 c = c + 1
1026 report("stage %a, cell %i, width %p",where,c,getwidth(n))
1027 elseif id == glue_code then
1028 report("stage %a, tabskip %s",where,node.direct.gluetostring(n))
1029 else
1030 report("stage %a, node %a",where,nodecodes[id])
1031 end
1032 end
1033 end
1034end
1035 |