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