math-ini.mkxl /size: 101 Kb    last modification: 2021-10-28 13:51
1%D \module
2%D   [       file=math-ini,
3%D        version=2008.01.02,
4%D          title=\CONTEXT\ Math Macros,
5%D       subtitle=Initializations,
6%D         author=Hans Hagen,
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 / Initializations}
15
16% todo: hpack as we skip math anyway
17%
18% todo: 0x2061 : function application
19% todo: 0x2062 : invisible times
20% todo: 0x2063 : invisible comma
21
22% a bit tricky way to set ... no (pseudo) registers but math hash values:
23%
24% \normalexpanded{\Umathlimitabovevgap\displaystyle=40\dimexpr\the\Umathlimitabovevgap\displaystyle\relax}
25
26% Todo in luatex maincontrol.w: also accept a number here:
27%
28%    case set_math_param_cmd:
29%        p = cur_chr;
30%        get_token();
31%        if (cur_cmd != math_style_cmd) {
32%
33% plus two new math styles: larger/smaller
34%
35% \protected\def\Umathshow#1%
36%   {\hbox{\infofont(\string#1:\the#1\textstyle,\the#1\scriptstyle,\the#1\scriptscriptstyle)}}
37
38%D This module provides namespaces for math fonts, thereby permitting mixed usage of
39%D math fonts. Although not strictly needed, we also provide a family name mapping
40%D mechanism as used in the (original) AMS math definition files, but here these
41%D names can recursively be remapped and if needed, dynamically be changed. We've
42%D tried to minimize the number of definition commands and use plain \TEX\
43%D definitions as fallback. We've tried to follow a couple of conventions from plain
44%D and AMS math in order to achieve backward compatinility. We also kept an eye on
45%D future usage of these modules in the perspective of MathML and unicode fonts.
46
47%D There is a subtle issue with grouping: the \type {\begingroup} method will not
48%D restore a changed mathstyle so best avoid that one. However, there are cases where
49%D we really need to use such grouping.
50
51% Weird, these fail, maybe amp is solved in a later state from char noads (needs a
52% fix in luatex):
53%
54% $\char"26$
55% $\a$
56% $\string&$
57
58% mathop applied to characters centers it vertically
59
60\unprotect
61
62%D We move these definitions into the format:
63
64% test  [[\char948 \cldcontext{utf.char(948)}]]
65% test $[[\char948 \cldcontext{utf.char(948)}]]$
66
67\registerctxluafile{math-ini}{autosuffix}
68\registerctxluafile{math-dim}{}
69\registerctxluafile{math-act}{autosuffix}
70\registerctxluafile{math-ext}{}
71\registerctxluafile{math-vfu}{autosuffix}
72\registerctxluafile{math-ttv}{}
73\registerctxluafile{math-map}{autosuffix}
74\registerctxluafile{math-ren}{}
75\registerctxluafile{math-noa}{autosuffix}
76\registerctxluafile{math-tag}{autosuffix}
77\registerctxluafile{math-fbk}{autosuffix}
78\registerctxluafile{math-dir}{}
79\registerctxluafile{math-spa}{}
80\registerctxluafile{math-fnt}{autosuffix}
81
82%D A starter:
83%D
84%D \startbuffer
85%D \mathsurround    10pt
86%D \mathsurroundskip30pt
87%D x $x + \ruledhbox{$x$} + x$ x
88%D \stopbuffer
89%D
90%D \typebuffer
91%D
92%D \start \blank \getbuffer \blank \stop
93
94\newcount\mathnestinglevel
95
96\appendtoks
97    \advance\mathnestinglevel\plusone
98\to \everymathematics
99
100%D A few compatibility helpers:
101
102\permanent\def\Umathbotaccent{\Umathaccent \s!bottom }
103\permanent\def\Umathtopaccent{\Umathaccent \s!top    }
104\permanent\def\Umathaccents  {\Umathaccent \s!both   } % strange highlighting
105
106%D The attributes that we will use (todo: pack some into one but uglier code):
107
108\definesystemattribute[mathalphabet]   [public]
109\definesystemattribute[mathsize]       [public]
110\definesystemattribute[mathpunctuation][public]
111\definesystemattribute[mathgreek]      [public] % will become generic
112\definesystemattribute[mathalternate]  [public]
113\definesystemattribute[mathrendering]  [public]
114\definesystemattribute[mathcategory]   [public]
115\definesystemattribute[mathmode]       [public]
116\definesystemattribute[mathitalics]    [public]
117\definesystemattribute[mathkernpairs]  [public]
118\definesystemattribute[mathbidi]       [public]
119\definesystemattribute[mathdomain]     [public]
120\definesystemattribute[mathcollapsing] [public]
121\definesystemattribute[mathunstack]    [public]
122
123\definesystemattribute[displaymath]    [public]
124
125\mathflattenmode\numexpr
126    \ordmathflattencode
127   +\binmathflattencode
128   +\relmathflattencode
129   +\punctmathflattencode
130   +\innermathflattencode
131\relax
132
133\ifdefined\ordlimits\else
134    \let\ordlimits\Umathlimits % downward compatible
135\fi
136
137\appendtoks
138    \c_attr_mathmode\plusone
139\to \everydisplay
140
141\appendtoks
142    \c_attr_mathmode   \plusone
143    \c_attr_displaymath\plusone
144\to \everybeforedisplayformula
145
146% defined at lua end \permanent\protected\def\resetmathattributes{\resetmathattributes}
147
148% handy
149
150\newconditional\indisplaymath
151
152\appendtoks
153    \setfalse\indisplaymath
154\to \everymath
155
156\appendtoks
157    \settrue\indisplaymath
158\to \everydisplay
159
160\permanent\def\inlineordisplaymath{\ifconditional\indisplaymath\expandafter\secondoftwoarguments\else\expandafter\firstoftwoarguments\fi}
161
162\permanent\protected\def\forcedisplaymath
163  {\ifmmode
164     \displaystyle
165     \settrue\indisplaymath
166   \fi}
167
168\permanent\protected\def\startforceddisplaymath
169  {\startimath
170   \displaystyle
171   \begingroup
172   \settrue\indisplaymath}
173
174\permanent\protected\def\stopforceddisplaymath
175  {\endgroup
176   \stopimath}
177
178\permanent\protected\def\startpickupmath % for the moment private
179  {\ifconditional\indisplaymath
180     \startforceddisplaymath
181     \enforced\let\stoppickupmath\stopforceddisplaymath
182   \else
183     \startimath
184     \enforced\let\stoppickupmath\stopimath
185   \fi}
186
187\aliased\let\stoppickupmath\relax
188
189% \protected\def\rawmathcharacter#1% slow but only for tracing
190%   {\begingroup
191%    \ifmmode
192%      \resetmathattributes\Uchar#1%
193%    \else
194%      \startimath\resetmathattributes\Uchar#1\stopimath
195%    \fi
196%    \endgroup}
197
198\permanent\protected\def\rawmathematics#1% slow but only for tracing
199  {\begingroup
200   \ifmmode
201     \resetmathattributes#1%
202   \else
203     \startimath\resetmathattributes#1\stopimath
204   \fi
205   \endgroup}
206
207%D Some measures (maybe spac-mth):
208
209% \def\mathskipsmall {\mskip\thinmuskip}
210% \def\mathskipmedium{\mskip\medmuskip}
211% \def\mathskipbig   {\mskip\thickmuskip}
212
213%D \macros
214%D   {setupmathematics}
215%D
216%D Configuration for integrals. (If needed we can speed this up and make it
217%D installable; no processaction is needed then).
218
219\installcorenamespace{mathematics}
220
221\installswitchcommandhandler \??mathematics {mathematics} \??mathematics
222
223\installmacrostack\currentmathematics
224
225% \permanent\protected\def\startmathematics % no grouping, if ever then also an optional second
226%   {\doifelsenextoptionalcs\math_mathematics_start_yes\math_mathematics_start_nop}
227%
228% \protected\def\math_mathematics_start_yes[#1]%
229%   {\push_macro_currentmathematics
230%    \edef\currentmathematics{#1}% check for valid
231%    \the\everyswitchmathematics}
232%
233% \protected\def\math_mathematics_start_nop
234%   {\push_macro_currentmathematics
235%    \let\currentmathematics\empty
236%    \the\everyswitchmathematics}
237
238\permanent\protected\tolerant\def\startmathematics[#1]% no grouping, if ever then also an optional second
239  {\push_macro_currentmathematics
240   \edef\currentmathematics{#1}% check for valid
241   \the\everyswitchmathematics}
242
243\permanent\protected\def\stopmathematics
244  {\pop_macro_currentmathematics
245   \the\everyswitchmathematics} % only needed at level zero
246
247\definemathematics[\v!default] % not needed, but nicer when nesting back to normal
248
249% Now we redefine \type {\mathematics} and \type {\m}:
250
251\pushoverloadmode
252
253    \permanent\protected\def\mathematics{\doifelsenextoptionalcs\math_m_yes\math_m_nop}
254
255    \aliased\let\m   \mathematics % we keep the simple versions
256    \aliased\let\math\mathematics % we keep the simple versions
257
258\popoverloadmode
259
260\def\math_m_yes
261  {\relax
262   \ifmmode
263     \expandafter\math_m_yes_math
264   \else
265     \expandafter\math_m_yes_text
266   \fi}
267
268\def\math_m_yes_math[#1]#2%
269  {#2}
270
271\def\math_m_yes_text[#1]%
272  {\begingroup
273   \ifcondition\validassignment{#1}%
274     \setupcurrentmathematics[#1]%
275   \else
276     \edef\currentmathematics{#1}% check for valid
277   \fi
278   \edef\p_openup{\mathematicsparameter\c!openup}%
279   \ifx\p_openup\v!yes
280     \expandafter\math_m_yes_text_openedup
281   \else
282     \expandafter\math_m_yes_text_normal
283   \fi}
284
285\def\math_m_yes_text_openedup#1%
286  {\setbox\scratchbox\hbox\bgroup
287      \the\everyswitchmathematics\relax
288      \normalstartimath
289      #1%
290      \normalstopimath
291   \egroup
292   \ifdim\ht\scratchbox>\strutht
293     \math_inline_openup_start_yes
294   \orelse\ifdim\dp\scratchbox>\strutdp
295     \math_inline_openup_start_yes
296   \else
297     \math_inline_openup_start_nop
298   \fi
299   \unhbox\scratchbox % \normalstartimath#1\normalstopimath
300   \math_inline_openup_stop
301   \endgroup}
302
303\def\math_m_yes_text_normal#1%
304  {\the\everyswitchmathematics\relax
305   \normalstartimath
306   #1%
307   \normalstopimath
308   \endgroup}
309
310\def\math_m_nop#1%
311  {\relax
312   \ifmmode
313     #1%
314   \else
315     \normalstartimath
316     #1%
317     \normalstopimath
318   \fi}
319
320% e.g.: \definemathematics[i:mp][setups=i:tight,openup=yes]
321
322\immutable\mugluespecdef\defaultthickmuskip      5mu plus 5mu
323\immutable\mugluespecdef\defaultmedmuskip        4mu plus 2mu minus 4mu
324\immutable\mugluespecdef\defaultthinmuskip       3mu
325
326\immutable\mugluespecdef\halfthickmuskip         2.5mu plus 2.5mu
327\immutable\mugluespecdef\halfmedmuskip           2.0mu plus 1.0mu minus 2.0mu
328\immutable\mugluespecdef\halfthinmuskip          1.5mu
329
330\immutable\mugluespecdef\hairmuskip              .15mu
331
332\immutable\integerdef   \defaultrelpenalty       500
333\immutable\integerdef   \defaultbinoppenalty     700
334\immutable\integerdef   \defaultprerelpenalty   -100
335\immutable\integerdef   \defaultprebinoppenalty -100
336
337% we need to control these otherwise:
338%
339% \prerelpenalty  \defaultprerelpenalty
340% \prebinoppenalty\defaultprebinoppenalty
341
342\startsetups math:spacing:default
343    \thickmuskip    \defaultthickmuskip
344    \medmuskip      \defaultmedmuskip
345    \thinmuskip     \defaultthinmuskip
346    \relpenalty     \defaultrelpenalty
347    \binoppenalty   \defaultbinoppenalty
348    \prebinoppenalty\maxdimen
349    \prerelpenalty  \maxdimen
350\stopsetups
351
352\startsetups math:spacing:split
353    \thickmuskip    \defaultthickmuskip
354    \medmuskip      \defaultmedmuskip
355    \thinmuskip     \defaultthinmuskip
356    \relpenalty     \defaultrelpenalty
357    \binoppenalty   \defaultbinoppenalty
358    \prebinoppenalty\defaultprebinoppenalty
359    \prerelpenalty  \defaultprerelpenalty
360\stopsetups
361
362\startsetups math:spacing:half
363    \thickmuskip    \halfthickmuskip
364    \medmuskip      \halfmedmuskip
365    \thinmuskip     \halfthinmuskip
366    \relpenalty     \defaultrelpenalty
367    \binoppenalty   \defaultbinoppenalty
368    \prebinoppenalty\maxdimen
369    \prerelpenalty  \maxdimen
370\stopsetups
371
372\startsetups math:spacing:tight
373    \ifcase\raggedstatus
374        \thickmuskip   \halfthickmuskip
375        \medmuskip     \halfmedmuskip
376        \thinmuskip    \halfthinmuskip
377    \else
378        \thickmuskip  1\halfthickmuskip
379        \medmuskip    1\halfmedmuskip
380        \thinmuskip   1\halfthinmuskip
381    \fi
382    \relpenalty     \defaultrelpenalty
383    \binoppenalty   \maxdimen
384    \prebinoppenalty\maxdimen
385    \prerelpenalty  \maxdimen
386\stopsetups
387
388\startsetups math:spacing:fixed
389    \ifcase\raggedstatus
390        \thickmuskip   \halfthickmuskip
391        \medmuskip     \halfmedmuskip
392        \thinmuskip    \halfthinmuskip
393    \else
394        \thickmuskip  1\halfthickmuskip
395        \medmuskip    1\halfmedmuskip
396        \thinmuskip   1\halfthinmuskip
397    \fi
398    \relpenalty     \maxdimen
399    \binoppenalty   \maxdimen
400    \prebinoppenalty\maxdimen
401    \prerelpenalty  \maxdimen
402\stopsetups
403
404% \dorecurse{80}{test \m[i:tight]{\red \fakeformula} test }
405
406\definemathematics[i:default][\c!setups=math:spacing:equal]
407\definemathematics[i:half]   [\c!setups=math:spacing:half]
408\definemathematics[i:tight]  [\c!setups=math:spacing:tight]
409\definemathematics[i:fixed]  [\c!setups=math:spacing:fixed]
410
411% Normally the next is applied to only one character.
412%
413% $ABC$ $\cal ABC$ $\mathaltcal ABC$
414
415% todo: only in mmode
416% these commands are semi-public but should not be used directly (lua names wil change)
417
418%permanent\protected\def\setmathattribute  #1#2{\ifmmode\clf_setmathattribute{#1}{#2}\fi}
419%permanent\protected\def\setmathalphabet     #1{\ifmmode\clf_setmathalphabet{#1}\fi}
420%permanent\protected\def\setmathfontstyle    #1{\ifmmode\clf_setmathstyle{#1}\fi}
421%permanent\protected\def\setmathfontalternate#1{\ifmmode\clf_setmathalternate{#1}\fi}
422
423\installcorenamespace{mathstylealternative} % might become a setuphandler
424
425\permanent\protected\def\setmathfontstylealternate#1%
426  {\ifcsname\??mathstylealternative\fontclass:#1\endcsname
427     \expandafter\setmathfontalternate\lastnamedcs
428   \orelse\ifcsname\??mathstylealternative#1\endcsname
429     \expandafter\setmathfontalternate\lastnamedcs
430   \fi}
431
432\permanent\tolerant\protected\def\setupmathrendering[#1]#*[#2]% the name might change
433  {\ifparameter#2\or
434     \getparameters[\??mathstylealternative#1:][#2]%
435   \else
436     \getparameters[\??mathstylealternative][#1]%
437   \fi}
438
439\appendtoks
440    \edef\p_stylealternative{\mathematicsparameter\c!stylealternative}%
441    \ifempty\p_stylealternative\else
442        \presetmathfontalternate{\p_stylealternative}%
443    \fi
444\to \everymathematics
445
446% if there were many features we could have a feature pass over math nodes but it makes no
447% sense now so we have commands to deal with it
448
449% \enabletrackers[math.alternates]
450% \setupbodyfont[lucidaot]
451%
452% \startTEXpage
453%     \setupmathematics[stylealternative={reset}]$x+\mathcal A$\par
454%     \setupmathematics[stylealternative={reset,calligraphic}]$x+\mathcal A$\par
455%     \setupmathematics[stylealternative={reset,italic}]$x+\mathcal A$\par
456%     \setupmathematics[stylealternative={reset,calligraphic,italic}]$x+\mathcal A$
457% \stopTEXpage
458
459% no longer needed now we have enforce so the next few lines will go
460
461% \pushoverloadmode
462%     \enforced\let\dotlessi\dotlessi
463%     \enforced\let\dotlessj\dotlessj
464% \popoverloadmode
465
466\permanent\protected\def\mathaltcalligraphic{\setmathfontalternate{calligraphic}\cal}          % set via goody file
467\permanent\protected\def\mathaltitalic      {\setmathfontalternate{italic}}                    % set via goody file
468\permanent\protected\def\mathslashedzero    {\begingroup\setmathfontalternate{zero}\endgroup} % set via goody file or automatic
469\permanent\protected\def\mathdotless        {\setmathfontalternate{dotless}}                   % set via goody file or automatic
470\permanent\protected\def\mathdotlessi       {\begingroup\mathdotless i\endgroup}
471\permanent\protected\def\mathdotlessj       {\begingroup\mathdotless j\endgroup}
472
473\aliased\let\mathaltcal\mathaltcalligraphic
474\aliased\let\mathaltit \mathaltitalic
475
476%aliased\let\textslashedzero\slashedzero \permanent\protected\def\autoslashedzero{\mathortext\mathslashedzero\textslashedzero}
477\aliased\let\textdotlessi   \dotlessi    \permanent\protected\def\autodotlessi   {\mathortext\mathdotlessi   \textdotlessi}
478\aliased\let\textdotlessj   \dotlessj    \permanent\protected\def\autodotlessj   {\mathortext\mathdotlessj   \textdotlessj}
479
480\appendtoks
481    %enforced\let\slashedzero\autoslashedzero
482    \enforced\let\dotlessi\autodotlessi
483    \enforced\let\dotlessj\autodotlessj
484\to \everymathematics
485
486\aliased\let\setmathfontalternative     \setmathfontalternate
487\aliased\let\setmathfontstylealternative\setmathfontstylealternate
488\aliased\let\mathalternate              \setmathfontalternate
489
490\permanent\protected\def\mathupright   {\setmathattribute\s!regular\s!tf\setmathfontstylealternate\s!tf}
491\permanent\protected\def\mathitalic    {\setmathattribute\s!regular\s!it\setmathfontstylealternate\s!it}
492\permanent\protected\def\mathscript    {\setmathalphabet \s!script      \setmathfontstylealternate\s!script}
493\permanent\protected\def\mathfraktur   {\setmathalphabet \s!fraktur     \setmathfontstylealternate\s!fraktur}
494\permanent\protected\def\mathblackboard{\setmathalphabet \s!blackboard  \setmathfontstylealternate\s!blackboard}
495
496\permanent\protected\def\mathrm        {\setmathattribute\s!rm\s!tf     \setmathfontstylealternate\s!tf}
497\permanent\protected\def\mathss        {\setmathattribute\s!ss\s!tf     \setmathfontstylealternate\s!tf}
498\permanent\protected\def\mathtt        {\setmathattribute\s!tt\s!tf     \setmathfontstylealternate\s!tf}
499
500\permanent\protected\def\mathtf        {\setmathfontstyle\s!tf         \setmathfontstylealternate\s!tf}
501\permanent\protected\def\mathsl        {\setmathfontstyle\s!it         \setmathfontstylealternate\s!it} % no sl
502\permanent\protected\def\mathit        {\setmathfontstyle\s!it         \setmathfontstylealternate\s!it}
503
504\permanent\protected\def\mathbf        {\setmathfontstyle\s!bf         \setmathfontstylealternate\s!bf}
505\permanent\protected\def\mathbs        {\setmathfontstyle\s!bi         \setmathfontstylealternate\s!bi} % no sl
506\permanent\protected\def\mathbi        {\setmathfontstyle\s!bi         \setmathfontstylealternate\s!bi}
507
508\aliased\let\mathdefault\mathitalic
509
510\appendtoks
511    \edef\p_default{\mathematicsparameter\c!default}%
512    \ifx\p_default\v!normal
513      \enforced\let\mathdefault\mathupright
514    \else
515      \enforced\let\mathdefault\mathitalic
516    \fi
517\to \everysetupmathematics
518
519\setupmathematics
520  [\c!default=\v!italic]
521
522\aliased\let\tfmath\mathtf % maybe a grouped command
523\aliased\let\slmath\mathsl
524\aliased\let\itmath\mathit
525
526\aliased\let\bfmath\mathbf
527\aliased\let\bsmath\mathbs
528\aliased\let\bimath\mathbi
529
530\aliased\let\Bbb\mathblackboard
531
532\permanent\protected\def\frak      {\ifmmode\expandafter\mathfraktur   \fi}
533\permanent\protected\def\cal       {\ifmmode\expandafter\mathscript    \fi}
534\permanent\protected\def\bbd       {\ifmmode\expandafter\mathblackboard\fi}
535\permanent\protected\def\blackboard{\ifmmode\expandafter\mathblackboard\fi}
536\permanent\protected\def\fraktur   {\ifmmode\expandafter\mathfraktur   \fi}
537\permanent\protected\def\gothic    {\ifmmode\expandafter\mathfraktur   \fi}
538
539\permanent\protected\def\mathcal #1{{\mathscript    #1}}  % for AMS compatibility
540\permanent\protected\def\mathfrak#1{{\mathfraktur   #1}}  % for AMS compatibility
541\permanent\protected\def\mathbb  #1{{\mathblackboard#1}}  % for AMS compatibility
542
543\ifdefined\normaltf \else \permanent\let\normaltf\tf \fi \permanent\protected\def\tf{\ifmmode\expandafter\mathtf\else\expandafter\normaltf\fi}
544\ifdefined\normalbf \else \permanent\let\normalbf\bf \fi \permanent\protected\def\bf{\ifmmode\expandafter\mathbf\else\expandafter\normalbf\fi}
545\ifdefined\normalit \else \permanent\let\normalit\it \fi \permanent\protected\def\it{\ifmmode\expandafter\mathit\else\expandafter\normalit\fi}
546\ifdefined\normalsl \else \permanent\let\normalsl\sl \fi \permanent\protected\def\sl{\ifmmode\expandafter\mathsl\else\expandafter\normalsl\fi}
547\ifdefined\normalbi \else \permanent\let\normalbi\bi \fi \permanent\protected\def\bi{\ifmmode\expandafter\mathbi\else\expandafter\normalbi\fi}
548\ifdefined\normalbs \else \permanent\let\normalbs\bs \fi \permanent\protected\def\bs{\ifmmode\expandafter\mathbs\else\expandafter\normalbs\fi}
549
550\permanent\protected\def\rm{\ifmmode\expandafter\mathrm\else\expandafter\normalrm\fi}
551\permanent\protected\def\ss{\ifmmode\expandafter\mathss\else\expandafter\normalss\fi}
552\permanent\protected\def\tt{\ifmmode\expandafter\mathtt\else\expandafter\normaltt\fi}
553
554\ifdefined\mr \else \let\mr\relax \fi % hm ... permanent
555\ifdefined\mb \else \let\mb\relax \fi % hm ... permanent
556
557% 1: $\setmathattribute{ss}{bf}3$
558% 2: $\setmathattribute{ss}{bf}\setmathfontstylealternate{bf}3$
559% 3: $\setmathattribute{ss}{bf}\setmathfontstyle{bf}3$
560% 4: $\setmathattribute{ss}{bf}\setmathfontstyle{bf}\setmathfontstylealternate{bf}3$
561% 5: $e=mc^2 \quad \mb e=mc^2$
562
563\prependtoks
564    \mathdefault
565\to \everymathematics
566
567%D We could set the rendering attribute at the \LUA\ end but as there can be many
568%D small math snippets we keep track of the state at the \TEX\ end (mapping is
569%D export safe).
570%D
571%D \starttyping
572%D \startformula
573%D     \reals {\mathbf R} \utfchar{"0211D} \utfchar{"1D411}
574%D \stopformula
575%D
576%D \setupmathematics
577%D   [symbolset=blackboard-to-bold]
578%D
579%D \startformula
580%D     \reals {\mathbf R} \utfchar{"0211D} \utfchar{"1D411}
581%D \stopformula
582%D \stoptyping
583
584\newcount\c_math_renderings_attribute
585
586\appendtoks
587    \c_math_renderings_attribute\clf_mathrenderset{\mathematicsparameter\c!symbolset}\relax
588\to \everysetupmathematics % only in mathematics
589
590\appendtoks
591    \ifcase\c_math_renderings_attribute\else
592        \c_attr_mathrendering\c_math_renderings_attribute
593    \fi
594\to \everymathematics
595
596\setupmathematics
597  [\c!symbolset=]
598
599%D \macros
600%D   {boldsymbol}
601%D
602%D To be done.
603
604\mutable\let\mathboldsymbol\relax % yet unsupported, will be
605
606\permanent\protected\def\boldsymbol
607  {\mathortext\mathboldsymbol\bold}
608
609%D Helpers (defined at the \LUA\ end):
610
611% \utfmathclass          #1
612% \utfmathstretch        #1
613% \utfmathcommand        #1
614% \utfmathfiller         #1
615%
616% \utfmathcommandabove   #1..
617% \utfmathcommandbelow   #1..
618% \utfmathcommandfiller  #1..
619%
620% \doifelseutfmathaccent #1#2#3
621% \doifelseutfmathabove  #1#2#3
622% \doifelseutfmathbelow  #1#2#3
623% \doifelseutfmathfiller #1#2#3
624% \doifelseutfmathlimop  #1#2#3
625
626\aliased\let\doifutfmathaccentelse \doifelseutfmathaccent
627\aliased\let\doifutfmathaboveelse  \doifelseutfmathabove
628\aliased\let\doifutfmathbelowelse  \doifelseutfmathbelow
629\aliased\let\doifutfmathfillerelse \doifelseutfmathfiller
630\aliased\let\doifutfmathlimopelse  \doifelseutfmathlimop
631
632%D Not used that much:
633
634\installcorenamespace{mathcodecommand}
635
636\permanent\protected\def\mathlimop#1{\mathop{#1}} %no \limits
637\permanent\protected\def\mathbox  #1{\dontleavehmode\hbox\Ustartmath\mathsurround\zeropoint#1\Ustopmath}
638\permanent\protected\def\mathnolop#1{\mathop{#1}\nolimits}
639
640\aliased\let\mathnothing\firstofoneunexpanded
641\aliased\let\mathalpha  \firstofoneunexpanded
642
643\setnewconstant\mathordcode     \zerocount  \letcsname\??mathcodecommand     ord\endcsname\mathord
644\setnewconstant\mathopcode      \plusone    \letcsname\??mathcodecommand      op\endcsname\mathop
645\setnewconstant\mathbincode     \plustwo    \letcsname\??mathcodecommand     bin\endcsname\mathbin
646\setnewconstant\mathrelcode     \plusthree  \letcsname\??mathcodecommand     rel\endcsname\mathrel
647\setnewconstant\mathopencode    \plusfour   \letcsname\??mathcodecommand    open\endcsname\mathopen
648\setnewconstant\mathclosecode   \plusfive   \letcsname\??mathcodecommand   close\endcsname\mathclose
649\setnewconstant\mathpunctcode   \plussix    \letcsname\??mathcodecommand   punct\endcsname\mathpunct
650\setnewconstant\mathalphacode   \plusseven  \letcsname\??mathcodecommand   alpha\endcsname\mathalpha
651\setnewconstant\mathinnercode   \zerocount  \letcsname\??mathcodecommand   inner\endcsname\mathinner
652\setnewconstant\mathnothingcode \zerocount  \letcsname\??mathcodecommand nothing\endcsname\mathnothing
653\setnewconstant\mathlimopcode   \plusone    \letcsname\??mathcodecommand   limop\endcsname\mathlimop
654\setnewconstant\mathnolopcode   \plusone    \letcsname\??mathcodecommand   nolop\endcsname\mathnolop
655\setnewconstant\mathboxcode     \zerocount  \letcsname\??mathcodecommand     box\endcsname\mathbox
656\setnewconstant\mathchoicecode  \zerocount  %letcsname\??mathcodecommand  choice\endcsname\mathnothing
657
658\setnewconstant\mathaccentcode  \pluseight
659\setnewconstant\mathradicalcode \plusnine
660
661\permanent          \def\mathcodenumber #1{\the\csname math#1code\endcsname}
662\permanent\protected\def\mathcodecommand#1{\csname\??mathcodecommand#1\endcsname}
663\permanent          \def\mathcodechecked#1{\ifcsname math#1code\endcsname\lastnamedcs\else#1\fi}
664
665% \startlines
666% $\mathopnolimits{\rm d}x$
667% $\mathopnolimits{\kern\zeropoint \rm d}x$
668% $\mathcodecommand{nolop}{\rm d}x$
669% $\mathcodecommand{nolop}{\kern\zeropoint\rm d}x$
670% \blank
671% $\mathcodecommand{nolop}{\mr d}x$
672% $\mathcodecommand{nolop}{\kern\zeropoint\mr d}x$
673% $\mathop{\kern\zeropoint\mr d}x$
674% $\mathopnolimits{\kern\zeropoint d}x$
675% \stoplines
676
677\installcorenamespace{mathcommand}
678
679% todo: define these commands as frozen!
680
681\permanent\tolerant\protected\def\definemathcommand[#1]#*[#2]#*[#3]#:#*#4% command class args meaning
682  {\ifparameter#3\or
683     \edef\scratchstringone{#3}% make this one m_arguments
684     \ifx\scratchstringone\v!one
685       \frozen\protected\defcsname\??mathcommand#1\endcsname##1{\mathcodecommand{#2}{#4{##1}}}%
686     \orelse\ifx\scratchstringone\v!two
687       \frozen\protected\defcsname\??mathcommand#1\endcsname##1##2{\mathcodecommand{#2}{#4{##1}{##2}}}%
688     \else
689       \frozen\protected\defcsname\??mathcommand#1\endcsname{\mathcodecommand{#2}{#4}}%
690     \fi
691   \orelse\ifparameter#2\or
692     \frozen\protected\defcsname\??mathcommand#1\endcsname{\mathcodecommand{#2}{#4}}%
693   \else
694     \frozen\protected\defcsname\??mathcommand#1\endcsname{\mathcodecommand{nothing}{#4}}%
695   \fi
696   \ifparameter#1\or % safeguard
697     \letcsname#1\expandafter\endcsname\csname\??mathcommand#1\endcsname
698   \fi}
699
700\permanent\protected\def\mathcommand#1%
701  {\begincsname\??mathcommand#1\endcsname}
702
703%D Let's define a few comands here:
704
705%definemathcommand [mathstrut]       {\vphantom{(}}
706%definemathcommand [joinrel]         {\mathrel{\mkern-3mu}}
707\definemathcommand [joinrel]   [rel] {\mkern-3mu}
708
709\immutable\chardef\c_math_strut"28
710
711% \protected\def\math_strut_htdp#1%
712%   {\s!height\fontcharht#1\c_math_strut
713%    \s!depth \fontchardp#1\c_math_strut}
714%
715% now we need this (kind of inefficient):
716
717% \protected\def\math_strut_htdp#1% nasty!
718%   {\s!height\dimexpr\mathscale#1\fontcharht#1\c_math_strut/\glyphscale\relax
719%    \s!depth \dimexpr\mathscale#1\fontchardp#1\c_math_strut/\glyphscale\relax}
720%
721% this overflows so we use this instead:
722
723\protected\def\math_strut_htdp#1% nasty!
724  {\s!height\dimexpr(\fontcharht#1\c_math_strut/\glyphscale)*\mathscale#1\relax
725   \s!depth \dimexpr(\fontchardp#1\c_math_strut/\glyphscale)*\mathscale#1\relax}
726
727\protected\def\math_strut_normal
728  {\vrule
729      \s!width \zeropoint
730      \normalexpanded{\math_strut_htdp{\mathstylefont\normalmathstyle}}%
731   \relax}
732
733\protected\def\math_strut_visual
734  {\hskip-.01\emwidth
735   \vrule
736      \s!width .02\emwidth
737      \normalexpanded{\math_strut_htdp{\mathstylefont\normalmathstyle}}%
738   \relax
739   \hskip-.01\emwidth}
740
741\permanent\protected\def\showmathstruts % let's not overload \math_strut_normal
742  {\enforced\let\math_strut\math_strut_visual}
743
744\let\math_strut\math_strut_normal
745
746% \protected\def\mathstrut{\mathcodecommand{nothing}{\math_strut}}
747
748\pushoverloadmode
749
750    \definemathcommand [mathstrut] {\math_strut}
751
752\popoverloadmode
753
754%D We could have a arg variant \unknown\ but not now.
755
756\permanent\protected\def\mathopwithlimits#1#2{\mathop{#1{#2}}\limits}
757\permanent\protected\def\stackrel        #1#2{\mathrel{\mathop{#2}\limits^{#1}}}
758
759%D Moved from font-ini.mkiv:
760%D
761%D \macros
762%D   {mf,mbox,enablembox,mathop}
763%D
764%D Todo:
765
766\permanent\protected\def\mf{\begincsname\fontalternative\endcsname} % todo: \frozen
767
768% \let\normalmathop\mathop % already defined
769
770% no longer needed as we no longer switch fonts
771%
772% \protected\def\mathop
773%   {\normalmathop
774%    \bgroup
775%   % no: \let\rm\mf
776%    \afterassignment\math_op\let\nexttoken=}
777%
778% \def\math_op{\ifx\nexttoken\bgroup\else\nexttoken\egroup\fi}
779
780% this one too: \letvalue{\??mathcodecommand op}\mathop ?
781
782\permanent\protected\def\normalmbox
783  {\normalhbox\bgroup
784   \usemathematicsstyleandcolor\c!textstyle\c!textcolor % new
785   \dowithnextboxcs\math_mbox_finish\normalhbox}
786
787\def\math_mbox_finish
788  {\flushnextbox
789   \egroup}
790
791\permanent\protected\def\mbox % we cannot add \dontleavehmode ... else no \setbox0\mbox possible
792  {\ifmmode\normalmbox\else\normalhbox\fi}
793
794\permanent\protected\def\enablembox
795  {\toksapp\everymathematics{\math_enable_mbox}}
796
797\permanent\def\math_enable_mbox % brrrr
798  {\enforced\let\hbox\mbox}
799
800\permanent\protected\def\snappedmath#1% sort of \struttedbox
801  {\dontleavehmode
802   \begingroup
803   \setbox\scratchbox\normalhbox\bgroup
804     \startimath#1\stopimath
805   \egroup
806   \ht\scratchbox\strutht
807   \dp\scratchbox\strutdp
808   \box\scratchbox
809   \endgroup}
810
811\permanent\protected\def\mtext#1%
812  {\text{\usemathematicsstyleandcolor\c!textstyle\c!textcolor#1}}
813
814%D The next hack is needed needed for sine, cosine etc.
815
816\aliased\let\mathfunction\firstofoneunexpanded
817
818\let\math_tags_function         \firstofoneunexpanded
819\let\math_tags_functionlabeltext\mathlabeltext
820
821\let\math_tags_mo\firstofoneunexpanded
822\let\math_tags_mi\firstofoneunexpanded
823
824\protected\def\math_tags_mn#1{\begingroup\mathupright\math_set_o_both#1\endgroup}
825\protected\def\math_tags_ms#1{\begingroup\mathupright\math_set_p_both#1\endgroup} % why not just \text
826
827% Once this is stable we can store the number at the tex end which is
828% faster. Functions getnumbers >= 1000.
829
830% \setupmathematics[functionstyle=normal] % will give ligatures and kerning
831
832\setupmathematics
833  [\c!textstyle=,     % rm ss etc i.e. known alternatives, otherwise math
834   \c!textcolor=,
835   \c!functionstyle=, % rm ss etc i.e. known alternatives, otherwise math
836   \c!functioncolor=]
837
838\protected\def\math_mfunction_styled
839  {\begingroup
840   \usemathematicscolorparameter\c!functioncolor
841   \edef\p_functionstyle{\mathematicsparameter\c!functionstyle}%
842   \ifempty\p_functionstyle
843     \expandafter\math_mfunction_styled_none
844   \orelse\ifcsname\??alternativestyle\p_functionstyle\endcsname
845     \expandafter\math_mfunction_styled_text
846   \else
847     \expandafter\math_mfunction_styled_math
848   \fi}
849
850\protected\def\math_mfunction_styled_text#1%
851 %{\mathoptext{\csname\??alternativestyle\p_functionstyle\endcsname#1}%
852  {\expandafter\mathoptext\expandafter{\lastnamedcs#1}%
853   \endgroup}
854
855\protected\def\math_mfunction_styled_math#1%
856  {\p_functionstyle
857   #1%
858   \endgroup}
859
860\protected\def\math_mfunction_styled_none#1%
861  {\mathupright
862   #1%
863   \endgroup}
864
865\permanent\protected\def\mfunction#1%
866  {\begingroup
867   \math_tags_mfunctiontxt{#1}\c_apply_function
868   \math_mfunction_styled{#1}%
869   \endgroup}
870
871\permanent\protected\def\mfunctionlabeltext#1%
872  {\begingroup
873   \math_tags_mfunctionlab{#1}\c_apply_function
874   \math_mfunction_styled{\mathlabeltext{#1}}%
875   \endgroup}
876
877\let\math_tags_mfunctiontxt\gobbletwoarguments
878\let\math_tags_mfunctionlab\gobbletwoarguments
879
880\permanent\protected\def\math_tags_mo_indeed#1{\begingroup            \c_attr_mathcategory\plusone                  #1\endgroup}
881\permanent\protected\def\math_tags_mi_indeed#1{\begingroup            \c_attr_mathcategory\plustwo                  #1\endgroup}
882\permanent\protected\def\math_tags_mn_indeed#1{\begingroup\mathupright\c_attr_mathcategory\plusthree\math_set_o_both#1\endgroup}
883\permanent\protected\def\math_tags_ms_indeed#1{\begingroup\mathupright\c_attr_mathcategory\plusfour \math_set_p_both#1\endgroup} % todo: mathoptext
884
885\newconditional\c_apply_function
886
887\permanent\protected\def\math_tags_apply#1#2%
888  {\begingroup
889   \settrue\c_apply_function
890   #1%
891   \endgroup
892   \begingroup
893   % todo: auto ()
894   #2%
895   \endgroup}
896
897\ifdefined\apply \else \aliased\let\apply\relax \fi
898
899\mutable\let\mo\relax
900\mutable\let\mi\relax
901\mutable\let\mn\relax
902\mutable\let\ms\relax
903
904\appendtoks
905    \enforced\let\math_tags_mfunctiontxt\clf_tagmfunctiontxt
906    \enforced\let\math_tags_mfunctionlab\clf_tagmfunctionlab
907    \enforced\let\math_tags_mo          \math_tags_mo_indeed
908    \enforced\let\math_tags_mi          \math_tags_mi_indeed
909    \enforced\let\math_tags_mn          \math_tags_mn_indeed
910    \enforced\let\math_tags_ms          \math_tags_ms_indeed
911\to \everyenableelements
912
913\appendtoks
914    \enforced\let\mo   \math_tags_mo
915    \enforced\let\mi   \math_tags_mi
916    \enforced\let\mn   \math_tags_mn
917    \enforced\let\ms   \math_tags_ms
918    \enforced\let\apply\math_tags_apply
919\to\everymathematics
920
921% \def\mlimitsfunction  #1{\mathlimopcomm{{\mr#1}}
922% \def\mnolimitsfunction#1{\mathnolopcomm{{\mr#1}}
923
924% %D Taco posted this solution as response to a mail by Olivier, so let's integrate
925% %D it here.
926%
927% \def\currentmscaledstyle{rm} % will be plugged into the typeface text=ss option
928%
929% \protected\def\math_function_style_opnolimits        #1{\mathop{\mscaledtext{#1}}\nolimits}
930% \protected\def\math_function_style_mfunction         #1{\mscaledtext{\math_tags_function{#1}}}
931% \protected\def\math_function_style_mfunctionlabeltext#1{\mscaledtext{\math_tags_functionlabeltext{#1}}}
932%
933% \protected\def\setmathfunctionstyle#1% rm ss tt (can be made faster if needed)
934%   {\doifsomething{#1}
935%      {\def\currentmscaledstyle{#1}%
936%       \let\mathopnolimits    \math_function_style_opnolimits
937%       \let\mfunction         \math_function_style_mfunction
938%       \let\mfunctionlabeltext\math_function_style_mfunctionlabeltext}}
939
940\mutable\def\currentmscaledstyle{rm} % will be plugged into the typeface text=ss option
941
942\permanent\protected\def\mscaledtext#1%
943  {\mathchoice
944     {\hbox{\csname\currentmscaledstyle\endcsname\tf  #1}}
945     {\hbox{\csname\currentmscaledstyle\endcsname\tf  #1}}
946     {\hbox{\csname\currentmscaledstyle\endcsname\tfx #1}}
947     {\hbox{\csname\currentmscaledstyle\endcsname\tfxx#1}}}
948
949\permanent\protected\def\setmathfunctionstyle#1%
950  {\setupmathematics[\c!functionstyle=#1]} % for old times sake
951
952%D Usage:
953%D
954%D \starttyping
955%D \setmathfunctionstyle\fontstyle % or {rm} or {ss} or ..
956%D \rm test $\sin{(x^{\sin(x^{\sin(x)})})}$ test
957%D \ss test $\sin{(x^{\sin(x^{\sin(x)})})}$ test
958%D \tt test $\sin{(x^{\sin(x^{\sin(x)})})}$ test
959%D \stoptyping
960
961%D \macros
962%D   {nonknuthmode, donknuthmode}
963%D
964%D The underscore is frequently used in manuals but unfortunately \TEX\ prefers
965%D it to be a math specific character. And since computer modern fonts didn't
966%D have an underscore, one had to use commands to fake one. Nowadays we do
967%D have underscores in latin modern, and since all other fonts have them, we
968%D decided to get away from the restriction to use the underscore character in
969%D text mode.
970%D
971%D \starttyping
972%D \def\test#1{#1}
973%D
974%D \nonknuthmode $x_2$ x_2 \test{$x_2$} \test{x_2}
975%D
976%D \donknuthmode $x_2$ x_2 \test{$x_2$} \test{x_2}
977%D \stoptyping
978%D
979%D The result is as expected: the first line typesets ok, while the second
980%D one triggers an error message.
981
982\setnewconstant\activemathcharcode "8000
983
984\newtoks\activatedmathcharacters
985
986\permanent\protected\def\activatemathcharacter#1%
987  {\appendtoks
988     \global\mathcode#1=\activemathcharcode
989   \to \activatedmathcharacters}
990
991\permanent\def\activatemathcharacters
992  {\the\activatedmathcharacters}
993
994% beware, not runtime, so has to happen at format generation
995
996\activatemathcharacter\circumflexasciicode
997\activatemathcharacter\underscoreasciicode
998\activatemathcharacter\ampersandasciicode
999
1000\permanent\def\normalmathaligntab{&} % \let\normalmathaligntab\aligntab does to work well in a let to & (a def works ok)
1001
1002\appendtoks
1003    \edef\p_ampersand{\mathematicsparameter\s!ampersand}%
1004    \ifx\p_ampersand\v!normal
1005        \enforced\let\specialmathaligntab\normalmathaligntab
1006    \else
1007        \enforced\let\specialmathaligntab\mathampersand
1008    \fi
1009\to \everysetupmathematics
1010
1011%D A simplified version of this code is:
1012%D
1013%D \starttyping
1014%D \catcode"26=12
1015%D
1016%D \bgroup
1017%D     \global\mathcode"26="8000
1018%D
1019%D     \catcode"26=4
1020%D
1021%D     \xdef\normalmathaligntab{&}
1022%D
1023%D     \catcode"26=13
1024%D
1025%D     \global\everymath{\def&{\normalmathaligntab}}
1026%D \egroup
1027%D \stoptyping
1028%D
1029%D The following works okay:
1030%D
1031%D \starttyping
1032%D A & B
1033%D \stoptyping
1034%D
1035%D As does:
1036%D
1037%D \starttyping
1038%D $A \Umathchar"2"0"26 B$
1039%D \stoptyping
1040%D
1041%D But the next code:
1042%D
1043%D \starttyping
1044%D $A \char"26 B$
1045%D \stoptyping
1046%D
1047%D fails with: \type{Misplaced alignment tab character &} and here is the
1048%D reason.
1049%D
1050%D When we have a letter or other category a check happens for an active
1051%D character and when it has one then it gets expanded and fed back into the
1052%D scanner (sort of).
1053%D
1054%D A \type {\char} is also fed back as raw character and again when it's letter
1055%D of other goes through the same process.
1056%D
1057%D This means that we cannot have a definition like:
1058%D
1059%D \starttyping
1060%D \def\AND{\char"26\relax}
1061%D \stoptyping
1062%D
1063%D that can be used in math mode, which is why the cweb macros do:
1064%D
1065%D \starttyping
1066%D \def\AND{\def\AND{\mathchar"2026\relax}\AND}
1067%D \stoptyping
1068%D
1069%D Maybe we need an option to treat chars like chars.
1070
1071% \activatemathcharacter\primeasciicode
1072
1073% not used:
1074%
1075% \mathcode\spaceasciicode\activemathcharcode
1076%
1077% not used:
1078%
1079% \bgroup
1080%     \catcode\underscoreasciicode\activecatcode
1081%     \doglobal\appendtoks
1082%         \mathcode\underscoreasciicode\activemathcharcode
1083%         \let_\activemathunderscore
1084%     \to \everymathematics
1085% \egroup
1086
1087% Here follows some plain legacy: primes.
1088%
1089% The \let\prime\math_prime_indeed might become an obsolete as we have \doubleprime
1090% and \tripleprime and collapsing can nicely handle the script then.
1091%
1092% Collapsing to 0x2033 and 0x2034 happens elsewhere.
1093%
1094% \switchtobodyfont[modern]
1095% \switchtobodyfont[cambria]
1096% \switchtobodyfont[xits]
1097% \switchtobodyfont[minion]
1098% \setupbodyfont[dejavu]
1099%
1100% \startbuffer
1101% \def\SampleLine#1{%
1102%    \NC#1
1103%    \NC\switchtobodyfont[#1]$f^2$                       %  1
1104%    \NC\switchtobodyfont[#1]$f\prime^2$                 %  2
1105%    \NC\switchtobodyfont[#1]$f\prime\prime^2$           %  3
1106%    \NC\switchtobodyfont[#1]$f\prime\prime\prime^2$     %  4
1107%    \NC\switchtobodyfont[#1]$f{\prime}^2$               %  5
1108%    \NC\switchtobodyfont[#1]$f{\prime\prime}^2$         %  6
1109%    \NC\switchtobodyfont[#1]$f{\prime\prime\prime}^2$   %  7
1110%    \NC\switchtobodyfont[#1]$f'(x)$                     %  8
1111%    \NC\switchtobodyfont[#1]$f''(x)$                    %  9
1112%    \NC\switchtobodyfont[#1]$f'''(x)$                   % 10
1113%    \NC\NR
1114% }
1115%
1116% \starttabulate[|Tl|Tc|Tc|Tc|Tc|Tc|Tc|Tc|Tc|Tc|Tc|]
1117%     \NC\NC1\NC2\NC3\NC4\NC5\NC6\NC7\NC8\NC9\NC10\NC\NR
1118%     \SampleLine{modern}
1119%     \SampleLine{cambria}
1120%     \SampleLine{xits}
1121%     \SampleLine{minion}
1122% \stoptabulate
1123% \stopbuffer
1124%
1125% \typebuffer \getbuffer
1126
1127% most math fonts have messed up primes, just test this: $\prime^{\prime^{\prime}}$
1128
1129{ \catcode\circumflexasciicode\othercatcode       \immutable\glet\othercircumflextoken      ^ }
1130{ \catcode\circumflexasciicode\superscriptcatcode \immutable\glet\superscriptcircumflextoken^ }
1131
1132\ifdefined \prime \else
1133    \Umathchardef\prime "0 "0 "2032
1134\fi
1135
1136% \let\math_prime_indeed_normal\prime
1137%
1138% \appendtoks
1139%     \let\math_prime_indeed_normal\prime    % gets defined later
1140%     \let\mathfontprime\prime               % for tracing
1141%     \let\prime\math_prime_indeed           % so this is needed
1142% \to \everydump
1143%
1144% \protected\def\math_prime_indeed
1145%   {\iffontchar\textfont\zerocount"FE325\relax
1146%     ^\bgroup
1147%      \expandafter\math_prime_indeed_virtual % virtual mess (using funny signal)
1148%    \else
1149%    % \expandafter\math_prime_indeed_normal  % gets collapsed
1150%      \expandafter\math_prime_indeed_crapped  % gets collapsed
1151%    \fi}
1152%
1153% \def\math_prime_indeed_crapped
1154%   {{^{\math_prime_indeed_normal}}}
1155%
1156% % \let\prime\math_prime_indeed
1157%
1158% \def\math_prime_indeed_virtual
1159%   {\math_prime_indeed_normal
1160%    \futurelet\nexttoken\math_prime_indeed_choice}
1161%
1162% \installcorenamespace{mathprime}
1163%
1164% \def\math_prime_indeed_choice
1165%   {\csname\??mathprime
1166%      \ifx                          '\nexttoken a\else
1167%      \ifx  \math_prime_indeed_normal\nexttoken a\else
1168%      \ifx                     \prime\nexttoken a\else
1169%      \ifx\superscriptcircumflextoken\nexttoken b\else
1170%      \ifx\othercircumflextoken      \nexttoken b\else
1171%                                                c\fi\fi\fi\fi\fi
1172%    \endcsname}
1173%
1174% \setvalue{\??mathprime a}#1{\math_prime_indeed_virtual}
1175% \setvalue{\??mathprime b}#1#2{#2\egroup}
1176% \setvalue{\??mathprime c}{\egroup}
1177%
1178% \let\activemathprime\math_prime_indeed
1179%
1180% \bgroup
1181%
1182%     \catcode\primeasciicode\activecatcode
1183%
1184%     \global\everymathematics\expandafter{\the\everymathematics\let'\math_prime_indeed} % todo: do this at the lua end
1185%
1186% \egroup
1187
1188% $\char26$ gives an error because it expands to an active character that
1189% then becomes an & which is then seen as an alignment character; anyway,
1190% even when we switch like this the different meaning only happens when
1191% we're in math mode which can be delayed till we're in a cell
1192
1193\bgroup
1194
1195    \catcode\underscoreasciicode\activecatcode
1196    \catcode\circumflexasciicode\activecatcode
1197    \catcode\ampersandasciicode \activecatcode
1198
1199    \aliased\glet\specialmathaligntab\normalmathaligntab
1200
1201    \permanent\protected\gdef\obeymathcatcodes{%
1202        \enforced\let _\normalsubscript
1203        \enforced\let ^\normalsuperscript
1204        \enforced\def &\specialmathaligntab
1205    }
1206
1207    \doglobal\appendtoks
1208        \enforced\let _\normalsubscript
1209        \enforced\let ^\normalsuperscript
1210        \enforced\let &\specialmathaligntab
1211    \to \everymathematics
1212
1213  % \permanent\protected\gdef\normalmathampersands
1214  %   {\let\specialmathaligntab\mathampersand}
1215
1216\egroup
1217
1218\newtoks\everydonknuthmode
1219\newtoks\everynonknuthmode
1220
1221\newconditional \knuthmode
1222
1223\aliased\let\nonknuthmode\relax % no longer needed in MkIV
1224\aliased\let\donknuthmode\relax % no longer needed in MkIV
1225
1226% \def\nonknuthmode
1227%   {\pushcatcodetable
1228%    \setcatcodetable\ctxcatcodes
1229%    \the\everynonknuthmode
1230%    \let\nonknuthmode\relax
1231%    \popcatcodetable}
1232%
1233% \def\donknuthmode
1234%   {\pushcatcodetable
1235%    \setcatcodetable\ctxcatcodes
1236%    \the\everydonknuthmode
1237%    \popcatcodetable}
1238%
1239% \bgroup
1240%
1241%     \catcode\underscoreasciicode\activecatcode
1242%     \catcode\circumflexasciicode\activecatcode
1243%     \catcode\ampersandasciicode \activecatcode
1244%
1245%     \global \everynonknuthmode {\appendtoks
1246%         \let_\normalsubscript
1247%         \let^\normalsuperscript
1248%         \let&\normalmathaligntab % use \def when it's \aligntab
1249%     \to \everymathematics}
1250%
1251% \egroup
1252%
1253% \appendtoks
1254%     \setfalse\knuthmode
1255%     \catcode\underscoreasciicode\othercatcode
1256%     \catcode\circumflexasciicode\othercatcode
1257%     \catcode\ampersandasciicode \othercatcode
1258% \to \everynonknuthmode
1259%
1260% \appendtoks
1261%     \settrue\knuthmode
1262%     \catcode\underscoreasciicode\subscriptcatcode
1263%     \catcode\circumflexasciicode\superscriptcatcode
1264%     \catcode\ampersandasciicode \alignmentcatcode
1265% \to \everydonknuthmode
1266%
1267% \appendtoks
1268%     \startextendcatcodetable\ctxcatcodes
1269%         \catcode\underscoreasciicode\othercatcode
1270%         \catcode\circumflexasciicode\othercatcode
1271%         \catcode\ampersandasciicode \othercatcode
1272%     \stopextendcatcodetable
1273% \to \everynonknuthmode
1274%
1275% \appendtoks
1276%     \startextendcatcodetable\ctxcatcodes
1277%         \catcode\underscoreasciicode\subscriptcatcode
1278%         \catcode\circumflexasciicode\superscriptcatcode
1279%         \catcode\ampersandasciicode \alignmentcatcode
1280%     \stopextendcatcodetable
1281% \to \everydonknuthmode
1282
1283%D Even more drastic (this code will move as nonknuthmode is default now)
1284
1285% \protected\def\enableasciimode
1286%   {\ctxlua{resolvers.macros.enablecomment()}%
1287%    \glet\enableasciimode\relax}
1288%
1289% \protected\def\asciimode
1290%   {\catcodetable\txtcatcodes
1291%    \enableasciimode
1292%    \nonknuthmode}
1293%
1294% \protected\def\startasciimode
1295%   {\pushcatcodetable
1296%    \catcodetable\txtcatcodes
1297%    \enableasciimode
1298%    \nonknuthmode}
1299%
1300% \protected\def\stopasciimode
1301%   {\popcatcodetable
1302%    \ifconditional\knuthmode\else\donknuthmode\fi}
1303
1304\permanent\protected\def\enableasciimode
1305  {\clf_enableasciimode} % relaxes itself
1306
1307\permanent\protected\def\asciimode
1308  {\catcodetable\txtcatcodes
1309   \clf_enableasciimode}
1310
1311\permanent\protected\def\startasciimode
1312  {\pushcatcodetable
1313   \catcodetable\txtcatcodes
1314   \clf_enableasciimode}
1315
1316\permanent\protected\def\stopasciimode
1317  {\popcatcodetable}
1318
1319%D Needed for unicode:
1320
1321\permanent\def\nulloperator{\mathortext{\mathop{\emptyhbox}}{\emptyhbox}}
1322
1323%D Memory saver:
1324
1325\def\math_basics_check_compact
1326  {\doifelse{\mathematicsparameter\c!compact}\v!yes
1327     \enabledirectives\disabledirectives[math.virtual.optional]}
1328
1329\appendtoks
1330    \ifempty\currentmathematics
1331        \math_basics_check_compact % less tracing
1332    \fi
1333\to \everysetupmathematics
1334
1335\setupmathematics
1336  [\c!compact=\v!no]
1337
1338% \enabletrackers[typesetters.directions.math]
1339
1340%D Right||to||left typesetting in math is supported by the \type {align} parameter
1341%D with as option the \type {bidi} parameter. Of course support for special symbols
1342%D like square roots depends on the font as well. We probably need to mirror a few
1343%D more characters.
1344%D
1345%D \startbuffer
1346%D     \removeunwantedspaces
1347%D     \m{   (  1 =   1)   }\quad
1348%D     \m{   (123 = 123)   }\quad
1349%D     \m{ a (  1 =   1) b }\quad
1350%D     \m{ a (123 = 123) b }\quad
1351%D     \m{ x = 123 y + (1 / \sqrt {x}) }
1352%D \stopbuffer
1353%D
1354%D \typebuffer
1355%D
1356%D \starttabulate[|T|T||]
1357%D \HL
1358%D \NC align \NC bidi \NC                                                  \NC \NR
1359%D \HL
1360%D \NC l2r   \NC no   \NC \setupmathematics[bidi=no]            \getbuffer \NC \NR
1361%D \NC l2r   \NC yes  \NC \setupmathematics[bidi=yes]           \getbuffer \NC \NR
1362%D \NC r2l   \NC no   \NC \setupmathematics[align=r2l,bidi=no]  \getbuffer \NC \NR
1363%D \NC r2l   \NC yes  \NC \setupmathematics[align=r2l,bidi=yes] \getbuffer \NC \NR
1364%D \HL
1365%D \stoptabulate
1366
1367% We will use proper constants when we go numbers instead of XXX.
1368
1369\newconditional\c_math_right_to_left
1370
1371\installcorenamespace{mathaligndirection}
1372
1373\defcsname\??mathaligndirection           r2l\endcsname{\settrue\c_math_right_to_left}
1374\defcsname\??mathaligndirection\v!righttoleft\endcsname{\settrue\c_math_right_to_left}
1375
1376\appendtoks
1377    \ifcsname\??mathaligndirection\mathematicsparameter\c!align\endcsname
1378      \lastnamedcs
1379    \else
1380      \setfalse\c_math_right_to_left
1381    \fi
1382\to \everyswitchmathematics
1383
1384\protected\def\math_basics_synchronize_direction
1385  {\mathdirection\ifconditional\c_math_right_to_left\directionrighttoleft\else\directionlefttoright\fi}
1386
1387% Not \everymathematics as it comes too late and I'm not in the mood for a mixed mode
1388% kludge now (should be a property of beginmath nodes and passed to callbacks).
1389
1390\appendtoks
1391    \math_basics_synchronize_direction
1392\to \everyswitchmathematics
1393
1394% experimental (needed for an article)
1395
1396\installcorenamespace {mathbidi}
1397
1398\newcount\c_math_bidi
1399
1400\def\math_bidi_enable {\clf_setmathdirection\plusone  \relax\c_math_bidi\plusone}
1401\def\math_bidi_disable{\clf_setmathdirection\zerocount\relax\c_math_bidi\attributeunsetvalue}
1402
1403\letcsname\??mathbidi\v!yes\endcsname\math_bidi_enable
1404\letcsname\??mathbidi\v!no \endcsname\math_bidi_disable
1405
1406\appendtoks
1407    \edef\p_bidi{\mathematicsparameter\c!bidi}% still needed ?
1408    \ifcsname\??mathbidi\p_bidi\endcsname\lastnamedcs\else\math_bidi_disable\fi
1409\to \everysetupmathematics
1410
1411\appendtoks
1412    \c_attr_mathbidi\ifconditional\c_math_right_to_left\c_math_bidi\else\attributeunsetvalue\fi
1413\to \everyswitchmathematics
1414
1415%D Delayed: greek.
1416%D
1417%D \starttyping
1418%D \usetypescript[cambria]\setupbodyfont[cambria]
1419%D \startTEXpage
1420%D     $\alpha \mathgreekupright \alpha \mathgreekitalic \alpha$
1421%D \stopTEXpage
1422%D \stoptyping
1423
1424% [lc uc] normal (upright) = 2, italic = 3, none = 0/1
1425
1426% We can move the setting to the lua end and use abstract numbers instead
1427% if funny ones here.
1428
1429\installcorenamespace{mathgreek}
1430
1431\newconstant\c_math_greek_attribute
1432
1433\defcsname\??mathgreek\v!none  \endcsname{1}
1434\defcsname\??mathgreek\v!normal\endcsname{2}
1435\defcsname\??mathgreek\v!italic\endcsname{3}
1436
1437% \appendtoks
1438%     \edef\p_sygreek{\mathematicsparameter\s!sygreek}%
1439%     \edef\p_lcgreek{\mathematicsparameter\s!lcgreek}%
1440%     \edef\p_ucgreek{\mathematicsparameter\s!ucgreek}%
1441%     \c_math_greek_attribute"% hex digits
1442%       \csname\??mathgreek\ifcsname\??mathgreek\p_sygreek\endcsname\p_sygreek\else\v!none\fi\endcsname
1443%       \csname\??mathgreek\ifcsname\??mathgreek\p_lcgreek\endcsname\p_lcgreek\else\v!none\fi\endcsname
1444%       \csname\??mathgreek\ifcsname\??mathgreek\p_ucgreek\endcsname\p_ucgreek\else\v!none\fi\endcsname
1445%     \relax
1446%     \ifcase\c_math_greek_attribute
1447%       \c_math_greek_attribute\attributeunsetvalue
1448%     \fi
1449% \to \everyswitchmathematics
1450
1451\appendtoks
1452    \edef\p_sygreek{\mathematicsparameter\s!sygreek}% still needed ?
1453    \edef\p_lcgreek{\mathematicsparameter\s!lcgreek}% still needed ?
1454    \edef\p_ucgreek{\mathematicsparameter\s!ucgreek}% still needed ?
1455    \c_math_greek_attribute"% hex digits
1456      \ifcsname\??mathgreek\p_sygreek\endcsname\lastnamedcs\else1\fi
1457      \ifcsname\??mathgreek\p_lcgreek\endcsname\lastnamedcs\else1\fi
1458      \ifcsname\??mathgreek\p_ucgreek\endcsname\lastnamedcs\else1\fi
1459    \relax
1460    \ifcase\c_math_greek_attribute
1461      \c_math_greek_attribute\attributeunsetvalue
1462    \fi
1463\to \everyswitchmathematics
1464
1465% only used local
1466
1467\permanent\protected\def\mathgreekupright{\c_attr_mathgreek"222\relax}
1468\permanent\protected\def\mathgreekitalic {\c_attr_mathgreek"333\relax}
1469\permanent\protected\def\mathgreekdefault{\c_attr_mathgreek"000\relax}
1470
1471\aliased\let\mathgreeknormal\mathgreekupright
1472\aliased\let\mathgreeknone  \mathgreekdefault
1473
1474\appendtoks
1475    \c_attr_mathgreek\c_math_greek_attribute
1476\to \everymathematics
1477
1478\setupmathematics
1479  [\s!sygreek=\v!normal,
1480   \s!lcgreek=\v!italic,
1481   \s!ucgreek=\v!normal] % was: none
1482
1483%D Math collapsing (ligatures)
1484
1485\installcorenamespace{mathcollapsing}
1486
1487\setnewconstant\c_math_collapsing_attribute\attributeunsetvalue
1488
1489\letcsname\??mathcollapsing       1\endcsname\plusone              % specials
1490\letcsname\??mathcollapsing       2\endcsname\plustwo              % specials + mathlist
1491\letcsname\??mathcollapsing       3\endcsname\plusthree            % mathlist + specials
1492\letcsname\??mathcollapsing\v!none \endcsname\attributeunsetvalue
1493\letcsname\??mathcollapsing\v!reset\endcsname\attributeunsetvalue
1494
1495\def\math_collapsing_initialize
1496  {\ifnum\c_math_collapsing_attribute=\attributeunsetvalue \else
1497     \clf_initializemathcollapsing % one time
1498     \glet\math_collapsing_initialize\relax
1499   \fi}
1500
1501\appendtoks
1502    \edef\p_collapsing{\mathematicsparameter\s!collapsing}%
1503    \c_math_collapsing_attribute
1504        \ifcsname\??mathcollapsing\p_collapsing\endcsname\lastnamedcs\else\attributeunsetvalue\fi
1505    \relax
1506\to \everyswitchmathematics % only in mathematics
1507
1508\appendtoks
1509    \math_collapsing_initialize
1510    \c_attr_mathcollapsing\c_math_collapsing_attribute
1511\to \everymathematics
1512
1513\setupmathematics
1514  [\s!collapsing=1] % so that we at least do primes
1515
1516%D Math italics (experiment)
1517
1518%D We need keys but what names to use and because we have hardcoded solution
1519%D we can stick to numbers.
1520
1521\installcorenamespace{mathitalics}
1522
1523\setnewconstant\c_math_italics_attribute\attributeunsetvalue
1524
1525\letcsname\??mathitalics       1\endcsname\plusone              % fontitalics
1526\letcsname\??mathitalics       2\endcsname\plustwo              % fontdata
1527\letcsname\??mathitalics       3\endcsname\plusthree            % quad based
1528\letcsname\??mathitalics       4\endcsname\plusfour             % combination of 1 and 3
1529\letcsname\??mathitalics \v!none\endcsname\attributeunsetvalue
1530\letcsname\??mathitalics\v!reset\endcsname\attributeunsetvalue
1531
1532\def\math_italics_initialize
1533  {\ifnum\c_math_italics_attribute=\attributeunsetvalue \else
1534     \clf_initializemathitalics % one time
1535     \glet\math_italics_initialize\relax
1536   \fi}
1537
1538\appendtoks
1539    \edef\p_italics{\mathematicsparameter\s!italics}%
1540    \c_math_italics_attribute
1541        \ifcsname\??mathitalics\p_italics\endcsname\lastnamedcs\else\attributeunsetvalue\fi
1542    \relax
1543  % \math_italics_initialize
1544\to \everyswitchmathematics % only in mathematics
1545
1546\appendtoks
1547    \math_italics_initialize
1548    \c_attr_mathitalics\c_math_italics_attribute
1549\to \everymathematics
1550
1551% \setupmathematics % done later
1552%   [\s!italics=3] % 4 is probably better
1553
1554% looks nicer but can generate bogus csnames
1555%
1556% \setvalue{\??mathitalics1}{\math_italics_initialize\c_math_italics_attribute\plusone  } % fontitalics
1557% \setvalue{\??mathitalics2}{\math_italics_initialize\c_math_italics_attribute\plustwo  } % fontdata
1558% \setvalue{\??mathitalics3}{\math_italics_initialize\c_math_italics_attribute\plusthree} % quad based
1559% \setvalue{\??mathitalics4}{\math_italics_initialize\c_math_italics_attribute\plusfour } % combination of 1 and 3
1560%
1561% \appendtoks
1562%     \c_math_italics_attribute\attributeunsetvalue
1563%     \csname\??mathitalics\mathematicsparameter\s!italics\endcsname
1564% \to \everyswitchmathematics % only in mathematics
1565
1566%D Math kerns (experiment)
1567
1568\installcorenamespace{mathkernpairs}
1569
1570\setnewconstant\c_math_kernpairs_attribute\attributeunsetvalue % no real need for an extra constant
1571
1572\def\math_kernpairs_initialize
1573  {\ifnum\c_math_kernpairs_attribute=\attributeunsetvalue \else
1574     \clf_initializemathkernpairs % one time
1575     \glet\math_kernpairs_initialize\relax
1576   \fi}
1577
1578\appendtoks
1579    \edef\p_kernpairs{\mathematicsparameter\s!kernpairs}%
1580    \c_math_kernpairs_attribute\ifx\p_kernpairs\v!yes\plusone\else\attributeunsetvalue\fi\relax
1581\to \everyswitchmathematics % only in mathematics
1582
1583\appendtoks
1584    \math_kernpairs_initialize
1585    \c_attr_mathkernpairs\c_math_kernpairs_attribute
1586\to \everymathematics
1587
1588\setupmathematics
1589  [\s!kernpairs=\v!no]
1590
1591%D \macros
1592%D   {enablemathpunctuation,disablemathpunctuation}
1593%D
1594%D \startbuffer
1595%D \enablemathpunctuation$(1,2) (1, 2) (1{,}2) \hbox{foo, not bar}$
1596%D \stopbuffer
1597%D
1598%D \typebuffer
1599%D
1600%D \blank{\getbuffer}\blank
1601
1602% \newconditional\automathpunctuation
1603%
1604% \protected\def\enablemathpunctuation {\settrue \automathpunctuation}
1605% \protected\def\disablemathpunctuation{\setfalse\automathpunctuation}
1606%
1607% \appendtoks
1608%     \doifelse{\mathematicsparameter\v!autopunctuation}\v!yes\settrue\setfalse\automathpunctuation
1609% \to \everyswitchmathematics
1610%
1611% \setupmathematics
1612%   [\v!autopunctuation=\v!no]
1613%
1614% \def\math_punctuation_next{\ifx\nexttoken\blankspace\signalcharacter\fi}
1615%
1616% \protected\def\math_punctuation_comma {\textcomma \futurelet\nexttoken\math_punctuation_next}
1617% \protected\def\math_punctuation_period{\textperiod\futurelet\nexttoken\math_punctuation_next}
1618%
1619% \setnewconstant\c_math_comma  "002C
1620% \setnewconstant\c_math_period "002E
1621% \setnewconstant\c_math_special"8000
1622%
1623% \bgroup
1624%
1625%     \catcode\c_math_comma \activecatcode
1626%     \catcode\c_math_period\activecatcode
1627%
1628%     \protected\gdef\math_punctuation_initialize_indeed
1629%       {\mathcode\c_math_comma \c_math_special
1630%        \mathcode\c_math_period\c_math_special
1631%        \let,\math_punctuation_comma
1632%        \let.\math_punctuation_period
1633%        \c_attr_mathpunctuation\plustwo}
1634%
1635%     \protected\gdef\math_punctuation_initialize_yes
1636%       {\c_attr_mathpunctuation\plustwo}
1637%
1638%     \protected\gdef\math_punctuation_initialize_nop
1639%       {\c_attr_mathpunctuation\plusone}
1640%
1641% \egroup
1642%
1643% \appendtoks
1644%     \ifconditional\automathpunctuation
1645%       \math_punctuation_initialize_indeed
1646%       \math_punctuation_initialize_yes
1647%       \let\enablemathpunctuation \math_punctuation_initialize_yes
1648%       \let\disablemathpunctuation\math_punctuation_initialize_nop
1649%     \fi
1650% \to \everymathematics
1651
1652% Later I will look again into a \LUATEX\ based solution. It only makes sense
1653% to delegate to \LUA\ when we have more variants and need analysis (experimental
1654% trickery removed for a while).
1655
1656% \def\math_punctuation_comma_next {\ifx\nexttoken\blankspace\mathpunct\else\mathord\fi{\textcomma }}
1657% \def\math_punctuation_period_next{\ifx\nexttoken\blankspace\mathpunct\else\mathord\fi{\textperiod}}
1658%
1659% \protected\def\math_punctuation_nop_comma {\mathpunct{\textcomma}}
1660% \protected\def\math_punctuation_nop_period{\mathord{\textperiod}}
1661%
1662% \protected\def\math_punctuation_all_comma {\futurelet\nexttoken\math_punctuation_comma_next}
1663% \protected\def\math_punctuation_all_period{\futurelet\nexttoken\math_punctuation_period_next}
1664%
1665%            \let\math_punctuation_yes_comma \math_punctuation_all_comma
1666%            \let\math_punctuation_yes_period\math_punctuation_nop_period
1667%
1668% The next one is more efficient as it produces more flat noad lists for numbers.
1669
1670\setnewconstant\c_math_comma    "002C
1671\setnewconstant\c_math_period   "002E
1672%setnewconstant\c_math_colon    "003A
1673\setnewconstant\c_math_semicolon"003B
1674\setnewconstant\c_math_special  "8000
1675
1676% todo: use \Umathclass\c_math_comma\mathpunctcode etc for temporary switching
1677
1678\def\math_set_o_comma    {\Umathcode\c_math_comma    \mathordcode  \zerocount\c_math_comma}
1679\def\math_set_p_comma    {\Umathcode\c_math_comma    \mathpunctcode\zerocount\c_math_comma}
1680\def\math_set_o_period   {\Umathcode\c_math_period   \mathordcode  \zerocount\c_math_period}
1681\def\math_set_p_period   {\Umathcode\c_math_period   \mathpunctcode\zerocount\c_math_period}
1682\def\math_set_o_semicolon{\Umathcode\c_math_semicolon\mathordcode  \zerocount\c_math_semicolon}
1683\def\math_set_p_semicolon{\Umathcode\c_math_semicolon\mathpunctcode\zerocount\c_math_semicolon}
1684
1685\edef\math_set_o_both {\math_set_o_period\math_set_o_comma}
1686\edef\math_set_p_both {\math_set_p_period\math_set_p_comma}
1687
1688\protected\def\math_punctuation_nop_comma    {\begingroup\math_set_p_comma    ,\endgroup}
1689\protected\def\math_punctuation_nop_period   {\begingroup\math_set_o_period   .\endgroup}
1690\protected\def\math_punctuation_nop_semicolon{\begingroup\math_set_p_semicolon;\endgroup}
1691
1692% todo: use new lookahead stuff
1693
1694\protected\def\math_punctuation_all_comma    {\futurelet\nexttoken\math_punctuation_comma_next}
1695\protected\def\math_punctuation_all_period   {\futurelet\nexttoken\math_punctuation_period_next}
1696\protected\def\math_punctuation_all_semicolon{\futurelet\nexttoken\math_punctuation_semicolon_next}
1697
1698          \let\math_punctuation_yes_comma    \math_punctuation_all_comma
1699          \let\math_punctuation_yes_period   \math_punctuation_nop_period
1700          \let\math_punctuation_yes_semicolon\math_punctuation_all_semicolon
1701
1702\def\math_punctuation_comma_next    {\begingroup\Umathcode\c_math_comma    \ifx\nexttoken\blankspace\mathordcode\else\mathordcode\fi\zerocount\c_math_comma    ,\endgroup}
1703\def\math_punctuation_period_next   {\begingroup\Umathcode\c_math_period   \ifx\nexttoken\blankspace\mathordcode\else\mathordcode\fi\zerocount\c_math_period   .\endgroup}
1704\def\math_punctuation_semicolon_next{\begingroup\Umathcode\c_math_semicolon\ifx\nexttoken\blankspace\mathordcode\else\mathordcode\fi\zerocount\c_math_semicolon;\endgroup}
1705
1706\installcorenamespace {mathautopunctuation}
1707
1708\bgroup
1709
1710    \catcode\c_math_comma    \activecatcode
1711    \catcode\c_math_period   \activecatcode
1712    \catcode\c_math_semicolon\activecatcode
1713
1714    \gdefcsname\??mathautopunctuation\v!no\endcsname
1715      {\let,\math_punctuation_nop_comma
1716       \let.\math_punctuation_nop_period
1717       \let;\math_punctuation_nop_semicolon}
1718
1719  %  more efficient list:
1720  %
1721  %  \gdefcsname\??mathautopunctuation\v!no\endcsname
1722  %    {\Umathcode\c_math_period\mathordcode  \zerocount\c_math_period
1723  %     \Umathcode\c_math_comma \mathpunctcode\zerocount\c_math_comma }
1724
1725    \gdefcsname\??mathautopunctuation\v!yes\endcsname
1726      {\let,\math_punctuation_yes_comma
1727       \let.\math_punctuation_yes_period
1728       \let;\math_punctuation_nop_semicolon}
1729
1730    \gdefcsname\??mathautopunctuation\v!all\endcsname
1731      {\let,\math_punctuation_all_comma
1732       \let.\math_punctuation_all_period
1733       \let;\math_punctuation_nop_semicolon}
1734
1735    \gdefcsname\??mathautopunctuation comma\endcsname
1736      {\let,\math_punctuation_yes_comma
1737       \let.\math_punctuation_yes_period
1738       \let;\math_punctuation_nop_semicolon}
1739
1740    \gdefcsname\??mathautopunctuation\v!yes\string,semicolon\endcsname
1741      {\let,\math_punctuation_yes_comma
1742       \let.\math_punctuation_yes_period
1743       \let;\math_punctuation_yes_semicolon}
1744
1745    \gdefcsname\??mathautopunctuation comma\string,semicolon\endcsname
1746      {\let,\math_punctuation_yes_comma
1747       \let.\math_punctuation_yes_period
1748       \let;\math_punctuation_yes_semicolon}
1749
1750    \gdefcsname\??mathautopunctuation\v!all\string,semicolon\endcsname
1751      {\let,\math_punctuation_all_comma
1752       \let.\math_punctuation_all_period
1753       \let;\math_punctuation_all_semicolon}
1754
1755\egroup
1756
1757% \appendtoks
1758%     \global\mathcode\c_math_comma    \c_math_special
1759%     \global\mathcode\c_math_period   \c_math_special
1760%     \global\mathcode\c_math_semicolon\c_math_special
1761% \to \everyjob
1762
1763% \activatemathcharacter\c_math_comma
1764% \activatemathcharacter\c_math_period
1765% \activatemathcharacter\c_math_semicolon
1766
1767\appendtoks
1768    \mathcode\c_math_comma    \c_math_special
1769    \mathcode\c_math_period   \c_math_special
1770    \mathcode\c_math_semicolon\c_math_special
1771    \begincsname\??mathautopunctuation\mathematicsparameter\v!autopunctuation\endcsname
1772\to \everymathematics
1773
1774\appendtoks
1775    \ifcsname\??mathautopunctuation\mathematicsparameter\v!autopunctuation\endcsname \else
1776        \letmathematicsparameter\v!autopunctuation\v!no
1777    \fi
1778\to \everysetupmathematics
1779
1780\permanent\protected\def\enablemathpunctuation {\csname\??mathautopunctuation\v!no \endcsname}
1781\permanent\protected\def\disablemathpunctuation{\csname\??mathautopunctuation\v!yes\endcsname}
1782
1783\setupmathematics
1784  [\v!autopunctuation=\v!no] % no | yes | all | comma | yes,semicolon | all,semicolon
1785
1786%D The consequences of setting this are as follows:
1787%D
1788%D \def\TestA#1#2#3%
1789%D   {\ifnum#1=0 \type{#2}\else\setupmathematics[autopunctuation={#2}]$#3$\fi}
1790%D \def\TestB#1#2%
1791%D   {\NC \TestA{#1}{no}           {#2}
1792%D    \NC \TestA{#1}{yes}          {#2}
1793%D    \NC \TestA{#1}{yes,semicolon}{#2}
1794%D    \NC \TestA{#1}{all}          {#2}
1795%D    \NC \TestA{#1}{all,semicolon}{#2}
1796%D    \NC \NR}
1797%D \starttabulate[|c|c|c|c|c|]
1798%D     \TestB{0}{}
1799%D     \TestB{1}{(1,2)=(1, 2)}
1800%D     \TestB{1}{(1.2)=(1. 2)}
1801%D     \TestB{1}{(1;2)=(1; 2)}
1802%D \stoptabulate
1803
1804%D \macros
1805%D   {mathstyle}
1806%D
1807%D If one want to be sure that something is typeset in the appropriate style, \type
1808%D {\mathstyle} can be used:
1809%D
1810%D \starttyping
1811%D \mathstyle{something}
1812%D \stoptyping
1813
1814% \def\mathstyle#1%
1815%   {\mathchoice
1816%      {\displaystyle     #1}%
1817%      {\textstyle        #1}%
1818%      {\scriptstyle      #1}%
1819%      {\scriptscriptstyle#1}}
1820%
1821% We now have a primitive operation for this. As the macro overloads a new
1822% primitive introduced in \LUATEX, we need to use \type {\normalmathstyle} when we
1823% consult the current math style.
1824%
1825% \let \mathstyle \Ustack % spoils cramped
1826%
1827% \let \mathstyle \firstofoneargument
1828%
1829% 0 = display
1830% 1 = crampeddisplay
1831% 2 = text
1832% 3 = crampedtext
1833% 4 = script
1834% 5 = crampedscript
1835% 6 = scriptscript
1836% 7 = crampedscriptscript
1837
1838\permanent\def\uncramped#1%
1839  {{\ifmathstyle
1840    \or \displaystyle      \or
1841    \or \textstyle         \or
1842    \or \scriptstyle       \or
1843    \or \scriptscriptstyle \fi
1844    #1}}
1845
1846\permanent\def\cramped#1%
1847  {{\ifmathstyle
1848    \crampeddisplaystyle      \or \or % 0 -> 1
1849    \crampedtextstyle         \or \or % 2 -> 3
1850    \crampedscriptstyle       \or \or % 4 -> 5
1851    \crampedscriptscriptstyle \fi     % 6 -> 7
1852    #1}}
1853
1854\permanent\def\triggermathstyle#1{\Ustyle\numexpr#1\relax}
1855%permanent\def\mathstyletrigger#1{\numexpr#1\relax}
1856\permanent\let\mathstyletrigger   \firstofoneargument
1857
1858\permanent\def\triggeredmathstyleparameter#1% to bypass the relax
1859  {\ifcase\numexpr\normalmathstyle\relax
1860     #1\displaystyle             \or % 0
1861     #1\crampeddisplaystyle      \or % 1
1862     #1\textstyle                \or % 2
1863     #1\crampedtextstyle         \or % 3
1864     #1\scriptstyle              \or % 4
1865     #1\crampedscriptstyle       \or % 5
1866     #1\scriptscriptstyle        \or % 6
1867     #1\crampedscriptscriptstyle \else
1868     % error
1869   \fi}
1870
1871\permanent\def\mathstylefont#1% #1 is number (\normalmathstyle)
1872  {\ifcase\numexpr#1\relax
1873     \textfont         \or
1874     \textfont         \or
1875     \textfont         \or
1876     \textfont         \or
1877     \scriptfont       \or
1878     \scriptfont       \or
1879     \scriptscriptfont \or
1880     \scriptscriptfont \else
1881     \textfont
1882   \fi\fam} % was \zerocount
1883
1884\permanent\def\somemathstylefont#1% #1 is number (\normalmathstyle)
1885  {\ifcase\numexpr#1\relax
1886     \textfont         \or
1887     \textfont         \or
1888     \textfont         \or
1889     \textfont         \or
1890     \scriptfont       \or
1891     \scriptfont       \or
1892     \scriptscriptfont \or
1893     \scriptscriptfont \else
1894     \textfont
1895   \fi}
1896
1897\permanent\def\mathsmallstylefont#1% #1 is number (\normalmathstyle)
1898  {\ifcase\numexpr#1\relax
1899     \scriptfont       \or
1900     \scriptfont       \or
1901     \scriptfont       \or
1902     \scriptfont       \or
1903     \scriptscriptfont \or
1904     \scriptscriptfont \or
1905     \scriptscriptfont \or
1906     \scriptscriptfont \else
1907     \scriptfont
1908   \fi\fam} % was \zerocount
1909
1910\permanent\def\mathstyleface#1% #1 is number (\normalmathstyle)
1911  {\ifcase\numexpr#1\relax
1912     \textface         \or
1913     \textface         \or
1914     \textface         \or
1915     \textface         \or
1916     \scriptface       \or
1917     \scriptface       \or
1918     \scriptscriptface \or
1919     \scriptscriptface \else
1920     \textface
1921   \fi}
1922
1923\permanent\def\mathsmallstyleface#1% #1 is number (\normalmathstyle)
1924  {\ifcase\numexpr#1\relax
1925     \scriptface       \or
1926     \scriptface       \or
1927     \scriptface       \or
1928     \scriptface       \or
1929     \scriptscriptface \or
1930     \scriptscriptface \or
1931     \scriptscriptface \or
1932     \scriptscriptface \else
1933     \scriptface
1934   \fi}
1935
1936\permanent\def\mathstylecommand#1#2#3%
1937  {\ifcase\numexpr\normalmathstyle\relax
1938     \expandafter#1\or
1939     \expandafter#1\or
1940     \expandafter#1\or
1941     \expandafter#1\or
1942     \expandafter#2\or
1943     \expandafter#2\or
1944     \expandafter#3\or
1945     \expandafter#3\else
1946     \expandafter#1\fi}
1947
1948% \permanent\def\textstyleface#1% #1 is number (\normalmathstyle)
1949%   {\ifcase\numexpr#1\relax
1950%      \tf   \or
1951%      \tf   \or
1952%      \tf   \or
1953%      \tf   \or
1954%      \tfx  \or
1955%      \tfx  \or
1956%      \tfxx \or
1957%      \tfxx \else
1958%      \tf
1959%    \fi}
1960
1961\permanent\protected\def\verbosemathstyle#1% #1 is number (\normalmathstyle)
1962  {{\normalexpanded{\relax\darkgray\ttxx[\number#1:\ifcase\numexpr#1\relax
1963                display\or   % 0
1964         crampeddisplay\or   % 1
1965                   text\or   % 2
1966            crampedtext\or   % 3
1967                 script\or   % 4
1968          crampedscript\or   % 5
1969           scriptscript\or   % 6
1970    crampedscriptscript\else % 7
1971                unknown\fi]}}}
1972
1973\permanent\protected\def\showmathstyle{\verbosemathstyle\normalmathstyle}
1974
1975%D Handy too:
1976
1977\permanent\def\mathcharwd{\fontcharwd\mathstylefont\normalmathstyle}
1978\permanent\def\mathcharht{\fontcharht\mathstylefont\normalmathstyle}
1979\permanent\def\mathchardp{\fontchardp\mathstylefont\normalmathstyle}
1980
1981%D Some dimension fun:
1982
1983\aliased  \let\mathexheight \exheight                   % also in math-ini.mkiv
1984\permanent\def\mathemwidth {\Umathquad\normalmathstyle} % also in math-ini.mkiv
1985
1986%D A plain inheritance:
1987
1988\permanent\def\mathpalette#1#2%
1989  {\mathchoice
1990     {#1\displaystyle     {#2}}%
1991     {#1\textstyle        {#2}}%
1992     {#1\scriptstyle      {#2}}%
1993     {#1\scriptscriptstyle{#2}}}
1994
1995%D \macros
1996%D    {cramedllap, crampedrlap, crampedclap}
1997%D
1998%D In many cases, one wants to use the \tex {clap} macro in math mode while using
1999%D subscripts. Normally, subscripts are in cramped mode, and these macros allow you
2000%D to go to cramped mode. For example:
2001%D
2002%D \startbuffer
2003%D \startformula
2004%D   \sum_{a^2 < b^2 < c^2} \quad
2005%D   \sum_{\clap{a^2 < b^2 < c^2}} \quad
2006%D   \sum_{\crampedclap{a^2 < b^2 < c^2}}
2007%D \stopformula
2008%D \stopbuffer
2009%D
2010%D \start
2011%D   \typebuffer
2012%D   \switchtobodyfont[24pt]
2013%D   \getbuffer
2014%D \stop
2015%D
2016%D This used to be in \type {supp-math.mkxl}:
2017
2018\permanent\protected\def\crampedllap#1{\llap{\cramped#1}}
2019\permanent\protected\def\crampedrlap#1{\rlap{\cramped#1}}
2020\permanent\protected\def\crampedclap#1{\clap{\cramped#1}}
2021
2022%D Often we can use:
2023%D
2024%D \startbuffer
2025%D $x^{\mathstylehbox{x^{\mathstylehbox{x}}}}$
2026%D \stopbuffer
2027%D
2028%D \typebuffer \getbuffer
2029
2030% to be tested: {#1} but it could have side effects
2031
2032% \protected\def\mathstylehbox#1% sensitive for: a \over b => {a\over b} or \frac{a}{b}
2033%   {\normalexpanded{\hbox\bgroup
2034%      \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup}
2035
2036\permanent\protected\def\mathstylehbox#1#% sensitive for: a \over b => {a\over b} or \frac{a}{b}
2037  {\math_style_hbox{#1}}
2038
2039\protected\def\math_style_hbox#1#2% sensitive for: a \over b => {a\over b} or \frac{a}{b}
2040  {\normalexpanded{\hbox#1\bgroup
2041     \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#2\stopimath\egroup}
2042
2043\permanent\protected\def\mathstylevbox#1%
2044  {\normalexpanded{\vbox\bgroup
2045     \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup}
2046
2047\permanent\protected\def\mathstylevcenter#1%
2048  {\normalexpanded{\vcenter\bgroup
2049     \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup}
2050
2051\permanent\protected\def\mathstylevcenteredhbox#1%
2052  {\normalexpanded{\vcenter\bgroup\hbox\bgroup
2053     \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup\egroup}
2054
2055\permanent\protected\def\mathstylevcenteredvbox#1%
2056  {\normalexpanded{\vcenter\bgroup\vbox\bgroup
2057     \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup\egroup}
2058
2059\permanent\protected\def\setmathsmalltextbox#1#2#%
2060  {\normalizebodyfontsize\m_math_text_choice_face{\mathsmallstyleface\normalmathstyle}%
2061   \setbox#1#2\bgroup
2062     \font_basics_switchtobodyfont\m_math_text_choice_face
2063     \let\next}
2064
2065\permanent\protected\def\setmathtextbox#1#2#%
2066  {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
2067   \setbox#1#2\bgroup
2068     \font_basics_switchtobodyfont\m_math_text_choice_face
2069     \let\next}
2070
2071%D Here is the new mechanism ... it might replace some of the above but we will do
2072%D that stepwise. Keep in mind that cramped only affects superscripts and even then,
2073%D only when in a smaller size than normal.
2074%D
2075%D \def\TestMe#1%
2076%D   {\NC \ttbf #1
2077%D    \NC \ruledhbox{$\setupmathstyle[#1]x + x_j^2 + x_i^{e^2} + \frac{1}{x}$}
2078%D    \NC \ruledhbox{$\setupmathstyle[#1,small]x + x_j^2 + x_i^{e^2} + \frac{1}{x}$}
2079%D    \NC \NR}
2080%D
2081%D \starttabulate[|l|r|l|]
2082%D \HL
2083%D \NC \NC \NC \ttbf ...,small \NC \NR
2084%D \HL
2085%D \TestMe{text}         \TestMe{text,cramped}
2086%D \TestMe{script}       \TestMe{script,cramped}
2087%D \TestMe{scriptscript} \TestMe{scriptscript,cramped}
2088%D \TestMe{display}      \TestMe{display,cramped}
2089%D \HL
2090%D \stoptabulate
2091
2092\permanent\def\triggerdisplaystyle
2093  {\ifmathstyle
2094     \displaystyle        \or
2095     \crampeddisplaystyle \or
2096     \displaystyle        \or
2097     \crampeddisplaystyle \or
2098     \displaystyle        \or
2099     \crampeddisplaystyle \or
2100     \displaystyle        \or
2101     \crampeddisplaystyle \or
2102   \fi}
2103
2104\permanent\def\triggertextstyle
2105  {\ifmathstyle
2106     \textstyle        \or
2107     \crampedtextstyle \or
2108     \textstyle        \or
2109     \crampedtextstyle \or
2110     \textstyle        \or
2111     \crampedtextstyle \or
2112     \textstyle        \or
2113     \crampedtextstyle \else
2114   \fi}
2115
2116\permanent\def\triggerscriptstyle
2117  {\ifmathstyle
2118     \scriptstyle        \or
2119     \crampedscriptstyle \or
2120     \scriptstyle        \or
2121     \crampedscriptstyle \or
2122     \scriptstyle        \or
2123     \crampedscriptstyle \or
2124     \scriptstyle        \or
2125     \crampedscriptstyle \or
2126   \fi}
2127
2128\permanent\def\triggerscriptscriptstyle
2129  {\ifmathstyle
2130     \scriptscriptstyle        \or
2131     \crampedscriptscriptstyle \or
2132     \scriptscriptstyle        \or
2133     \crampedscriptscriptstyle \or
2134     \scriptscriptstyle        \or
2135     \crampedscriptscriptstyle \or
2136     \scriptscriptstyle        \or
2137     \crampedscriptscriptstyle \or
2138   \fi}
2139
2140\permanent\def\triggeruncrampedstyle
2141  {\ifmathstyle
2142    \or \displaystyle      \or
2143    \or \textstyle         \or
2144    \or \scriptstyle       \or
2145    \or \scriptscriptstyle \fi}
2146
2147\permanent\def\triggercrampedstyle
2148  {\ifmathstyle
2149   \crampeddisplaystyle      \or \or
2150   \crampedtextstyle         \or \or
2151   \crampedscriptstyle       \or \or
2152   \crampedscriptscriptstyle \fi}
2153
2154\permanent\def\triggersmallstyle
2155  {\ifmathstyle
2156     \scriptstyle              \or
2157     \crampedscriptstyle       \or
2158     \scriptstyle              \or
2159     \crampedscriptstyle       \or
2160     \scriptscriptstyle        \or
2161     \crampedscriptscriptstyle \or
2162     \scriptscriptstyle        \or
2163     \crampedscriptscriptstyle \or
2164    \fi}
2165
2166\permanent\def\triggeruncrampedsmallstyle
2167  {\ifmathstyle
2168     \scriptstyle       \or
2169     \scriptstyle       \or
2170     \scriptstyle       \or
2171     \scriptstyle       \or
2172     \scriptscriptstyle \or
2173     \scriptscriptstyle \or
2174     \scriptscriptstyle \or
2175     \scriptscriptstyle \or
2176    \fi}
2177
2178\permanent\def\triggercrampedsmallstyle
2179  {\ifmathstyle
2180     \crampedscriptstyle       \or
2181     \crampedscriptstyle       \or
2182     \crampedscriptstyle       \or
2183     \crampedscriptstyle       \or
2184     \crampedscriptscriptstyle \or
2185     \crampedscriptscriptstyle \or
2186     \crampedscriptscriptstyle \or
2187     \crampedscriptscriptstyle \or
2188    \fi}
2189
2190\permanent\def\triggerbigstyle
2191  {\ifmathstyle
2192     \displaystyle        \or
2193     \crampeddisplaystyle \or
2194     \textstyle           \or
2195     \crampedtextstyle    \or
2196     \textstyle           \or
2197     \crampedtextstyle    \or
2198     \scriptstyle         \or
2199     \crampedscriptstyle  \or
2200    \fi}
2201
2202\permanent\def\triggeruncrampedbigstyle
2203  {\ifmathstyle
2204     \displaystyle \or
2205     \displaystyle \or
2206     \textstyle    \or
2207     \textstyle    \or
2208     \textstyle    \or
2209     \textstyle    \or
2210     \scriptstyle  \or
2211     \scriptstyle  \or
2212    \fi}
2213
2214\permanent\def\triggercrampedbigstyle
2215  {\ifmathstyle
2216     \crampeddisplaystyle \or
2217     \crampeddisplaystyle \or
2218     \crampedtextstyle    \or
2219     \crampedtextstyle    \or
2220     \crampedtextstyle    \or
2221     \crampedtextstyle    \or
2222     \crampedscriptstyle  \or
2223     \crampedscriptstyle  \or
2224    \fi}
2225
2226\newcount\c_math_saved_style
2227
2228\permanent\protected\def\pushmathstyle % assumes begingroup .. endgroup
2229  {\c_math_saved_style\mathstyle}
2230
2231\permanent\protected\def\popmathstyle
2232  {\ifnum\mathstyle=\c_math_saved_style\else
2233     \triggermathstyle\c_math_saved_style
2234   \fi}
2235
2236\installcorenamespace{mathstylecommand}
2237\installcorenamespace{mathstylecache}
2238
2239\newconstant\c_math_styles_state_style
2240\newconstant\c_math_styles_state_cramped
2241\newconstant\c_math_styles_state_size
2242
2243\def\math_style_add_to_cache_choice {%
2244  \ifcase\c_math_styles_state_size
2245    \ifcase\c_math_styles_state_style
2246        \ifcase\c_math_styles_state_cramped
2247        \relax                               \or
2248        \noexpand\triggeruncrampedstyle      \or
2249        \noexpand\triggercrampedstyle        \fi
2250    \or\ifcase\c_math_styles_state_cramped
2251        \noexpand\triggerdisplaystyle        \or
2252        \displaystyle                        \or
2253        \crampeddisplaystyle                 \fi
2254    \or\ifcase\c_math_styles_state_cramped
2255        \noexpand\triggertextstyle           \or
2256        \textstyle                           \or
2257        \crampedtextstyle                    \fi
2258    \or\ifcase\c_math_styles_state_cramped
2259        \noexpand\triggerscriptstyle         \or
2260        \scriptstyle                         \or
2261        \crampedscriptstyle                  \fi
2262    \or\ifcase\c_math_styles_state_cramped
2263        \noexpand\triggerscriptscriptstyle   \or
2264        \scriptscriptstyle                   \or
2265        \crampedscriptscriptstyle            \fi
2266    \fi
2267  \or % small
2268    \ifcase\c_math_styles_state_style
2269        \ifcase\c_math_styles_state_cramped
2270        \noexpand\triggersmallstyle          \or
2271        \noexpand\triggeruncrampedsmallstyle \or
2272        \noexpand\triggercrampedsmallstyle   \fi
2273    \or\ifcase\c_math_styles_state_cramped
2274        \noexpand\triggerscriptstyle         \or
2275        \scriptstyle                         \or
2276        \crampedscriptstyle                  \fi
2277    \or\ifcase\c_math_styles_state_cramped
2278        \noexpand\triggerscriptstyle         \or
2279        \scriptstyle                         \or
2280        \crampedscriptstyle                  \fi
2281    \or\ifcase\c_math_styles_state_cramped
2282        \noexpand\triggerscriptscriptstyle   \or
2283        \scriptscriptstyle                   \or
2284        \crampedscriptscriptstyle            \fi
2285    \or\ifcase\c_math_styles_state_cramped
2286        \noexpand\triggerscriptscriptstyle   \or
2287        \scriptscriptstyle                   \or
2288        \crampedscriptscriptstyle            \fi
2289    \fi
2290  \or % large
2291    \ifcase\c_math_styles_state_style
2292        \ifcase\c_math_styles_state_cramped
2293        \noexpand\triggerbigstyle            \or
2294        \noexpand\triggeruncrampedbigstyle   \or
2295        \noexpand\triggercrampedbigstyle     \fi
2296    \or\ifcase\c_math_styles_state_cramped
2297        \noexpand\triggerdisplaystyle        \or
2298        \displaystyle                        \or
2299        \crampeddisplaystyle                 \fi
2300    \or\ifcase\c_math_styles_state_cramped
2301        \noexpand\triggertextstyle           \or
2302        \textstyle                           \or
2303        \crampedtextstyle                    \fi
2304    \or\ifcase\c_math_styles_state_cramped
2305        \noexpand\triggertextstyle           \or
2306        \textstyle                           \or
2307        \crampedtextstyle                    \fi
2308    \or\ifcase\c_math_styles_state_cramped
2309        \noexpand\triggerscriptstyle         \or
2310        \scriptstyle                         \or
2311        \crampedscriptstyle                  \fi
2312    \fi
2313  \fi
2314}
2315
2316\permanent\tolerant\protected\def\setmathstyle[#1]#;#=% so we accept [] and {}
2317  {\edef\m_math_style_asked{#1#2}%
2318   \ifempty\m_math_style_asked \else
2319     \math_style_set_indeed
2320   \fi}
2321
2322\permanent\def\installmathstyle#1#2%
2323  {\ifcsname\??mathstylecommand#1\endcsname \else
2324     \setvalue{\??mathstylecommand#1}{#2}%
2325   \fi}
2326
2327\def\math_style_collect#1%
2328  {\csname\??mathstylecommand#1\endcsname}
2329
2330\defcsname\??mathstylecommand\s!display     \endcsname{\c_math_styles_state_style  \plusone}
2331\defcsname\??mathstylecommand\s!text        \endcsname{\c_math_styles_state_style  \plustwo}
2332\defcsname\??mathstylecommand\s!script      \endcsname{\c_math_styles_state_style  \plusthree}
2333\defcsname\??mathstylecommand\s!scriptscript\endcsname{\c_math_styles_state_style  \plusfour}
2334
2335\defcsname\??mathstylecommand\s!uncramped   \endcsname{\c_math_styles_state_cramped\plusone}
2336\defcsname\??mathstylecommand\s!cramped     \endcsname{\c_math_styles_state_cramped\plustwo}
2337\defcsname\??mathstylecommand\v!normal      \endcsname{\c_math_styles_state_cramped\plusone}
2338\defcsname\??mathstylecommand\v!packed      \endcsname{\c_math_styles_state_cramped\plustwo}
2339
2340\defcsname\??mathstylecommand\v!small       \endcsname{\c_math_styles_state_size   \plusone}
2341\defcsname\??mathstylecommand\v!big         \endcsname{\c_math_styles_state_size   \plustwo}
2342
2343\permanent\protected\def\setupmathstyle[#1]%
2344  {\edef\m_math_style_asked{#1}%
2345   \ifempty\m_math_style_asked \else
2346     \math_style_set_indeed
2347   \fi}
2348
2349\permanent\protected\def\usemathstyleparameter#1% faster local variant
2350  {\edef\m_math_style_asked{#1\c!mathstyle}%
2351   \ifempty\m_math_style_asked \else
2352     \math_style_set_indeed
2353   \fi}
2354
2355%D \startbuffer
2356%D \definemathstyle[mystyle][scriptscript]
2357%D
2358%D $text\startmathstyle[mystyle]scriptscript\stopmathstyle text$
2359%D \stopbuffer
2360%D
2361%D \typebuffer \blank \start \getbuffer \stop \blank
2362
2363\installcorenamespace {mathstyle}
2364
2365\permanent\tolerant\protected\def\definemathstyle[#1]#*[#2]%
2366  {\c_math_styles_state_style  \zerocount
2367   \c_math_styles_state_cramped\zerocount
2368   \c_math_styles_state_size   \zerocount
2369   \rawprocesscommacommand[#2]\math_style_collect
2370   \letcsname\??mathstyle#1\normalexpanded{\endcsname\math_style_add_to_cache_choice}}
2371
2372\def\math_style_set_indeed
2373  {\ifcsname\??mathstyle\m_math_style_asked\endcsname
2374     \lastnamedcs
2375   \else
2376     \math_style_set_mathstyle_mathstyle
2377   \fi}
2378
2379\def\math_style_set_mathstyle_mathstyle
2380  {\ifcsname\??mathstylecache\m_math_style_asked\endcsname
2381     \lastnamedcs
2382   \else
2383     \math_style_set_mathstyle_mathstylecache
2384   \fi}
2385
2386\def\math_style_set_mathstyle_mathstylecache
2387  {\c_math_styles_state_style  \zerocount
2388   \c_math_styles_state_cramped\zerocount
2389   \c_math_styles_state_size   \zerocount
2390   \rawprocesscommacommand[\m_math_style_asked]\math_style_collect
2391   \gletcsname\??mathstylecache\m_math_style_asked\normalexpanded{\endcsname\math_style_add_to_cache_choice}%
2392   \csname\??mathstylecache\m_math_style_asked\endcsname}
2393
2394\letcsname\??mathstyle     \??mathstyle     \endcsname\math_style_set_mathstyle_mathstyle      % still needed?
2395\letcsname\??mathstylecache\??mathstylecache\endcsname\math_style_set_mathstyle_mathstylecache % still needed?
2396
2397%D \startbuffer
2398%D $x\begingroup\setupmathstyle[script]x\endgroup x$
2399%D $x{\setupmathstyle[script]x}x$
2400%D $x\startmathstyle[script]x\stopmathstyle x$
2401%D \stopbuffer
2402%D
2403%D \typebuffer \getbuffer
2404
2405\permanent\protected\def\startmathstyle[#1]%
2406  {\edef\m_math_style_asked{#1}%
2407   \ifempty\m_math_style_asked
2408     \enforced\aliased\let\stopmathstyle\relax
2409   \else
2410     \bgroup
2411     \math_style_set_indeed
2412     \enforced\aliased\let\stopmathstyle\egroup
2413   \fi}
2414
2415\aliased\let\stopmathstyle\relax
2416
2417\permanent\protected\def\startusemathstyleparameter#1%
2418  {\edef\m_math_style_asked{#1\c!mathstyle}%
2419   \ifempty\m_math_style_asked
2420     \enforced\let\stopusemathstyleparameter\relax
2421   \else
2422     \bgroup
2423     \math_style_set_indeed
2424     \enforced\let\stopusemathstyleparameter\egroup
2425   \fi}
2426
2427\aliased\let\stopusemathstyleparameter\relax
2428
2429%D Something similar can be used in the (re|)|definition of \type {\text}. This
2430%D version is a variation on the one in the math module (see \type{m-math} and|/|or
2431%D \type {m-newmat}).
2432
2433\let\m_math_text_choice_face\relax
2434
2435% if needed we can get rid of the normalize (predo in font code)
2436
2437% \def\math_text_choice_font#1#2#%
2438%   {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
2439%    \hbox#2\bgroup
2440%    \font_basics_switchtobodyfont\m_math_text_choice_face
2441%    #1%
2442%    \let\next}
2443
2444% \def\math_text_choice_word#1#2#%
2445%   {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
2446%    \hbox#2\bgroup
2447%    \font_basics_switchtobodyfont\m_math_text_choice_face
2448%    #1%
2449%    \nospacing % \normalnospaces\plusone
2450%    \let\next}
2451
2452%D We accept a low level box specification so that one can make helpers:
2453%D
2454%D \startbuffer
2455%D \startformula
2456%D     \startalign[m=2,align={middle}]
2457%D         \NC \text to 6cm{One\hfill}           \NC a = 1 \NR
2458%D         \NC \text to 6cm{One Two\hfill}       \NC b = 2 \NR
2459%D         \NC \text to 6cm{One Two Three\hfill} \NC c = 3 \NR
2460%D     \stopalign
2461%D \stopformula
2462%D \stopbuffer
2463%D
2464%D \typebuffer \getbuffer
2465
2466\def\math_text_choice_font#1#2#%
2467  {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
2468   \hbox#2\bgroup
2469   \bgroup
2470   \aftergroup\hss
2471   \aftergroup\egroup
2472   \hss
2473   \font_basics_switchtobodyfont\m_math_text_choice_face
2474   #1%
2475   \let\next}
2476
2477\def\math_text_choice_word#1#2#%
2478  {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
2479   \hbox#2\bgroup
2480   \bgroup
2481   \aftergroup\hss
2482   \aftergroup\egroup
2483   \hss
2484   \font_basics_switchtobodyfont\m_math_text_choice_face
2485   #1%
2486   \nospacing % \normalnospaces\plusone
2487   \let\next}
2488
2489% \ruledhbox{$\mathtext{abc ffi}$}
2490% \ruledhbox{$\mathword{abc ffi}$}
2491
2492% I need to decide:
2493%
2494%mathscriptboxmode    \zerocount % no kerning
2495%mathscriptboxmode    \plusone   % lists
2496\mathscriptboxmode    \plustwo   % lists and boxes
2497\mathscriptcharmode   \plusone   % lists and boxes
2498%mathscriptboxmode    \plusthree % lists and boxes with \boundary=1 (also for testing and demo)
2499\mathrulethicknessmode\plusone   % adaptive
2500
2501\permanent\protected\def\mathtext  {\mathortext{\math_text_choice_font\relax}\hbox}
2502\permanent\protected\def\mathword  {\mathortext{\math_text_choice_word\relax}\hbox}
2503
2504\permanent\protected\def\mathtexttf{\mathortext{\math_text_choice_font\tf}\hbox}
2505\permanent\protected\def\mathtextit{\mathortext{\math_text_choice_font\it}\hbox}
2506\permanent\protected\def\mathtextsl{\mathortext{\math_text_choice_font\sl}\hbox}
2507\permanent\protected\def\mathtextbf{\mathortext{\math_text_choice_font\bf}\hbox}
2508\permanent\protected\def\mathtextbi{\mathortext{\math_text_choice_font\bi}\hbox}
2509\permanent\protected\def\mathtextbs{\mathortext{\math_text_choice_font\bs}\hbox}
2510
2511\permanent\protected\def\mathwordtf{\mathortext{\math_text_choice_word\tf}\hbox}
2512\permanent\protected\def\mathwordit{\mathortext{\math_text_choice_word\it}\hbox}
2513\permanent\protected\def\mathwordsl{\mathortext{\math_text_choice_word\sl}\hbox}
2514\permanent\protected\def\mathwordbf{\mathortext{\math_text_choice_word\bf}\hbox}
2515\permanent\protected\def\mathwordbi{\mathortext{\math_text_choice_word\bi}\hbox}
2516\permanent\protected\def\mathwordbs{\mathortext{\math_text_choice_word\bs}\hbox}
2517
2518%D Safeguard against redefinitions:
2519
2520\appendtoks
2521    \enforced\let\_\normalunderscore % is textunderscore or fakeunderscore
2522\to \everymathematics
2523
2524%D Because we may overload \type {\text} in other (structuring) macros, we say:
2525
2526\appendtoks
2527    \enforced\let\text\mathtext
2528\to \everymathematics
2529
2530%D The next code is derived from plain \TEX. The names will change!
2531
2532\newcount\interdisplaylinepenalty \interdisplaylinepenalty\plushundred
2533
2534% Actually, not using an if saves one macro so there is no penalty for splitting up
2535% this macro.
2536%
2537% \newif\ifdt@p
2538%
2539% \def\displ@y
2540%   {\global\dt@ptrue
2541%    \math_openup\displayopenupvalue % was \openup\jot
2542%    \everycr
2543%      {\noalign
2544%         {\ifdt@p
2545%            \global\dt@pfalse
2546%            \ifdim\prevdepth>-\thousandpoint
2547%              \vskip-\lineskiplimit
2548%              \vskip\normallineskiplimit
2549%            \fi
2550%          \else
2551%            \penalty\interdisplaylinepenalty
2552%          \fi}}}
2553
2554\newtoks\mathdisplayaligntweaks
2555
2556% this can become an option:
2557
2558\let\math_display_align_hack_indeed\relax
2559
2560\protected\def\math_display_align_hack % I don't like the global, maybe we should push and pop
2561  {\glet\math_display_align_hack_indeed\math_display_align_hack_remove_skip
2562   \math_openup\displayopenupvalue % was \math_openup\jot
2563   \everycr{\noalign{\math_display_align_hack_indeed}}}
2564
2565\def\math_display_align_hack_remove_skip
2566  {\ifdim\prevdepth>-\thousandpoint
2567     \vskip\dimexpr-\lineskiplimit+\normallineskiplimit\relax
2568   \fi
2569   \glet\math_display_align_hack_indeed\math_display_align_hack_insert_penalty}
2570
2571\def\math_display_align_hack_insert_penalty
2572  {\penalty\interdisplaylinepenalty}
2573
2574\appendtoks
2575    \math_display_align_hack
2576\to \mathdisplayaligntweaks
2577
2578%D Text in math:
2579
2580\permanent\protected\def\mathortext
2581  {\ifmmode
2582     \expandafter\firstoftwoarguments
2583   \else
2584     \expandafter\secondoftwoarguments
2585   \fi}
2586
2587% \defineactivecharacter _ {\mathortext{_}{\_}} text_text  $a^2$
2588
2589% force text mode, will be overloaded later
2590
2591\ifdefined\text\else \aliased\let\text\hbox \fi
2592
2593% \protected\def\mathoptext#1{\mathop{\text{#1}}}
2594
2595\permanent\protected\def\mathoptext
2596  {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
2597  %\showmathstyle
2598   \dowithnextbox
2599     {\mathop{\box\nextbox}}%
2600     \hbox\bgroup\font_basics_switchtobodyfont\m_math_text_choice_face\let\next}
2601
2602% new:
2603
2604% \startsetups math:morespacing
2605%     \Umathordordspacing\textstyle 1mu plus .5mu minus .25mu\relax
2606% \stopsetups
2607%
2608% \setupmathematics
2609%   [setups=math:morespacing]
2610
2611\appendtoks
2612    \edef\p_setups{\mathematicsparameter\c!setups}%
2613    \ifempty\p_setups\else
2614        \directsetup\p_setups
2615    \fi
2616\to \everyswitchmathematics
2617
2618% new:
2619
2620\permanent\protected\def\smallmathsymbol#1%
2621  {\mathematics{\mathbin{\normalexpanded{\raise.15\exheight\hbox{\normalstartimath
2622     \triggermathstyle{\the\numexpr\normalmathstyle+2\relax}#1%
2623   \normalstopimath}}}}}
2624
2625% this should be a primitive:
2626
2627\permanent\def\mathextensiblecode#1#2{\clf_extensiblecode\numexpr#1\relax\numexpr#2\relax} % todo: use public lua but needs testing
2628\permanent\def\mathhorizontalcode#1#2{\clf_horizontalcode\numexpr#1\relax\numexpr#2\relax} % todo: use public lua but needs testing
2629
2630% experimental:
2631
2632%D \starttyping
2633%D \enabletrackers[math.openedup]
2634%D
2635%D \dorecurse{10}{\dorecurse{#1}{whatever }}
2636%D
2637%D \startitemize[packed]
2638%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
2639%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
2640%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
2641%D \stopitemize
2642%D \startitemize[packed,columns]
2643%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
2644%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
2645%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
2646%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
2647%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
2648%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
2649%D \stopitemize
2650%D
2651%D \dorecurse{5}{\dorecurse{#1}{whatever }\openedupimath{\frac{1}{2}} }
2652%D
2653%D \startitemize[packed,columns]
2654%D     \startitem whatever \openedupimath{1+2} whatever
2655%D     \startitem whatever \openedupimath{1+2} whatever
2656%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
2657%D     \startitem whatever \openedupimath{1+2} whatever
2658%D     \startitem whatever \openedupimath{1+2} whatever
2659%D \stopitemize
2660%D
2661%D \dorecurse{5}{\dorecurse{#1}{whatever }\openedupimath{1+2} }
2662%D
2663%D \startitemize[packed]
2664%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
2665%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
2666%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
2667%D \stopitemize
2668%D
2669%D \dorecurse{10}{whatever }
2670%D \dorecurse {5}{\dorecurse{#1}{whatever }\openedupimath{\frac{1}{2}} }
2671%D \dorecurse{10}{whatever }
2672%D \stoptyping
2673
2674\def\m_math_inline_openup_ht{\dimexpr\ifinsidecolumns\strutdp\else\lineheight\fi/\plusfour\relax}
2675\def\m_math_inline_openup_dp{\dimexpr\ifinsidecolumns\strutdp\else\lineheight\fi/\plusfour\relax}
2676
2677% \def\m_math_inline_openup_ht{\dimexpr\lineheight/\ifinsidecolumns\pluseight\else\plusfour\fi\relax}
2678% \def\m_math_inline_openup_dp{\dimexpr\lineheight/\ifinsidecolumns\pluseight\else\plusfour\fi\relax}
2679
2680\installtextracker
2681  {math.openedup}
2682  {\let\math_inline_openup_start_yes\math_inline_openup_traced_start}
2683  {\let\math_inline_openup_start_yes\math_inline_openup_normal_start}
2684
2685\protected\def\math_inline_openup_normal_start
2686  {\scratchheight\dimexpr\ht\scratchbox+\m_math_inline_openup_ht\relax
2687   \scratchdepth \dimexpr\dp\scratchbox+\m_math_inline_openup_dp\relax
2688   \vrule\s!width\zeropoint\s!height\scratchheight\s!depth\scratchdepth\relax
2689   \begingroup
2690   \let\math_inline_openup_stop\math_inline_openup_normal_stop}
2691
2692\protected\def\math_inline_openup_normal_stop
2693   {\endgroup
2694    \vrule\s!width\zeropoint\s!height\scratchheight\s!depth\scratchdepth\relax}
2695
2696\protected\def\math_inline_openup_traced_start
2697  {\scratchtopoffset   \ht\scratchbox
2698   \scratchbottomoffset\dp\scratchbox
2699   \scratchheight      \dimexpr\scratchtopoffset   +\m_math_inline_openup_ht\relax
2700   \scratchdepth       \dimexpr\scratchbottomoffset+\m_math_inline_openup_dp\relax
2701   \vrule\s!width\zeropoint\s!height\scratchheight\s!depth\scratchdepth\relax
2702   \begingroup
2703     \dousecolorparameter{darkred}%
2704     \vrule\s!width\emwidth\s!height\scratchheight\s!depth-\scratchtopoffset\relax
2705   \endgroup
2706   \kern-\emwidth
2707   \begingroup
2708   \let\math_inline_openup_stop\math_inline_openup_traced_stop}
2709
2710\protected\def\math_inline_openup_traced_stop
2711  {\endgroup
2712   \kern-\emwidth
2713   \begingroup
2714     \dousecolorparameter{darkblue}%
2715     \vrule\s!width\emwidth\s!height-\scratchbottomoffset\s!depth\scratchdepth\relax
2716   \endgroup
2717   \vrule\s!width\zeropoint\s!height\scratchheight\s!depth\scratchdepth\relax}
2718
2719\let\math_inline_openup_start_yes\math_inline_openup_normal_start
2720\let\math_inline_openup_stop     \relax
2721
2722\def\math_inline_openup_start_nop
2723  {\let\math_inline_openup_stop\relax}
2724
2725\permanent\protected\def\openedupimath
2726  {\dontleavehmode
2727   \begingroup
2728   \ifmmode
2729     \expandafter\openedupimath_math
2730   \else
2731     \expandafter\openedupimath_text
2732   \fi}
2733
2734\protected\def\openedupimath_math#1%
2735  {\setbox\scratchbox\mathstylehbox{#1}%
2736   \ifdim\ht\scratchbox>\strutht
2737     \math_inline_openup_start_yes
2738   \orelse\ifdim\dp\scratchbox>\strutdp
2739     \math_inline_openup_start_yes
2740   \else
2741     \math_inline_openup_start_nop
2742   \fi
2743   #1%
2744   \math_inline_openup_stop
2745   \endgroup}
2746
2747\protected\def\openedupimath_text#1%
2748  {\setbox\scratchbox\hbox{\startimath#1\stopimath}%
2749   \ifdim\ht\scratchbox>\strutht
2750     \math_inline_openup_start_yes
2751   \orelse\ifdim\dp\scratchbox>\strutdp
2752     \math_inline_openup_start_yes
2753   \else
2754     \math_inline_openup_start_nop
2755   \fi
2756   \startimath
2757   #1%
2758   \stopimath
2759   \math_inline_openup_stop
2760   \endgroup}
2761
2762% Also handy, especially for units:
2763%
2764% 0x002B=plus 0x2212=minus 0x2013=endash
2765
2766\permanent\protected\def\mathplus     {+}
2767\permanent\protected\def\mathminus    {\ifmmode \orelse\iffontchar\font`−−\else \fi}
2768\permanent\protected\def\mathplusminus{±}
2769
2770%D The \type {\displaywidth} is only known inside a display formula, so we need to catch
2771%D it when still zero.
2772
2773\permanent\def\checkeddisplaywidth % hsize if zero
2774  {\dimexpr
2775     \ifzeropt\displaywidth
2776       \hsize
2777     \else
2778       \displaywidth
2779     \fi
2780   \relax}
2781
2782\permanent\def\maximizeddisplaywidth % larger than zero but within hsize
2783  {\dimexpr
2784     \ifzeropt\displaywidth
2785       \hsize
2786     \orelse\ifdim\displaywidth>\hsize
2787        \hsize
2788     \else
2789       \displaywidth
2790     \fi
2791   \relax}
2792
2793%D Experiment: (todo: same switch as italic, using \type {\everyswitchmathematics}).
2794
2795\newcount\c_math_domain_attribute
2796
2797\def\math_domain_initialize
2798  {\ifnum\c_math_domain_attribute=\attributeunsetvalue \else
2799     \clf_initializemathdomain % one time
2800     \glet\math_domain_initialize\relax
2801   \fi}
2802
2803\appendtoks
2804    \edef\p_domain{\mathematicsparameter\c!domain}%
2805    \ifempty\p_domain
2806        \c_math_domain_attribute\attributeunsetvalue
2807    \else
2808        \c_math_domain_attribute\clf_getmathdomain\p_domain\relax
2809        \math_domain_initialize
2810    \fi
2811\to \everyswitchmathematics % only in mathematics
2812
2813\appendtoks
2814    \c_attr_mathdomain\c_math_domain_attribute
2815\to \everymathematics
2816
2817\setupmathematics
2818  [\s!italics=3] % for the moment only this one makes sense .. still experimental
2819
2820%D For special purposed we set this one:
2821
2822\installcorenamespace{mathrules}
2823
2824\permanent\protected\def\enablemathrules{\letgvalue{\??mathrules\fontclass}\plusone}
2825
2826\appendtoks
2827    \mathrulesmode\ifcsname\??mathrules\fontclass\endcsname
2828      \lastnamedcs
2829    \else
2830      \zerocount
2831    \fi
2832    \mathrulesfam\zerocount
2833\to \everymathematics
2834
2835%D Maybe:
2836
2837% \starttabulate[|||c|c|]
2838% \BC positive                            \BC negative                               \BC text                           \BC math \NC \NR
2839% \NC \tex {f1} \tex {hairspace}  \tex{,} \NC \tex {b1} \tex {neghairspace}          \NC {\darkred\vl}\f1{\darkblue\vl} \NC ${\darkred\vl}\f1{\darkblue\vl}$ \NC \NR
2840% \NC \tex {f2} \tex {thinspace}  \tex{:} \NC \tex {b2} \tex {negthinspace}  \tex{!} \NC {\darkred\vl}\f2{\darkblue\vl} \NC ${\darkred\vl}\f2{\darkblue\vl}$ \NC \NR
2841% \NC \tex {f3} \tex {medspace}   \tex{;} \NC \tex {b3} \tex {negmedspace}           \NC {\darkred\vl}\f3{\darkblue\vl} \NC ${\darkred\vl}\f3{\darkblue\vl}$ \NC \NR
2842% \NC \tex {f4} \tex {thickspace}         \NC \tex {b4} \tex {negthickspace}         \NC {\darkred\vl}\f4{\darkblue\vl} \NC ${\darkred\vl}\f4{\darkblue\vl}$ \NC \NR
2843% \NC \tex {f5} \tex {enspace}            \NC \tex {b5}                              \NC {\darkred\vl}\f5{\darkblue\vl} \NC ${\darkred\vl}\f5{\darkblue\vl}$ \NC \NR
2844% \NC \tex {f6} \tex {emspace}            \NC \tex {b6}                              \NC {\darkred\vl}\f6{\darkblue\vl} \NC ${\darkred\vl}\f6{\darkblue\vl}$ \NC \NR
2845% \stoptabulate
2846
2847% \protected\def\negenspace{\kern-.5\emwidth}
2848% \protected\def\negemspace{\kern-  \emwidth}
2849%
2850% \protected\def\math_f#1%
2851%   {\ifcase#1\or
2852%      \hairspace
2853%    \or
2854%      \thinspace
2855%    \or
2856%      \medspace
2857%    \or
2858%      \thickspace
2859%    \or
2860%      \enspace
2861%    \or
2862%      \emspace
2863%    \fi}
2864%
2865% \protected\def\math_b#1%
2866%   {\ifcase#1\or
2867%      \neghairspace
2868%    \or
2869%      \negthinspace
2870%    \or
2871%      \negmedspace
2872%    \or
2873%      \negthickspace
2874%    \or
2875%      \negenspace
2876%    \or
2877%      \negemspace
2878%    \fi}
2879%
2880% \appendtoks
2881%     \let\f\math_f
2882%     \let\b\math_b
2883% \to \everymathematics
2884
2885%D Experiment
2886
2887\permanent\protected\def\math_scripts_stack
2888  {\c_attr_mathunstack\attributeunsetvalue}
2889
2890\permanent\protected\def\math_scripts_unstack
2891  {\clf_enablescriptunstacking
2892   \c_attr_mathunstack\plusone}
2893
2894\ifdefined\stackscripts   \else \aliased\let\stackscripts  \relax \fi
2895\ifdefined\unstackscripts \else \aliased\let\unstackscripts\relax \fi
2896
2897\appendtoks
2898    \enforced\let\stackscripts  \math_scripts_stack
2899    \enforced\let\unstackscripts\math_scripts_unstack
2900\to \everymathematics
2901
2902%D Expensive (tracing and inject) but a primitive (using factors) is tricky as we
2903%D want this frozen support.
2904
2905% \def\math_openup_parameter#1#2%
2906%   {\ifzeropt#1\displaystyle            \orelse\ifdim#1\displaystyle            =\maxdimen\else\frozen#1\displaystyle            #2#1\displaystyle            \fi
2907%    \ifzeropt#1\crampeddisplaystyle     \orelse\ifdim#1\crampeddisplaystyle     =\maxdimen\else\frozen#1\crampeddisplaystyle     #2#1\crampeddisplaystyle     \fi
2908%    \ifzeropt#1\textstyle               \orelse\ifdim#1\textstyle               =\maxdimen\else\frozen#1\textstyle               #2#1\textstyle               \fi
2909%    \ifzeropt#1\crampedtextstyle        \orelse\ifdim#1\crampedtextstyle        =\maxdimen\else\frozen#1\crampedtextstyle        #2#1\crampedtextstyle        \fi
2910%    \ifzeropt#1\scriptstyle             \orelse\ifdim#1\scriptstyle             =\maxdimen\else\frozen#1\scriptstyle             #2#1\scriptstyle             \fi
2911%    \ifzeropt#1\crampedscriptstyle      \orelse\ifdim#1\crampedscriptstyle      =\maxdimen\else\frozen#1\crampedscriptstyle      #2#1\crampedscriptstyle      \fi
2912%    \ifzeropt#1\scriptscriptstyle       \orelse\ifdim#1\scriptscriptstyle       =\maxdimen\else\frozen#1\scriptscriptstyle       #2#1\scriptscriptstyle       \fi
2913%    \ifzeropt#1\crampedscriptscriptstyle\orelse\ifdim#1\crampedscriptscriptstyle=\maxdimen\else\frozen#1\crampedscriptscriptstyle#2#1\crampedscriptscriptstyle\fi}
2914
2915% \def\mdim#1#2%
2916%   {\ifcase\ifzeropt#1#2\plusone\orelse\ifdim#1#2=\maxdimen\plusone\else\zerocount\fi}
2917%
2918% \def\mdim
2919%   {\afterassignment\mmdim\scratchdimen}
2920%
2921% \def\mmdim
2922%   {\ifcase\ifzeropt\scratchdimen\plusone\orelse\ifdim\scratchdimen=\maxdimen\plusone\else\zerocount\fi}
2923%
2924% \def\math_openup_parameter#1#2%
2925%   {\ifcondition\mdim#1\displaystyle            \frozen#1\displaystyle            #2\dimexpr#1\displaystyle            \relax\fi
2926%    \ifcondition\mdim#1\crampeddisplaystyle     \frozen#1\crampeddisplaystyle     #2\dimexpr#1\crampeddisplaystyle     \relax\fi
2927%    \ifcondition\mdim#1\textstyle               \frozen#1\textstyle               #2\dimexpr#1\textstyle               \relax\fi
2928%    \ifcondition\mdim#1\crampedtextstyle        \frozen#1\crampedtextstyle        #2\dimexpr#1\crampedtextstyle        \relax\fi
2929%    \ifcondition\mdim#1\scriptstyle             \frozen#1\scriptstyle             #2\dimexpr#1\scriptstyle             \relax\fi
2930%    \ifcondition\mdim#1\crampedscriptstyle      \frozen#1\crampedscriptstyle      #2\dimexpr#1\crampedscriptstyle      \relax\fi
2931%    \ifcondition\mdim#1\scriptscriptstyle       \frozen#1\scriptscriptstyle       #2\dimexpr#1\scriptscriptstyle       \relax\fi
2932%    \ifcondition\mdim#1\crampedscriptscriptstyle\frozen#1\crampedscriptscriptstyle#2\dimexpr#1\crampedscriptscriptstyle\relax\fi}
2933
2934% \ifmathparameter : 0=zero, 1=set, 2=unset (les stracing clutter this way)
2935
2936%D New stuff:
2937%D
2938%D \starttyping
2939%D $\mathopenupparameter\Umathradicalvgap{10.5}\sqrt[3]{x}$
2940%D \stoptyping
2941
2942\permanent\protected\def\mathopenupparameter#1#2%
2943  {\ifmathparameter#1\displaystyle            \or\frozen#1\displaystyle            #2#1\displaystyle            \fi
2944   \ifmathparameter#1\crampeddisplaystyle     \or\frozen#1\crampeddisplaystyle     #2#1\crampeddisplaystyle     \fi
2945   \ifmathparameter#1\textstyle               \or\frozen#1\textstyle               #2#1\textstyle               \fi
2946   \ifmathparameter#1\crampedtextstyle        \or\frozen#1\crampedtextstyle        #2#1\crampedtextstyle        \fi
2947   \ifmathparameter#1\scriptstyle             \or\frozen#1\scriptstyle             #2#1\scriptstyle             \fi
2948   \ifmathparameter#1\crampedscriptstyle      \or\frozen#1\crampedscriptstyle      #2#1\crampedscriptstyle      \fi
2949   \ifmathparameter#1\scriptscriptstyle       \or\frozen#1\scriptscriptstyle       #2#1\scriptscriptstyle       \fi
2950   \ifmathparameter#1\crampedscriptscriptstyle\or\frozen#1\crampedscriptscriptstyle#2#1\crampedscriptscriptstyle\fi}
2951
2952%D New stuff:
2953%D
2954%D \startbuffer
2955%D $x\mathopen   {!}+123+\mathclose  {!}x$
2956%D $x\tomathopen  ! +123+\tomathclose ! x$
2957%D $x\mathclose  {!}+123+\mathopen   {!}x$
2958%D $x\tomathclose ! +123+\tomathopen  ! x$
2959%D $x             ! +123+             ! x$
2960%D \stopbuffer
2961%D
2962%D \typebuffer
2963%D
2964%D \startlines
2965%D \getbuffer
2966%D \stoplines
2967
2968\permanent\protected\def\tomathord  {\Umathclass\zerocount}
2969\permanent\protected\def\tomathop   {\Umathclass\plusone  } % \mathinfix
2970\permanent\protected\def\tomathbin  {\Umathclass\plustwo  }
2971\permanent\protected\def\tomathrel  {\Umathclass\plusthree}
2972\permanent\protected\def\tomathopen {\Umathclass\plusfour } % \mathprefix
2973\permanent\protected\def\tomathclose{\Umathclass\plusfive } % \mathsuffix
2974\permanent\protected\def\tomathpunct{\Umathclass\plussix  }
2975
2976%D Prescripts. These work in \CONTEXT\ because we have the super- and subscript
2977%D triggers enabled as active characters but when we would have
2978%D
2979%D \starttyping
2980%D \catcode\underscoreasciicode\subscriptcatcode
2981%D \catcode\circumflexasciicode\superscriptcatcode
2982%D \stoptyping
2983%D
2984%D we also need the next line to disable character escaping via \type {^} in
2985%D math mode:
2986%D
2987%D \startbuffer
2988%D \blank \hbox{
2989%D     \ruledhbox{${\tf X} ^1 _2 ^^3 __4$}
2990%D     \ruledhbox{${\tf X} ^1           $}
2991%D     \ruledhbox{${\tf X}    _2        $}
2992%D     \ruledhbox{${\tf X}       ^^3    $}
2993%D     \ruledhbox{${\tf X}           __4$}
2994%D     \ruledhbox{${\tf X} ^1 _2        $}
2995%D     \ruledhbox{${\tf X} ^1    ^^3    $}
2996%D     \ruledhbox{${\tf X} ^1        __4$}
2997%D     \ruledhbox{${\tf X}    _2 ^^3    $}
2998%D     \ruledhbox{${\tf X}    _2     __4$}
2999%D     \ruledhbox{${\tf X} ^1 _2 ^^3    $}
3000%D     \ruledhbox{${\tf X} ^1 _2     __4$}
3001%D     \ruledhbox{${\tf X}    _2 ^^3    $}
3002%D     \ruledhbox{${\tf X}    _2 ^^3 __4$}
3003%D     \ruledhbox{${\tf X}       ^^3 __4$}
3004%D } \blank
3005%D
3006%D \typebuffer \getbuffer
3007
3008\normalsupmarkmode\plusone % 2 also disable ^[^+] in text mode
3009
3010\permanent\protected\tolerant\def\supscr[#1]#:#2%
3011  {\ifchkdim#1\or\Umathopenupheight#1\relax\fi
3012   \Usuperscript{#2}}
3013
3014\permanent\protected\tolerant\def\subscr[#1]#:#2%
3015  {\ifchkdim#1\or\Umathopenupdepth #1\relax\fi
3016   \Usubscript{#2}}
3017
3018\permanent\protected\tolerant\def\supsubscr[#1]#:#2#3%
3019  {\ifchkdim#1\or\Umathopenupheight#1\relax\Umathopenupdepth#1\relax\fi
3020   \Usuperscript{#2}\Usubscript{#3}}
3021
3022\permanent\protected\tolerant\def\subsupscr[#1]#:#*#2#3%
3023  {\ifchkdim#1\or\Umathopenupheight#1\relax\Umathopenupdepth#1\relax\fi
3024   \Usubscript{#2}\Usuperscript{#3}}
3025
3026\permanent\protected\tolerant\def\supprescr[#1]#:#2%
3027  {\ifchkdim#1\or\Umathopenupheight#1\relax\fi
3028   \Usuperprescript{#2}}
3029
3030\permanent\protected\tolerant\def\subprescr[#1]#:#2%
3031  {\ifchkdim#1\or\Umathopenupdepth #1\relax\fi
3032   \Usubprescript{#2}}
3033
3034\permanent\protected\tolerant\def\supsubprescr[#1]#:#2#3%
3035  {\ifchkdim#1\or\Umathopenupheight#1\relax\Umathopenupdepth#1\relax\fi
3036   \Usuperprescript{#2}\Usubprescript{#3}}
3037
3038\permanent\protected\tolerant\def\subsupprescr[#1]#:#*#2#3%
3039  {\ifchkdim#1\or\Umathopenupheight#1\relax\Umathopenupdepth#1\relax\fi
3040   \Usubprescript{#2}\Usuperprescript{#3}}
3041
3042%D For now (needed in asciimath):
3043
3044\def\math_relax_limits{\enforced\let\limits\relax}
3045
3046\protect \endinput
3047
3048% % not used (yet)
3049%
3050% \newtoks \everystartimath
3051% \newtoks \everystopimath
3052%
3053% \protected\def\startimath{\Ustartmath\the\everystartimath}
3054% \protected\def\stopimath {\the\everystopimath\Ustopmath}
3055%
3056% \protected\def\m%
3057%   {\relax
3058%    \ifmmode\expandafter\math_m_stay\else\expandafter\math_m_math\fi}
3059%
3060% \protected\def\math_m_math#1%
3061%   {\startimath#1\stopimath}
3062%
3063% \let\math_m_stay\firstofoneargument
3064