math-ali.mkxl /size: 125 Kb    last modification: 2025-02-21 11:03
1%D \module
2%D   [       file=math-ali,
3%D        version=2008.10.20,
4%D          title=\CONTEXT\ Math Macros,
5%D       subtitle=Math Alignments,
6%D         author={Hans Hagen, Taco Hoekwater \& Aditya Mahajan},
7%D           date=\currentdate,
8%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
9%C
10%C This module is part of the \CONTEXT\ macro||package and is
11%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
12%C details.
13
14\writestatus{loading}{ConTeXt Math Macros / Math Alignments}
15
16\unprotect
17
18\registerctxluafile{math-ali}{autosuffix}
19
20%D The code here has been moved from other files. Beware: the \MKII\ and \MKIV\ code
21%D is not gathered in files with the same name. In the meantime this code has been
22%D adapted to \MKIV\ but more is possible. The code is somewhat complicated by the
23%D fact that alignments are tricky with rspect to tagging.
24
25% export:
26%
27% alignment : ok
28% cases     :
29% matrix    : ok
30% substack  :
31
32% Alignment overhaul timestamp: around watching GhostNote Live in Utrecht 2022
33% (energizing funky professionalism).
34
35%D The following macros are moved to this module because here we deal mostly with
36%D alignment issues. In principle one should see strc-mat, math-ini and math-ali as
37%D a close operation. The \type {\displaywidth} and \type {\displayindent} variables
38%D are only known and used inside a display formula, In \MKXL\ we no longer use
39%D display mode at all.
40
41% \checkeddisplaywidth   % obsolete
42% \maximizeddisplaywidth % obsolete
43
44%D \macros
45%D   {definemathalignment, setupmathalignment, startmathalignment}
46%D
47%D Modules may provide additional alignment features. The following kind of plain
48%D mechanisms are provided by the core.
49
50% \startformula
51%     \startalign[m=3, n=2, align={1:right,2:left},distance=2em]
52%         \NC 1.1 \NC = 1.2 \NC 2.1 \NC = 2.2 \NC 3.1 \NC = 3.2 \NR
53%         \NC 1   \NC = 1   \NC 2   \NC = 2   \NC 3   \NC = 3   \NR
54%         \NC 1.1 \NC = 1.2 \NC 2.1 \NC = 2.2 \NC 3.1 \NC = 3.2 \NR
55%     \stopalign
56% \stopformula
57
58\newtoks     \t_math_align_a
59\newtoks     \t_math_align_b
60\newtoks     \t_math_align_c
61\newgluespec \d_math_eqalign_distance
62\newgluespec \d_math_eqalign_rulethickness
63\newdimension\d_math_eqalign_number_distance
64\newinteger  \c_math_eqalign_repeat
65\newtoks     \t_math_matrix_NL_NR
66
67\mutable\def\displayopenupvalue{.25\bodyfontsize}
68
69\installcorenamespace{mathalignendclass}   % maybe {complexmathendclass}
70
71\global\expandafter\integerdef\csname\??mathalignendclass\the\zerocount\endcsname\mathendcode
72
73\protected\def\math_eqalign_distance
74  {\global\expandafter\integerdef\csname\??mathalignendclass\the\c_math_eqalign_column\endcsname\mathendcode
75   \mathalignmentparameter\c!separator
76   \relax}
77
78%D For compatibility we have this location stuff. It is kind of messy and uses
79%D tabskip magick plus signal 0x08 for an exception. Contrary to normal left
80%D aligned formulas we keep the number inline.
81
82% \startbuffer
83%     \startformula
84%       A = B
85%     \stopformula
86%
87%     \startplaceformula \startformula
88%       A = B
89%     \stopformula \stopplaceformula
90%
91%     \startformula \startalign
92%       \NC A \EQ B \NR
93%       \NC A \EQ B \NR
94%     \stopalign \stopformula
95%
96%     \startplaceformula \startformula \startalign
97%       \NC A \EQ B \NR[+]
98%       \NC A \EQ B \NR[+]
99%     \stopalign \stopformula \stopplaceformula
100% \stopbuffer
101%
102% \startbuffer[all]
103%     \section[title=middle] \setupmathalignment[location={center,middle}] \getbuffer
104%     \section[title=left]   \setupmathalignment[location={center,left}]   \getbuffer
105%     \section[title=right]  \setupmathalignment[location={center,right}]  \getbuffer
106% \stopbuffer
107%
108% {\setupformula[location=right] \getbuffer[all] \page}
109% {\setupformula[location=left]  \getbuffer[all] \page}
110
111\newcount\c_math_eqalign_slots
112
113\def\math_build_eqalign
114  {\scratchtoks\emptytoks
115   \d_math_eqalign_distance\mathalignmentparameter\c!distance\relax
116   \ifcstok{\mathalignmentparameter\c!align}\v!auto
117     \d_math_eqalign_number_distance{\mathalignmentparameter\c!numberdistance}%
118     \letmathalignmentparameter\c!align\v!middle
119   \else
120     \d_math_eqalign_number_distance\zeropoint
121   \fi
122   \scratchcounterone{\mathalignmentparameter\c!m}%
123   \scratchcountertwo{\mathalignmentparameter\c!n}%
124   \etoksapp\scratchtoks\t_math_align_a
125   \toksapp\scratchtoks{\global\c_math_eqalign_repeat\zerocount}%
126   \scratchcounter\plusone
127   \localcontrolledrepeat{\scratchcounterone*\scratchcountertwo-\plusone}%
128     {\ifnum\scratchcounter=\scratchcountertwo
129        \scratchcounter\plusone
130        % preamble expansion hell ...
131        \toksapp\scratchtoks {\tabskip\d_math_eqalign_distance\relax}%
132        % so ...
133        \toksapp\scratchtoks {\relax\math_eqalign_distance}%
134        \etoksapp\scratchtoks{\global\advanceby\c_math_eqalign_repeat\the\scratchcountertwo\relax}%
135      \else
136        \advanceby\scratchcounter\plusone
137      \fi
138      \etoksapp\scratchtoks\t_math_align_b}%
139   \etoksapp\scratchtoks\t_math_align_c
140   \c_math_eqalign_slots{\scratchcounterone*\scratchcountertwo}%
141   \toksapp\scratchtoks{\global\c_math_eqalign_repeat\zerocount}}
142
143\def\math_eqalign_set_defaults
144  {%\normalbaselines % per januari 2024 commented
145   \mathsurround\zeropoint
146   \mathsurroundskip\zeroskip
147   \tabskip\zeroskip
148   \everycr\emptytoks}
149
150\protected\def\math_math_in_eqalign_start
151  {\mathbeginclass
152     \ifconditional\c_math_eqalign_force_text
153       % really? check mtext
154       \mathordcode
155     \orelse\ifcase\c_math_eqalign_column\or
156       \mathunsetcode
157     \orelse\ifcsname\??mathalignendclass\tointeger{\c_math_eqalign_column-\plusone}\endcsname
158       \lastnamedcs
159     \else
160       \mathunsetcode
161     \fi
162   \mathendclass\mathordinarycode % added
163   \ifconditional\c_math_eqalign_force_text
164     \usemathstyleparameter\mathalignmentparameter\c!textstyle
165   \else
166     \startforceddisplaymath
167     \usemathstyleparameter\mathalignmentparameter\c!mathstyle
168   \fi}
169
170\protected\def\math_math_in_eqalign_stop
171  {\ifconditional\c_math_eqalign_force_text
172     % really? check mtext
173     \global\expandafter\integerdef\csname\??mathalignendclass\the\c_math_eqalign_column\endcsname\mathordcode
174   \else
175      \stopforceddisplaymath
176      \ifnum\lastrightclass<\mathunsetcode
177        \global\expandafter\integerdef\csname\??mathalignendclass\the\c_math_eqalign_column\endcsname\lastrightclass
178      \fi
179   \fi
180   \global\c_math_eqalign_force_text\conditionalfalse}
181
182\protected\def\math_math_in_eqalign#1% protected is not obeyed with \span
183  {% preamble \span ... i really need some extension
184   \tabskip\zeroskip
185   \everycr\emptytoks
186   \math_math_in_eqalign_start % protected
187   #1%
188   \math_math_in_eqalign_stop} % protected
189
190\noaligned\protected\def\math_text_in_eqalign#1%
191  {\mathbeginclass\mathordcode
192   \mathendclass  \mathordcode
193   \startimath
194   \tabskip\zeroskip
195   \everycr\emptytoks
196   #1% huh, imath?
197   \stopimath}
198
199\def\math_place_number_in_alignment#1#2%
200  {\c_strc_formulas_number_in_alignment\conditionaltrue
201   \dostarttaggednodetail\t!mtext
202     \strc_formulas_place_number_nested{#1}{#2}%
203   \dostoptagged}
204
205%D There was a request for rules on the list when we had the 2024 meeting:
206%D
207%D \starttyping
208%D \startformula
209%D \startalign[n=7,align=*:middle,rulecolor=red,rulethickness=.25ex]
210%D \NC 1   \NC + \NC 222 \NC + \NC  33  \NC + \NC  44  \NR
211%D \HL
212%D \NC 11  \NC + \NC 22  \NC + \NC  3   \NC + \NC  4   \NR
213%D \HL[1,green,3mm,3,reset,5,blue,7]
214%D \NC 111 \NC + \NC 2   \NC + \NC  333 \NC + \NC  444 \NR
215%D \stopalign
216%D \stopformula
217%D \stoptyping
218
219% musical timestamp, listening to Anna Von Hausswolff on pipe organ (ctx 2024 after
220% party with Mikael S)
221
222\lettonothing\p_math_alignment_HL_color
223\newdimension\d_math_alignment_HL_width
224
225\protected\def\math_alignment_HL_rule
226  {\leaders
227     \hrule
228       \s!height \d_math_alignment_HL_width
229       \s!depth  \d_math_alignment_HL_width
230     \relax
231     \hfill}
232
233\def\math_alignment_HL_reset
234  {\d_math_alignment_HL_width{\mathalignmentparameter\c!rulethickness/2}%
235   \edef\p_math_alignment_HL_color{\mathalignmentparameter\c!rulecolor}}
236
237\def\math_alignment_HL_step_add#1%
238  {\ifcase\scratchcounter\else
239     \expandedrepeat{#1-\scratchcounter}{\toksapp\scratchtoks{\aligntab\omit}}%
240   \fi
241   \scratchcounter#1\relax
242   \etoksapp\scratchtoks{%
243   % \noexpand\def\noexpand\p_math_alignment_HL_color{\p_math_alignment_HL_color}%
244     \colo_helpers_activate{\p_math_alignment_HL_color}%
245     \d_math_alignment_HL_width\the\d_math_alignment_HL_width\relax
246     \math_alignment_HL_rule}}
247
248\def\math_alignment_HL_step#1%
249  {\ifcstok{#1}\v!reset
250     \math_alignment_HL_reset
251   \orelse\ifchkdim#1\or
252     \d_math_alignment_HL_width#1\relax
253   \orelse\ifchknum#1\or
254     \math_alignment_HL_step_add{#1}%
255   \else
256     \def\p_math_alignment_HL_color{#1}%
257   \fi}
258
259\tolerant\def\math_alignment_HL[#1]%
260  {\noalign{\nointerlineskip}%
261   \omit\aligntab\omit
262   \math_alignment_HL_reset
263   \novrule
264     \s!height {\mathalignmentparameter\c!toffset}%
265     \s!depth  {\mathalignmentparameter\c!boffset}%
266   \relax
267   \ifparameter#1\or
268     \global\scratchcounter\zerocount
269     \scratchtoks{\aligntab\omit}%
270     \processcommalist[#1]\math_alignment_HL_step
271     \expand\scratchtoks
272   \else
273     \colo_helpers_activate\p_math_alignment_HL_color
274     \math_alignment_HL_rule
275     \expandedrepeat{\c_math_eqalign_slots+\minusone}{\span\omit}%
276   \fi
277   \crcr
278   \noalign{\nointerlineskip}}
279
280% the preamble is scanned for tabskips so we need the span to prevent an error
281% message but we can probably do without that hack now .. best not change this
282% now .. what works now keeps working
283
284\setnewconstant\c_strc_formulas_check_width\plusone
285
286\newboundary\c_math_align_l_marker
287\newboundary\c_math_align_r_marker
288
289\permanent\def\strc_math_effective_width
290  {\dimexpr
291     \ifzeropt\d_strc_formulas_display_width
292       \hsize
293     \else
294       \d_strc_formulas_display_width
295     \fi
296      -\leftskip
297      -\rightskip
298   \relax}
299
300% formula   : numbermethod        down : default
301% formula   : numberlocation   overlay : option
302% mathalign : align           ..| auto :
303% mathalign : adaptive             yes : synchronize glue
304
305% \startplaceformula
306% \startformula[numbermethod=down,numberlocation=normal]
307% \medmuskip 4mu plus 2mu minus 2mu \showmakeup[mathglue]\showglyphs\showboxes
308% \startalign[adaptive=yes,align=auto]
309% \NC aaa+x+xxxxxxxx+x+xxxx \EQ x+xxx                   \NR[eq:two:zz]
310% \NC x+x                   \EQ x+x+x+xxx+x+x+xxx+xx+xx \NR[eq:two:xx]
311% \stopalign
312% \stopformula
313% \stopplaceformula
314%
315% \startplaceformula
316% \startformula[numbermethod=normal,numberlocation=normal]
317% \medmuskip 4mu plus 2mu minus 2mu \showmakeup[mathglue]\showglyphs\showboxes
318% \startalign[adaptive=no,align=middle]
319% \NC aaa+x+xxxxxxxx+x+xxxx \EQ x+xxx                   \NR[eq:two:zz]
320% \NC x+x                   \EQ x+x+x+xxx+x+x+xxx+xx+xx \NR[eq:two:xx]
321% \stopalign
322% \stopformula
323% \stopplaceformula
324
325\newconditional\c_math_align_overflow_mode     \c_math_align_overflow_mode\conditionaltrue
326\newconditional\c_math_align_reformat_mode     \c_math_align_reformat_mode\conditionaltrue
327\newconditional\c_strc_formulas_overlay_number \c_strc_formulas_overlay_number\conditionaltrue
328
329\protected\def\math_text_in_align
330  {\scratchcounter{\c_math_eqalign_row+\plusone}%
331   \usemathalignmentstyleandcolor\c!textstyle\c!textcolor
332   \usemathalignmentstyleandcolor{\c!textstyle:\the\scratchcounter}{\c!textcolor:\the\scratchcounter}%
333   \mathalignmentparameter\c!text
334   \dostarttaggednodetail\t!mtext
335   \mathalignmentparameter{\c!text:\the\scratchcounter}%
336   \dostoptagged}
337
338\def\math_align_initialize_class_states
339  {}
340
341\protected\def\math_align_reset_class_states
342  {\lastleftclass \mathbegincode
343   \lastrightclass\mathendcode}
344
345% the fill skips are somewhat hackery here ...
346
347% left
348
349\def\math_prepare_l_eqalign_no_a
350  {\relax
351   \strut
352   \math_text_in_align
353   \aligncontent % for picking up the number
354   \ifcase\c_strc_formulas_align_alignment
355     \ifnum\c_strc_math_ragged_status=\plusthree
356       \tabskip\zeroskip
357     \else
358       \tabskip\centeringskip
359     \fi
360   \or
361     \ifnum\c_strc_math_ragged_status=\plusthree
362       \tabskip\zeroskip
363     \else
364       \tabskip\centeringskip
365     \fi
366   \or
367     \tabskip\stretchingfillskip
368   \fi
369   \boundary\c_math_align_l_marker
370   \math_align_reset_class_states
371   \aligntab
372   \math_first_in_eqalign
373   \hfil
374   \math_left_of_eqalign
375   \span
376   \math_math_in_eqalign{\aligncontent}%
377   \math_right_of_eqalign
378   \tabskip\zeroskip}
379
380\def\math_prepare_l_eqalign_no_b
381  {\aligntab
382   \math_next_in_eqalign
383   \math_left_of_eqalign
384   \span
385   \math_math_in_eqalign{\aligncontent}%
386   \math_right_of_eqalign
387   \tabskip\zeroskip
388   }
389
390\def\math_prepare_l_eqalign_no_c_three
391  {\hfil
392   \tabskip\zeroskip
393   \aligntab
394   \span
395   \boundary\c_math_align_r_marker
396   \math_alignment_rbox{\aligncontent}%
397   \tabskip\zeroskip}
398
399\def\math_prepare_l_eqalign_no_c_one
400  {\hfil
401   \tabskip\stretchingfillskip
402   \aligntab
403   \span
404   \boundary\c_math_align_r_marker
405   \math_alignment_rbox{\aligncontent}%
406   \tabskip\zeroskip}
407
408\def\math_prepare_l_eqalign_no_c_other
409  {\hfil
410   \tabskip\centeringskip
411   \aligntab
412   \span
413   \boundary\c_math_align_r_marker
414   \math_alignment_rbox{\aligncontent}%
415   \ifcase\c_strc_formulas_align_alignment
416     \tabskip\zeroskip
417   \or
418     \ifconditional\c_strc_formulas_handle_number
419      %\tabskip\zeroskip
420       \tabskip\stretchingfillskip
421     \else
422       \tabskip\stretchingfillskip
423     \fi
424   \or
425     \tabskip\zeroskip
426   \fi
427  }
428
429\def\math_prepare_l_eqalign_no  % \checkeddisplaymath
430  {\math_align_initialize_class_states
431   \t_math_align_a{\math_prepare_l_eqalign_no_a}%
432   \t_math_align_b{\math_prepare_l_eqalign_no_b}%
433   \ifnum\c_strc_math_ragged_status=\plusthree
434     \t_math_align_c{\math_prepare_l_eqalign_no_c_three}%
435   \orelse\ifnum\c_strc_math_ragged_status=\plusone
436     \t_math_align_c{\math_prepare_l_eqalign_no_c_one}%
437   \else
438     \t_math_align_c{\math_prepare_l_eqalign_no_c_other}%
439   \fi
440   \math_build_eqalign
441   \ifnum\c_strc_math_ragged_status=\plusthree
442     \tabskip\stretchingfillskip
443   \else
444     \tabskip\zeroskip
445   \fi}
446
447% right
448
449\def\math_prepare_r_eqalign_no_a
450  {\relax
451   \strut
452   \math_text_in_align
453   \tabskip\centeringskip
454   \aligncontent % for picking up the number
455   \ifcase\c_strc_formulas_align_alignment
456     % middle
457     \boundary\c_math_align_l_marker% This is flush left when number
458     \tabskip\centeringskip
459   \or
460     % left
461     \tabskip\zeroskip
462   \or
463     % right
464     \tabskip\stretchingfilllskip
465   \fi
466   \math_align_reset_class_states
467   \aligntab
468   \math_first_in_eqalign
469   \hfil
470   \math_left_of_eqalign
471   \span
472   \math_math_in_eqalign{\aligncontent}%
473   \math_right_of_eqalign
474   \tabskip\zeroskip}
475
476\def\math_prepare_r_eqalign_no_b
477  {\aligntab
478   \math_next_in_eqalign
479   \math_left_of_eqalign
480   \span
481   \math_math_in_eqalign{\aligncontent}%
482   \math_right_of_eqalign
483   \tabskip\zeroskip}
484
485\def\math_prepare_r_eqalign_no_c_three
486  {\hfil
487   \aligntab
488   \hfill % the only one !
489   \span
490   \boundary\c_math_align_r_marker
491   \math_alignment_lbox{\aligncontent}%
492   \tabskip\zeroskip}
493
494\def\math_prepare_r_eqalign_no_c_one_one
495  {\hfil
496   \tabskip\stretchingfillskip
497   \aligntab
498   \span
499   \boundary\c_math_align_r_marker
500   \math_alignment_lbox{\aligncontent}%
501   \tabskip\zeroskip}
502
503\def\math_prepare_r_eqalign_no_c_one_other
504  {\hfil
505   \tabskip\zeroskip
506   \aligntab
507   \span
508   \boundary\c_math_align_r_marker
509   \math_alignment_lbox{\aligncontent}%
510   \tabskip\stretchingfillskip}
511
512\def\math_prepare_r_eqalign_no_c_other
513  {\hfil
514   \ifcase\c_strc_formulas_align_alignment
515     % middle
516     \tabskip\centeringskip % fails in some cases
517   \or
518     % left
519     \ifconditional\c_strc_formulas_handle_number
520       \tabskip\stretchingfillskip
521     \else
522       \tabskip\zeroskip
523     \fi
524   \or
525     % right
526     \ifconditional\c_strc_formulas_handle_number
527       \tabskip\stretchingfillskip
528     \else
529       \tabskip\zeroskip
530     \fi
531   \fi
532   \aligntab
533   \span
534   \hss % for MS to test this
535   \boundary\c_math_align_r_marker
536   \math_alignment_lbox{\aligncontent}%
537   \ifcase\c_strc_formulas_align_alignment
538     % middle
539     \tabskip\zeroskip
540   \or
541     % left
542     \ifconditional\c_strc_formulas_handle_number
543       \tabskip\zeroskip
544     \else
545       \tabskip\stretchingfillskip
546     \fi
547   \or
548     % right
549     \ifconditional\c_strc_formulas_handle_number
550       \tabskip\stretchingfillskip
551     \else
552       \tabskip\zeroskip
553     \fi
554   \fi}
555
556\def\math_prepare_r_eqalign_no
557  {\math_align_initialize_class_states
558   \t_math_align_a{\math_prepare_r_eqalign_no_a}%
559   \t_math_align_b{\math_prepare_r_eqalign_no_b}%
560   \ifnum\c_strc_math_ragged_status=\plusthree
561     \t_math_align_c{\math_prepare_r_eqalign_no_c_three}%
562   \orelse\ifnum\c_strc_math_ragged_status=\plusone
563     \ifnum\c_strc_math_number_variant=\plusone
564       \t_math_align_c{\math_prepare_r_eqalign_no_c_one_one}%
565     \else
566       \t_math_align_c{\math_prepare_r_eqalign_no_c_one_other}%
567     \fi
568   \else
569     \t_math_align_c{\math_prepare_r_eqalign_no_c_other}%
570   \fi
571   \math_build_eqalign
572   \tabskip\zeroskip}
573
574% done
575%
576% if we have an issue then we need to check the unless case below
577
578\def\math_halign_checked
579  {\enablemathalignrelocate
580   \halign
581     \ifconditional\c_math_align_overflow_mode
582       \s!callback
583         \align_callback_mathalign
584       \s!attr
585         \mathnumberlocationattribute{% on whole, different on l/rbox
586            %\unless
587            \ifcase\c_strc_formulas_align_alignment
588              \plustwo
589            \orelse\ifconditional\c_math_align_reformat_mode
590              \plusfour
591            \orelse\ifnum\c_strc_formulas_align_alignment=\plusone
592              \ifcstok{\formulaparameter\c!location}\v!left
593                \pluseight
594              \else
595                \plustwo
596              \fi
597            \else
598              \plustwo
599            \fi
600          * \plussixteen % just a signal
601       }%
602     \fi
603     \ifcase\c_strc_formulas_check_width\else
604        to \strc_math_effective_width
605     \fi}
606
607\installcorenamespace {mathalignlocation}
608
609\setnewconstant\c_strc_formulas_align_alignment\zerocount % 1=left 2=right
610\setnewconstant\c_strc_formulas_align_packed   \zerocount
611
612\defcsname\??mathalignlocation\v!top   \endcsname{\let\math_alignment_location_box\tpack}
613\defcsname\??mathalignlocation\v!bottom\endcsname{\let\math_alignment_location_box\vpack}
614\defcsname\??mathalignlocation\v!center\endcsname{\let\math_alignment_location_box\vcenter}
615
616\defcsname\??mathalignlocation\v!middle\endcsname{\c_strc_formulas_align_alignment\zerocount}
617\defcsname\??mathalignlocation\v!left  \endcsname{\c_strc_formulas_align_alignment\plusone}
618\defcsname\??mathalignlocation\v!right \endcsname{\c_strc_formulas_align_alignment\plustwo}
619
620\defcsname\??mathalignlocation\v!packed\endcsname
621  {\c_strc_formulas_align_packed\plusone}
622
623\defcsname\??mathalignlocation\v!unpacked\endcsname
624  {\c_strc_formulas_align_packed\plustwo}
625
626\defcsname\??mathalignlocation\v!formula\endcsname
627  {\c_strc_formulas_align_alignment
628     \ifcstok{\formulaparameter\c!align}\v!flushleft
629       \plusone
630   % \orelse\expandafter\ifx\lastnamedcs\v!flushright
631     \orelse\ifcstok{\lastnamedcs}\v!flushright
632       \plustwo
633     \else
634       \zerocount
635     \fi}
636
637\def\math_alignment_location_box_set#1{\begincsname\??mathalignlocation#1\endcsname}
638
639\def\math_alignment_location_check#1%
640  {\c_strc_formulas_align_alignment\zerocount
641   \c_strc_formulas_align_packed\zerocount
642   \let\math_alignment_location_box\vcenter
643   \processcommacommand[#1]\math_alignment_location_box_set}
644
645%D Here we implement the user interface part. We start with basic math alignments:
646
647\newinteger    \c_math_eqalign_column
648\newinteger    \c_math_eqalign_row
649\newconditional\c_math_eqalign_first
650
651\newtoks       \everymathalignment
652\newtoks       \everymathalignmentdone
653
654\newdimension  \d_math_eqalign_number_threshold
655
656\definesystemattribute[mathnumberlocation] [public]
657\definesystemattribute[mathnumberthreshold][public]
658
659\protected\def\math_alignment_lbox#1%
660  {\begingroup
661   \setbox\scratchbox\hbox{\resetformulaparameter\c!location#1}%
662   \ifzeropt\wd\scratchbox\else
663     \hpack
664       \s!attr \mathnumberlocationattribute{%
665        % \c_strc_formulas_align_packed*\pluscclvi % 0x0.00
666          \c_math_alignment_packed_signal          % 0x0.00
667        + \c_strc_math_ragged_status*\plussixteen  % 0x00.0
668        + \plusone                                 % 0x000.
669       }%
670       \s!attr \mathnumberthresholdattribute{%
671         \d_math_eqalign_number_threshold
672       }%
673       {\strc_formulas_add_distance \plustwo\v!left\mathalignmentparameter
674        \box\scratchbox
675        \hskip\d_math_alignment_packed_margin
676        }%
677   \fi
678   \global\d_math_eqalign_number_threshold\zeropoint % move to begin of row
679   \endgroup}
680
681\protected\def\math_alignment_rbox#1%
682  {\begingroup
683   \setbox\scratchbox\hbox{\resetformulaparameter\c!location#1}%
684   \ifzeropt\wd\scratchbox\else
685     \hpack
686       \s!attr \mathnumberlocationattribute{%
687        % \c_strc_formulas_align_packed*\pluscclvi % 0x0.00
688          \c_math_alignment_packed_signal          % 0x0.00
689        + \c_strc_math_ragged_status*\plussixteen  % 0x00.0
690        + \plustwo                                 % 0x000.
691       }%
692       \s!attr \mathnumberthresholdattribute{%
693         \d_math_eqalign_number_threshold
694       }%
695       {\hskip\d_math_alignment_packed_margin
696        \box\scratchbox
697        \strc_formulas_add_distance \plustwo\v!right\mathalignmentparameter}%
698   \fi
699   \global\d_math_eqalign_number_threshold\zeropoint % move to begin of row
700   \endgroup}
701
702\permanent\tolerant\protected\def\math_alignment_NN[#1]#*[#2]%
703  {\aligntab
704   \strc_formulas_place_number_nested{#1}{#2}}
705
706\permanent\tolerant\protected\def\math_alignment_NR[#1]#*[#2]%
707  {\aligntab
708%    \dostarttaggednodetail\t!mtext
709% \c_strc_formulas_number_in_alignment\conditionaltrue
710%    \strc_formulas_place_number_nested{#1}{#2}%
711% \dostoptagged % mtext
712\math_place_number_in_alignment{#1}{#2}%
713\dostoptagged % math
714\dostoptagged % subformla
715   \math_number_right_of_eqalign
716   \global\c_math_eqalign_first\conditionaltrue
717   \crcr}
718
719\permanent\protected\def\math_alignment_NC
720  {\relax
721   \ifconditional\c_math_eqalign_first
722     \ifx\p_math_alignment_number\v!auto
723       \strc_formulas_place_number_nested{+}{}%
724     \fi
725     \global\c_math_eqalign_first\conditionalfalse
726   \fi
727   \math_number_left_of_eqalign
728   \aligntab}
729
730\newconditional\c_math_eqalign_force_text
731
732\permanent\protected\def\math_alignment_TC
733  {\relax
734   \ifconditional\c_math_eqalign_first
735     \ifx\p_math_alignment_number\v!auto
736       \strc_formulas_place_number_nested{+}{}%
737     \fi
738     \global\c_math_eqalign_first\conditionalfalse
739   \fi
740   \math_number_left_of_eqalign
741   \global\c_math_eqalign_force_text\conditionaltrue
742   \aligntab}
743
744\permanent\protected\def\math_alignment_EQ
745  {\NC=}
746
747\noaligned\tolerant\protected\def\math_common_TB[#1]%
748  {\noalign{\blank[#1]}}
749
750\installmacrostack\NC % maybe more to shared table definitions
751\installmacrostack\TC % idem
752\installmacrostack\NN % idem
753\installmacrostack\EQ % idem
754\installmacrostack\NR % idem
755\installmacrostack\BC % idem
756\installmacrostack\EC % idem
757\installmacrostack\HL % idem
758\installmacrostack\TB % idem
759
760\appendtoks
761    \push_macro_NC
762    \push_macro_TC
763    \push_macro_NN
764    \push_macro_EQ
765    \push_macro_NR
766    \push_macro_HL
767    \push_macro_TB
768    \enforced\let\NC\math_alignment_NC
769    \enforced\let\TC\math_alignment_TC
770    \enforced\let\NN\math_alignment_NN
771    \enforced\let\EQ\math_alignment_EQ
772    \enforced\let\NR\math_alignment_NR
773    \enforced\let\HL\math_alignment_HL
774    \enforced\let\TB\math_common_TB
775    \global\c_math_eqalign_first\conditionaltrue
776    \global\s_strc_math_alignment_inbetween\zeroskip
777\to \everymathalignment
778
779\appendtoks
780    \pop_macro_TB
781    \pop_macro_HL
782    \pop_macro_NR
783    \pop_macro_EQ
784    \pop_macro_NN
785    \pop_macro_TC
786    \pop_macro_NC
787    \global\s_strc_math_alignment_inbetween\zeroskip
788\to \everymathalignmentdone
789
790\newconditional\c_math_alignment_auto_number
791
792% \begingroup not permitted ($$...assignments...\halign... ).. check in luametatex
793
794% \definemathmatrix
795%   [pmatrix]
796%   [matrix:parentheses]
797% % [align=1:right]
798%   [align=all:right]
799% % [align=2:right]
800% % [align={1:left,2:middle,3:right}]
801
802\newgluespec\s_strc_math_alignment_inbetween
803
804\def\strc_math_setup_spacing_aligned#1%
805  {\begingroup
806   % here we abuse the whitespace setter
807   \edef\v_spac_whitespace_current{#1\c!spaceinbetween}%
808   \ifempty\v_spac_whitespace_current
809     \global\s_strc_math_alignment_inbetween\zeroskip
810   \orelse\ifgridsnapping
811     \global\s_strc_math_alignment_inbetween\zeroskip
812   \else
813     \spac_whitespace_setup
814     \global\s_strc_math_alignment_inbetween\parskip
815   \fi
816   \endgroup}
817
818\newinteger  \c_math_alignment_packed_signal
819\newdimension\d_math_alignment_packed_margin
820
821\def\math_alignment_packed_start
822  {%\math_eqalign_set_defaults
823   \c_strc_formulas_check_width\zerocount
824   \c_math_alignment_packed_signal{\c_strc_formulas_align_packed*\pluscclvi}%
825   \d_math_alignment_packed_margin\rightskip
826   \mathatom
827     \s!class \mathwrappedcode
828     \s!attr  \mathnumberlocationattribute \c_math_alignment_packed_signal
829   \relax
830   \bgroup
831 % \scratchdimen\mathalignmentparameter\c!leftmargin\relax
832 % \ifzeropt\scratchdimen\else\kern\scratchdimen\fi
833 % \mathalignmentparameter\c!left\relax
834   \math_fenced_start_wrap{\mathalignmentparameter\c!fences}%
835   \mathatom
836     \s!class \mathconstructcode
837   \bgroup}
838
839\def\math_alignment_packed_stop
840  {\egroup
841   \math_fenced_stop_wrap
842 % \mathalignmentparameter\c!right\relax
843 % \scratchdimen\mathalignmentparameter\c!rightmargin\relax
844 % \ifzeropt\scratchdimen\else\kern\scratchdimen\fi
845 % \setbox\scratchbox\hbox{\mathalignmentparameter\c!text}%
846 % \ifvoid\scratchbox\else
847 %   \kern\mathalignmentparameter\c!textdistance
848 %   \vcenter{\box\scratchbox}%
849 % \fi
850   \egroup
851   \d_math_alignment_packed_margin\zeropoint
852   \c_math_alignment_packed_signal\zerocount}
853
854\permanent\tolerant\protected\def\math_alignment_start[#1]#*[#S#2]%
855  {\begingroup
856   \currentmathblobnesting\minusone
857   \cdef\currentmathalignment{#1}%
858   \ifarguments\or\or
859     \setupmathalignment[#1][#2]%
860   \fi
861   \ifcstok{\mathalignmentparameter\c!adaptive}\v!yes
862     \c_math_align_reformat_mode\conditionaltrue
863   \else
864     \c_math_align_reformat_mode\conditionalfalse
865   \fi
866   \math_alignment_location_check{\mathalignmentparameter\c!location}% vcenter etc
867   %
868   \expand\everymathalignment
869   \c_math_eqalign_row   \zerocount
870   \c_math_eqalign_column\zerocount
871   \processcommacommand
872     [\mathalignmentparameter\c!align]%
873     {\advanceby\c_math_eqalign_column\plusone\math_eqalign_set_column}% takes argument
874   \global\c_math_eqalign_column\plusone
875   %
876   \edef\p_math_alignment_number{\mathalignmentparameter\c!number}%
877   \strc_math_setup_spacing_aligned\mathalignmentparameter
878   % make preamble
879   \ifcstok{\formulaparameter\c!location}\v!left
880     \math_prepare_l_eqalign_no
881   \else
882     \math_prepare_r_eqalign_no
883   \fi
884   %
885   \ifcase\c_strc_formulas_align_packed\else
886     \math_alignment_packed_start
887   \fi
888 % \everycr{\ifcase\c_math_eqalign_row\else\noalign{\penalty\interdisplaylinepenalty}\fi}%
889   \math_alignment_location_box \bgroup
890   \math_halign_checked\expandafter\bgroup\the\scratchtoks\crcr}
891
892\def\math_alignment_stop % can be protected
893  {\crcr
894   \egroup
895   \egroup
896   \ifcase\c_strc_formulas_align_packed\else
897     \math_alignment_packed_stop
898   \fi
899   \expand\everymathalignmentdone
900   \endgroup}
901
902\installcorenamespace{mathalignment}
903\installcorenamespace{mathalignmentvariant}
904
905\installcommandhandler \??mathalignment {mathalignment} \??mathalignment
906
907\appendtoks
908              \frozen\protected\instance\edefcsname\e!start\currentmathalignment\endcsname{\math_alignment_start[\currentmathalignment]}%
909    \noaligned\frozen\protected\instance \defcsname\e!stop \currentmathalignment\endcsname{\math_alignment_stop}%
910\to \everydefinemathalignment
911
912% to be tested
913%
914% \appendtoks
915%               \frozen\instance\protected\defcsname\e!start\currentmathalignment\endcsname{\math_alignment_start[\currentmathalignment]}%
916%     \noaligned\frozen\instance\protected\defcsname\e!stop \currentmathalignment\endcsname{\math_alignment_stop}%
917% \to \everydefinemathalignment
918
919\setupmathalignment
920  [\c!n=2,
921   \c!m=1,
922   \c!leftmargin=\zeropoint,
923   \c!rightmargin=\zeropoint,
924   \c!fences=,
925   \c!left=,
926   \c!right=,
927   \c!distance=\emwidth,
928   \c!location=\v!formula,
929   \c!spaceinbetween=\formulaparameter\c!spaceinbetween,
930   \c!numberthreshold=\zeropoint,
931   \c!grid=\v!math,
932  %\c!rulecolor=red,
933   \c!moffset=.25\exheight,
934   \c!toffset=\mathalignmentparameter\c!moffset,
935   \c!boffset=\mathalignmentparameter\c!moffset,
936   \c!rulethickness=\linewidth]
937
938\definemathalignment[align]            % default case (this is what amstex users expect)
939\definemathalignment[\v!mathalignment] % prefered case (this is cleaner, less clashing)
940
941% special case.. in case one mistypes ..
942
943\ifdefined \startalignment
944
945    \pushoverloadmode
946
947    \aliased\let\align_math_normal_start\startalign
948    \aliased\let\align_math_normal_stop \stopalign
949
950    \aliased\let\align_text_normal_start\startalignment
951    \aliased\let\align_text_normal_stop \stopalignment
952
953    \permanent\overloaded\protected\def\startalign
954      {\ifmmode
955         \enforced\let\stopalign\align_math_normal_stop % cannot be a protected def ... lookahead in align
956         \expandafter\align_math_normal_start
957       \orelse\ifinformula
958         \enforced\let\stopalign\align_math_normal_stop
959         \expandafter\align_math_normal_start
960       \else
961         \enforced\let\stopalign\align_text_normal_stop
962         \expandafter\align_text_normal_start
963       \fi}
964
965    \aliased\let\stopalign\relax
966
967    \permanent\overloaded\protected\def\startalignment
968      {\ifmmode
969         \enforced\let\stopalignment\align_math_normal_stop % cannot be a protected def ... lookahead in align
970         \expandafter\align_math_normal_start
971       \orelse\ifinformula
972         \enforced\let\stopalignment\align_math_normal_stop % cannot be a protected def ... lookahead in align
973         \expandafter\align_math_normal_start
974       \else
975         \enforced\let\stopalignment\align_text_normal_stop
976         \expandafter\align_text_normal_start
977       \fi}
978
979    \aliased\let\stopalignment\relax
980
981    \pushoverloadmode
982
983\fi
984
985%
986
987\protected\def\math_first_in_eqalign % protection prevents tagging expansion
988  {\global\c_math_eqalign_column\plusone
989   \global\advanceby\c_math_eqalign_row\plusone
990   \currentmathblobnesting\minusone
991   \dostarttaggednodetail\t!subformula
992   \dostarttaggednodetail\t!math
993   }
994
995\protected\def\math_next_in_eqalign % protection prevents tagging expansion
996  {\global\advanceby\c_math_eqalign_column\plusone
997   \currentmathblobnesting\minusone}
998
999\protected\def\math_left_of_eqalign
1000  {\ifcsname\??mathalignmentvariant\the\c_math_eqalign_column\endcsname
1001     \ifcase\lastnamedcs \or \relax \or \hfill \or \hfill \fi
1002   \orelse\ifcsname\??mathalignmentvariant\the\zerocount\endcsname
1003     \ifcase\lastnamedcs \or \relax \or \hfill \or \hfill \fi
1004   \orelse\ifcsname\??mathalignmentvariant\tointeger{\c_math_eqalign_column-\c_math_eqalign_repeat}\endcsname
1005     \ifcase\lastnamedcs \or \relax \or \hfill \or \hfill \fi
1006   \fi}
1007
1008\protected\def\math_right_of_eqalign
1009  {\ifcsname\??mathalignmentvariant\the\c_math_eqalign_column\endcsname
1010     \ifcase\lastnamedcs \or \hfill \or \relax \or \hfill \fi
1011   \orelse\ifcsname\??mathalignmentvariant\the\zerocount\endcsname
1012     \ifcase\lastnamedcs \or \hfill \or \relax \or \hfill \fi
1013   \orelse\ifcsname\??mathalignmentvariant\tointeger{\c_math_eqalign_column-\c_math_eqalign_repeat}\endcsname
1014     \ifcase\lastnamedcs \or \hfill \or \relax \or \hfill \fi
1015   \fi}
1016
1017\newconditional\c_math_alignment_local_number % not used but when true puts in front (todo)
1018
1019\def\math_number_right_of_eqalign
1020  {\ifcase\d_strc_formulas_number\else
1021     \ifconditional\c_math_alignment_local_number
1022       \ifcase\c_strc_math_number_location\or\or
1023         \strc_math_flush_number_box
1024       \fi
1025     \else
1026       \strc_math_flush_number_box
1027     \fi
1028   \fi}
1029
1030\def\math_number_left_of_eqalign
1031  {\ifcase\d_strc_formulas_number\else
1032     \ifconditional\c_math_alignment_local_number
1033       \ifcase\c_strc_math_number_location\or
1034         \strc_math_flush_number_box
1035       \fi
1036     \fi
1037   \fi}
1038
1039\protected\def\math_eqalign_set_column_indeed[#1:#2:#3]% we don't really check for all (so * will do too) ... yet
1040  {\ifempty{#2}%
1041     % current counter
1042   \orelse\ifchknumber#1\or
1043     \c_math_eqalign_column\lastchknumber
1044   \else
1045     \c_math_eqalign_column\zerocount
1046   \fi
1047   \expandafter\integerdef\csname\??mathalignmentvariant\the\c_math_eqalign_column\endcsname
1048     \ifcsname\??mathalignmentvariant#2\endcsname\lastnamedcs\else\zerocount\fi\relax}
1049
1050\def\math_eqalign_set_column#1%
1051  {\normalexpanded{\math_eqalign_set_column_indeed[#1::]}}
1052
1053\def\math_eqalign_set_columns_step
1054  {\advanceby\c_math_eqalign_column\plusone
1055  %\c_math_matrix_columns\c_math_eqalign_column
1056   \math_eqalign_set_column}
1057
1058\def\math_eqalign_set_columns#1%
1059  {\c_math_eqalign_column\zerocount
1060   \rawprocesscommacommand[#1]\math_eqalign_set_columns_step}
1061
1062% can't we reuse these numbers ?
1063
1064\letcsname\??mathalignmentvariant\v!normal    \endcsname\zerocount
1065\letcsname\??mathalignmentvariant\v!flushright\endcsname\plusone
1066\letcsname\??mathalignmentvariant\v!left      \endcsname\plusone
1067\letcsname\??mathalignmentvariant\v!right     \endcsname\plustwo
1068\letcsname\??mathalignmentvariant\v!flushleft \endcsname\plustwo
1069\letcsname\??mathalignmentvariant\v!middle    \endcsname\plusthree
1070
1071%D \starttyping
1072%D \placeformula[eqn0]\startformula \startalign[n=1] a\NR       \stopalign \stopformula See \in[eqn0]
1073%D \placeformula[eqn1]\startformula \startalign[n=1] a\NR       \stopalign \stopformula See \in[eqn1]
1074%D \placeformula      \startformula \startalign[n=1] a\NR[eqn2] \stopalign \stopformula See \in[eqn2]
1075%D \placeformula[eqn3]\startformula \startalign[n=1] a\NR[+]    \stopalign \stopformula See \in[eqn3]
1076%D \stoptyping
1077
1078%D \startbuffer
1079%D \placeformula \startformula \startalign
1080%D \NC  a \EQ b \NR[+]
1081%D \NC  c \EQ d \NR
1082%D \NC    \EQ f \NR[for:demo-a-1]
1083%D \NC    \EQ g \NR[for:demo-a-2][a]
1084%D \NC    \EQ h \NR[for:demo-a-3][b]
1085%D \NC    \EQ i \NR
1086%D \stopalign \stopformula
1087%D \stopbuffer
1088%D
1089%D \typebuffer \getbuffer
1090%D
1091%D \startbuffer
1092%D \placeformula \startformula \startalign
1093%D \NC a \EQ b \NR[+]
1094%D \NC c \EQ d \NR
1095%D \NC   \EQ f \NR
1096%D \NC   \EQ g \NR
1097%D \NC   \EQ h \NR
1098%D \NC   \EQ i \NR[+]
1099%D \stopalign \stopformula
1100%D \stopbuffer
1101%D
1102%D \typebuffer \getbuffer
1103%D
1104%D \startbuffer
1105%D \placeformula \startformula \startalign
1106%D \NC  a \NC \eq  b \NR[+]
1107%D \NC  c \NC \neq d \NR
1108%D \NC    \NC \neq f \NR[for:demo-b-1]
1109%D \NC    \NC \geq g \NR[for:demo-b-2][a]
1110%D \NC    \NC \leq h \NR[for:demo-b-3][b]
1111%D \NC    \NC \neq i \NR
1112%D \stopalign \stopformula
1113%D \stopbuffer
1114%D
1115%D \typebuffer \getbuffer
1116%D
1117%D \startbuffer
1118%D \placeformula \startformula \startalign[n=3,align={left,middle,right}]
1119%D \NC       l \NC = \NC r     \NR
1120%D \NC    left \NC = \NC right \NR
1121%D \stopalign \stopformula
1122%D \stopbuffer
1123%D
1124%D \typebuffer \getbuffer
1125%D
1126%D \startbuffer
1127%D \placeformula \startformula \startalign[n=3,align={right,middle,left}]
1128%D \NC       l \NC = \NC r     \NR
1129%D \NC    left \NC = \NC right \NR
1130%D \stopalign \stopformula
1131%D \stopbuffer
1132%D
1133%D \typebuffer \getbuffer
1134%D
1135%D \startbuffer
1136%D \placeformula \startformula \startalign[n=3,align={middle,middle,middle}]
1137%D \NC       l \NC = \NC r     \NR
1138%D \NC    left \NC = \NC right \NR
1139%D \stopalign \stopformula
1140%D \stopbuffer
1141%D
1142%D \typebuffer \getbuffer
1143%D
1144%D \startbuffer
1145%D \placeformula
1146%D \startformula
1147%D     \startalign[n=3,align={middle,middle,middle}]
1148%D         \NC a  \NC = \NC b  \NR[+]
1149%D         \NC 2a \NC = \NC 2b \NR
1150%D     \stopalign
1151%D \stopformula
1152%D \stopbuffer
1153%D
1154%D \typebuffer \getbuffer
1155%D
1156%D \startbuffer
1157%D \placeformula
1158%D \startformulas
1159%D     \setupmathalignment[n=3,align={middle,middle,middle}]%
1160%D     \startformula
1161%D         \startalign
1162%D             \NC a  \NC = \NC b  \NR[+]
1163%D             \NC 2a \NC = \NC 2b \NR
1164%D         \stopalign
1165%D     \stopformula
1166%D     \startformula
1167%D         \startalign
1168%D             \NC a  \NC = \NC b  \NR[+]
1169%D             \NC 2a \NC = \NC 2b \NR
1170%D         \stopalign
1171%D     \stopformula
1172%D \stopformulas
1173%D \stopbuffer
1174%D
1175%D \typebuffer \getbuffer
1176%D
1177%D \startbuffer
1178%D \placeformula
1179%D \startformulas
1180%D     \dorecurse{5}{\startformula
1181%D         \startalign[n=3,align={middle,middle,middle}]
1182%D             \NC a  \NC = \NC b  \NR[+]
1183%D             \NC 2a \NC = \NC 2b \NR
1184%D         \stopalign
1185%D     \stopformula}
1186%D \stopformulas
1187%D \stopbuffer
1188%D
1189%D \typebuffer \getbuffer
1190
1191%D \macros
1192%D   {definemathcases, setupmathcases, startmathcases}
1193%D
1194%D Another wish \unknown
1195
1196\installcorenamespace{mathcases}
1197
1198\installcommandhandler \??mathcases {mathcases} \??mathcases
1199
1200\setupmathcases
1201  [\c!distance=\emwidth,
1202   \c!strut=\v!yes, % new
1203   \c!spaceinbetween=\mathalignmentparameter\c!spaceinbetween,
1204  %\c!numberdistance=2.5\emwidth,
1205   \c!numberdistance=\zeropoint]
1206
1207\appendtoks
1208    \frozen\instance\protected\edefcsname\e!start\currentmathcases\endcsname{\math_cases_start[\currentmathcases]}%
1209    \frozen\instance          \defcsname \e!stop \currentmathcases\endcsname{\math_cases_stop}%
1210\to \everydefinemathcases
1211
1212%D Why not \unknown:
1213%D
1214%D \starttyping
1215%D \definemathcases[mycases][simplecommand=mycases]
1216%D
1217%D \startformula
1218%D \startmycases
1219%D \NC 1  \NC x>0 \NR
1220%D \NC -1 \NC x<0 \NR
1221%D \stopmycases
1222%D \stopformula
1223%D
1224%D \startformula
1225%D     \mycases{1,x>0;-1,x<0}
1226%D \stopformula
1227%D \stoptyping
1228
1229\permanent\tolerant\protected\def\math_cases_simple[#1]#*[#2]#:#3%
1230  {\begingroup
1231   \cdef\currentmathcases{#1}%
1232   \setupcurrentmathcases[#2]%
1233   \math_cases_start[\currentmathcases]%
1234   \clf_simplecases{\mathcasesparameter\c!action}{#3}%
1235   \math_cases_stop
1236   \endgroup}
1237
1238\appendtoks
1239    \edef\p_simplecommand{\mathcasesparameter\c!simplecommand}%
1240    \ifempty\p_simplecommand\else
1241        \frozen\protected\instance\edefcsname\p_simplecommand\endcsname{\math_cases_simple[\currentmathcases]}%
1242    \fi
1243\to \everydefinemathcases
1244
1245\let\math_cases_strut\relax
1246
1247\newinteger\c_math_cases_nc
1248
1249\def\math_cases_NC_zero
1250  {\ifmmode\else
1251     \startimath
1252     \usemathstyleparameter\mathcasesparameter\c!mathstyle
1253   \fi}
1254
1255\def\math_cases_NC_one
1256  {\mathcasesparameter\c!lefttext\relax
1257   \ifmmode\stopimath\fi
1258   \aligntab
1259   \ifmmode\else
1260     \startimath
1261     \usemathstyleparameter\mathcasesparameter\c!mathstyle
1262   \fi
1263   \mathcasesparameter\c!righttext\relax}
1264
1265\def\math_cases_NC_two
1266  {\ifmmode\stopimath\fi}
1267
1268\def\math_cases_TC_zero % needs checking
1269 %{\ifmmode\else\startimath\fi}
1270  {}
1271
1272\def\math_cases_TC_one
1273  {\ifmmode\stopimath\fi
1274   \aligntab}
1275
1276\def\math_cases_TC_two
1277 %{\ifmmode\stopimath\fi} % needs checking
1278  {}
1279
1280\permanent\protected\def\math_cases_NC
1281  {\ifcase\c_math_cases_nc
1282     \expandafter\math_cases_NC_zero
1283   \or
1284     \expandafter\math_cases_NC_one
1285   \or
1286     \expandafter\math_cases_NC_zero
1287   \else
1288     % error
1289   \fi
1290   \global\advanceby\c_math_cases_nc\plusone}
1291
1292\permanent\protected\def\math_cases_TC
1293  {\ifcase\c_math_cases_nc
1294     \expandafter\math_cases_TC_zero
1295   \or
1296     \expandafter\math_cases_TC_one
1297   \or
1298     \expandafter\math_cases_TC_two
1299   \else
1300     % error
1301   \fi
1302   \global\advanceby\c_math_cases_nc\plusone}
1303
1304%D The \type {#.} catches this case:
1305%D
1306%D \starttyping
1307%D \dm {
1308%D     \startcases[righttext=\mtext{if }]
1309%D         \NC x  \NC x > 0 \NR
1310%D         \NC -x \NC x < 0 \NR
1311%D
1312%D     \stopcases
1313%D }
1314%D \stoptyping
1315
1316% \noaligned\tolerant\permanent\protected\def\math_cases_NR#.[#1]#*[#2]%
1317%   {\unskip
1318%    \ifmmode\stopimath\fi
1319%    \aligntab
1320%    \global\c_math_cases_nc\zerocount
1321%    \strc_formulas_place_number_nested{#1}{#2}%
1322%    \math_number_right_of_eqalign
1323%    \box\b_strc_formulas_number
1324%    \crcr}
1325
1326\noaligned\tolerant\permanent\protected\def\math_cases_NR#.[#1]#*[#2]%
1327  {\unskip
1328   \ifmmode\stopimath\fi
1329   \aligntab
1330   \global\c_math_cases_nc\zerocount
1331% \c_strc_formulas_number_in_alignment\conditionaltrue
1332% \dostarttaggednodetail\t!mtext
1333%    \strc_formulas_place_number_nested{#1}{#2}%
1334% \dostoptagged
1335\math_place_number_in_alignment{#1}{#2}%
1336   \math_number_right_of_eqalign
1337   \dostarttaggednodetail\t!mtablerow
1338   \dostarttaggednodetail\t!mtablecell
1339   \hpack{\box\b_strc_formulas_number}%
1340   \dostoptagged % cell
1341   \dostoptagged % row
1342   \crcr}
1343
1344\installglobalmacrostack\c_math_cases_nc
1345
1346\permanent\tolerant\protected\def\math_cases_start[#1]#*[#S#2]%
1347  {\begingroup
1348   \currentmathblobnesting\minusone
1349   \cdef\currentmathcases{#1}%
1350   \ifarguments\or\or
1351     \setupcurrentmathcases[#2]%
1352   \fi
1353   \edef\p_strut{\mathcasesparameter\c!strut}%
1354   \ifx\p_strut\v!yes
1355     \enforced\let\math_cases_strut\strut
1356   \else
1357     \enforced\let\math_cases_strut\relax
1358   \fi
1359   \push_macro_c_math_cases_nc
1360   \mathatom \s!class \mathwrappedcode \bgroup
1361   \scratchdimen{\mathcasesparameter\c!leftmargin}%
1362   \ifzeropt\scratchdimen\else\kern\scratchdimen\fi
1363   \mathcasesparameter\c!left
1364   \math_fenced_start_wrap{\mathcasesparameter\c!fences}%
1365   \mathatom \s!class \mathconstructcode \bgroup
1366   \vcenter\bgroup
1367   \mathbeginclass\zerocount % added, cases can be in an alignment cell
1368   \enforced\let\MC\math_cases_NC
1369   \enforced\let\NC\math_cases_NC
1370   \enforced\let\NR\math_cases_NR
1371   \enforced\let\TC\math_cases_TC
1372   \enforced\let\TB\math_common_TB
1373   \math_eqalign_set_defaults
1374   \global\c_math_eqalign_column\plusone
1375   \global\c_math_eqalign_row\plusone
1376   \global\c_math_cases_nc\zerocount
1377   \strc_math_setup_spacing_aligned\mathcasesparameter
1378   \enablemathalignrelocate
1379   \dostarttagged\t!math{cases}% \empty
1380   \dostarttagged\t!mtable\currentmathcases
1381   \halign
1382     \s!callback
1383       \align_callback_mathalign
1384     \s!attr
1385       \mathnumberlocationattribute \zerocount
1386     \bgroup % use \indexofregister here
1387     \dostarttaggednodetail\t!mtablerow
1388     \ifmmode\else\startimath\fi
1389     \usemathstyleparameter\mathcasesparameter\c!mathstyle
1390     \dostarttaggednodetail\t!mtablecell
1391     \aligncontent
1392     \dostoptagged % cell
1393     \ifmmode\stopimath\fi
1394     \hfil
1395     \aligntab
1396     \kern{\mathcasesparameter\c!distance}%
1397     \math_cases_strut % looks better
1398     \dostarttaggednodetail\t!mtablecell
1399     \aligncontent
1400     \dostoptagged % cell
1401     \hfil
1402     \aligntab
1403     \kern{\mathcasesparameter\c!numberdistance}%
1404     \span
1405     \math_text_in_eqalign
1406       {\dostarttaggednodetail\t!mtablecell
1407        \aligncontent
1408        \dostoptagged % cell
1409        \dostoptagged}% row
1410     \crcr} % todo: number
1411
1412\noaligned\permanent\protected\def\math_cases_stop
1413  {\crcr
1414   \egroup
1415   \dostoptagged % table
1416   \dostoptagged % math
1417   \egroup
1418   \egroup
1419   \math_fenced_stop_wrap
1420   \mathcasesparameter\c!right\relax
1421   \scratchdimen{\mathcasesparameter\c!rightmargin}%
1422   \ifzeropt\scratchdimen\else\kern\scratchdimen\fi
1423   \egroup
1424   \pop_macro_c_math_cases_nc
1425   \endgroup}
1426
1427% \definemathfence [cases] [\c!left="007B,\c!right=\v!none]
1428% \definemathfence [sesac] [\c!left=\v!none,\c!right="007D]
1429
1430\definemathcases[cases]
1431\definemathcases[\v!mathcases]
1432
1433% This might become key=cases in the end:
1434
1435\setupmathcases
1436% [cases]
1437  [\c!leftmargin=\zeropoint,
1438   \c!rightmargin=\zeropoint,
1439   \c!left=,
1440   \c!right=,
1441   \c!fences=cases]
1442
1443\definemathcases
1444  [sesac]
1445  [\c!fences=sesac]
1446
1447%D \startbuffer
1448%D \placeformula \startformula \startcases
1449%D \NC 2 \NC y > 0     \NR
1450%D \NC 7 \NC x = 7     \NR[+]
1451%D \NC 4 \TC otherwise \NR
1452%D \stopcases \stopformula
1453%D \stopbuffer
1454%D
1455%D \typebuffer \getbuffer
1456%D
1457%D \startbuffer
1458%D \placeformula \startformula x \startcases
1459%D \NC 2 \NC y > 0     \NR[+]
1460%D \NC 7 \NC x = 7     \NR
1461%D \NC 4 \TC otherwise \NR
1462%D \stopcases \stopformula
1463%D \stopbuffer
1464%D
1465%D \typebuffer \getbuffer
1466%D
1467%D \startbuffer
1468%D \placeformula \startformula \startcases
1469%D \NC 2 \NC y > 0     \NR
1470%D \NC 7 \NC x = 7     \NR
1471%D \NC 4 \TC otherwise \NR
1472%D \stopcases \stopformula
1473%D \stopbuffer
1474%D
1475%D \typebuffer \getbuffer
1476%D
1477%D \startbuffer
1478%D \placeformula \startformula x \startcases
1479%D \NC 2 \NC y > 0     \NR
1480%D \NC 7 \NC x = 7     \NR
1481%D \NC 4 \TC otherwise \NR
1482%D \stopcases \stopformula
1483%D \stopbuffer
1484%D
1485%D \typebuffer \getbuffer
1486
1487%D \macros
1488%D   {definemathmatrix, setupmathmatrix, startmathmatrix}
1489%D
1490%D Yet another one \unknown. This time we implement the lot a bit
1491%D different which is a side effect of getting the tagging right. In
1492%D retrospect the main alignment could be done this way but \unknown
1493
1494%D In the end is is way easier to not use alignments and just paste boxes
1495%D together but let's be a bit texie.
1496
1497\installcorenamespace{mathmatrix}
1498
1499\installcommandhandler \??mathmatrix {mathmatrix} \??mathmatrix
1500
1501\setupmathmatrix
1502  [\c!distance=\emwidth,
1503   \c!fences=,
1504   \c!left=,
1505   \c!right=,
1506   \c!align=\v!middle,
1507   \c!leftmargin=\zeropoint,
1508   \c!rightmargin=\zeropoint,
1509   \c!rulecolor=,
1510   \c!rulethickness=\linewidth]
1511
1512\appendtoks
1513    \frozen\instance\protected\edefcsname\e!start\currentmathmatrix\endcsname{\math_matrix_start[\currentmathmatrix]}%
1514    % \noaligned\protected should work here:
1515    \frozen\instance          \defcsname \e!stop \currentmathmatrix\endcsname{\math_matrix_stop}% no u else lookahead problem
1516\to \everydefinemathmatrix
1517
1518\newinteger\c_math_matrix_columns
1519
1520\def\math_matrix_start_table
1521  {\global\c_math_eqalign_column\zerocount
1522   \global\c_math_eqalign_row\zerocount
1523   \global\c_math_matrix_columns\zerocount
1524   \dostarttaggednodetail\t!math
1525   \dostarttaggednodetail\t!mtable}
1526
1527\def\math_matrix_stop_table
1528  {\dostoptagged
1529   \dostoptagged}
1530
1531\def\math_matrix_start_row
1532  {\beginlocalcontrol
1533   \global\c_math_matrix_columns\c_math_eqalign_column
1534   \global\c_math_eqalign_column\zerocount
1535   \global\advanceby\c_math_eqalign_row\plusone
1536   \dostarttaggednodetail\t!mtablerow
1537   \endlocalcontrol}
1538
1539\def\math_matrix_stop_row
1540  {\beginlocalcontrol
1541   \dostoptagged
1542   \endlocalcontrol}
1543
1544\protected\def\math_matrix_start_cell
1545  {\currentmathblobnesting\minusone
1546   \dostarttaggednodetail\t!mtablecell
1547   \hss
1548   \math_left_of_eqalign
1549   \everycr\emptytoks
1550   \startimath
1551   \math_matrix_set_style}
1552
1553\protected\def\math_matrix_stop_cell
1554  {\stopimath
1555   \math_right_of_eqalign
1556   \hss
1557   \dostoptagged}
1558
1559% \dorecurse{10}{test }
1560%
1561% \startformula
1562%     \startmatrix[left=\left(,right=\right)]
1563%       \NC x \NC       \NC yy \NC       \NC zzz \NR
1564%       \NC x \NC \dots \NC yy \NC \dots \NC zzz \NR
1565%       \HF[2]                                   \NR
1566%       \NC x \NC \dots \NC yy \NC \dots \NC zzz \NR
1567%       \HF                                      \NR
1568%       \NC x \NC \dots \NC yy \NC \dots \NC zzz \NR
1569%       \NC \HF[2]                               \NR
1570%       \NC x \NC \dots \NC yy \NC \dots \NC zzz \NR
1571%       \NC \NC \HF[2][rule]                     \NR
1572%       \NC x \NC \dots \NC yy \NC \dots \NC zzz \NR
1573%       \HL
1574%       \NC x \VL \dots \VL yy \NC \dots \VL zzz \NR
1575%       \NC x \VL \dots \VL yy \NC \dots \VL zzz \NR
1576%       \HL
1577%     \stopmatrix
1578% \stopformula
1579%
1580% \dorecurse{10}{test }
1581%
1582% \startformula
1583%     \startmatrix[left=\left(,right=\right)]
1584%       \NC        \TT \ttx 1 \NC       \TT \ttx 2 \NC       \TT \ttx 3 \NC        \NR
1585%       \LT \ttx 1 \NC a      \NC \dots \NC aa     \NC \dots \NC aaa    \RT \ttx 1 \NR
1586%       \LT \ttx 2 \NC b      \NC \dots \NC bb     \NC \dots \NC bbb    \RT \ttx 2 \NR
1587%       \LT \ttx 3 \NC c      \NC \dots \NC cc     \NC \dots \NC ccc    \RT \ttx 3 \NR
1588%       \NC        \BT \ttx 1 \NC       \BT \ttx 2 \NC       \BT \ttx 3 \NC        \NR
1589%     \stopmatrix
1590% \stopformula
1591%
1592% \dorecurse{10}{test }
1593%
1594% \startformula
1595%     \startmatrix[left=\left(,right=\right)]
1596%       \NC        \TT \ttx 1 \NC       \TT \ttx 2 \NC       \TT \ttx 3 \NR
1597%       \LT \ttx 1 \NC a      \NC \dots \NC aa     \NC \dots \NC aaa    \NR
1598%       \LT \ttx 2 \NC b      \NC \dots \NC bb     \NC \dots \NC bbb    \NR
1599%       \LT \ttx 3 \NC c      \NC \dots \NC cc     \NC \dots \NC ccc    \NR
1600%       \NC        \BT \ttx 1 \NC       \BT \ttx 2 \NC       \BT \ttx 3 \NR
1601%     \stopmatrix
1602% \stopformula
1603%
1604% \dorecurse{10}{test }
1605
1606\newtoks\everymathmatrix
1607
1608\tolerant\permanent\def\math_matrix_HF[#1]#*[#2]% [n] [name] | [name] | [n]
1609  {\expandedloop
1610     \plusone
1611     {\ifchknumber#1\or\lastchknumber\else(\c_math_matrix_columns+\minusone)\fi*\plustwo}%
1612     \plusone
1613   {\omit\span}%
1614   \normalexpanded{\filler[%
1615     \ifcsname\??filleralternative matrix:#1\endcsname matrix:#1\orelse
1616     \ifcsname\??filleralternative matrix:#2\endcsname matrix:#2\orelse
1617     \ifcsname\??filleralternative        #1\endcsname        #1\orelse
1618     \ifcsname\??filleralternative        #2\endcsname        #2\else
1619                                                matrix:\v!normal\fi
1620   ]}}
1621
1622\appendtoks
1623   \enforced\let\HF\math_matrix_HF
1624\to \everymathmatrix
1625
1626\definefiller
1627  [matrix:\v!normal]
1628  [\c!symbol=\textperiod,
1629  %\c!style=\v!normal,
1630   \c!method=\v!broad,
1631   \c!width=\emwidth,
1632   \c!leftmargin=-.1\emwidth,
1633   \c!rightmargin=-.1\emwidth]
1634
1635\definefiller
1636  [matrix:\v!middle]
1637  [\c!symbol=\textperiod,
1638  %\c!style=\v!normal,
1639   \c!method=\v!middle,
1640   \c!width=\emwidth,
1641   \c!leftmargin=.5\emwidth,
1642   \c!rightmargin=.5\emwidth]
1643
1644\definefiller
1645  [matrix:ldots]
1646  [matrix:\v!normal]
1647
1648\definefiller
1649  [matrix:cdots]
1650  [matrix:\v!normal]
1651  [\c!symbol=\cdot]
1652
1653% We could construct a preamble with alignment and such embedded but the number
1654% of matrices with many rows is normally so low that it doesn't pay of at all.
1655
1656\newconditional\c_math_matrix_first
1657\newconstant   \c_math_matrix_anchor_mode
1658\newconditional\c_math_matrix_sl_seen
1659
1660% enabled    : 1
1661% left/both  : 2
1662% right/both : 4
1663
1664\permanent\protected\def\setmathmatrixanchoring[#1]%
1665  {\c_math_matrix_anchor_mode\zerocount
1666   \processaction
1667     [#1]%
1668     [\v!both=>\c_math_matrix_anchor_mode\plusone,%
1669       \v!yes=>\c_math_matrix_anchor_mode\plusone]}
1670
1671\def\math_matrix_anchor
1672  {\ifcase\c_math_matrix_anchor_mode\else
1673     \markanchor{matrix}{\numexpr\c_math_eqalign_column+\plusone\relax}\c_math_eqalign_row
1674   \fi}
1675
1676\protected\def\math_matrix_anchor_first
1677  {\relax
1678   \ifcase\c_math_matrix_anchor_mode\else
1679     \math_matrix_anchor
1680   % \ifdim\d_math_eqalign_distance>\zeropoint
1681   %   \ifbitwiseand\c_math_matrix_anchor_mode\plustwo
1682   %      \kern.5\d_math_eqalign_distance
1683   %   \fi
1684   % \fi
1685   \fi}
1686
1687\protected\def\math_matrix_anchor_last
1688  {\relax
1689   \ifcase\c_math_matrix_anchor_mode\else
1690   % \ifdim\d_math_eqalign_distance>\zeropoint
1691   %   \ifbitwiseand\c_math_matrix_anchor_mode\plusfour
1692   %     \kern.5\d_math_eqalign_distance
1693   %   \fi
1694   % \fi
1695     \math_matrix_anchor
1696   \fi}
1697
1698\def\math_matrix_preamble
1699  {\math_matrix_strut
1700   \math_matrix_anchor_first
1701   \global\advanceby\c_math_eqalign_column\plusone
1702   \math_matrix_start_cell
1703     \aligncontent
1704   \math_matrix_stop_cell
1705   \aligntab
1706   \aligntab
1707   \math_matrix_anchor
1708   \kern.5\d_math_eqalign_distance
1709   \aligncontent
1710   \aligntab
1711   \global\advanceby\c_math_eqalign_column\plusone
1712   \math_matrix_start_cell
1713     \aligncontent
1714   \math_matrix_stop_cell}
1715
1716% \permanent\protected\def\math_matrix_NR
1717%   {\math_matrix_anchor_last
1718%    \math_matrix_stop_row
1719%    \math_matrix_pickup
1720%    \crcr
1721%    \math_matrix_start_row}
1722
1723\permanent\protected\def\math_matrix_NR
1724  {% we need to make sure we end the cell first (otherwise export looses mtd)
1725   \math_matrix_stop_cell
1726   \let\math_matrix_stop_cell\relax
1727   %
1728   \math_matrix_anchor_last
1729   \math_matrix_stop_row
1730   \math_matrix_pickup
1731   \crcr
1732   \math_matrix_start_row}
1733
1734\permanent\protected\def\math_matrix_NC
1735  {\ifconditional\c_math_matrix_first
1736     \expandafter\math_matrix_NC_yes
1737   \else
1738     \expandafter\math_matrix_NC_nop
1739   \fi}
1740
1741\permanent\protected\def\math_matrix_pickup{\global\c_math_matrix_first\conditionaltrue}
1742\permanent\protected\def\math_matrix_NC_yes{\global\c_math_matrix_first\conditionalfalse}
1743\permanent\protected\def\math_matrix_NC_nop{\aligntab\aligntab} % avoids lookahead
1744
1745\def\math_matrix_check_rule_step#1%
1746  {\ifchkdim#1\or
1747     \scratchdimen#1\relax
1748 % \orelse\ifchknum#1\or
1749   \orelse\ifchkdim#1pt\or
1750     \scratchdimen#1\d_math_eqalign_rulethickness
1751   \else
1752     \edef\p_rulecolor{#1}
1753   \fi}
1754
1755\def\math_matrix_check_rule[#1]%
1756  {\d_math_eqalign_rulethickness{\mathmatrixparameter\c!rulethickness}%
1757   \scratchdimen\d_math_eqalign_rulethickness
1758   \edef\p_rulecolor{\mathmatrixparameter\c!rulecolor}%
1759   \ifempty{#1}\else
1760     \rawprocesscommalist[#1]\math_matrix_check_rule_step
1761   \fi
1762   \ifempty\p_rulecolor\else
1763     \dousecolorparameter\p_rulecolor
1764   \fi}
1765
1766% These offset are an experiment so we abuse some existing keys or we have to
1767% cook up new ones. Maybe we then should provide small medium big halfline etc.
1768% but all depends on actual demand for this feature.
1769
1770% Musical timestamp VL, NL, SL: Bad Hombre II by Antonio Sanches
1771%
1772% \startformula
1773% \startmatrix[left=\left(,right=\right)]
1774% \NC 0  \NL 0  \NC 0  \NC 2x \NC 1  \NC 0  \NC 0  \NL \NR
1775% \NC 0  \VL 0  \NC 0  \NC 0  \NC 2x \NC 0  \NC 0  \NL \NR
1776% \NC 0  \VL 0  \NC 0  \NC 0  \NC 0  \NC 3x \NC 0  \NL \NR
1777% \NC 0  \NL 0  \NC 0  \NC 0  \NC 0  \NC 0  \NC 4x \VL \NR
1778% \stopmatrix
1779% \stopformula
1780%
1781% \startformula
1782% \startmatrix[left=\left(,right=\right)]
1783% \SL[3]               \NL    \NL    \NL    \NL    \NL \NR
1784% \VL 2x \NL 1  \NL 0  \VL 0  \NL 0  \NL 0  \NL 0  \NL \NR
1785% \VL 0  \NL 2x \NL 1  \VL 0  \NL 0  \NL 0  \NL 0  \NL \NR
1786% \VL 0  \NL 0  \NL 2x \VL 0  \NL 0  \NL 0  \NL 0  \NL \NR
1787% \SL[5]                             \NL    \NL    \NL \NR
1788% \NL 0  \NL 0  \NL 0  \VL 2x \NL 1  \VL 0  \NL 0  \NL \NR
1789% \NL 0  \NL 0  \NL 0  \VL 0  \NL 2x \VL 0  \NL 0  \NL \NR
1790% \NL    \NL    \NL    \SL[3]               \NL    \NL \NR
1791% \NL 0  \NL 0  \NL 0  \NL 0  \NL 0  \VL 3x \VL 0  \NL \NR
1792% \NL    \NL    \NL    \NL    \NL    \SL[2]        \NL \NR
1793% \NL 0  \NL 0  \NL 0  \NL 0  \NL 0  \NL 0  \VL 3x \VL \NR
1794% \NL    \NL    \NL    \NL    \NL    \NL    \SL[1] \NL \NR
1795% \stopmatrix
1796% \stopformula
1797
1798\definesystemattribute[mathalignmentvrule][public]
1799\definesystemattribute[mathalignmenthrule][public]
1800\definesystemattribute[mathalignmenttop]  [public]
1801\definesystemattribute[mathalignmentmid]  [public]
1802\definesystemattribute[mathalignmentbot]  [public]
1803
1804\setupmathmatrix
1805  [\c!moffset=.25\exheight,
1806   \c!toffset=\mathmatrixparameter\c!moffset,
1807   \c!boffset=\mathmatrixparameter\c!toffset]
1808
1809\newconditional\c_math_matrix_trace_hl
1810
1811\installtextracker
1812  {math.matrices.hl}
1813  {\c_math_matrix_trace_hl\conditionaltrue}
1814  {\c_math_matrix_trace_hl\conditionalfalse}
1815
1816\def\math_matrix_HL_indeed#1#2%
1817  {\noalign\bgroup
1818     \math_matrix_check_rule[#2]%
1819     \divideby\scratchdimen\plustwo
1820     \ifdim\scratchdimen>\zeropoint
1821       \attribute\mathalignmenttopattribute\dimexpr\mathmatrixparameter\c!toffset\relax
1822       \attribute\mathalignmentbotattribute\dimexpr\mathmatrixparameter\c!boffset\relax
1823       \scratchdistance{\mathmatrixparameter\c!moffset}%
1824       \ifdim\scratchdistance>\zeropoint
1825         \begingroup
1826         \ifconditional\c_math_matrix_trace_hl
1827           \darkred \hrule \s!width \onepoint
1828         \else
1829           \nohrule
1830         \fi
1831           \s!attr  \mathalignmentvruleattribute\plustwo
1832           \s!height\scratchdistance
1833           \s!depth \zeropoint
1834         \relax
1835         \endgroup
1836       \fi
1837       \hrule
1838         \s!attr  \mathalignmentvruleattribute\plusthree
1839         \s!height\scratchdimen
1840         \s!depth \scratchdimen
1841       \relax
1842       \scratchdimentwo\zeropoint
1843       \ifnum#1>\plusone
1844         \scratchdimenone.125\d_math_eqalign_distance
1845         \localcontrolledloop\plustwo#1\plusone
1846            {\kern\scratchdimenone
1847             \advanceby\scratchdimentwo\scratchdimenone
1848             \hrule
1849               \s!attr  \mathalignmentvruleattribute\plusthree
1850               \s!height\scratchdimen
1851               \s!depth \scratchdimen
1852             \relax
1853             \advanceby\scratchdimentwo\scratchdimen
1854             \advanceby\scratchdimentwo\scratchdimen
1855            }%
1856       \fi
1857       \ifdim\scratchdistance>\zeropoint
1858         \begingroup
1859         \ifconditional\c_math_matrix_trace_hl
1860           \darkgreen \hrule \s!width \onepoint
1861         \else
1862           \nohrule
1863         \fi
1864           \s!attr  \mathalignmentvruleattribute\plusfour
1865           \s!attr  \mathalignmentmidattribute\scratchdimentwo
1866           \s!height\zeropoint
1867           \s!depth \scratchdistance
1868         \relax
1869         \endgroup
1870       \fi
1871     \else
1872        % zero dimensions disable the rule
1873     \fi
1874   \egroup}
1875
1876\permanent\tolerant\noaligned\protected\def\math_matrix_HL  [#1]#*{\math_matrix_HL_indeed\plusone{#1}}
1877\permanent\tolerant\noaligned\protected\def\math_matrix_HLHL[#1]#*{\math_matrix_HL_indeed\plustwo{#1}}
1878
1879\protected\def\math_matrix_vertical_rule_indeed#1#2%
1880  {\math_matrix_check_rule[#2]%
1881   \enablematrixrules
1882   #1
1883      \s!attr   \mathalignmentvruleattribute\plusone
1884      \s!width  \scratchdimen
1885      \s!top   -\dimexpr\mathmatrixparameter\c!toffset\relax
1886      \s!bottom-\dimexpr\mathmatrixparameter\c!boffset\relax
1887   \relax}
1888
1889\protected\def\math_matrix_vertical_rule_yes{\math_matrix_vertical_rule_indeed\vrule  }
1890\protected\def\math_matrix_vertical_rule_nop{\math_matrix_vertical_rule_indeed\novrule}
1891
1892\installcorenamespace{mathmatrixrulealternative}
1893
1894\newboundary\c_math_matrix_vl_boundary
1895%newboundary\c_math_matrix_sl_boundary
1896
1897\protected\def\math_matrix_horizontal_rule_indeed#1#2%
1898  {\math_matrix_check_rule[#2]%
1899   \global\c_math_matrix_first\conditionalfalse
1900   \global\c_math_matrix_sl_seen\conditionaltrue
1901   \enablematrixrules
1902 % \begingroup
1903 % \attribute\mathalignmenthruleattribute\plusone % we check the glue
1904   \leaders#1%
1905      \s!attr   \mathalignmenthruleattribute\plusone
1906      \s!height .5\scratchdimen
1907      \s!depth  .5\scratchdimen
1908    % \s!top   -\dimexpr\mathmatrixparameter\c!toffset\relax
1909    % \s!bottom-\dimexpr\mathmatrixparameter\c!boffset\relax
1910   \hfilll
1911 % \endgroup
1912   \kern{.5\d_math_eqalign_distance}%
1913   \aligntab}
1914
1915\protected\def\math_matrix_horizontal_rule_yes{\math_matrix_horizontal_rule_indeed\hrule  }
1916\protected\def\math_matrix_horizontal_rule_nop{\math_matrix_horizontal_rule_indeed\nohrule}
1917
1918\def\math_matrix_hrule_progress_rest#1%
1919  {\expandedloop
1920     \plusone
1921     {(\ifchknumber#1\or\lastchknumber\else\c_math_matrix_columns\fi)*\plustwo+\minusone}%
1922     \plusone
1923   {\span\omit}}%
1924
1925\def\math_matrix_hrule_progress_first#1%
1926  {\expandedloop
1927     \plusone
1928     {(\ifchknumber#1\or\lastchknumber\else\c_math_matrix_columns\fi+\minusone)*\plustwo+\plusone}%
1929     \plusone
1930   {\span\omit}}%
1931
1932\def\math_matrix_hrule_progress
1933  {\NL
1934   \ifconditional\c_math_matrix_first
1935     \expandafter\math_matrix_hrule_progress_first
1936   \else
1937     \expandafter\math_matrix_hrule_progress_rest
1938   \fi}
1939
1940\tolerant\permanent\protected\def\math_matrix_SL[#1]#*[#2]#*% [n] [name] | [name] | [n]
1941  {\ifcsname\??mathmatrixrulealternative#2\endcsname
1942     \lastnamedcs{#1}{#2}%
1943   \orelse\ifcsname\??mathmatrixrulealternative#1\endcsname
1944     \lastnamedcs{#2}{#1}%
1945   \else
1946     \csname\??mathmatrixrulealternative\v!auto\endcsname{#1}{#2}%
1947   \fi}
1948
1949\defcsname\??mathmatrixrulealternative\v!auto\endcsname#1#2%
1950  {\math_matrix_hrule_progress{#1}%
1951 % \ifzero\c_math_matrix_first
1952 %   \kern-\dimexpr\linewidth\relax
1953 % \else
1954 %   \kern-\dimexpr.5\d_math_eqalign_distance+\linewidth\relax
1955 % \fi
1956   \kern-\dimexpr\ifzero\c_math_matrix_first\else.5\d_math_eqalign_distance+\fi\linewidth\relax
1957   \math_matrix_horizontal_rule_yes{#2}%
1958   %boundary\c_math_matrix_sl_boundary
1959   \enforced\let\SL\math_matrix_SL
1960   \enforced\let\NR\math_matrix_NL_NR}
1961
1962\def\math_matrix_VL_indeed#1#2%%
1963  {\aligntab
1964   \math_matrix_vertical_rule_yes{#2}%
1965   \localcontrolledloop\plustwo#1\plusone
1966     {\kern.125\d_math_eqalign_distance
1967      \math_matrix_vertical_rule_yes{#2}}%
1968   \kern.5\d_math_eqalign_distance
1969   \global\c_math_matrix_first\conditionalfalse
1970   \aligntab
1971   \boundary\c_math_matrix_vl_boundary
1972   \enforced\let\NR\math_matrix_NL_NR}
1973
1974\appendtoks
1975    % vl delegated to lua tex rules
1976    \ifnum\lastboundary=\c_math_matrix_vl_boundary
1977        \kern\ifconditional \c_math_matrix_sl_seen-1.5\else-.5\fi\d_math_eqalign_distance
1978    \fi
1979\to \t_math_matrix_NL_NR
1980
1981\permanent\tolerant\protected\def\math_matrix_VL  [#1]#*{\math_matrix_VL_indeed\plusone{#1}}
1982\permanent\tolerant\protected\def\math_matrix_VLVL[#1]#*{\math_matrix_VL_indeed\plustwo{#1}}
1983
1984\permanent\tolerant\protected\def\math_matrix_NL[#1]#*%
1985  {\span\omit
1986   \ifconditional\c_math_matrix_first\else
1987     \kern.5\d_math_eqalign_distance
1988   \fi
1989   \math_matrix_vertical_rule_nop{#1}%
1990   \kern.5\d_math_eqalign_distance
1991   \global\c_math_matrix_first\conditionalfalse
1992   \aligntab
1993   \boundary\c_math_matrix_vl_boundary
1994   \enforced\let\NR\math_matrix_NL_NR}
1995
1996\permanent\protected\def\math_matrix_NL_NR
1997  {\expand\t_math_matrix_NL_NR
1998   \math_matrix_anchor_last
1999   \math_matrix_stop_row
2000   \math_matrix_pickup
2001   \crcr
2002   \math_matrix_start_row}
2003
2004\appendtoks
2005   \enforced\let\NL\math_matrix_NL
2006   \global\c_math_matrix_sl_seen\conditionalfalse
2007\to \everymathmatrix
2008
2009\permanent\tolerant\protected\def\math_matrix_VC[#1]#*%
2010  {\NC
2011   \math_matrix_vertical_rule_yes{#1}%
2012   \NC}
2013
2014\permanent\tolerant\protected\def\math_matrix_VT[#1]#*%
2015  {\span\omit
2016   \math_matrix_vertical_rule_yes{#1}%
2017   \aligntab}
2018
2019\def\math_matrix_start_row
2020  {\beginlocalcontrol
2021   \global\c_math_matrix_columns\c_math_eqalign_column
2022   \global\c_math_eqalign_column\zerocount
2023   \global\advanceby\c_math_eqalign_row\plusone
2024   \dostarttaggednodetail\t!mtablerow
2025   \endlocalcontrol}
2026
2027\appendtoks
2028   \enforced\let\NR\math_matrix_NR
2029   \enforced\let\NC\math_matrix_NC
2030   \enforced\let\MC\math_matrix_NC
2031   \enforced\let\HL\math_matrix_HL % like the old ones
2032   \enforced\let\VL\math_matrix_VL % like the old ones
2033   \enforced\let\VC\math_matrix_VC % bonus, extra column
2034   \enforced\let\VT\math_matrix_VT % bonus, idem but tight
2035   \enforced\let\TB\math_common_TB
2036   % just because it's easy:
2037   \enforced\let\VLVL\math_matrix_VLVL
2038   \enforced\let\HLHL\math_matrix_HLHL
2039\to \everymathmatrix
2040
2041% \definesystemattribute[mathmatrixornament][public]
2042
2043\newdimension\d_math_matrix_margin_l
2044\newdimension\d_math_matrix_margin_r
2045\newdimension\d_math_matrix_margin_t
2046\newdimension\d_math_matrix_margin_b
2047
2048\newdimension\d_math_matrix_max_left
2049\newdimension\d_math_matrix_max_right
2050
2051\newboundary \c_math_matrix_ornament_l
2052\newboundary \c_math_matrix_ornament_r
2053\newboundary \c_math_matrix_ornament_t
2054\newboundary \c_math_matrix_ornament_b
2055
2056% anchors are wrong now
2057
2058\newconditional\c_math_matrix_text
2059\newconditional\c_math_matrix_text_l
2060\newconditional\c_math_matrix_text_r
2061\newconditional\c_math_matrix_text_t
2062\newconditional\c_math_matrix_text_b
2063
2064\def\math_matrix_ornaments#1#2%
2065  {\NC
2066   \enablematrixornaments
2067   \global\c_math_matrix_text\conditionaltrue
2068   \global#1\conditionaltrue
2069   \boundary#2%
2070   \ignorespaces}
2071
2072\permanent\protected\def\math_matrix_LT{\math_matrix_ornaments\c_math_matrix_text_l\c_math_matrix_ornament_l}
2073\permanent\protected\def\math_matrix_RT{\math_matrix_ornaments\c_math_matrix_text_r\c_math_matrix_ornament_r}
2074\permanent\protected\def\math_matrix_TT{\math_matrix_ornaments\c_math_matrix_text_t\c_math_matrix_ornament_t}
2075\permanent\protected\def\math_matrix_BT{\math_matrix_ornaments\c_math_matrix_text_b\c_math_matrix_ornament_b}
2076
2077\appendtoks
2078   \global\c_math_matrix_text\conditionalfalse
2079   \global\c_math_matrix_text_l\conditionalfalse
2080   \global\c_math_matrix_text_r\conditionalfalse
2081   \global\c_math_matrix_text_t\conditionalfalse
2082   \global\c_math_matrix_text_b\conditionalfalse
2083   \enforced\let\LT\math_matrix_LT
2084   \enforced\let\RT\math_matrix_RT
2085   \enforced\let\TT\math_matrix_TT
2086   \enforced\let\BT\math_matrix_BT
2087\to \everymathmatrix
2088
2089\newconditional\c_math_matrix_text_mode
2090
2091% \def\math_matrix_start_processing
2092%   {%
2093%    \ifmmode
2094%      \c_math_matrix_text_mode\conditionalfalse
2095%    \else
2096%      \c_math_matrix_text_mode\conditionaltrue
2097%    \fi
2098%    \ifconditional\c_math_matrix_text_mode
2099%      \dontleavehmode
2100%    \else
2101%      \mathmatrixparameter\c!left\relax
2102%      \math_fenced_start_wrap{\mathmatrixparameter\c!fences}%
2103%      \mathatom \s!class \mathconstructcode
2104%    \fi
2105%    \bgroup
2106%    \d_math_matrix_margin_l\mathmatrixparameter\c!leftmargin \relax
2107%    \d_math_matrix_margin_r\mathmatrixparameter\c!rightmargin\relax
2108%    \d_math_matrix_margin_t\strutdp
2109%    \d_math_matrix_margin_b\strutht
2110%    \global\d_math_matrix_max_left \zeropoint
2111%    \global\d_math_matrix_max_right\zeropoint
2112%   %\tabskip.5\d_math_eqalign_distance
2113%    \tabskip\zeroskip
2114%    \math_matrix_pickup
2115%    \expand\everymathmatrix
2116%    %
2117%    \setbox\nextbox\vbox\bgroup
2118%    \math_matrix_start_table
2119%    \halign
2120%       \s!callback
2121%         \align_callback_mathmatrix
2122%    \bgroup
2123%      % preamble
2124%      \span\math_matrix_preamble
2125%      % done
2126%      \crcr
2127%      \math_matrix_start_row}
2128%
2129% \def\math_matrix_stop_processing
2130%   {%\math_matrix_stop_wrapup % optional
2131%    \math_matrix_stop_row
2132%    \egroup
2133%    \math_matrix_stop_table
2134%    \egroup
2135%    \mathmatrixleft  % experimental hook
2136%    \math_matrix_finish_nextbox
2137%    \mathmatrixright % experimental hook
2138%    \egroup
2139%    \ifconditional\c_math_matrix_text_mode\else
2140%      \math_fenced_stop_wrap
2141%      \mathmatrixparameter\c!right\relax
2142%    \fi}
2143
2144\def\math_matrix_start_processing
2145  {\bgroup % outer
2146   \ifmmode
2147     \c_math_matrix_text_mode\conditionalfalse
2148   \else
2149     \c_math_matrix_text_mode\conditionaltrue
2150     \dontleavehmode
2151     \startimath
2152   \fi
2153   \d_math_matrix_margin_l{\mathmatrixparameter\c!leftmargin }%
2154   \d_math_matrix_margin_r{\mathmatrixparameter\c!rightmargin}%
2155   \d_math_matrix_margin_t\strutdp
2156   \d_math_matrix_margin_b\strutht
2157   \global\d_math_matrix_max_left \zeropoint
2158   \global\d_math_matrix_max_right\zeropoint
2159  %\tabskip.5\d_math_eqalign_distance
2160   \tabskip\zeroskip
2161   \math_matrix_pickup
2162   \expand\everymathmatrix
2163   %
2164   \setbox\nextbox\vbox
2165   \bgroup % vbox
2166   \math_matrix_start_table
2167   \halign \s!callback \align_callback_mathmatrix
2168   \bgroup % halign
2169     % preamble
2170     \span\math_matrix_preamble
2171     % done
2172     \crcr
2173     \math_matrix_start_row}
2174
2175\def\math_matrix_stop_processing
2176  {%\math_matrix_stop_wrapup % optional
2177   \math_matrix_stop_row
2178   \egroup % halign
2179   \math_matrix_stop_table
2180   \egroup % vbox
2181   \mathmatrixleft  % experimental hook
2182   \math_matrix_finish_nextbox
2183   \mathmatrixright % experimental hook
2184   \ifconditional\c_math_matrix_text_mode
2185     \stopimath
2186   \fi
2187   \egroup} % outer
2188
2189\permanent\protected\def\mathmatrixmaxleftwidth {\d_math_matrix_max_left }
2190\permanent\protected\def\mathmatrixmaxrightwidth{\d_math_matrix_max_right}
2191
2192\let\math_matrix_strut    \strut
2193\let\math_matrix_set_style\relax
2194
2195\def\math_matrix_check_settings
2196  {\edef\p_strut{\mathmatrixparameter\c!strut}%
2197   \ifx\p_strut\v!no
2198     \enforced\let\math_matrix_strut\relax
2199   \else
2200     \enforced\let\math_matrix_strut\strut
2201     \ifx\p_strut\v!yes\else
2202       \spacing\p_strut
2203     \fi
2204   \fi
2205   \d_math_eqalign_distance\mathmatrixparameter\c!distance\relax
2206 % \d_math_eqalign_rulethickness\mathmatrixparameter\c!rulethickness\relax
2207 % \edef\p_rulecolor{\mathmatrixparameter\c!rulecolor}
2208   \edef\math_matrix_set_style{\mathmatrixparameter\c!mathstyle}}
2209
2210\newinteger\c_math_eqalign_column_saved
2211\newinteger\c_math_eqalign_row_saved
2212
2213% \installglobalmacrostack\c_math_matrix_first
2214
2215\tolerant\protected\def\math_matrix_start[#1]#*[#S#2]%
2216  {\begingroup
2217   \currentmathblobnesting\minusone
2218   \globalpushmacro\c_math_matrix_first % hm, does that work?
2219   \c_math_eqalign_column_saved\c_math_eqalign_column
2220   \c_math_eqalign_row_saved\c_math_eqalign_row
2221   \globalpushmacro\c_math_eqalign_first
2222   \cdef\currentmathmatrix{#1}%
2223   \setupcurrentmathmatrix[#2]%
2224   \math_matrix_check_settings
2225   \math_eqalign_set_defaults
2226   \math_eqalign_set_columns{\mathmatrixparameter\c!align}%
2227   \math_matrix_start_processing}
2228
2229\def\math_matrix_stop
2230  {\math_matrix_stop_processing
2231   \globalpushmacro\c_math_eqalign_first
2232   \global\c_math_eqalign_column\c_math_eqalign_column_saved
2233   \global\c_math_eqalign_row\c_math_eqalign_row_saved
2234   \globalpopmacro\c_math_matrix_first
2235   \endgroup}
2236
2237% vcenter:
2238%
2239% delta     = (height(v) + depth(v))/2
2240% axis      = math_axis_size(cur_size)
2241% height(v) = delta + axis
2242% depth(v)  = delta - axis
2243
2244\installcorenamespace{mathmatrixalignlocation}
2245
2246\mutable\lettonothing\mathmatrixleft  % experimental hook
2247\mutable\lettonothing\mathmatrixright % experimental hook
2248
2249% This alignment option will either go away or become a atom property (key).
2250
2251\defcsname\??mathmatrixalignlocation\v!top   \endcsname{\raise{(\nextboxdp-\nextboxht)/2+\mathaxisheight\mathstyle}}
2252\defcsname\??mathmatrixalignlocation\v!high  \endcsname{\raise{(\nextboxdp-\nextboxht)/2}}
2253\defcsname\??mathmatrixalignlocation\v!center\endcsname{\relax}
2254\defcsname\??mathmatrixalignlocation\v!lohi  \endcsname{\relax}
2255\defcsname\??mathmatrixalignlocation\v!normal\endcsname{\relax}
2256\defcsname\??mathmatrixalignlocation\v!bottom\endcsname{\lower{(\nextboxdp-\nextboxht)/2+\mathaxisheight\mathstyle}}
2257\defcsname\??mathmatrixalignlocation\v!low   \endcsname{\lower{(\nextboxdp-\nextboxht)/2}}
2258
2259% \def\math_matrix_finish_nextbox
2260%   {\scratchcounter\mathstyle\relax
2261%    \scratchwidth\wd\nextbox
2262% \setbox\scratchbox\hbox\bgroup
2263%    \begincsname\??mathmatrixalignlocation\mathmatrixparameter\c!location\endcsname\hbox\bgroup
2264%      \normalstartimath
2265%      \givenmathstyle\scratchcounter
2266%      \ifzeropt\d_math_matrix_margin_l\else\kern\d_math_matrix_margin_l\fi
2267%      \ifconditional\c_math_matrix_text_mode
2268%        \mathmatrixparameter\c!left\relax
2269%        \math_fenced_start_wrap{\mathmatrixparameter\c!fences}%
2270%        \mathatom \s!class \mathconstructcode {\vcenter{\box\nextbox}}% \was \vcenter
2271%        \math_fenced_stop_wrap
2272%        \mathmatrixparameter\c!right\relax
2273%      \else
2274%         \vcenter{\box\nextbox}% \was \vcenter
2275%      \fi
2276%      \ifzeropt\d_math_matrix_margin_r\else\kern\d_math_matrix_margin_r\fi
2277%      \normalstopimath
2278%    \egroup
2279% \egroup
2280%    \ifconditional\c_math_matrix_text
2281%      \ifempty{\mathmatrixparameter\c!left\mathmatrixparameter\c!right\mathmatrixparameter\c!fences}\else
2282%        \scratchdistance\dimexpr(\wd\scratchbox-\scratchwidth)/\plustwo\relax
2283%        \advanceby\d_math_matrix_margin_l\scratchdistance
2284%        \advanceby\d_math_matrix_margin_r\scratchdistance
2285%        \clf_shiftmatrixornaments\scratchbox
2286%      \fi
2287%    \fi
2288%    \ifconditional\c_math_matrix_text_b
2289%      \dp\scratchbox\dimexpr\dp\scratchbox+\lineheight\relax
2290%    \fi
2291%    \ifconditional\c_math_matrix_text_t
2292%      \ht\scratchbox\dimexpr\ht\scratchbox+\lineheight\relax
2293%    \fi
2294%    \edef\p_leftedge {\mathmatrixparameter\c!leftedge }%
2295%    \edef\p_rightedge{\mathmatrixparameter\c!rightedge}%
2296%    \ifempty\p_leftedge\else
2297%      \hskip\dimexpr\d_math_matrix_max_left+\p_leftedge\relax
2298%    \fi
2299% %    \ifconditional\c_math_matrix_text_mode
2300%      \box\scratchbox
2301% %    \else
2302% %      \mathatom \s!class \mathconstructcode {\box\scratchbox}%
2303% %    \fi
2304%    \ifempty\p_rightedge\else
2305%      \hskip\dimexpr\d_math_matrix_max_right+\p_rightedge\relax
2306%    \fi
2307%    }
2308
2309%D \starttyping
2310%D \ruledhbox{\im{
2311%D     \startmatrix[left=\left(,right=\right)]
2312%D       \NC        \TT \ttx 1 \NC       \TT \ttx 2 \NC       \TT \ttx 3 \NC        \NR
2313%D       \LT \ttx 1 \NC a      \NC \dots \NC aa     \NC \dots \NC aaa    \RT \ttx 1 \NR
2314%D       \LT \ttx 2 \NC b      \NC \dots \NC bb     \NC \dots \NC bbb    \RT \ttx 2 \NR
2315%D       \LT \ttx 3 \NC c      \NC \dots \NC cc     \NC \dots \NC ccc    \RT \ttx 3 \NR
2316%D       \NC        \BT \ttx 1 \NC       \BT \ttx 2 \NC       \BT \ttx 3 \NC        \NR
2317%D     \stopmatrix
2318%D }}
2319%D \ruledhbox{\im{
2320%D     \startmatrix[left=\left(,right=\right),rightedge=none,leftedge=none]
2321%D       \NC        \TT \ttx 1 \NC       \TT \ttx 2 \NC       \TT \ttx 3 \NC        \NR
2322%D       \LT \ttx 1 \NC a      \NC \dots \NC aa     \NC \dots \NC aaa    \RT \ttx 1 \NR
2323%D       \LT \ttx 2 \NC b      \NC \dots \NC bb     \NC \dots \NC bbb    \RT \ttx 2 \NR
2324%D       \LT \ttx 3 \NC c      \NC \dots \NC cc     \NC \dots \NC ccc    \RT \ttx 3 \NR
2325%D       \NC        \BT \ttx 1 \NC       \BT \ttx 2 \NC       \BT \ttx 3 \NC        \NR
2326%D     \stopmatrix
2327%D }}
2328%D \stoptyping
2329
2330\newconstant\c_math_last_l_class
2331\newconstant\c_math_last_r_class
2332
2333\setupmathmatrix
2334  [\c!rightedge=\zeropoint,
2335   \c!leftedge=\zeropoint]
2336
2337\def\math_matrix_finish_nextbox
2338  {\scratchcounter\mathstyle\relax
2339   \scratchwidth\wd\nextbox
2340   \dostarttagged\t!math\empty % needed !
2341   \setbox\scratchbox\hbox\bgroup
2342     \begincsname\??mathmatrixalignlocation\mathmatrixparameter\c!location\endcsname\hbox\bgroup
2343       \normalstartimath
2344       \givenmathstyle\scratchcounter
2345       \ifzeropt\d_math_matrix_margin_l\else\kern\d_math_matrix_margin_l\fi
2346       \mathmatrixparameter\c!left\relax
2347       \math_fenced_start_wrap{\mathmatrixparameter\c!fences}%
2348       \mathatom \s!class \mathconstructcode {%
2349            \vcenter{%
2350                \box\nextbox
2351            }%
2352       }%
2353       \math_fenced_stop_wrap
2354       \mathmatrixparameter\c!right\relax
2355       \ifzeropt\d_math_matrix_margin_r\else\kern\d_math_matrix_margin_r\fi
2356       \normalstopimath
2357       % or carry over one group
2358       \global\c_math_last_l_class\lastleftclass
2359       \global\c_math_last_r_class\lastrightclass
2360     \egroup
2361   \egroup
2362   \ifconditional\c_math_matrix_text % not _mode
2363     \ifempty{\mathmatrixparameter\c!left\mathmatrixparameter\c!right\mathmatrixparameter\c!fences}\else
2364       \scratchdistance{(\wd\scratchbox-\scratchwidth)/\plustwo}%
2365       \advanceby\d_math_matrix_margin_l\scratchdistance
2366       \advanceby\d_math_matrix_margin_r\scratchdistance
2367       \clf_shiftmatrixornaments\scratchbox
2368     \fi
2369   \fi
2370   \ifconditional\c_math_matrix_text_b
2371     \dp\scratchbox{\dp\scratchbox+\lineheight}%
2372   \fi
2373   \ifconditional\c_math_matrix_text_t
2374     \ht\scratchbox{\ht\scratchbox+\lineheight}%
2375   \fi
2376   \mathatom
2377     \s!leftclass  \c_math_last_l_class
2378     \s!rightclass \c_math_last_r_class
2379     \bgroup
2380       \edef\p_leftedge {\mathmatrixparameter\c!leftedge }%
2381       \edef\p_rightedge{\mathmatrixparameter\c!rightedge}%
2382       \ifempty\p_leftedge\orelse\ifx\p_leftedge\v!none\else
2383         \hkern{\d_math_matrix_max_left+\p_leftedge}%
2384       \fi
2385       \box\scratchbox
2386       \ifempty\p_rightedge\orelse\ifx\p_rightedge\v!none\else
2387         \hkern{\d_math_matrix_max_right+\p_rightedge}%
2388       \fi
2389     \egroup
2390   \dostoptagged}
2391
2392%D Begin of plugin.
2393%D
2394%D Fancy:
2395%D
2396%D \starttyping
2397%D \startformula \showstruts
2398%D     \startmatrix
2399%D         \NC 1         \NC   \NC \GL[2][m,s,h]  \NC 3 \NC \NR
2400%D         \NC 1         \NC   \NC               \NC 3 \NC \NR
2401%D         \NC 1         \NC   \NC               \NC 3 \NC \NR
2402%D         \NC \GL[2][d] \NC 2 \NC \GL[2][s,d,c] \NC 3 \NC \NR
2403%D     \stopmatrix
2404%D \stopformula
2405%D
2406%D \startformula \showstruts
2407%D     \startmatrix[fences=bracket,rulecolor=red]
2408%D         \NC 1 \NC \GL[2][a]      \NC \GL[2][a,e] \NC \NR
2409%D         \NC 1 \NC \GL[2][x,blue] \NC \GL[2][x,e] \NC \NR
2410%D         \NC 1 \NC 2              \NC 3           \NC \NR
2411%D         \NC 1 \NC 2              \NC 3           \NC \NR
2412%D         \NC 1 \NC \GL[2][a]      \NC \GL[2][a,e] \NC \NR
2413%D     \stopmatrix
2414%D \stopformula
2415%D
2416%D \startformula \showstruts
2417%D     \startmatrix[fences=bracket]
2418%D         \NC 1 \NC   \NC \GL[2][t] \NC 3 \NC \NR
2419%D         \NC 1 \NC   \NC           \NC 3 \NC \NR
2420%D         \NC 1 \NC   \NC           \NC 3 \NC \NR
2421%D         \NC 1 \NC 2 \NC \GL[2][b] \NC 3 \NC \NR
2422%D     \stopmatrix
2423%D \stopformula
2424%D
2425%D \startformula \showstruts
2426%D     \startmatrix[fences=bracket,rulecolor=red]
2427%D         \NC 1 \NC   \NC \GL[2][T] \NC 3 \NC \NR
2428%D         \NC 1 \NC   \NC           \NC 3 \NC \NR
2429%D         \NC 1 \NC   \NC           \NC 3 \NC \NR
2430%D         \NC 1 \NC 2 \NC \GL[2][B] \NC 3 \NC \NR
2431%D     \stopmatrix
2432%D \stopformula
2433%D
2434%D \startformula
2435%D     \startmatrix[fences=bracket]
2436%D         \NC \GL[2][h] \NC 2 \NC \GL[2][h]   \NC 3 \NC \NR
2437%D         \NC           \NC 2 \NC             \NC 3 \NC \NR
2438%D         \NC           \NC 2 \NC             \NC 3 \NC \NR
2439%D         \NC \GL[2][d] \NC 2 \NC \GL[2][d,c] \NC 3 \NC \NR
2440%D     \stopmatrix
2441%D \stopformula
2442%D
2443%D \startformula
2444%D     \startmatrix
2445%D         \NC \GL[2][h] \NC 2 \NC       \NC \GL[2][h]     \NC             \NC \NR
2446%D         \NC \GL[3][d] \NC \GL[3][d,e] \NC \NC \GL[2][d] \NC \GL[2][d]   \NC \NR
2447%D         \NC           \NC 2 \NC       \NC 3             \NC \GL[3][d] \hskip1cm \GL[3][d,e] \NC \NR
2448%D         \NC \GL[2][d] \NC 2 \NC       \NC 3             \NC \GL[2][d,c] \NC \NR
2449%D     \stopmatrix
2450%D \stopformula
2451%D \stoptyping
2452%D
2453%D % \graphicline[1][o]\input tufte \removeunwantedspaces\graphicline[1][o,e]
2454%D
2455%D Easier:
2456%D
2457%D \starttyping
2458%D \startformula
2459%D     \startmatrix[fences=bracket,rulecolor=red]
2460%D         \NC 1 \NC 2 \VL 3 \NR
2461%D         \NC 1 \NC 2 \VL 3 \NR
2462%D     \stopmatrix
2463%D \stopformula
2464%D
2465%D \startformula
2466%D     \startmatrix[fences=bracket,rulecolor=red]
2467%D         \NC 1 \NC 2 \VL 3 \VL \NR
2468%D         \NC 1 \NC 2 \VL 3 \VL \NR
2469%D     \stopmatrix
2470%D \stopformula
2471%D
2472%D \startformula
2473%D     \startmatrix[fences=bracket,rulecolor=red]
2474%D         \NC 1 \NC 2 \VLT 3 \VLT[2,blue] 4 \NR
2475%D         \NC 1 \NC 2 \NC  3 \NC  4 \NR
2476%D         \NC 1 \NC 2 \VLB 3 \VLB 4 \NR
2477%D     \stopmatrix
2478%D \stopformula
2479%D
2480%D \startformula
2481%D     \startmatrix[fences=bracket,rulecolor=red]
2482%D         \NC 1 \NC 2 \VLT 3 \VLT[2pt,blue] 4 \NR
2483%D         \NC 1 \NC 2 \NC  3 \NC  4 \NR
2484%D         \NC 1 \NC 2 \VLB 3 \VLB 4 \NR
2485%D     \stopmatrix
2486%D \stopformula
2487%D \stoptyping
2488
2489\installcorenamespace{matrixvl}
2490
2491\appendtoks
2492    \enforced\let\GL\grph_line_inject
2493\to \everymathmatrix
2494
2495\newboundary\c_math_matrix_vlx_boundary
2496
2497\tolerant\permanent\protected\def\grph_line_inject_VLT[#1]%
2498  {\aligntab
2499   \grph_line_inject[\??matrixvl:\number\c_math_eqalign_column][T,#1]%
2500   \kern.5\d_math_eqalign_distance
2501   \global\c_math_matrix_first\conditionalfalse
2502   \aligntab
2503   \enforced\let\NR\math_matrix_NL_NR
2504   \boundary\c_math_matrix_vlx_boundary}
2505
2506\tolerant\permanent\protected\def\grph_line_inject_VLB[#1]%
2507  {\aligntab
2508   \grph_line_inject[\??matrixvl:\number\c_math_eqalign_column][B,#1]%
2509   \kern.5\d_math_eqalign_distance
2510   \global\c_math_matrix_first\conditionalfalse
2511   \aligntab
2512   \enforced\let\NR\math_matrix_NL_NR
2513   \boundary\c_math_matrix_vlx_boundary}
2514
2515\appendtoks
2516    \enforced\let\VLT\grph_line_inject_VLT
2517    \enforced\let\VLB\grph_line_inject_VLB
2518\to \everymathmatrix
2519
2520\appendtoks
2521    % vl delegated to lua graphiclines
2522    \ifnum\lastboundary=\c_math_matrix_vlx_boundary
2523        \kern\ifconditional \c_math_matrix_sl_seen-1.5\else-.5\fi\d_math_eqalign_distance
2524    \fi
2525\to \t_math_matrix_NL_NR
2526
2527%D End of plugin.
2528
2529\definemathmatrix[matrix]
2530\definemathmatrix[\v!mathmatrix]
2531
2532%D \startbuffer
2533%D \placeformula \startformula[-] \startmatrix
2534%D \NC 1 \NC x \NC a \NR
2535%D \NC 2 \NC y \NC b \NR
2536%D \NC 3 \NC z \NC c \NR
2537%D \stopmatrix \stopformula
2538%D \stopbuffer
2539%D
2540%D \typebuffer \getbuffer
2541%D
2542%D \definemathmatrix[bmatrix][left={\left[\mskip\thinmuskip},right={\mskip\thinmuskip\right]},strut=1.25]
2543%D
2544%D \startbuffer
2545%D \placeformula \startformula[-] \startbmatrix
2546%D \NC 1 \NC x \NC a \NR
2547%D \NC 2 \NC y \NC b \NR
2548%D \NC 3 \NC z \NC c \NR
2549%D \stopbmatrix \stopformula
2550%D \stopbuffer
2551%D
2552%D \typebuffer \getbuffer
2553%D
2554%D Taco added some code (dedicated to Aditya Mahajan) that gives more
2555%D control over aligments:
2556
2557%D \startbuffer
2558%D \startformula
2559%D   \startmatrix
2560%D    \NC a + x \NC = \NC a + d \NR
2561%D    \NC y     \NC = \NC d     \NR
2562%D   \stopmatrix
2563%D \stopformula
2564%D \stopbuffer
2565%D
2566%D \typebuffer \getbuffer
2567
2568%D \startbuffer
2569%D \startformula
2570%D   \startmatrix [distance=3pt,align={right,left}]
2571%D    \NC a + x \NC = a + d \NR
2572%D    \NC y     \NC = d     \NR
2573%D   \stopmatrix
2574%D \stopformula
2575%D \stopbuffer
2576%D
2577%D \typebuffer \getbuffer
2578
2579%D \startbuffer
2580%D \startformula
2581%D   \startmatrix [left=\left(,right=\right)]
2582%D    \NC a + x \NR
2583%D    \NC y    \NR
2584%D   \stopmatrix
2585%D \stopformula
2586%D \stopbuffer
2587%D
2588%D \typebuffer \getbuffer
2589%D
2590%D A bit more complex code:
2591%D
2592%D \startbuffer
2593%D \startformula
2594%D    \text{Let }{\cal R} = \bigcup_{P_{X_1},P_{X_2}}
2595%D    \left\{ (R_1, R_2) :
2596%D    \startmatrix[distance=1em,align={left,left,right}]
2597%D      \NC R_1        \NC < I(X_1 ; Y \mid X_2)      \NC R_1       \NR
2598%D      \NC \hfill Q_2 \NC < I(X_2 ; Y \mid X_1)      \NC R_2       \NR
2599%D      \NC R_1 + R_2  \NC < I(X_1 ; Y)               \NC R_1 + R_2 \NR
2600%D    \stopmatrix
2601%D    \right\}
2602%D \stopformula
2603%D \stopbuffer
2604%D
2605%D \typebuffer \getbuffer
2606
2607%D \macros
2608%D   {startmatrices}
2609%D
2610%D Just a handy keystroke safer:
2611
2612\permanent\protected\def\startmatrices
2613  {\begingroup
2614   \setupmathmatrix}
2615
2616\permanent\protected\def\stopmatrices
2617  {\endgroup}
2618
2619%D \startbuffer
2620%D \startformula
2621%D   \startmatrix[left={\left(},right={\right)}]
2622%D     \NC A \NC B \NR \NC C \NC D \NR
2623%D   \stopmatrix
2624%D   =
2625%D   \startmatrix[left={\left(},right={\right)},location=low]
2626%D     \NC A \NC B \NR \NC C \NC D \NR
2627%D   \stopmatrix
2628%D   =
2629%D   \startmatrix[left={\left(},right={\right)},location=high]
2630%D     \NC A \NC B \NR \NC C \NC D \NR
2631%D   \stopmatrix
2632%D \stopformula
2633%D \stopbuffer
2634%D
2635%D \typebuffer \getbuffer
2636%D
2637%D \startbuffer
2638%D \startformula
2639%D   \startmatrices[left={\left(},right={\right)}]
2640%D     \startmatrix
2641%D       \NC A \NC B \NR \NC C \NC D \NR
2642%D     \stopmatrix
2643%D     =
2644%D     \startmatrix[location=bottom]
2645%D       \NC A \NC B \NR \NC C \NC D \NR
2646%D     \stopmatrix
2647%D     =
2648%D     \startmatrix[location=top]
2649%D       \NC A \NC B \NR \NC C \NC D \NR
2650%D     \stopmatrix
2651%D   \stopmatrices
2652%D \stopformula
2653%D \stopbuffer
2654%D
2655%D \typebuffer  % does not run well: \getbuffer
2656
2657%D Handy for the \type {m-matrix} module:
2658
2659\permanent\tolerant\protected\def\startnamedmatrix[#1]#*[#S#2]%
2660  {\begingroup
2661   \cdef\currentmathmatrix{#1}%
2662   \setupcurrentmathmatrix[#2]%
2663   \math_matrix_start[\currentmathmatrix]}
2664
2665\noaligned\permanent\protected\def\stopnamedmatrix
2666  {\math_matrix_stop
2667   \endgroup}
2668
2669%D The following code is derived from Aditya's simplematrix prototype but adapted to
2670%D regular mathmatrices. With a little help from \LUA\ we now have this:
2671%D
2672%D \startbuffer
2673%D \definemathmatrix [Pmatrix] [matrix:parentheses]
2674%D   [align={all:right},
2675%D    simplecommand=Pmatrix]
2676%D
2677%D \definemathmatrix [Tmatrix] [Pmatrix]
2678%D   [action=transpose,
2679%D    simplecommand=Tmatrix]
2680%D
2681%D \definemathmatrix [Nmatrix] [Pmatrix]
2682%D   [action=negate,
2683%D    simplecommand=Nmatrix]
2684%D
2685%D \startformula
2686%D     \Pmatrix{ -1, 2, 3; 4,-5, 6; 7, 8,-9 } \neq
2687%D     \Tmatrix{ -1, 2, 3; 4,-5, 6; 7, 8,-9 } \neq
2688%D     \Nmatrix{ -1, 2, 3; 4,-5, 6; 7, 8,-9 }
2689%D \stopformula
2690%D
2691%D \startformula
2692%D     \bmatrix { {A__1(x,y)} ; {A__2(x,y)} } =
2693%D     \bmatrix { {A__1(x,y)}; {A__2(x,y)} } =
2694%D     \bmatrix {{A__1(x,y)};{A__2(x,y)}}
2695%D \stopformula
2696%D \stopbuffer
2697%D
2698%D \typebuffer \getbuffer
2699
2700\permanent\tolerant\protected\def\math_matrix_simple[#1]#*[#S#2]#:#3%
2701  {\begingroup
2702   \cdef\currentmathmatrix{#1}%
2703   \setupcurrentmathmatrix[#2]%
2704   \math_matrix_start[\currentmathmatrix]%
2705   \clf_simplematrix{\mathmatrixparameter\c!action}{#3}%
2706   \math_matrix_stop
2707   \endgroup}
2708
2709%D We hook it into the normal mathmatrix code:
2710
2711\appendtoks
2712    \edef\p_simplecommand{\mathmatrixparameter\c!simplecommand}%
2713    \ifempty\p_simplecommand\else
2714        \frozen\protected\instance\edefcsname\p_simplecommand\endcsname{\math_matrix_simple[\currentmathmatrix]}%
2715    \fi
2716\to \everydefinemathmatrix
2717
2718%D And predefine some matrices:
2719
2720% \definemathmatrix[matrix:parentheses][\c!left={\left(\mskip\thinmuskip},\c!right={\mskip\thinmuskip\right)},\c!align=\v!middle]
2721% \definemathmatrix[matrix:brackets]   [\c!left={\left[\mskip\thinmuskip},\c!right={\mskip\thinmuskip\right]},\c!align=\v!middle]
2722% \definemathmatrix[matrix:bars]       [\c!left={\left|\mskip\thinmuskip},\c!right={\mskip\thinmuskip\right|},\c!align=\v!middle]
2723
2724\definemathmatrix
2725  [matrix:none]
2726  [\c!align=\v!middle,
2727   \c!simplecommand=matrix]
2728
2729\definemathmatrix
2730  [matrix:brackets]
2731  [\c!fences=bracket,
2732   \c!align=\v!middle,
2733   \c!simplecommand=bmatrix]
2734
2735\definemathmatrix
2736  [matrix:parentheses]
2737  [\c!fences=parenthesis,
2738   \c!align=\v!middle,
2739   \c!simplecommand=pmatrix]
2740
2741\definemathmatrix
2742  [matrix:bars]
2743  [\c!fences=bar,
2744   \c!align=\v!middle,
2745   \c!simplecommand=vmatrix]
2746
2747\definemathmatrix
2748  [matrix:doublebars]
2749  [\c!fences=doublebar,
2750   \c!align=\v!middle,
2751   \c!simplecommand=vvmatrix]
2752
2753\definemathmatrix
2754  [matrix:triplebars]
2755  [\c!fences=triplebar,
2756   \c!align=\v!middle,
2757   \c!simplecommand=vvvmatrix]
2758
2759\definemathmatrix
2760  [matrix:groups]
2761  [\c!fences=group,
2762   \c!align=\v!middle,
2763   \c!simplecommand=gmatrix]
2764
2765\definemathmatrix
2766  [matrix:braces]
2767  [\c!fences=brace,
2768   \c!align=\v!middle,
2769   \c!simplecommand=bracematrix]%Seldom used, bmatrix occupied by brackets
2770
2771% MPS: Is this one really used? Yes, in the test suite ...
2772
2773\definemathmatrix
2774  [thematrix]
2775  [matrix:parentheses]
2776  [\c!simplecommand=thematrix]
2777
2778%D \startbuffer
2779%D \startformula
2780%D \thematrix{1,2,3,4;5,6,7,8;9,10,11,12}
2781%D \stopformula
2782%D \stopbuffer
2783%D
2784%D \typebuffer \getbuffer
2785%D
2786%D \startbuffer
2787%D \startformula
2788%D \startthematrix
2789%D     \NC 1\NC 2\NC 3\NC 4\NR
2790%D     \NC 5\NC 6\NC 7\NC 8\NR
2791%D     \NC 9\NC10\NC11\NC12\NR
2792%D \stopthematrix
2793%D \stopformula
2794%D \stopbuffer
2795%D
2796%D \typebuffer \getbuffer
2797
2798%D Mikael needed this matrix in one of his advanced math courses that ran begin april 2022
2799%D where new concepts were introduced:
2800
2801% \definemathfence
2802%   [tekcarb]
2803%   [\c!left="005D,\c!right="005B]
2804
2805\definemathmatrix
2806  [xıɹʇɐɯ]
2807  [\c!fences=tekcarb]
2808
2809%D Fortunately we were read for it:
2810%D
2811%D \startbuffer
2812%D \startformula
2813%D \startxıɹʇɐɯ
2814%D   \NC a_1 \NC b_1 \NC c_1 \NR
2815%D   \NC a_2 \NC b_2 \NC c_2 \NR
2816%D \stopxıɹʇɐɯ
2817%D \stopformula
2818%D \stopbuffer
2819%D
2820%D \typebuffer \getbuffer
2821
2822%D \macros
2823%D   {startintertext}
2824%D
2825%D Preliminary feature:
2826%D
2827%D {\em example code}
2828%D
2829%D The intertext commands have to be expandable (in aligment lookahead) so
2830%D we cannot use \type {\protected}.
2831
2832\permanent\def\startintertext#1\stopintertext
2833  {\noalign{\math_intertext{#1}}}
2834
2835\permanent\let\stopintertext\relax
2836
2837\permanent\def\intertext#1%
2838  {\noalign{\math_intertext{#1}}}
2839
2840\protected\def\math_intertext#1%
2841  {\penalty\postdisplaypenalty
2842   \afterdisplayspace
2843   \vbox{\forgetall\noindent#1\par}%
2844   \penalty\predisplaypenalty
2845   \beforedisplayspace}
2846
2847%D \macros
2848%D   {substack}
2849%D
2850%D Preliminary code:
2851%D
2852%D \startbuffer
2853%D \startformula
2854%D    \sum_{%
2855%D      \startsubstack
2856%D       i = 1 \NR
2857%D       i \neq n \NR
2858%D       i \neq m
2859%D       \stopsubstack
2860%D     }a_i
2861%D \stopformula
2862%D \stopbuffer
2863%D
2864%D \getbuffer which was typed as \typebuffer
2865%D
2866%D Notice that these macros give the correct spacing for
2867%D subscripts. Compare for example
2868%D
2869%D \startbuffer
2870%D \startformula
2871%D \sum_{\startsubstack a \NR b \NR \stopsubstack}
2872%D \text{ and }
2873%D \sum_{\scriptstyle a \atop \scriptstyle}
2874%D \stopformula
2875%D \stopbuffer
2876%D
2877%D \typebuffer which gives \getbuffer
2878
2879% \permanent\protected\def\startsubstack
2880%   {\begingroup
2881%    \vcenter\bgroup
2882%    \currentmathblobnesting\minusone
2883%    \baselineskip\mathstacktotal
2884%    \lineskip\mathstackvgap
2885%    \lineskiplimit\lineskip
2886%    \mathsurround\zeropoint
2887%    \mathsurroundskip\zeroskip
2888%    \everycr\emptytoks
2889%    \enforced\let\NC\relax
2890%    \enforced\let\MC\relax
2891%    \enforced\let\NR\crcr
2892%  % \enablemathalignrelocate
2893%    \dostarttagged\t!math{substack}% needed, otherwise no mtr
2894%    \dostarttaggednodetail\t!mtable
2895%    \halign\bgroup
2896%     \dostarttaggednodetail\t!mtablerow
2897%     \hfil
2898%     \dostarttaggednodetail\t!mtablecell
2899%     \normalstartimath
2900%     \scriptstyle
2901%     \aligncontent
2902%     \normalstopimath
2903%     \dostoptagged
2904%     \hfil
2905%     \dostoptagged
2906%     \crcr}
2907%
2908% \noaligned\permanent\protected\def\stopsubstack
2909%   {\crcr
2910%    \egroup
2911%    \dostoptagged
2912%    \dostoptagged
2913%    \egroup
2914%    \endgroup}
2915
2916\newinteger\c_align_substack
2917
2918\permanent\protected\def\startsubstack
2919  {\begingroup
2920   \vcenter\bgroup
2921   \currentmathblobnesting\minusone
2922   \baselineskip\mathstacktotal
2923   \lineskip\mathstackvgap
2924   \lineskiplimit\lineskip
2925   \mathsurround\zeropoint
2926   \mathsurroundskip\zeroskip
2927   \everycr\emptytoks
2928   \enforced\let\NC\relax
2929   \enforced\let\MC\relax
2930   \enforced\let\NR\crcr
2931   \dostarttagged\t!math{substack}% \empty
2932   \pushmacro\c_align_substack
2933   \global\c_align_substack\plusone
2934   \halign\bgroup
2935    \dostarttaggednodetail\t!mstack
2936    \global\advanceby\c_align_substack\plusone
2937    \hfil
2938    \normalstartimath
2939    \scriptstyle
2940    \aligncontent
2941    \normalstopimath
2942    \hfil
2943    \crcr}
2944
2945\noaligned\permanent\protected\def\stopsubstack
2946  {\crcr
2947   \egroup
2948   \dorecurse\c_align_substack\dostoptagged
2949   \egroup
2950   \popmacro\c_align_substack
2951   \endgroup}
2952
2953%D \macros{overset, underset}
2954%D
2955%D The macros \type {\overset} and \type {\underset} are provided by \AMS\ packages
2956%D in \LATEX. These macro allows you to place a symbol above or below another
2957%D symbol, irrespective of whether the other symbol is a relation or something else,
2958%D and without influencing the spacing. Because in \LUAMETATEX\ we're less limited,
2959%D we have rather simple definitions compared to \MKIV. One cna also do:
2960%D
2961%D \starttyping
2962%D $b\limits^a$
2963%D $<\limits^a$
2964%D \stoptyping
2965
2966\permanent\protected\def\overset #1#2{\mathrel{#2}\limits\normalsuperscript{#1}}
2967\permanent\protected\def\underset#1#2{\mathrel{#2}\limits\normalsubscript  {#1}}
2968
2969%D The following code comes from \type {math-str.mkiv}.
2970%D
2971%D Here we implement a basic math alignment mechanism. Numbers are also handled. The
2972%D macros \type {\startinnermath} and \type {\stopinnermath} can be overloaded in
2973%D specialized modules.
2974
2975\installcorenamespace{mathinnerstart}
2976\installcorenamespace{mathinnerstop}
2977
2978\permanent\protected\def\startinnermath{\expandnamespaceparameter\??mathinnerstart\formulaparameter\c!align\v!normal}
2979\permanent\protected\def\stopinnermath {\expandnamespaceparameter\??mathinnerstop \formulaparameter\c!align\v!normal}
2980
2981\permanent\protected\def\defineinnermathhandler#1#2#3%
2982  {\defcsname\??mathinnerstart#1\endcsname{#2}%
2983   \defcsname\??mathinnerstop #1\endcsname{#3}}
2984
2985\def\strc_math_flush_number_box_normal{\box\b_strc_formulas_number}
2986\def\strc_math_flush_number_box_visual{\ruledhbox{\box\b_strc_formulas_number}}
2987
2988\let\strc_math_flush_number_box\strc_math_flush_number_box_normal
2989
2990% \newdimension  \d_strc_math_display_width
2991% \newdimension  \d_strc_math_indent
2992% \newconditional\c_strc_math_indent
2993
2994\newconditional\c_strc_math_display_overflow
2995\newconstant   \c_strc_math_number_location
2996\newconstant   \c_strc_math_number_variant
2997\newconstant   \c_strc_formulas_frame_mode
2998\newdimension  \d_strc_math_framed_width
2999
3000\defcsname\??formulaoption\v!frame\endcsname
3001  {\edef\p_frame{\formulaparameter\c!frame}%
3002   \ifx\p_frame\v!number
3003     \c_strc_formulas_frame_mode\plustwo % inside frame
3004   \else
3005     \c_strc_formulas_frame_mode\plusone % outside frame
3006   \fi}
3007
3008% The next section is experimental ...
3009
3010\permanent\protected\def\grph_handle_formula_image_tagged#1#2%
3011  {\begingroup
3012   \def\figurecategory{formula}%
3013   \global\advanceby\nofexportedboxes\plusone
3014   \dostarttagged\t!image{\the\nofexportedboxes}%
3015   \setbox\b_grph_image\vpack\bgroup
3016     \vkern\zeropoint
3017     \hpack\bgroup
3018       \hkern-\d_strc_math_left_shift
3019       \copy#2%
3020       \hkern-\d_strc_math_right_shift
3021     \egroup
3022     \vkern\zeropoint
3023   \egroup
3024 % \copy\b_grph_image
3025   \dotagexported
3026   \dostoptagged
3027   \dotagregisterformula{\number\c_strc_formulas_n}{\number\nofexportedboxes}%
3028   \ifconditional\c_grph_exported % move up
3029     \putboxincache\s!exported{\the\nofexportedboxes}\b_grph_image
3030   \fi
3031   #1#2%
3032   \endgroup}
3033
3034\permanent\protected\def\grph_handle_formula_image_normal#1#2%
3035  {#1#2}
3036
3037\enforced\let\handle_formula_image\grph_handle_formula_image_normal
3038
3039\appendtoks % this might move
3040    \enforced\let\handle_formula_image\grph_handle_formula_image_tagged
3041\to \everyenableelements
3042
3043% ... till here.
3044
3045% mode: 0=no frame | 1=number inside frame | 2=number outside frame
3046
3047% it is a bit of a mess because we solve all kind of bordercases but at some
3048% point it will become clean
3049
3050\def\strc_math_flush_aligned_boxed_direct_yes
3051  {\dontleavehmode
3052   \handle_formula_image\box\b_strc_math_display
3053   \llap{\strc_math_flush_number_box}}
3054
3055\def\strc_math_flush_aligned_boxed_direct_nop
3056  {\dontleavehmode
3057   \handle_formula_image\box\b_strc_math_display}
3058
3059\def\strc_math_flush_aligned_left_number_indeed#1%
3060  {\ifvoid\b_strc_formulas_number\else
3061     \setbox\b_strc_formulas_number\hbox to \d_strc_formulas_display_width\bgroup
3062       \hss
3063% \ifcase#1\orelse\ifdim\dimexpr\d_strc_math_max_left-\d_strc_math_first_left\relax>\zeropoint
3064%    \raise\htdp\b_strc_formulas_number % horrible hack
3065% \fi
3066       \hbox{\strc_math_flush_number_box}%
3067     \egroup
3068     \ifcase\c_strc_math_number_location\or
3069       \boxxoffset\b_strc_formulas_number{-\d_strc_formulas_display_width+\d_strc_formulas_number+\s_strc_formulas_margin_left}% brrrrr
3070       \boxyoffset\b_strc_formulas_number-\d_strc_math_first_height
3071       \htdp\b_strc_formulas_number\zeropoint
3072       \strc_math_flush_number_box % left
3073     \fi
3074   \fi}
3075
3076% \def\strc_math_flush_aligned_right_number_indeed
3077%   {\ifvoid\b_strc_formulas_number\else
3078%      \setbox\b_strc_formulas_number\hbox to \d_strc_formulas_display_width\bgroup
3079%        \hss
3080%        \hbox{\strc_math_flush_number_box}%
3081%      \egroup
3082%      \ifcase\c_strc_math_number_location\or\else
3083%        \boxxoffset\b_strc_formulas_number{-\s_strc_formulas_margin_right}% brrrrr
3084%        \boxyoffset\b_strc_formulas_number\d_strc_math_last_depth
3085%        \htdp\b_strc_formulas_number\zeropoint
3086%        \strc_math_flush_number_box % right
3087%      \fi
3088%    \fi}
3089
3090\def\strc_math_flush_aligned_right_number_indeed#1%
3091  {\ifvoid\b_strc_formulas_number\else
3092     \setbox\b_strc_formulas_number\hbox to \d_strc_formulas_display_width\bgroup
3093       \hss
3094\ifcase#1\orelse\ifdim{\d_strc_math_max_right-\d_strc_math_last_right}>\zeropoint
3095   \lower\htdp\b_strc_formulas_number % horrible hack
3096\fi
3097       \hbox{\strc_math_flush_number_box}%
3098     \egroup
3099     \ifcase\c_strc_math_number_location\or\else
3100       \boxxoffset\b_strc_formulas_number-\s_strc_formulas_margin_right
3101       \boxyoffset\b_strc_formulas_number\d_strc_math_last_depth
3102       \htdp\b_strc_formulas_number\zeropoint
3103     \strc_math_flush_number_box % right
3104     \fi
3105   \fi}
3106
3107% \c_strc_math_ignore_number\conditionaltrue
3108
3109% cleanup timestamp: tales of time, joe bonamassa (live blu-ray in loop mode, 2023)
3110
3111\dimensiondef\d_strc_math_number_eps 5\scaledpoint
3112
3113% line mode
3114
3115\def\strc_math_flush_line_mode
3116  {\ifcase\c_strc_math_ragged_status\or\or\hfill\or\hfill\fi
3117   \handle_formula_image\box\b_strc_math_display
3118   \ifcase\c_strc_math_ragged_status\or\hfill\or\hfill\or\fi}
3119
3120% wrap/flow mode
3121
3122\def\strc_math_flush_v_box_bottom
3123  {\ifdone
3124     \global\c_strc_math_positioning42\relax
3125     \handle_formula_image\unvbox\b_strc_math_display
3126     \strc_math_flush_number_box
3127   \else
3128     \global\c_strc_math_positioning43\relax
3129     \handle_formula_image\unvbox\b_strc_math_display
3130     \nointerlineskip
3131     \ht\b_strc_formulas_number\zeropoint
3132     \dp\b_strc_formulas_number\zeropoint
3133     \boxyoffset\b_strc_formulas_number\d_strc_math_last_depth
3134     \strc_math_flush_number_box % right
3135     \prevdepth\d_strc_math_last_depth
3136   \fi}
3137
3138\def\strc_math_flush_v_box_top
3139  {\ifdone
3140     \global\c_strc_math_positioning45\relax
3141     \dontleavehmode
3142     \strc_math_flush_number_box
3143     \handle_formula_image\unvbox\b_strc_math_display
3144   \else
3145     \scratchdepth\dp\b_strc_formulas_number
3146     \global\c_strc_math_positioning46\relax
3147     \ht\b_strc_formulas_number\strutht
3148     \dp\b_strc_formulas_number\strutdp
3149     \dontleavehmode
3150     \vkern{\d_strc_math_first_height+\scratchdepth-\lineheight}%
3151% or \ht\b_strc_formulas_number{\d_strc_math_first_height+\scratchdepth-\strutdp}%
3152     \nointerlineskip
3153     \strc_math_flush_number_box % left
3154     \vkern{-\d_strc_math_first_height-\scratchdepth}%
3155     \handle_formula_image\unvbox\b_strc_math_display
3156   \fi}
3157
3158\def\strc_math_flush_v_box_right
3159  {\ifconditional\c_strc_math_ignore_number
3160     \d_strc_formulas_number\zeropoint
3161   \fi
3162   \strc_formulas_start_side_box
3163   \ifzeropt\d_strc_formulas_number
3164     \global\c_strc_math_positioning41\relax
3165     \handle_formula_image\unvbox\b_strc_math_display
3166   \else
3167     % better verbose than compact so some overlap in code here
3168     \ifcase\c_strc_math_number_variant\or
3169       \s_strc_formulas_margin_right\zeroskip
3170     \fi
3171     \setbox\b_strc_formulas_number\hbox to \d_strc_formulas_display_width\bgroup
3172       \hss
3173       \strc_math_flush_number_box
3174       \kern\s_strc_formulas_margin_right
3175     \egroup
3176     \ifcstok{\formulaparameter\c!order}\v!reverse
3177       \ifdim{\d_strc_math_first_right-\s_strc_formulas_margin_right}<{\d_strc_formulas_number-\d_strc_math_number_eps}%
3178         \donetrue
3179       \else
3180         \donefalse
3181       \fi
3182       \strc_math_flush_v_box_top
3183     \else
3184       \ifdim{\d_strc_math_last_right-\s_strc_formulas_margin_right}<{\d_strc_formulas_number-\d_strc_math_number_eps}%
3185         \donetrue
3186       \else
3187         \donefalse
3188       \fi
3189       \strc_math_flush_v_box_bottom
3190     \fi
3191   \fi
3192   \strc_formulas_stop_side_box}
3193
3194\def\strc_math_flush_v_box_left
3195  {\ifconditional\c_strc_math_ignore_number
3196     \d_strc_formulas_number\zeropoint
3197   \fi
3198   \strc_formulas_start_side_box
3199   \ifzeropt\d_strc_formulas_number
3200     \global\c_strc_math_positioning44\relax
3201     \handle_formula_image\unvbox\b_strc_math_display
3202   \else
3203     % better verbose than compact so some overlap in code here
3204     \ifcase\c_strc_math_number_variant\or
3205       \s_strc_formulas_margin_left\zeroskip
3206     \fi
3207     \setbox\b_strc_formulas_number\hbox to \d_strc_formulas_display_width\bgroup
3208       \kern\s_strc_formulas_margin_left
3209       \strc_math_flush_number_box
3210       \hss
3211     \egroup
3212     \ifcstok{\formulaparameter\c!order}\v!reverse
3213       \ifdim{\d_strc_math_last_left-\s_strc_formulas_margin_left}<{\d_strc_formulas_number-\d_strc_math_number_eps}%
3214         \donetrue
3215       \else
3216         \donefalse
3217       \fi
3218       \strc_math_flush_v_box_bottom
3219     \else
3220       \ifdim{\d_strc_math_first_left-\s_strc_formulas_margin_left}<{\d_strc_formulas_number-\d_strc_math_number_eps}%
3221         \donetrue
3222       \else
3223         \donefalse
3224       \fi
3225       \strc_math_flush_v_box_top
3226     \fi
3227   \fi
3228   \strc_formulas_stop_side_box}
3229
3230\def\strc_math_flush_h_mode
3231  {\global\c_strc_math_positioning\plusthree
3232   \dontleavehmode
3233   \strc_math_flush_aligned_left_number_indeed\zerocount
3234   \handle_formula_image\box\b_strc_math_display
3235   \strc_math_flush_aligned_right_number_indeed\zerocount}
3236
3237\def\strc_math_flush_h_box
3238  {\global\c_strc_math_positioning\plusfive
3239   \dontleavehmode
3240   \strc_math_flush_aligned_left_number_indeed\zerocount
3241   \handle_formula_image\box\b_strc_math_display
3242   \strc_math_flush_aligned_right_number_indeed\zerocount}
3243
3244\def\strc_math_flush_text_mode
3245  {\strc_math_setup_align_auto
3246   \bgroup
3247     \leftskip \zeroskip
3248     \rightskip\zeroskip
3249     \ifhmode
3250       % nil the tracing
3251       \strc_math_flush_h_mode
3252     \orelse\ifvbox\b_strc_math_display
3253       \ifnum\c_strc_math_number_location=\plusone
3254         \strc_math_flush_v_box_left
3255       \else
3256         \strc_math_flush_v_box_right
3257       \fi
3258     \else
3259       % nil the tracing, might never happen
3260       \strc_math_flush_h_box
3261     \fi
3262   \egroup
3263   \ifvmode
3264     \nointerlineskip
3265   \fi}
3266
3267% all modes:
3268
3269\protected\def\strc_math_flush_aligned
3270  {\ifconditional\c_strc_math_split_mode
3271     \strc_math_flush_text_mode
3272   \else
3273     \strc_math_flush_line_mode
3274   \fi}
3275
3276\def\strc_math_flush_box_normal
3277  {\ifconditional\c_strc_math_split_mode
3278     \strc_math_flush_aligned
3279   \else
3280     \hbox to \d_strc_formulas_display_width\bgroup
3281        \strc_math_flush_aligned
3282     \egroup
3283   \fi}
3284
3285\def\strc_math_flush_box_framed_common
3286  {\d_strc_math_framed_width\d_strc_formulas_display_width
3287   \setformulaframedparameter\c!align{\formulaparameter\c!align}%
3288   \letformulaframedparameter\c!strut\v!no
3289   \d_framed_formula\ht\b_strc_math_display
3290   \ifcase\c_strc_math_ragged_status\or      \or\hfill\or\hfill\fi
3291   \inheritedformulaframedframed{\handle_formula_image\box\b_strc_math_display}%
3292   \ifcase\c_strc_math_ragged_status\or\hfill\or\hfill         \fi}
3293
3294\def\strc_math_flush_box_framed_display
3295  {\let\currentformulaframed\currentformula
3296   \letformulaframedparameter\c!location\v!formula
3297   \setformulaframedparameter\c!width{\d_strc_math_framed_width}%
3298   \strc_math_flush_box_framed_common}
3299
3300\def\strc_math_flush_box_framed_fit_inline
3301  {\let\currentformulaframed\currentformula
3302   \resetformulaframedparameter\c!location
3303   \letformulaframedparameter\c!width\v!fit
3304   \strc_math_flush_box_framed_common}
3305
3306\def\strc_math_flush_box_framed_fit_display
3307  {\let\currentformulaframed\currentformula
3308   \letformulaframedparameter\c!location\v!formula
3309   \letformulaframedparameter\c!width\v!fit
3310   \strc_math_flush_box_framed_common}
3311
3312% combiners
3313
3314\def\strc_math_flush_number_box_left {\ifconditional\c_strc_formulas_overlay_number\rlap\fi{\strc_math_flush_number_box}}
3315\def\strc_math_flush_number_box_right{\ifconditional\c_strc_formulas_overlay_number\llap\fi{\strc_math_flush_number_box}}
3316
3317\def\strc_math_flush_box
3318  {\ifcase\c_strc_formulas_frame_mode
3319     \strc_math_flush_box_normal
3320   \else
3321     \strc_math_flush_box_framed_display
3322   \fi}
3323
3324\def\strc_math_number_right_normal
3325  {\strc_math_flush_aligned
3326   \hss % hss makes room for number
3327   \strc_math_flush_number_box_right}
3328
3329\def\strc_math_number_left_normal
3330  {\strc_math_flush_number_box_left
3331   \strc_math_flush_aligned
3332   \hss} % hss makes room for number
3333
3334\def\strc_math_number_right_normal_outside
3335  {\ifconditional\c_strc_formulas_tight
3336     \strc_math_flush_box_framed_fit_display
3337   \else
3338     \strc_math_flush_box_framed_display
3339   \fi
3340   \hss % hss makes room for number
3341   \rlap{\strc_math_flush_number_box}} % needs checking
3342
3343\def\strc_math_number_left_normal_outside
3344  {\llap{\strc_math_flush_number_box}% needs checking
3345   \hss % hss makes room for number
3346   \ifconditional\c_strc_formulas_tight
3347     \strc_math_flush_box_framed_fit_display
3348   \else
3349     \strc_math_flush_box_framed_display
3350   \fi}
3351
3352\def\strc_math_number_right_normal_inside
3353  {\setbox\b_strc_math_display\hpack to {\d_strc_formulas_display_width-\d_framed_locator_lo-\d_framed_locator_ro}\bgroup
3354     \strc_math_flush_aligned
3355     \hss
3356     \strc_math_flush_number_box
3357   \egroup
3358   \strc_math_flush_box_framed_fit_inline}
3359
3360\def\strc_math_number_left_normal_inside
3361  {\setbox\b_strc_math_display\hpack to {\d_strc_formulas_display_width-\d_framed_locator_lo-\d_framed_locator_ro}\bgroup
3362     \strc_math_flush_number_box
3363     \hss
3364     \strc_math_flush_aligned
3365   \egroup
3366   \strc_math_flush_box_framed_fit_inline}
3367
3368\def\strc_math_number_right_overflow
3369  {\vpack\bgroup
3370     \strc_math_flush_box
3371     \par
3372     \hpack to \d_strc_formulas_display_width\bgroup
3373       \hss
3374       \strc_math_flush_number_box_right
3375     \egroup
3376   \egroup}
3377
3378\def\strc_math_number_left_overflow
3379  {\vpack\bgroup
3380     \hpack to \d_strc_formulas_display_width\bgroup
3381       \strc_math_flush_number_box_left
3382       \hss
3383     \egroup
3384     \strc_math_flush_box
3385   \egroup}
3386
3387\def\strc_math_number_right_overflow_outside
3388  {\vpack\bgroup
3389     \strc_math_flush_box_framed_fit_inline
3390    %\hskip\zeroskip % nicely breaks the line without introducing funny vertical spacing ... why o why
3391     \hpack to \d_strc_formulas_display_width\bgroup
3392       \hss
3393       \strc_math_flush_number_box
3394     \egroup
3395   \egroup}
3396
3397\def\strc_math_number_left_overflow_outside
3398  {\vpack\bgroup
3399     \hpack to {\d_strc_formulas_display_width-\d_framed_locator_lo}\bgroup
3400       \strc_math_flush_number_box
3401       \hss
3402     \egroup
3403     \hskip\zeroskip % nicely breaks the line without introducing funny vertical spacing ... why o why
3404     \strc_math_flush_box_framed_fit_inline
3405   \egroup}
3406
3407\def\strc_math_number_right_overflow_inside
3408  {\setbox\b_strc_math_display\vpack\bgroup
3409     \handle_formula_image\box\b_strc_math_display
3410     \hpack to \d_strc_formulas_display_width\bgroup
3411       \hss
3412       \strc_math_flush_number_box
3413       \kern\d_framed_locator_ro
3414     \egroup
3415   \egroup
3416   \strc_math_flush_box_framed_fit_inline}
3417
3418\def\strc_math_number_left_overflow_inside
3419  {\setbox\b_strc_math_display\vpack\bgroup
3420     \hpack to \d_strc_formulas_display_width\bgroup
3421     % \kern\d_framed_locator_lo
3422       \strc_math_flush_number_box
3423       \hss
3424     \egroup
3425     \handle_formula_image\box\b_strc_math_display
3426   \egroup
3427   \strc_math_flush_box_framed_fit_inline}
3428
3429% checkers
3430
3431\setupmathalignment
3432  [\c!numberdistance=\formulaparameter\c!numberdistance]
3433
3434\protected\def\d_strc_math_total_display_width
3435  {\dimexpr
3436     \d_strc_math_display_width+\d_strc_formulas_number
3437     \ifconditional\c_strc_formulas_overlay_number
3438        \ifcase\c_strc_math_ragged_status\or\or+\d_strc_formulas_number\or\fi
3439     \fi
3440   \relax}
3441
3442\def\strc_math_number_check
3443  {\d_strc_math_display_width\wd\b_strc_math_display
3444   \ifconditional\c_strc_formulas_tight
3445     \ifdim\d_strc_math_total_display_width>\d_strc_formulas_display_width
3446       \c_strc_math_display_overflow\conditionaltrue
3447     \else
3448       \d_strc_formulas_display_width\d_strc_math_total_display_width
3449       \c_strc_math_display_overflow\conditionalfalse
3450     \fi
3451   \else
3452     \ifdim{\d_strc_math_total_display_width+(\formulaparameter\c!numberthreshold)}>\d_strc_formulas_display_width
3453       \c_strc_math_display_overflow\conditionaltrue
3454     \else
3455       \c_strc_math_display_overflow\conditionalfalse
3456     \fi
3457   \fi}
3458
3459\def\strc_math_number_check_outside
3460  {\d_strc_math_display_width\naturalwd\b_strc_math_display
3461   \ifdim{\d_strc_math_total_display_width+\d_framed_locator_lo+\d_framed_locator_ro}>\d_strc_formulas_display_width
3462     \c_strc_math_display_overflow\conditionaltrue
3463   \else
3464     \c_strc_math_display_overflow\conditionalfalse
3465   \fi
3466   % still ok?
3467   \ifnum\c_strc_math_ragged_status=\plustwo
3468     \d_strc_math_framed_width{\d_strc_formulas_display_width-2\d_strc_formulas_number}%
3469   \else
3470     \d_strc_math_framed_width{\d_strc_formulas_display_width- \d_strc_formulas_number}%
3471   \fi}
3472
3473\let\strc_math_number_check_inside\strc_math_number_check_outside
3474
3475% offsets
3476
3477\def\strc_math_number_check_offsets
3478  {\begingroup
3479     \setbox\scratchbox\hbox
3480       {\inheritedformulaframedframed
3481          {\pack_framed_locator_set_lo\pack_framed_locator_set_ro}}%
3482   \endgroup}
3483
3484% tracing
3485
3486\def\strc_math_traced_state_yes
3487  {\llap{\setbox\scratchbox\hbox{\infofont
3488   \ifcase\c_strc_math_ragged_status unset\or flushleft\or middle\or flushright\fi
3489   \space
3490   \ifcase\c_strc_formulas_frame_mode no\or out\or in\fi
3491   \space
3492   \ifconditional\c_strc_math_display_overflow overflow\else fit\fi
3493   \quad}\ht\scratchbox\zeropoint\dp\scratchbox\zeropoint\box\scratchbox}}
3494
3495\let\strc_math_traced_state\relax
3496
3497\installtextracker
3498  {formulas.framed}
3499  {\let\strc_math_traced_state\strc_math_traced_state_yes}
3500  {\let\strc_math_traced_state\relax}
3501
3502% packaging
3503
3504\installcorenamespace{mathboxlocation}
3505
3506\defcsname\??mathboxlocation\v!left \endcsname
3507  {\c_strc_math_number_location\plusone}
3508
3509\defcsname\??mathboxlocation\v!right\endcsname
3510  {\c_strc_math_number_location\plustwo}
3511
3512\defcsname\??mathboxlocation\v!atleftmargin\endcsname
3513  {\c_strc_math_number_location\plusone
3514   \ifzeropt\s_strc_formulas_margin_left
3515     % this can be a helper as now mixed in math-ali
3516     \parinitleftskip\zeroskip
3517   \else
3518     \c_strc_math_number_variant \plusone
3519   \fi}
3520
3521\defcsname\??mathboxlocation\v!atrightmargin\endcsname
3522  {\c_strc_math_number_location\plustwo
3523   \ifzeropt\s_strc_formulas_margin_right
3524     % this can be a helper as now mixed in math-ali
3525     \parfillrightskip\zeroskip
3526   \else
3527     \c_strc_math_number_variant \plusone
3528   \fi}
3529
3530\newconditional\c_strc_math_signal
3531
3532\protected\def\strc_math_check_location
3533  {\c_strc_math_signal\conditionalfalse}
3534
3535\protected\def\strc_math_signal_location
3536  {\ifconditional\c_strc_math_signal
3537     \signalrightpage
3538   \fi}
3539
3540\defcsname\??mathboxlocation\v!outer\endcsname
3541  {\c_strc_math_signal\conditionaltrue
3542   \doifelseupcomingrightpage
3543     {\letformulaparameter\c!location\v!right}%
3544     {\letformulaparameter\c!location\v!left}%
3545   \begincsname\??mathboxlocation\formulaparameter\c!location\endcsname}
3546
3547\defcsname\??mathboxlocation\v!inner\endcsname
3548  {\c_strc_math_signal\conditionaltrue
3549   \doifelseupcomingrightpage
3550     {\letformulaparameter\c!location\v!left}%
3551     {\letformulaparameter\c!location\v!right}%
3552   \begincsname\??mathboxlocation\formulaparameter\c!location\endcsname}
3553
3554\protected\def\strc_math_box_start#1%
3555  {\c_strc_math_ragged_status#1\relax % already set
3556   \useformulacolorparameter\c!color
3557   \c_strc_math_number_location\zerocount
3558   \c_strc_math_number_variant \zerocount
3559   \strc_math_check_location
3560   \begincsname\??mathboxlocation\formulaparameter\c!location\endcsname
3561   %
3562   % We collect the math formula in an hbox. Dimensions don't really play
3563   % a role yet but beware of nesting!
3564   %
3565   \dontcomplain
3566  %\holdingmigrations\plusfour
3567   \setbox\b_strc_math_display\hbox retain \plusfour\bgroup
3568     \strc_math_signal_location
3569     \startforceddisplaymath}
3570
3571\protected\def\strc_math_box_stop
3572  {\stopforceddisplaymath
3573   \egroup
3574   % preroll left and right offsets
3575   \ifcase\c_strc_formulas_frame_mode
3576     % no frame
3577   \else
3578     \strc_math_number_check_offsets
3579   \fi
3580   \ifcase\c_strc_formulas_frame_mode
3581     \strc_math_number_check
3582   \or
3583     \strc_math_number_check_outside
3584   \else
3585     \strc_math_number_check_inside
3586   \fi
3587   \strc_math_traced_state
3588   \ifconditional\c_strc_math_split_mode
3589     \bgroup
3590   \else
3591     \noindent % \noindentation % not \dontleavehmode
3592     \hbox to \strc_math_effective_width \bgroup
3593   \fi
3594   \ifcase\c_strc_math_number_location
3595     \strc_math_flush_box
3596   \or % number left
3597     \ifzeropt\d_strc_formulas_number
3598       \strc_math_flush_number_no
3599     \else
3600       \strc_math_flush_number_left
3601     \fi
3602   \else % number right
3603     \ifzeropt\d_strc_formulas_number
3604       \strc_math_flush_number_no
3605     \else
3606       \strc_math_flush_number_right
3607     \fi
3608   \fi
3609   \egroup
3610   \ifconditional\c_strc_math_split_mode
3611     \ifhmode \else
3612       \strc_math_show_margins
3613     \fi
3614   \fi}
3615
3616\defineinnermathhandler\v!left      {\strc_math_box_start\plusthree}{\strc_math_box_stop}
3617\defineinnermathhandler\v!flushright{\strc_math_box_start\plusthree}{\strc_math_box_stop}
3618\defineinnermathhandler\v!right     {\strc_math_box_start\plusone  }{\strc_math_box_stop}
3619\defineinnermathhandler\v!flushleft {\strc_math_box_start\plusone  }{\strc_math_box_stop}
3620\defineinnermathhandler\v!center    {\strc_math_box_start\plustwo  }{\strc_math_box_stop}
3621\defineinnermathhandler\v!middle    {\strc_math_box_start\plustwo  }{\strc_math_box_stop}
3622\defineinnermathhandler\v!normal    {\strc_math_box_start\plustwo  }{\strc_math_box_stop}
3623\defineinnermathhandler\v!atmargin  {\strc_math_box_start\plusfour }{\strc_math_box_stop}
3624
3625\def\strc_math_flush_number_no
3626  {\ifconditional\c_strc_math_split_mode
3627     \strc_math_flush_box
3628   \orelse\ifconditional\c_strc_math_display_overflow
3629     \ifcase\c_strc_formulas_frame_mode
3630       \strc_math_flush_box_normal
3631     \else
3632       \strc_math_flush_box_framed_fit_inline
3633     \fi
3634   \orelse\ifcase\c_strc_formulas_frame_mode
3635     \strc_math_flush_box_normal
3636   \orelse\ifconditional\c_strc_formulas_tight
3637      \strc_math_flush_box_framed_fit_inline
3638   \else
3639      \strc_math_flush_box_framed_display
3640   \fi}
3641
3642\def\strc_math_flush_number_left
3643  {\ifconditional\c_strc_math_split_mode
3644     \strc_math_flush_aligned % we flush in here, otherwise wrong positioning of number (we need to unvbox)
3645   \orelse\ifconditional\c_strc_math_display_overflow
3646     \ifcase\c_strc_formulas_frame_mode
3647       \strc_math_number_left_overflow
3648     \or
3649       \strc_math_number_left_overflow_outside
3650     \or
3651       \strc_math_number_left_overflow_inside
3652     \fi
3653   \else
3654     \ifcase\c_strc_formulas_frame_mode
3655       \strc_math_number_left_normal
3656     \or
3657       \strc_math_number_left_normal_outside
3658     \or
3659       \strc_math_number_left_normal_inside
3660     \fi
3661   \fi}
3662
3663\def\strc_math_flush_number_right
3664  {\ifconditional\c_strc_math_split_mode
3665     \strc_math_flush_aligned
3666   \orelse\ifconditional\c_strc_math_display_overflow
3667     \ifcase\c_strc_formulas_frame_mode
3668       \strc_math_number_right_overflow
3669     \or
3670       \strc_math_number_right_overflow_outside
3671     \or
3672       \strc_math_number_right_overflow_inside
3673     \fi
3674   \else
3675     \ifcase\c_strc_formulas_frame_mode
3676       \strc_math_number_right_normal
3677     \or
3678       \strc_math_number_right_normal_outside
3679     \or
3680       \strc_math_number_right_normal_inside
3681     \fi
3682   \fi}
3683
3684%D Some inline math tweak.
3685
3686\appendtoks
3687    \ifcase\mathnestinglevel\or
3688        % 4=disable 6=only when no spaces
3689        \mathsurroundskip{\mathematicsparameter\c!textdistance}%
3690        \ifzeropt\mathsurroundskip
3691          \ifzeropt\gluestretch\mathsurroundskip
3692            \ifzeropt\glueshrink\mathsurroundskip
3693              \mathsurroundmode\plussix
3694            \else
3695              \mathsurroundskip\zeroskip
3696              \mathsurroundmode\plusfour
3697            \fi
3698          \else
3699            \mathsurroundmode\plussix
3700          \fi
3701        \else
3702          \mathsurroundmode\plussix
3703        \fi
3704    \else
3705      \mathsurroundmode\plusfour
3706      \mathsurroundskip\zeroskip
3707    \fi
3708\to \everymathematics
3709
3710\setupmathematics
3711  [\c!textdistance=\zeropoint]
3712
3713%D Kind of new (February 2022):
3714
3715\installcorenamespace {maththreshold}
3716
3717\setupmathematics[\c!threshold=\zeropoint]
3718
3719\permanent\protected\def\installmaththreshold#1#2%
3720  {\expandafter\gluespecdef\csname\??maththreshold#1\endcsname#2\relax}
3721
3722\installmaththreshold\v!none  {\zeropoint}
3723\installmaththreshold\v!small {3\emwidth plus 0.50\emwidth minus 0.25\emwidth}
3724\installmaththreshold\v!medium{4\emwidth plus 0.75\emwidth minus 0.50\emwidth}
3725\installmaththreshold\v!big   {5\emwidth plus 1.00\emwidth minus 0.75\emwidth}
3726
3727\appendtoks
3728    \edef\p_threshold{\mathematicsparameter\c!threshold}%
3729    \maththreshold\ifcsname\??maththreshold\p_threshold\endcsname\lastnamedcs\else\p_threshold\fi\relax
3730% \to \everymath % \everymathematics
3731\to \everymathematics
3732
3733%D Here is simple alignment mechanism:
3734
3735\installcorenamespace{mathsimplealign}
3736
3737\installcommandhandler \??mathsimplealign {mathsimplealign} \??mathsimplealign
3738
3739\setupmathsimplealign
3740  [\c!distance=\v!math,
3741   \c!leftmargin=\zeropoint,
3742   \c!rightmargin=\zeropoint,
3743   \c!left=,
3744   \c!right=,
3745   \c!strut=\v!yes,
3746   \c!spaceinbetween=\mathalignmentparameter\c!spaceinbetween,
3747   \c!align=\v!all:\v!middle,
3748   \c!textdistance=.25\emwidth]
3749
3750\appendtoks
3751    \frozen\instance\protected\edefcsname\e!start\currentmathsimplealign\endcsname{\math_simplealign_start[\currentmathsimplealign]}%
3752    \frozen\instance          \defcsname \e!stop \currentmathsimplealign\endcsname{\math_simplealign_stop}%
3753\to \everydefinemathsimplealign
3754
3755\permanent\protected\def\math_simplealign_NC
3756  {\aligntab}
3757
3758% \permanent\protected\def\math_simplealign_EQ
3759%   {\aligntab=\aligntab}
3760
3761\permanent\protected\def\math_simplealign_EQ
3762  {\aligntab=}
3763
3764\noaligned\tolerant\permanent\protected\def\math_simplealign_NR[#1]#*[#2]%
3765  {\unskip
3766%    \strc_formulas_place_number_nested{#1}{#2}%
3767\math_place_number_in_alignment{#1}{#2}%
3768   \math_number_right_of_eqalign
3769   \crcr}
3770
3771\aliased\let\math_align_strut\relax
3772
3773\newconditional\c_math_align_text
3774
3775\permanent\protected\def\math_simplealign_NC{\relax\global\c_math_align_text\conditionalfalse\aligntab}
3776\permanent\protected\def\math_simplealign_EQ{\relax\global\c_math_align_text\conditionalfalse\aligntab=}
3777\permanent\protected\def\math_simplealign_TC{\relax\global\c_math_align_text\conditionaltrue \aligntab}
3778
3779\installcorenamespace{mathsimpleendclass}
3780
3781\global\expandafter\integerdef\csname\??mathsimpleendclass\the\zerocount\endcsname\mathendcode
3782
3783% \permanent\tolerant\protected\def\math_simplealign_start[#1]#*[#S#2]%
3784%   {\begingroup
3785%    \cdef\currentmathsimplealign{#1}%
3786%    \ifarguments\or\or
3787%      \setupcurrentmathsimplealign[#2]%
3788%    \fi
3789%    \edef\p_strut{\mathsimplealignparameter\c!strut}%
3790%    \ifx\p_strut\v!yes
3791%      \enforced\let\math_align_strut\strut
3792%    \else
3793%      \enforced\let\math_align_strut\relax
3794%    \fi
3795%    \mathatom \s!class \mathwrappedcode \bgroup
3796%    \scratchdimen\mathsimplealignparameter\c!leftmargin\relax
3797%    \ifzeropt\scratchdimen\else\kern\scratchdimen\fi
3798%    \mathsimplealignparameter\c!left\relax
3799%    \math_fenced_start_wrap{\mathsimplealignparameter\c!fences}%
3800%    \mathatom \s!class \mathconstructcode \bgroup
3801%    \math_alignment_location_check{\mathsimplealignparameter\c!location}% vcenter etc
3802%    \math_alignment_location_box
3803%    \bgroup
3804%    \enforced\let\MC\math_simplealign_NC
3805%    \enforced\let\NC\math_simplealign_NC
3806%    \enforced\let\TC\math_simplealign_TC
3807%    \enforced\let\NR\math_simplealign_NR
3808%    \enforced\let\EQ\math_simplealign_EQ
3809%    \enforced\let\TB\math_common_TB
3810%    \math_eqalign_set_defaults
3811%    \math_eqalign_set_columns{\mathsimplealignparameter\c!align}%
3812%    \global\c_math_eqalign_column\zerocount
3813%    \global\c_math_eqalign_row\plusone
3814%    \edef\m_simplealign_distance{\mathsimplealignparameter\c!distance}%
3815%    \strc_math_setup_spacing_aligned\mathsimplealignparameter
3816%    \enablemathalignrelocate
3817%    \halign
3818%      \s!callback
3819%        \align_callback_mathalign
3820%      \s!attr
3821%        \mathnumberlocationattribute \zerocount
3822%      \bgroup
3823%      \global\c_math_eqalign_column\zerocount
3824%      \global\advanceby\c_math_eqalign_row\zerocount
3825%      \ignorespaces
3826%      \aligncontent % dummy
3827%      \removeunwantedspaces
3828%      \lastleftclass \mathbegincode
3829%      \lastrightclass\mathendcode
3830%      \aligntab
3831%      \global\advanceby\c_math_eqalign_column\plusone
3832%      \math_left_of_eqalign  % \hfil
3833%      \ignorespaces
3834%      \math_align_strut
3835%    % \mathbeginclass\ifcsname\??mathsimpleendclass\the\numexpr\c_math_eqalign_column-\plusone\relax\endcsname\lastnamedcs\else\mathunsetcode\fi
3836%      \mathbeginclass\mathbegincode
3837%      \startforceddisplaymath
3838%      \aligncontent
3839%      \stopforceddisplaymath
3840%      \ifnum\lastrightclass<\mathunsetcode
3841%        \global\expandafter\integerdef\csname\??mathsimpleendclass\the\c_math_eqalign_column\endcsname\lastrightclass
3842%      \fi
3843%      \removeunwantedspaces
3844%      \math_right_of_eqalign % \hfil
3845%      \aligntab
3846%      \aligntab
3847%      % repeater
3848%      \global\advanceby\c_math_eqalign_column\plusone
3849%      \math_left_of_eqalign  % \hfil
3850%      \ifx\m_simplealign_distance\v!math
3851%        \mathbeginclass\ifcsname\??mathsimpleendclass\the\numexpr\c_math_eqalign_column-\plusone\relax\endcsname\lastnamedcs\else\mathunsetcode\fi
3852%      \else
3853%        \kern\m_simplealign_distance
3854%      \fi
3855%      \ignorespaces
3856%      \math_align_strut
3857%      \ifconditional\c_math_align_text
3858%        % somehow we can't use content as an argument
3859%      \else
3860%        \startforceddisplaymath
3861%      \fi
3862%      \aligncontent
3863%      \ifmmode
3864%        \stopforceddisplaymath
3865%      \fi
3866%      \ifnum\lastrightclass<\mathunsetcode
3867%        \global\expandafter\integerdef\csname\??mathsimpleendclass\the\c_math_eqalign_column\endcsname\lastrightclass
3868%      \fi
3869%      \removeunwantedspaces
3870%      \math_right_of_eqalign % \hfil
3871%      \crcr}
3872%
3873% \noaligned\permanent\protected\def\math_simplealign_stop
3874%   {\crcr
3875%    \egroup
3876%    \egroup
3877%    \egroup
3878%    \math_fenced_stop_wrap
3879%    \mathsimplealignparameter\c!right\relax
3880%    \scratchdimen\mathsimplealignparameter\c!rightmargin\relax
3881%    \ifzeropt\scratchdimen\else\kern\scratchdimen\fi
3882%    \setbox\scratchbox\hbox{\mathsimplealignparameter\c!text}%
3883%    \ifvoid\scratchbox\else
3884%      \kern\mathsimplealignparameter\c!textdistance
3885%      \vcenter{\box\scratchbox}%
3886%    \fi
3887%    \egroup
3888%    \endgroup}
3889
3890% Split up so we can better compare to the normal align:
3891
3892\newtoks\everymathsimplealign
3893\newtoks\everymathsimplealigndone
3894
3895\def\math_simplealign_preamble
3896  {\global\c_math_eqalign_column\zerocount
3897   \global\advanceby\c_math_eqalign_row\zerocount
3898   \ignorespaces
3899   \aligncontent % dummy
3900   \removeunwantedspaces
3901   \lastleftclass \mathbegincode
3902   \lastrightclass\mathendcode
3903   \aligntab
3904   \global\advanceby\c_math_eqalign_column\plusone
3905   \math_left_of_eqalign  % \hfil
3906   \ignorespaces
3907   \math_align_strut
3908   \mathbeginclass\ifcsname\??mathsimpleendclass\tointeger{\c_math_eqalign_column-\plusone}\endcsname\lastnamedcs\else\mathunsetcode\fi
3909   \mathbeginclass\mathbegincode
3910   \startforceddisplaymath
3911   \aligncontent
3912   \stopforceddisplaymath
3913   \ifnum\lastrightclass<\mathunsetcode
3914     \global\expandafter\integerdef\csname\??mathsimpleendclass\the\c_math_eqalign_column\endcsname\lastrightclass
3915   \fi
3916   \removeunwantedspaces
3917   \math_right_of_eqalign % \hfil
3918   \aligntab
3919   \aligntab
3920   % repeater
3921   \global\advanceby\c_math_eqalign_column\plusone
3922   \math_left_of_eqalign  % \hfil
3923   \ifx\m_simplealign_distance\v!math
3924     \mathbeginclass\ifcsname\??mathsimpleendclass\tointeger{\c_math_eqalign_column-\plusone}\endcsname\lastnamedcs\else\mathunsetcode\fi
3925   \else
3926     \kern\m_simplealign_distance
3927   \fi
3928   \startforceddisplaymath
3929   \aligncontent
3930   \stopforceddisplaymath
3931   \ifnum\lastrightclass<\mathunsetcode
3932     \global\expandafter\integerdef\csname\??mathsimpleendclass\the\c_math_eqalign_column\endcsname\lastrightclass
3933   \fi
3934   \math_right_of_eqalign} % \hfil
3935
3936\appendtoks
3937   \enforced\let\MC\math_simplealign_NC
3938   \enforced\let\NC\math_simplealign_NC
3939   \enforced\let\TC\math_simplealign_TC
3940   \enforced\let\NR\math_simplealign_NR
3941   \enforced\let\EQ\math_simplealign_EQ
3942   \enforced\let\TB\math_common_TB
3943\to \everymathsimplealign
3944
3945\appendtoks
3946\to \everymathsimplealigndone
3947
3948\def\math_simple_halign_checked
3949  {\enablemathalignrelocate
3950   \halign
3951     \s!callback
3952       \align_callback_mathalign
3953     \s!attr
3954       \mathnumberlocationattribute \zerocount}
3955
3956\permanent\tolerant\protected\def\math_simplealign_start[#1]#*[#S#2]%
3957  {\begingroup
3958   \currentmathblobnesting\minusone
3959   \cdef\currentmathsimplealign{#1}%
3960   \ifarguments\or\or
3961     \setupcurrentmathsimplealign[#2]%
3962   \fi
3963   \edef\p_strut{\mathsimplealignparameter\c!strut}%
3964   \ifx\p_strut\v!yes
3965     \enforced\let\math_align_strut\strut
3966   \else
3967     \enforced\let\math_align_strut\relax
3968   \fi
3969   \expand\everymathsimplealign
3970   \global\c_math_eqalign_column\zerocount
3971   \global\c_math_eqalign_row\plusone
3972   \math_eqalign_set_defaults
3973   \math_eqalign_set_columns{\mathsimplealignparameter\c!align}%
3974   \math_alignment_location_check{\mathsimplealignparameter\c!location}% vcenter etc
3975   \edef\m_simplealign_distance{\mathsimplealignparameter\c!distance}%
3976   \strc_math_setup_spacing_aligned\mathsimplealignparameter
3977   %
3978   \mathatom \s!class \mathwrappedcode \bgroup
3979   \scratchdimen{\mathsimplealignparameter\c!leftmargin}%
3980   \ifzeropt\scratchdimen\else\kern\scratchdimen\fi
3981   \mathsimplealignparameter\c!left\relax
3982   \math_fenced_start_wrap{\mathsimplealignparameter\c!fences}%
3983   \mathatom \s!class \mathconstructcode \bgroup
3984   \math_alignment_location_box \bgroup
3985   \math_simple_halign_checked\expandafter\bgroup\math_simplealign_preamble\crcr}
3986
3987\noaligned\permanent\protected\def\math_simplealign_stop
3988  {\crcr
3989   \egroup % halign
3990   \egroup % box
3991   \egroup % construct
3992   \math_fenced_stop_wrap
3993   \mathsimplealignparameter\c!right\relax
3994   \scratchdimen{\mathsimplealignparameter\c!rightmargin}%
3995   \ifzeropt\scratchdimen\else\kern\scratchdimen\fi
3996   \setbox\scratchbox\hbox{\mathsimplealignparameter\c!text}%
3997   \ifvoid\scratchbox\else
3998     \kern{\mathsimplealignparameter\c!textdistance}%
3999     \vcenter{\box\scratchbox}%
4000   \fi
4001   \egroup % wrapped
4002   \expand\everymathsimplealigndone
4003   \endgroup}
4004
4005%D It's not that spectacular apart from spacing being proper inter atom spacing
4006%D using one of the new \LUAMETATEX\ mechanisms.
4007%D
4008%D \starttyping
4009%D \definemathsimplealign
4010%D   [whatever]
4011%D   [left={\startmathfenced[sesac]},
4012%D    right=\stopmathfenced]
4013%D
4014%D  % distance=math,
4015%D  % distance=\zeropoint,
4016%D  % distance=1cm,
4017%D  % align={all:left}]
4018%D
4019%D \startformula
4020%D     \startwhatever[text=simple]
4021%D       \NC x \NC = r           \cos\theta \NR
4022%D       \NC y \NC = \frac{1}{2} \sin\theta \NR
4023%D       \NC 9 \NC = 123         \sin\theta \NR
4024%D     \stopwhatever
4025%D \stopformula
4026%D \stoptyping
4027
4028%D Usage \type {\sum _ {\mstack {i \in V_{0}, i \neq j}}}, documented by Mikael:
4029
4030\permanent\protected\def\mstack#1% todo: make it configurable
4031   {\begingroup
4032    \scratchtoks\emptytoks \setcharstrut(\relax
4033    \processcommalist[#1]{\ifempty\scratchtoks\else\toksapp\scratchtoks{\mathstrut\NR}\fi\toksapp\scratchtoks}%
4034    \expandafter\startsubstack\the\scratchtoks\mathstrut\stopsubstack
4035    \endgroup}
4036
4037%D Similar to simplecases:
4038%D
4039%D \starttyping
4040%D \startformula
4041%D     \equationsystem {
4042%D        {(1-a)}x^{2x} - 3y_2 + 14z  = 2 + x,
4043%D        {(1-a)}x^2    - 3y_2 +  4z <= 62,
4044%D        {(1-a)}x^a    - 3y_2 +  4z >= 12,
4045%D        {(1-a)}x^{2a} - 3y_2 + 24z != 4,
4046%D               x^^2   - 3y_2 +  4z ~  1,
4047%D               x^^2   - 3y_2 +  4z ≠  1,
4048%D             -2x      -         4z <> 10,
4049%D     }
4050%D \stopformula
4051%D \stoptyping
4052
4053\permanent\tolerant\protected\def\math_align_simple[#1]#*[#S#2]#:#3%
4054  {\begingroup
4055   \cdef\currentmathsimplealign{#1}%
4056   \setupcurrentmathsimplealign[#2]%
4057   \math_simplealign_start[\currentmathsimplealign]%
4058   \clf_simplealign{\mathsimplealignparameter\c!alternative}{\mathsimplealignparameter\c!action}{#3}%
4059   \math_simplealign_stop
4060   \endgroup}
4061
4062\appendtoks
4063    \edef\p_simplecommand{\mathsimplealignparameter\c!simplecommand}%
4064    \ifempty\p_simplecommand\else
4065        \frozen\protected\instance\edefcsname\p_simplecommand\endcsname{\math_align_simple[\currentmathsimplealign]}%
4066    \fi
4067\to \everydefinemathsimplealign
4068
4069\definemathsimplealign % new !
4070  [equationsystem]
4071  [\c!simplecommand=equationsystem,
4072   \c!alternative=equationsystem, % for the moment we use this key
4073   \c!align={all:right},
4074   \c!distance=\v!math,
4075   \c!left=,
4076   \c!right=]
4077
4078\definemathsimplealign
4079  [lequationsystem]
4080  [equationsystem]
4081  [\c!simplecommand=lequationsystem,
4082   \c!left={\startmathfenced[cases]},
4083   \c!right=\stopmathfenced]
4084
4085\definemathsimplealign
4086  [requationsystem]
4087  [equationsystem]
4088  [\c!simplecommand=requationsystem,
4089   \c!left={\startmathfenced[sesac]},
4090   \c!right=\stopmathfenced]
4091
4092%D There are users who use this so let's for now keep it (I also need to adapt
4093%D x-mathml.mkxl):
4094
4095\newskip \math_old_hideskip   \math_old_hideskip  = -1000pt plus 1fill
4096\newskip \math_old_centering  \math_old_centering =     0pt plus 1000pt minus 1000pt
4097
4098\permanent\protected\def\eqalign#1% rather plain, is this used at all ...
4099  {\dontleavehmode
4100   \mskip\thinmuskip\vcenter\bgroup % \vcenter \s!class \mathwrappercode \bgroup
4101     \currentmathblobnesting\minusone
4102     \mathsurround\zeropoint        % \math_eqalign_set_defaults
4103     \everycr\emptytoks
4104     \tabskip\zeroskip
4105     \enforced\let\hideskip\math_old_hideskip
4106     \enforced\let\centering\math_old_centering
4107     \enforced\def\hidewidth{\hskip\hideskip} % for alignment entries that can stick out
4108     \amcode\ampersandasciicode\alignmentcatcode
4109     \halign
4110       {\strut
4111        \hfil
4112        \mathbeginclass\mathordcode
4113        \mathendclass  \mathordcode
4114        \startforceddisplaymath\aligncontent\stopforceddisplaymath
4115        \aligntab
4116        \mathbeginclass\mathordcode
4117        \mathendclass  \mathordcode
4118        \startforceddisplaymath\aligncontent\stopforceddisplaymath
4119        \hfil
4120        \crcr
4121        #1%
4122        \crcr}%
4123   \egroup\mskip\thinmuskip}        % \egroup
4124
4125\protect \endinput
4126
4127% \placeformula \startformula[-] \startmatrix
4128% \NC 1 \NC x \NC a \NR
4129% \NC 2 \NC y \NC b \NR
4130% \NC 3 \NC z \NC c \NR
4131% \stopmatrix \stopformula
4132
4133% \definemathmatrix[bordermatrix][left={\left[\mskip\thinmuskip},right={\mskip\thinmuskip\right]}]
4134
4135% \placeformula \startformula[-] \startbordermatrix
4136% \NC 1 \NC x \NC a \NR
4137% \NC 2 \NC y \NC b \NR
4138% \NC 3 \NC z \NC c \NR
4139% \stopbordermatrix \stopformula
4140