%D \module
%D   [       file=math-ini,
%D        version=2008.01.02,
%D          title=\CONTEXT\ Math Macros,
%D       subtitle=Initializations,
%D         author={Hans Hagen \& Mikael Sundqvist},
%D           date=\currentdate,
%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

\writestatus{loading}{ConTeXt Math Macros / Initializations}

% Needs checking:
%
% \Umathruleheight
% \Umathruledepth
% \Umathfractionnumup
% \Umathfractionnumdown
% \Umathfractiondelsize
% \Umathskeweddelimitertolerance

%D This is the \LMTX\ version of math support what evolved over decades. We started
%D out with native display math, battled for years with the heuristic spacing,
%D assumptions wrt number locations etc. Advanced alignments were implemented with
%D the help of Aditya. In \MKIV\ everything got upgraded, and we ended up with three
%D models for spacing and numbering: traditional (display), improved (using some
%D \LUATEX\ control options), and future (using emulated display) where we also
%D could handle multi|-|line formulas well. As \LUAMETATEX\ evolved it became clear
%D that we should drop the first two models completely and stick to the emulated
%D display mode combined with the ability to format multi|-|line formulas in greater
%D detail.
%D
%D One can wonder what this does with compatibility. Of course we try to be
%D interface compatible but better micro typography spacing has consequences.
%D However, in practice it looks like we get better results without too many side
%D effects. Also, we're not bound to for instance \AMS\ math because \CONTEXT\ is
%D not used by scientific publishers. In fact over the 15 plus years of development
%D (2022), no professional publisher (or large scale \TEX\ user) ever expressed
%D interest in \LUATEX\ and \LUAMETATEX, definitely not in relation to math, which
%D made it even more easy to upgrade the engine as well as \CONTEXT\ math and over
%D time users have demonstrated to appreciate improvements. We can do as we like, as
%D long as users like it too. It's with that mindset that Mikael Sundqvist and I
%D undertook this effort which took a year to mature. It started out with
%D implementing advanced spacing models based on inter|-|atom properties and control
%D but stepwise more got added and improved. We also settled on the fact that fonts
%D will never be perfect and that we need runtime fixing. That took some work but in
%D the end put less burden on the engine.
%D
%D After an extremely short discussion MS and HH decided that we will not support
%D \quote {BS ISO 80000-2:2009} because it doesn't comply to the CMS quality
%D standards and is BS anyway.

%D Musical timestamp for the April 2022 math (inline) snapping sub activity: eNerd⁴
%D Time Capsule 2020 a.k.a. Farewell Party for Normalcy (DSD on the squeezebox with
%D a proper DAC connected but it can hardly keep up which also counts for me with MS
%D testing faster than I can provide variants (www.youtube.com/watch?v=xzQCqAJNOSM).

\unprotect

\newdimension   \mathstrutht
\newdimension   \mathstrutdp
\newinteger     \mathnestinglevel

\newcount       \c_math_strc_hangafter
\newdimen       \d_math_strc_hangindent

\newcount       \c_strc_math_n_of_lines

\newdimension   \d_strc_math_max_right
\newdimension   \d_strc_math_first_right
\newdimension   \d_strc_math_last_right

\newdimension   \d_strc_math_max_left
\newdimension   \d_strc_math_first_left
\newdimension   \d_strc_math_last_left

\newdimension   \d_strc_math_first_height
\newdimension   \d_strc_math_last_depth

\newdimension   \d_strc_math_display_width
\newdimension   \d_strc_math_indent
\newconditional \c_strc_math_indent

\newdimension   \d_strc_math_left_shift
\newdimension   \d_strc_math_right_shift

\newinteger     \currentmathblob
\newinteger     \currentmathblobnesting % could be a primitive

\newconditional \c_math_extensibles \c_math_extensibles\conditionaltrue

\newboundary    \c_math_display_mode_boundary % experiment, saves attributes

\registerctxluafile{math-ini}{autosuffix}
\registerctxluafile{math-dim}{autosuffix}
%registerctxluafile{math-act}{autosuffix}
\registerctxluafile{math-ext}{autosuffix} % might go
\registerctxluafile{math-vfu}{autosuffix}
%registerctxluafile{math-ttv}{autosuffix} % save no time, only memory
\registerctxluafile{math-map}{autosuffix}
\registerctxluafile{math-act}{autosuffix}
\registerctxluafile{math-ren}{autosuffix}
\registerctxluafile{math-noa}{autosuffix}
\registerctxluafile{math-tag}{autosuffix}
\registerctxluafile{math-fbk}{autosuffix}
%registerctxluafile{math-dir}{autosuffix}
\registerctxluafile{math-spa}{autosuffix}
\registerctxluafile{math-fnt}{autosuffix}
\registerctxluafile{math-pre}{autosuffix}
\registerctxluafile{math-txt}{autosuffix}

%D Some neat units:

\aliased\let\Umathemwidth\Umathquad

\protected\def\mathaxisunit    {\scaledmathaxis    \mathstyle\norelax}
\protected\def\mathexheightunit{\scaledmathexheight\mathstyle\norelax}
\protected\def\mathquadunit    {\scaledmathemwidth \mathstyle\norelax}

\newuserunit \mathaxisunit     ma
\newuserunit \mathexheightunit mx
\newuserunit \mathquadunit     mq

%D Basic spacing:

% \mathfencesmode \plusone % gone

\delimiterfactor    \plusthousand
\delimitershortfall \zeropoint

%D Low level only:

% \fixedsuperorsubscriptsmodecode
% \fixedsuperandsubscriptsmodecode
%
% Needed for multiple scripts:
%
% \mathscriptsmode\ignoreemptyscriptsmodecode

\integerdef\ignoreemptyscriptsmodecode\numexpr
    \ignoreemptysuperscriptsmodecode
  + \ignoreemptysubscriptsmodecode
  + \ignoreemptyprimescriptsmodecode
\relax

\mathscriptsmode\ignoreemptyscriptsmodecode % we default to this but in manuals we can set it to zero

% These need to be set because otherwise the engine will not honor some font
% properties. It also permits tracing. These might become engine defaults. As a
% consequence we no longer check for traditional fonts but one can use font control
% options.

% \mathcontrolmode\plusone

\mathfontcontrol\numexpr
    \zerocount
   +\overrulemathcontrolcode                % let the node family/font win over current family/font
   +\underrulemathcontrolcode               % idem
   +\radicalrulemathcontrolcode             % idem
   +\fractionrulemathcontrolcode            % idem
   +\accentskewhalfmathcontrolcode          % fall back to half width skewing when no topaccent is given
   +\accentskewapplymathcontrolcode         % use topaccent, otherwise use skew char
   +\applyordinarykernpairmathcontrolcode   % old fonts
   +\applyverticalitalickernmathcontrolcode % best do this indeed
   +\applyordinaryitalickernmathcontrolcode % best do this indeed
 % +\applycharitalickernmathcontrolcode     % not done
 % +\reboxcharitalickernmathcontrolcode     % old code path
   +\applyboxeditalickernmathcontrolcode    % best do this indeed
   +\staircasekernmathcontrolcode           % use these when set
   +\applytextitalickernmathcontrolcode
   +\checktextitalickernmathcontrolcode
 % +\checkspaceitalickernmathcontrolcode    % old code path
   +\applyscriptitalickernmathcontrolcode
 % +\italicshapekernmathcontrolcode         % obsolete: instead of adding pre italic to the shift, inject a kern
   +\analyzescriptnucleuscharmathcontrolcode
   +\analyzescriptnucleuslistmathcontrolcode
   +\analyzescriptnucleusboxmathcontrolcode
   +\accenttopskewwithoffsetmathcontrolcode
 % +\ignorekerndimensionsmathcontrolcode    % xits needs this (bad depth of fences)
 % +\ignoreflataccentsmathcontrolcode
   +\extendaccentsmathcontrolcode
   +\extenddelimitersmathcontrolcode
\relax

% \mathpenaltiesmode\plusone

% These are frozen values because otherwise we need to sync them when the predefined
% muskip (internal) registers are changed.

\permanent\immutable\mugluespecdef\defaultthickermuskip    7mu plus 5mu
\permanent\immutable\mugluespecdef\defaultthickmuskip      5mu plus 3mu minus 1mu
\permanent\immutable\mugluespecdef\defaultmedmuskip        4mu plus 2mu minus 2mu
\permanent\immutable\mugluespecdef\defaultthinmuskip       3mu
\permanent\immutable\mugluespecdef\defaulttinymuskip       2mu minus 1mu
\permanent\immutable\mugluespecdef\defaultpettymuskip      1mu minus 0.5mu

\permanent\immutable\mugluespecdef\halfthickmuskip         2.5mu plus 1.5mu minus 0.5mu
\permanent\immutable\mugluespecdef\halfmedmuskip           2mu plus 1mu minus 1mu
\permanent\immutable\mugluespecdef\halfthinmuskip          1.5mu
\permanent\immutable\mugluespecdef\halftinymuskip          1mu minus 0.5mu
\permanent\immutable\mugluespecdef\halfpettymuskip         0.5mu minus 0.25mu

\permanent\immutable\mugluespecdef\hairmuskip                .15mu

\permanent\immutable\integerdef   \defaultrelpenalty       500
\permanent\immutable\integerdef   \defaultbinoppenalty     700
\permanent\immutable\integerdef   \defaultprerelpenalty   -100
\permanent\immutable\integerdef   \defaultprebinoppenalty -100

\newmuskip\thickermuskip      \thickermuskip      \defaultthickermuskip
\newmuskip\fencemuskip        \fencemuskip        \defaultpettymuskip
\newmuskip\continuationmuskip \continuationmuskip \zeromuskip

% Handy

\setnewconstant\mathstylevariantidentity  "01234567
\setnewconstant\mathstylevariantcramped   "11335577
\setnewconstant\mathstylevariantuncramped "00224466

% Beware: we don't support mathinner any longer. We do have construct, wrapper, ellipsis etc
% as replacements and all inner spacing is basically unset.

\setnewconstant\mathallcode             \mathclassvalue all
\setnewconstant\mathbegincode           \mathclassvalue begin
\setnewconstant\mathendcode             \mathclassvalue end
\setnewconstant\mathunsetcode           \mathclassvalue unset

\setnewconstant\mathordinarycode        \mathclassvalue ordinary         \aliased\let\mathordcode  \mathordinarycode
\setnewconstant\mathoperatorcode        \mathclassvalue operator         \aliased\let\mathopcode   \mathoperatorcode
\setnewconstant\mathbinarycode          \mathclassvalue binary           \aliased\let\mathbincode  \mathbinarycode
\setnewconstant\mathrelationcode        \mathclassvalue relation         \aliased\let\mathrelcode  \mathrelationcode
\setnewconstant\mathopencode            \mathclassvalue open
\setnewconstant\mathclosecode           \mathclassvalue close
\setnewconstant\mathpunctuationcode     \mathclassvalue punctuation      \aliased\let\mathpunctcode\mathpunctuationcode
\setnewconstant\mathvariablecode        \mathclassvalue variable
\setnewconstant\mathactivecode          \mathclassvalue active
\setnewconstant\mathinnercode           \mathclassvalue inner
\setnewconstant\mathundercode           \mathclassvalue under
\setnewconstant\mathovercode            \mathclassvalue over
\setnewconstant\mathfractioncode        \mathclassvalue fraction
\setnewconstant\mathradicalcode         \mathclassvalue radical
\setnewconstant\mathmiddlecode          \mathclassvalue middle
\setnewconstant\mathprimecode           \mathclassvalue prime
\setnewconstant\mathaccentcode          \mathclassvalue accent
\setnewconstant\mathfencedcode          \mathclassvalue fenced          % unlikely to be seen but can be used
\setnewconstant\mathghostcode           \mathclassvalue ghost           % transparent for classes
\setnewconstant\mathvcentercode         \mathclassvalue vcenter
\setnewconstant\mathexplicitcode        \mathclassvalue explicit        % only for for control
\setnewconstant\mathimaginarycode       \mathclassvalue imaginary
\setnewconstant\mathdifferentialcode    \mathclassvalue differential
\setnewconstant\mathexponentialcode     \mathclassvalue exponential
\setnewconstant\mathintegralcode        \mathclassvalue integral
\setnewconstant\mathellipsiscode        \mathclassvalue ellipsis        % replacement for inner
\setnewconstant\mathfunctioncode        \mathclassvalue function
\setnewconstant\mathdigitcode           \mathclassvalue digit
\setnewconstant\mathdivisioncode        \mathclassvalue division
\setnewconstant\mathfactorialcode       \mathclassvalue factorial
\setnewconstant\mathwrappedcode         \mathclassvalue wrapped         % replacement for inner
\setnewconstant\mathconstructcode       \mathclassvalue construct       % replacement for inner
\setnewconstant\mathdimensioncode       \mathclassvalue dimension
\setnewconstant\mathunarycode           \mathclassvalue unary           % dedicated to Alan
\setnewconstant\mathtextpunctuationcode \mathclassvalue textpunctuation % for punctuation in text font followed by interword spacing
\setnewconstant\mathunspacedcode        \mathclassvalue unspaced        % for cases where we don't want spacing at all
\setnewconstant\mathexperimentalcode    \mathclassvalue experimental    % for MS and HH testing purposed only
\setnewconstant\mathfakecode            \mathclassvalue fake
\setnewconstant\mathnumbergroupcode     \mathclassvalue numbergroup
\setnewconstant\mathcontinuationcode    \mathclassvalue continuation

%D Here we had a curious overload: mathnumbergroupcode was also defined in
%D toks-ini/aux so it was an engine thing that I then decide to rename to
%D equationnumbergroup to make life easier.

%D \starttyping
%D \enabletrackers[math.suspicious]
%D
%D \Umathchardef \foo \mathmaybeordinarycode 0 `o
%D \Umathchardef \oof \mathmayberelationcode 0 `=
%D \Umathchardef \ofo \mathmaybebinarycode   0 `+
%D
%D \starttext
%D     $ \foo _ 1 \ofo \foo _ 2 \oof \foo _ 3 + 4 $
%D \stoptext
%D \stoptyping
%D
%D Gives:
%D
%D \starttyping
%D mathematics     > suspicious > class 36, U+1D45C 𝑜
%D mathematics     > suspicious > class 38, U+0002B +
%D mathematics     > suspicious > class 37, U+0003D =
%D \stoptyping

\setnewconstant\mathmaybeordinarycode \mathclassvalue maybeordinary
\setnewconstant\mathmayberelationcode \mathclassvalue mayberelation
\setnewconstant\mathmaybebinarycode   \mathclassvalue maybebinary

%D Chemistry

\setnewconstant\mathchemicalbondcode  \mathclassvalue chemicalbond
\setnewconstant\mathimplicationcode   \mathclassvalue implication

%setnewconstant\mathtopaccentcode     \mathclassvalue topaccent    % these are private and above 31
%setnewconstant\mathbottomaccentcode  \mathclassvalue bottomaccent % these are private and above 31
%setnewconstant\mathdelimitercode     \mathclassvalue delimiter    % these are private and above 31
%setnewconstant\mathrootcode          \mathclassvalue root         % these are private and above 31
%setnewconstant\mathprimecode         \mathclassvalue prime        % these are private and above 31

%letmathspacing \mathimaginarycode    \mathordinarycode \mathordinarycode \mathordinarycode \mathordinarycode
%letmathspacing \mathdifferentialcode \mathordinarycode \mathordinarycode \mathordinarycode \mathordinarycode
%letmathspacing \mathexponentialcode  \mathordinarycode \mathordinarycode \mathordinarycode \mathordinarycode
%letmathspacing \mathfunctioncode     \mathordinarycode \mathordinarycode \mathordinarycode \mathordinarycode
%letmathspacing \mathdigitcode        \mathordinarycode \mathordinarycode \mathordinarycode \mathordinarycode

\copymathspacing \mathimaginarycode      \mathordinarycode
\copymathspacing \mathdifferentialcode   \mathordinarycode
\copymathspacing \mathfactorialcode      \mathordinarycode
\copymathspacing \mathexponentialcode    \mathordinarycode
\copymathspacing \mathintegralcode       \mathoperatorcode
\copymathspacing \mathdigitcode          \mathordinarycode
\copymathspacing \mathfunctioncode       \mathoperatorcode
\copymathspacing \mathwrappedcode        \mathfractioncode
\copymathspacing \mathunarycode          \mathordinarycode

\copymathspacing \mathvariablecode       \mathordinarycode

\copymathspacing \mathmaybeordinarycode  \mathordinarycode
\copymathspacing \mathmayberelationcode  \mathrelationcode
\copymathspacing \mathmaybebinarycode    \mathbinarycode

%copymathspacing \mathnumbergroupcode    \mathpunctuationcode
\copymathspacing \mathnumbergroupcode    \mathrelationcode     % for now

\copymathspacing \mathchemicalbondcode   \mathordinarycode
\copymathspacing \mathimplicationcode    \mathrelationcode

\setnewconstant\mathlimopcode \plusone % these will go away
\setnewconstant\mathnolopcode \plusone % these will go away

\pushoverloadmode % so we drop \mathaccent !

\aliased\let\mathordinary   \normalmathord
\aliased\let\mathoperator   \normalmathop
\aliased\let\mathbinary     \normalmathbin
\aliased\let\mathrelation   \normalmathrel
\aliased\let\mathopen       \normalmathopen
\aliased\let\mathclose      \normalmathclose
\aliased\let\mathpunctuation\normalmathpunct
\aliased\let\mathinner      \normalmathinner

%untraced\protected\def\mathordinary    {\mathatom \s!class \mathordinarycode    } % use \mathord
%untraced\protected\def\mathoperator    {\mathatom \s!class \mathoperatorcode    } % use \mathop
%untraced\protected\def\mathbinary      {\mathatom \s!class \mathbinarycode      } % use \mathbin
%untraced\protected\def\mathrelation    {\mathatom \s!class \mathrelationcode    } % use \mathrel
%untraced\protected\def\mathopen        {\mathatom \s!class \mathopencode        } % primitive
%untraced\protected\def\mathclose       {\mathatom \s!class \mathclosecode       } % primitive
%untraced\protected\def\mathpunctuation {\mathatom \s!class \mathpunctuationcode } % use \mathpunct
%untraced\protected\def\mathinner       {\mathatom \s!class \mathinnercode       } % primitive
%untraced\protected\def\mathover        {\mathatom \s!class \mathovercode        } % macro
%untraced\protected\def\mathunder       {\mathatom \s!class \mathundercode       } % macro
\untraced\protected\def\mathfraction    {\mathatom \s!class \mathfractioncode    } % use \mathfrac
\untraced\protected\def\mathradical     {\mathatom \s!class \mathradicalcode     } % use \mathrad
\untraced\protected\def\mathmiddle      {\mathatom \s!class \mathmiddlecode      } % primitive
\untraced\protected\def\mathaccent      {\mathatom \s!class \mathaccentcode      } % primitive
\untraced\protected\def\mathfenced      {\mathatom \s!class \mathfencedcode      } % primitive
\untraced\protected\def\mathghost       {\mathatom \s!class \mathghostcode       } % primitive
\untraced\protected\def\mathvariable    {\mathatom \s!class \mathvariablecode    } % alphabetical
\untraced\protected\def\mathactive      {\mathatom \s!class \mathactivecode      } % useless
\untraced\protected\def\mathvcenter     {\mathatom \s!class \mathvcentercode     } % useless
\untraced\protected\def\mathimaginary   {\mathatom \s!class \mathimaginarycode   }
\untraced\protected\def\mathdifferential{\mathatom \s!class \mathdifferentialcode}
\untraced\protected\def\mathexponential {\mathatom \s!class \mathexponentialcode }
%untraced\protected\def\mathintegral    {\mathatom \s!class \mathintegralcode    }
%untraced\protected\def\mathfunction    {\mathatom \s!class \mathfunctioncode    } % macro
\untraced\protected\def\mathdigit       {\mathatom \s!class \mathdigitcode       }
%untraced\protected\def\mathexplicit    {\mathatom \s!class \mathexplicitcode    } % dangerous
\untraced\protected\def\mathdivision    {\mathatom \s!class \mathdivisioncode    }
\untraced\protected\def\mathfactorial   {\mathatom \s!class \mathfactorialcode   }
\untraced\protected\def\mathwrapped     {\mathatom \s!class \mathwrappedcode     }
\untraced\protected\def\mathconstruct   {\mathatom \s!class \mathconstructcode   }
\untraced\protected\def\mathchemicalbond{\mathatom \s!class \mathchemicalbondcode}
\untraced\protected\def\mathimplication {\mathatom \s!class \mathimplicationcode }
\untraced\protected\def\mathdimension   {\mathatom \s!class \mathdimensioncode   }
%untraced\protected\def\mathbegin       {\mathatom \s!class \mathbegincode       } % dangerous
%untraced\protected\def\mathend         {\mathatom \s!class \mathendcode         } % dangerous
\untraced\protected\def\mathunary       {\mathatom \s!class \mathunarycode       }

\popoverloadmode

% obsolete

\setnewconstant\mathboxcode     \zerocount
\setnewconstant\mathchoicecode  \zerocount
\setnewconstant\mathalphacode   \zerocount
\setnewconstant\mathnothingcode \zerocount

%D At some point we will drop these in the \LUAMETATEX\ engine becuase we have many
%D more options there.

\pushoverloadmode
    \untraced\permanent\protected\def\binoppenalty   {\setmathpostpenalty\mathbinarycode}
    \untraced\permanent\protected\def\prebinoppenalty{\setmathprepenalty \mathbinarycode}
    \untraced\permanent\protected\def\relpenalty     {\setmathpostpenalty\mathrelationcode}
    \untraced\permanent\protected\def\prerelpenalty  {\setmathprepenalty \mathrelationcode}
\popoverloadmode

%D These verbose commands are obsolete because there are plenty more classes in
%D \LMTX\ than in \MKIV, so \typ {\ordordspacing}, typ {\fractionclosespacing}
%D are gone now.

% \setmathignore\Umathspacebeforescript  \plusone
% \setmathignore\Umathspaceafterscript   \plusone
% \setmathignore\Umathradicaldegreebefore\plusone % done in math-rad.mklx

\setmathignore\Umathspacebeforescript\zerocount
\setmathignore\Umathspaceafterscript \zerocount

% \setmathignore \Umathspacebeforescript\plustwo % can be set but does not init
% \setmathignore \Umathspaceafterscript \plustwo % can be set but does not init

% \setmathignore\Umathxscale\plustwo
% \setmathignore\Umathyscale\plustwo

% can become
%
% \setmathignore \Umathspacebeforescript\plustwo % can be set but does not init
% \setmathignore \Umathspaceafterscript \plustwo % idem

\mathslackmode       \plusone
\mathgroupingmode    \plusone
%mathdoublescriptmode\zerocount % -1 will give an error (as usual) .. "LLRR (left class, right class)

%D \starttyping
%D \startTEXpage[offset=1dk]
%D     $ 1 {\red +} 2$\par
%D     $ 1 \color[red]{+} 2$\par
%D     \mathgroupingmode0
%D     $ 1 {\red +} 2$\par
%D     $ 1 \mathbinary{\red +} 2$\par
%D     $ 1 \color[red]{+} 2$\par
%D \stopTEXpage
%D \stoptyping

% $x ^^1__2 ^3_4 ^5_6 ^7_8 $

\integerdef\defaultmathclassoptions\numexpr
   \zerocount
 % +\nopreslackclassoptioncode
 % +\nopostslackclassoptioncode
 % +\lefttopkernclassoptioncode        % applied in a late stage e.g. division
 % +\righttopkernclassoptioncode       % applied in a late stage e.g. division
 % +\leftbottomkernclassoptioncode     % applied in a late stage e.g. division
 % +\rightbottomkernclassoptioncode    % applied in a late stage e.g. division
 % +\lookaheadforendclassoptioncode    % signed whatevers
 % +\noitaliccorrectionclassoptioncode
 % +\openfenceclassoptioncode          % the engine doesn't really used this property but maybe
 % +\closefenceclassoptioncode         % at some point we want to have to have access to it at
 % +\middlefenceclassoptioncode        % lua end ... so we keep it (also in the engine) commented
 % +\checkligatureclassoptioncode      % no font provides this so it is more a compatibility feature
 % +\checkkernpairclassoptioncode
 % +\flattenclassoptioncode
 % +\omitpenaltyclassoptioncode        % old school check, we do pairwise instead
 % +\carryoverlefttopkernclassoptioncode
 % +\carryoverleftbottomkernclassoptioncode
 % +\carryoverrighttopkernclassoptioncode
 % +\carryoverrightbottomkernclassoptioncode
 % +\preferdelimiterdimensionsclassoptioncode
\relax

% \showmakeup[penalty]
%
% \preinlinepenalty       23 \postinlinepenalty      56 x$xx$x\par x$x$x\par x$x^2$x\par x$!$x\par
% \preshortinlinepenalty 123 \postshortinlinepenalty456 x$xx$x\par x$x$x\par x$x^2$x\par x$!$x\par

% \permanent\immutable\integerdef\defaultpreshortinlinepenalty  150

% when we want \preshortinlinepenalty to kick in here we need to have a bit more shrink
% maybe advance it by \shortinlinemaththreshold/100
%
% \startbuffer[1]
% The Pythagorean theorem states that for a right triangle with legs \im{a} and \im{b}, and hypotenuse \im{c}, it holds that \im{a^2 + b^2 = c^2}. This is a famous theorem with many different proofs.
% \stopbuffer
% \startbuffer[2]
% The Pythagorean theorem states that for a right triangle with legs \im{\frac{a}{b}} and \im{\hat{b}}, and hypotenuse \im{\hat{c}}, it holds that \im{\hat{a}^2 + \hat{b}^2 = \hat{c}^2}. This is a famous theorem with many different proofs.
% \stopbuffer
% \hsize 12.25cm
% \bgroup
% \preshortinlinepenalty 300
% \getbuffer[1]
% \egroup
% \bgroup % don't use (x)spaceskip like this ... we just demo here
% \xspaceskip\interwordspace plus \interwordstretch minus 2\interwordshrink
% \spaceskip \interwordspace plus \interwordstretch minus 2\interwordshrink
% \preshortinlinepenalty 300
% \getbuffer[2]
% \egroup

\preshortinlinepenalty 150

\appendtoks
    \shortinlinemaththreshold\emwidth % only for boxed stuff like accents and fractions
\to \everybodyfont

%D Actually a bit low level so it might move:

\permanent\protected\untraced\def\setmathoption
  {\afterassigned
     {\afterassigned
        {\scratchcounter\setmathoptions\scratchcounterone
         \bitwiseflip\scratchcounter\scratchcountertwo
         \setmathoptions\scratchcounterone\scratchcounter}%
      \scratchcountertwo}%
    \scratchcounterone}

\permanent\protected\untraced\def\resetmathoption
  {\afterassigned
     {\afterassigned
        {\scratchcounter\setmathoptions\scratchcounterone
         \bitwiseflip\scratchcounter-\scratchcountertwo
         \setmathoptions\scratchcounterone\scratchcounter}%
      \scratchcountertwo}%
    \scratchcounterone}

% \midaligned{\infofont open  : \showbits{classoptioncodes}\setmathoptions\mathopencode}
% \midaligned{\infofont close : \showbits{classoptioncodes}\setmathoptions\mathclosecode}

%D The initial values, best don't change these:

\setmathoptions\mathordinarycode\numexpr
    \zerocount
   +\noitaliccorrectionclassoptioncode
 % +\checkligatureclassoptioncode
   +\checkkernpairclassoptioncode
 % +\flattenclassoptioncode
   +\shortinlineclassoptioncode
\relax

\setmathoptions\mathoperatorcode\numexpr
    \zerocount
   +\nopreslackclassoptioncode
   +\nopostslackclassoptioncode
 % +\checkligatureclassoptioncode
   +\checkkernpairclassoptioncode
\relax

\setmathoptions\mathintegralcode\numexpr
    \zerocount
   +\nopreslackclassoptioncode
   +\nopostslackclassoptioncode
 % +\checkligatureclassoptioncode
   +\checkkernpairclassoptioncode
\relax

\copymathatomrule\mathintegralcode\mathoperatorcode

% we tweak away weird italics so only special cases see this:
%
% \def\IntOr{\Umathchar\mathordinarycode"00"00222B }
% \def\IntOp{\Umathchar\mathoperatorcode"00"00222B }
%
% \showglyphs \showfontitalics
% $\IntOp\limits x \quad \IntOp\limits^1_2 x \quad \IntOp\nolimits^1_2 x $\blank
% $\IntOr\limits x \quad \IntOr\limits^1_2 x \quad \IntOr\nolimits^1_2 x $\blank
%
% $\mathop{f}     (x) \quad \mathop{f}\limits     (x) \quad \mathop{f}\nolimits     (x)$\blank
% $\mathop{f}^a_b (x) \quad \mathop{f}\limits^a_b (x) \quad \mathop{f}\nolimits^a_b (x)$\blank

\setmathoptions\mathbinarycode\numexpr
    \zerocount
   +\nopreslackclassoptioncode
   +\nopostslackclassoptioncode
   +\lookaheadforendclassoptioncode
   +\noitaliccorrectionclassoptioncode
 % +\checkligatureclassoptioncode
   +\checkkernpairclassoptioncode
 % +\flattenclassoptioncode
   +\obeynestingclassoptioncode
   +\shortinlineclassoptioncode
\relax

\setmathoptions\mathrelationcode\numexpr
    \zerocount
   +\nopreslackclassoptioncode
   +\nopostslackclassoptioncode
   +\noitaliccorrectionclassoptioncode
 % +\checkligatureclassoptioncode
   +\checkkernpairclassoptioncode
 % +\flattenclassoptioncode
 % +\omitpenaltyclassoptioncode
   +\obeynestingclassoptioncode
   +\shortinlineclassoptioncode
\relax

\setmathoptions\mathimplicationcode\numexpr
    \zerocount
   +\nopreslackclassoptioncode
   +\nopostslackclassoptioncode
   +\noitaliccorrectionclassoptioncode
 % +\checkligatureclassoptioncode
   +\checkkernpairclassoptioncode
 % +\flattenclassoptioncode
 % +\omitpenaltyclassoptioncode
   +\obeynestingclassoptioncode
   +\shortinlineclassoptioncode
\relax

\setmathoptions\mathopencode\numexpr
    \zerocount
   +\nopreslackclassoptioncode
 % +\nopostslackclassoptioncode
   +\noitaliccorrectionclassoptioncode
 % +\openfenceclassoptioncode
 % +\checkligatureclassoptioncode
   +\checkkernpairclassoptioncode
   +\pushnestingclassoptioncode
   +\shortinlineclassoptioncode
\relax

\setmathoptions\mathclosecode\numexpr
    \zerocount
 % +\nopreslackclassoptioncode
   +\nopostslackclassoptioncode
   +\noitaliccorrectionclassoptioncode
 % +\closefenceclassoptioncode
 % +\checkligatureclassoptioncode
   +\checkkernpairclassoptioncode
   +\raiseprimeclassoptioncode
   +\popnestingclassoptioncode
   +\shortinlineclassoptioncode
\relax

\setmathoptions\mathpunctuationcode\numexpr
    \zerocount
   +\nopreslackclassoptioncode
   +\nopostslackclassoptioncode
   +\noitaliccorrectionclassoptioncode
 % +\checkligatureclassoptioncode
 % +\flattenclassoptioncode
   +\checkkernpairclassoptioncode
   +\removeitaliccorrectionclassoptioncode
   +\obeynestingclassoptioncode
   +\shortinlineclassoptioncode
\relax

\setmathoptions\mathvariablecode\numexpr
    \zerocount
   +\noitaliccorrectionclassoptioncode
   +\shortinlineclassoptioncode
\relax

\copymathatomrule\mathvariablecode\mathordinarycode

\setmathoptions\mathactivecode\numexpr
    \zerocount
   +\noitaliccorrectionclassoptioncode
\relax

%setmathoptions\mathinnercode\numexpr
%   \noitaliccorrectionclassoptioncode
%  +\flattenclassoptioncode
%relax

\setmathoptions\mathmiddlecode\numexpr
    \zerocount
   +\noitaliccorrectionclassoptioncode
 % +\middlefenceclassoptioncode
   +\raiseprimeclassoptioncode
   +\carryoverlefttopkernclassoptioncode
   +\carryoverleftbottomkernclassoptioncode
   +\carryoverrighttopkernclassoptioncode
   +\carryoverrightbottomkernclassoptioncode
   +\preferdelimiterdimensionsclassoptioncode
\relax

\setmathoptions\mathfractioncode\numexpr
    \zerocount
   +\nopreslackclassoptioncode
   +\nopostslackclassoptioncode
   +\raiseprimeclassoptioncode
   +\carryoverlefttopkernclassoptioncode
   +\carryoverleftbottomkernclassoptioncode
   +\carryoverrighttopkernclassoptioncode
   +\carryoverrightbottomkernclassoptioncode
   +\preferdelimiterdimensionsclassoptioncode
   +\shortinlineclassoptioncode
\relax

\setmathoptions\mathradicalcode\numexpr
    \zerocount
   +\nopreslackclassoptioncode
   +\nopostslackclassoptioncode
   +\raiseprimeclassoptioncode
   +\carryoverlefttopkernclassoptioncode
   +\carryoverleftbottomkernclassoptioncode
   +\carryoverrighttopkernclassoptioncode
   +\carryoverrightbottomkernclassoptioncode
   +\preferdelimiterdimensionsclassoptioncode
   +\shortinlineclassoptioncode
\relax

\setmathoptions\mathaccentcode\numexpr
    \zerocount
   +\nopreslackclassoptioncode
   +\nopostslackclassoptioncode
   +\autoinjectclassoptioncode
   +\shortinlineclassoptioncode
   +\lefttopkernclassoptioncode
   +\leftbottomkernclassoptioncode
   +\righttopkernclassoptioncode
   +\rightbottomkernclassoptioncode
\relax

% ord spacing but with support for \m{m^2/x__3}

\setmathoptions\mathdivisioncode\numexpr
    \zerocount
   +\nopreslackclassoptioncode
   +\nopostslackclassoptioncode
   +\lefttopkernclassoptioncode
 % +\righttopkernclassoptioncode
 % +\leftbottomkernclassoptioncode
   +\rightbottomkernclassoptioncode
   +\shortinlineclassoptioncode
\relax

\setmathoptions\mathbegincode\numexpr
    \zerocount
   +\nopostslackclassoptioncode
\relax

\setmathoptions\mathendcode\numexpr
    \zerocount
   +\nopreslackclassoptioncode
\relax

% Fenced is only used internally as these fences become open, middle and close
% subtypes. If we don't set the following we should actually also define the
% spacing rules.

\setmathoptions\mathfencedcode\numexpr
    \zerocount
   +\unpackclassoptioncode
   +\carryoverlefttopkernclassoptioncode
   +\carryoverleftbottomkernclassoptioncode
   +\carryoverrighttopkernclassoptioncode
   +\carryoverrightbottomkernclassoptioncode
   +\preferdelimiterdimensionsclassoptioncode
\relax

% MS will check

\setmathoptions\mathexponentialcode\numexpr
    \zerocount
   +\shortinlineclassoptioncode
\relax

\setmathoptions\mathimaginarycode\numexpr
    \zerocount
   +\shortinlineclassoptioncode
\relax

\setmathoptions\mathdifferentialcode\numexpr
    \zerocount
   +\shortinlineclassoptioncode
\relax

\setmathoptions\mathdigitcode\numexpr
    \zerocount
   +\shortinlineclassoptioncode
\relax

\copymathatomrule\mathexponentialcode \mathordinarycode
\copymathatomrule\mathimaginarycode   \mathordinarycode
\copymathatomrule\mathdifferentialcode\mathordinarycode
\copymathatomrule\mathdigitcode       \mathordinarycode

% test case for \lefttopkernclassoptioncode and \leftbottomkernclassoptioncode in cambria close:
%
% \setupbodyfont[cambria]
% %\enableexperiments[math.extensibles]
% %\disableexperiments[math.extensibles]
%
% \startTEXpage[offset=1dk]
%     \startformula \showglyphs
%         \left\{ \mathatom class \mathfractioncode {\raise .6ex\hbox{\blackrule[color=blue,  height=3cm,depth=3cm]}} \right\} ^1 _4 +
%         \left\( \mathatom class \mathfractioncode {\raise .6ex\hbox{\blackrule[color=green, height=4cm,depth=4cm]}} \right\) ^2 _3 -
%         \left\{ \mathatom class \mathfractioncode {\raise .6ex\hbox{\blackrule[color=red,   height=2cm,depth=2cm]}} \right\} ^3 _2 +
%         \left\( \mathatom class \mathfractioncode {\raise .6ex\hbox{\blackrule[color=yellow,height=1cm,depth=1cm]}} \right\) ^4 _1
%     \stopformula
% \stopTEXpage

%D For now \unknown (todo: make it adapt to style but we're in text anyway)

\permanent\protected\def\math_discretionary_plus {\discretionary class \mathbinarycode {$+$}{$+$}{$+$}}
\permanent\protected\def\math_discretionary_minus{\discretionary class \mathbinarycode {$-$}{$-$}{$-$}}

\newtoks\everymathdiscretionaries

\appendtoks
    \enforced\let\+\math_discretionary_plus
    \enforced\let\-\math_discretionary_minus
\to \everymathdiscretionaries

\appendtoks
    \ifconditional\c_math_discretionaries
        \expand\everymathdiscretionaries
    \fi
\to \everymathematics

\newconditional\c_math_discretionaries

\installtexexperiment
  {mathematics.discretionaries}
  {\c_math_discretionaries\conditionaltrue}
  {\c_math_discretionaries\conditionalfalse}

%D This is moved here from supp-mat:

\permanent\protected\def\dimension#1%
  {\mathematics
     {\mathatom
        \s!leftclass  \mathdimensioncode
        \s!rightclass \mathordinarycode
      {\tf #1}}}

\permanent\protected\def\nodimension#1%
  {#1}

%D A starter:
%D
%D \startbuffer
%D \mathsurround    10pt
%D \mathsurroundskip30pt
%D x $x + \ruledhbox{$x$} + x$ x
%D \stopbuffer
%D
%D \typebuffer
%D
%D \start \blank \getbuffer \blank \stop

% \newinteger\mathnestinglevel % see top

\appendtoks
    \advanceby\mathnestinglevel\plusone
\to \everymathematics

%D The attributes that we will use (todo: pack some into one but uglier code):

\definesystemattribute[mathalphabet]   [public]
%definesystemattribute[mathsize]       [public] % we now use the engine features
\definesystemattribute[mathpunctuation][public]
\definesystemattribute[mathgreek]      [public] % will become generic
\definesystemattribute[mathalternate]  [public]
\definesystemattribute[mathrendering]  [public]
\definesystemattribute[mathcategory]   [public]
\definesystemattribute[mathmode]       [public]
%definesystemattribute[mathitalics]    [public]
\definesystemattribute[mathkernpairs]  [public]
\definesystemattribute[mathbidi]       [public]
\definesystemattribute[mathdomain]     [public]
\definesystemattribute[mathcollapsing] [public]
\definesystemattribute[mathunstack]    [public]
\definesystemattribute[mathvariant]    [public]
\definesystemattribute[mathnumbers]    [public]
\definesystemattribute[mathspacing]    [public]
\definesystemattribute[mathfencing]    [public]
\definesystemattribute[mathintervals]  [public]

% \mathflattenmode\numexpr
%     \ordmathflattencode
%    +\binmathflattencode
%    +\relmathflattencode
%    +\punctmathflattencode
%    +\innermathflattencode
% \relax

\ifdefined\ordlimits\else
    \let\ordlimits\Umathlimits % downward compatible
\fi

%D Defined at the \LUA end:
%D
%D \starttyping
%D \permanent\protected\def\resetmathattributes{\resetmathattributes}
%D \stoptyping

% \appendtoks
%     \linebreakpasses\zerocount
% \to \everymathematics

%D We used to do this with an attribute but that oen then gets assigned to every
%D node in the formula which is a waste.

% \appendtoks
%     \c_attr_mathmode\plusone
% \to \everybeforedisplayformula

%D So instead we went for a boundary node but then one really has to make sure that
%D it comes first (unless we look ahead a few nodes). That said, this is the robust
%D approach:

% \def\math_display_mode_signal{\c_attr_mathmode\plusone}

%D This one is cheaper but it needs checking when we change leading stuff:

\def\math_display_mode_signal{\boundary\c_math_display_mode_boundary} % default per 2025-11-01

%D Here we do the same but more granular (like more modes in the future):

% \def\math_display_mode_signal{\attributeboundary\c_math_display_mode_boundary\inlineordisplaymath\zerocount\plusone}% mnore granular

%D Double dollars now are just inline (the mode is set later in this
%D file). So in \CONTEXT\ these double dollars just bring us into
%D displaystyle!

% \appendtoks
%     \c_attr_mathmode\plusone % actually we don't use display math
% \to \everydisplay

\newconditional\indisplaymath

\permanent\def\inlineordisplaymath
  {\ifconditional\indisplaymath
     \expandafter\secondoftwoarguments
   \else
     \expandafter\firstoftwoarguments
   \fi}

%D This is the only place where we assign these two registers and changing will make
%D math mostly work out bad! We might eventually protect them. That would mean that
%D we also need some special way to reset math, see for instance in \type
%D {supp-mat.mkxl}, where we reset \typ {\everymathematics} in \typ {\textmath}.

%D Watch out: \type {\everyinsidemathematics} is done explicitly at the moment that
%D it makes sense!

\immutable \everymath {%
    \expand\everymathematics
    \indisplaymath\conditionalfalse
}

\immutable \everydisplay {%
    \expand\everymathematics
    \indisplaymath\conditionaltrue
    \displaystyle
}

\permanent\protected\def\forcedisplaymath
  {\ifmmode
     \displaystyle
     \indisplaymath\conditionaltrue
   \fi}

\permanent\protected\def\forceinlinemath
  {\ifmmode
     \textstyle
     \indisplaymath\conditionalfalse
   \fi}

\permanent\protected\def\startforceddisplaymath
  {\Ustartmathmode\displaystyle
   \begingroup % can go
   \indisplaymath\conditionaltrue
   \expand\everyinsidemathematics\relax % check
}

\permanent\protected\def\stopforceddisplaymath
  {\endgroup % can go
   \Ustopmathmode}

\permanent\protected\def\startpickupmath % for the moment private
  {\ifconditional\indisplaymath
     \startforceddisplaymath
     \enforced\let\stoppickupmath\stopforceddisplaymath
   \else
     \startimath % maybe also forced and conditional etc
     \enforced\let\stoppickupmath\stopimath
   \fi}

\aliased\let\stoppickupmath\relax

\permanent\protected\def\rawmathematics#1% slow but only for tracing
  {\begingroup
   \ifmmode
     \resetmathattributes#1%
   \else
     \startimath\resetmathattributes#1\stopimath
   \fi
   \endgroup}

%D Some measures (maybe spac-mth):

% \def\mathskipsmall {\mskip\thinmuskip}
% \def\mathskipmedium{\mskip\medmuskip}
% \def\mathskipbig   {\mskip\thickmuskip}

%D \macros
%D   {setupmathematics}
%D
%D Configuration for integrals. (If needed we can speed this up and make it
%D installable; no processaction is needed then).

\installcorenamespace{mathematics}

\installswitchcommandhandler \??mathematics {mathematics} \??mathematics

\installmacrostack\currentmathematics

\permanent\protected\tolerant\def\startmathematics[#1]% no grouping, if ever then also an optional second
  {\push_macro_currentmathematics
   \cdef\currentmathematics{#1}% check for valid
   \expand\everyswitchmathematics}

\permanent\protected\def\stopmathematics
  {\pop_macro_currentmathematics
   \expand\everyswitchmathematics} % only needed at level zero

\definemathematics[\v!default] % not needed, but nicer when nesting back to normal

% Now we redefine \type {\mathematics} and \type {\m}:

\pushoverloadmode
    \permanent\protected\def\mathematics{\doifelsenextoptionalcs\math_m_yes\math_m_nop}

    \aliased\let\m   \mathematics % we keep the simple versions
    \aliased\let\math\mathematics % we keep the simple versions
\popoverloadmode

\def\math_m_yes
  {\relax
   \ifmmode
     \expandafter\math_m_yes_math
   \else
     \expandafter\math_m_yes_text
   \fi}

\def\math_m_yes_math[#1]#2%
  {#2} % grouping permits \mathbf etc

\def\math_m_yes_text[#S#1]%
  {\begingroup
   \ifhastok={#1}%
     \setupcurrentmathematics[#1]%
   \else
     \cdef\currentmathematics{#1}% todo: check for valid
   \fi
   \expand\everyswitchmathematics % kind of special here as we append to it/ check
   \usemathematicscolorparameter\c!color
   \ifcstok{\mathematicsparameter\c!openup}\v!yes
     \expandafter\math_m_yes_text_openedup
   \else
     \expandafter\math_m_yes_text_normal
   \fi}

\def\math_m_yes_text_openedup#1%
  {\setbox\scratchbox\hbox\bgroup
      \expand\everyswitchmathematics\relax
      \Ustartmathmode\expandedmathstyleparameter\mathematicsparameter\c!mathstyle
      \math_style_set_main % here
      \expand\everyinsidemathematics\relax
      #1%
      \Ustopmathmode
   \egroup
   \ifdim\ht\scratchbox>\strutht
     \math_inline_openup_start_yes
   \orelse\ifdim\dp\scratchbox>\strutdp
     \math_inline_openup_start_yes
   \else
     \math_inline_openup_start_nop
   \fi
   \unhbox\scratchbox % \normalstartimath#1\normalstopimath
   \math_inline_openup_stop
   \endgroup}

\def\math_m_yes_text_normal#1%
  {\expand\everyswitchmathematics\relax
   \Ustartmathmode\expandedmathstyleparameter\mathematicsparameter\c!mathstyle
   \math_style_set_main % here
   \expand\everyinsidemathematics\relax
   \begingroup#1\endgroup % grouping permits aftergroups trickery
   \Ustopmathmode
   \endgroup}

\def\math_m_nop#1%
  {\relax
   \ifmmode
     #1%
   \else
     \normalstartimath
     \usemathstyleparameter\mathematicsparameter\c!mathstyle
     \expand\everyinsidemathematics\relax
     \begingroup#1\endgroup % grouping permits aftergroups trickery
     \normalstopimath
   \fi}

%D We wrap in a construct so that we can do:
%D
%D \starttyping
%D \startformula
%D     \dm{f(x) = \frac{x}{y}} \mtp{,}
%D     \im{g(x) = \frac{x}{y}} \mtp{.}
%D \stopformula
%D \stoptyping

\let\math_trace_blobs\relax

\def\math_trace_blobs_indeed_yes
  {\markblobindexdone{\currentlanguage}\scratchcounter
   \expanded{\csname\v!mathnote\endcsname
     [\v!mathnote:\currentlanguage:\the\scratchcounter]%
     {\definedfont[\s!MathRoman]\getmathtextblob{\currentlanguage}\the\currentmathblob}}}

\def\math_trace_blobs_indeed_nop
  {\expanded{\note[\v!mathnote:\currentlanguage:\the\scratchcounter]}}

\protected\def\math_trace_blobs_indeed
  {\dontleavehmode
   \hbox to \zeropoint \bgroup
      \resetinteractioncontrastcolor
      \resetinteractionstyle
      \scratchcounter\getmathblobindex\currentmathblob
      \bgroup
        \darkgray
        \vrule \s!height .9\strutht \s!depth .9\strutdp \s!width \onepoint \relax
        \hbox to \zeropoint \bgroup
          \smallinfofont
          \the\currentmathblob\hss
          \hbox to \zeropoint \s!yoffset -.8\strutdp \bgroup
            \currentlanguage
            \ifconditional\c_strc_tags_global
              \space
              \tohexadecimal\getmathblobmapping\currentmathblob
            \fi
            \hss
          \egroup
        \egroup
      \egroup
      \ifinsidefloat
        \math_trace_blobs_indeed_yes
      \orelse\ifblobindexdone{\currentlanguage}\scratchcounter
        \math_trace_blobs_indeed_nop
      \else
        \math_trace_blobs_indeed_yes
      \fi
      \hss
   \egroup}

\protected\def\math_trace_blobs_checked
  {\iftrialtypesetting
     % no need for it, not even the note dimensions
   \orelse\ifnum\currentmathblobnesting<\zerocount\else
     \aftergroup\math_trace_blobs_indeed
   \fi}

\installtextracker
  {math.textblobs}
  {\let\math_trace_blobs\math_trace_blobs_checked}
  {\let\math_trace_blobs\relax}

\appendtoks
    \math_trace_blobs
\to \everymathematics

\permanent\protected\def\dm#1%
  {\relax
   \ifmmode
    %\beginmathgroup\forcedisplaymath#1\endmathgroup
    %\mathconstruct{\forcedisplaymath#1}%
     \mathconstruct{\displaystyle\indisplaymath\conditionaltrue#1}%
   \else
    %\startimath\begingroup\forcedisplaymath#1\endgroup\stopimath
     \Ustartmathmode\displaystyle
       \indisplaymath\conditionaltrue
       \expand\everyinsidemathematics\relax % check
       #1%
     \Ustopmathmode % grouping for \aftergroup ?
   \fi}

\permanent\protected\def\im#1%
  {\relax
   \ifmmode
    %\beginmathgroup\forceinlinemath#1\endmathgroup
    %\mathconstruct{\forceinlinemath#1}%
     \mathconstruct{\textstyle\indisplaymath\conditionalfalse#1}%
   \else
    %\startimath#1\stopimath
     \Ustartmathmode\textstyle
       \indisplaymath\conditionalfalse
       \expand\everyinsidemathematics\relax % check
       #1%
     \Ustopmathmode
   \fi}

\permanent\protected\def\nm#1%
  {\dontleavehmode
   \begingroup
   \mathoptions\textmathoptioncode % we can at some point simplify tags here
   \im{#1}%
   \endgroup}

% \aliased\let\m\mathematics % we keep the simple versions

% e.g.: \definemathematics[i:mp][setups=i:tight,openup=yes]

% we need to control these otherwise:
%
% \prerelpenalty  \defaultprerelpenalty
% \prebinoppenalty\defaultprebinoppenalty

\startsetups math:spacing:default
    \thickmuskip    \defaultthickmuskip
    \medmuskip      \defaultmedmuskip
    \thinmuskip     \defaultthinmuskip
    \tinymuskip     \defaulttinymuskip
    \pettymuskip    \defaultpettymuskip
    \relpenalty     \defaultrelpenalty
    \binoppenalty   \defaultbinoppenalty
    \prebinoppenalty\maxdimen
    \prerelpenalty  \maxdimen
\stopsetups

\startsetups math:spacing:split
    \thickmuskip    \defaultthickmuskip
    \medmuskip      \defaultmedmuskip
    \thinmuskip     \defaultthinmuskip
    \tinymuskip     \defaulttinymuskip
    \pettymuskip    \defaultpettymuskip
    \relpenalty     \defaultrelpenalty
    \binoppenalty   \defaultbinoppenalty
    \prebinoppenalty\defaultprebinoppenalty
    \prerelpenalty  \defaultprerelpenalty
\stopsetups

\startsetups math:spacing:half
    \thickmuskip    \halfthickmuskip
    \medmuskip      \halfmedmuskip
    \thinmuskip     \halfthinmuskip
    \tinymuskip     \halftinymuskip
    \pettymuskip    \halfpettymuskip
    \relpenalty     \defaultrelpenalty
    \binoppenalty   \defaultbinoppenalty
    \prebinoppenalty\maxdimen
    \prerelpenalty  \maxdimen
\stopsetups

\startsetups math:spacing:tight
    \ifcase\raggedstatus
        \thickmuskip   \halfthickmuskip
        \medmuskip     \halfmedmuskip
        \thinmuskip    \halfthinmuskip
        \tinymuskip    \halftinymuskip
        \pettymuskip   \halfpettymuskip
    \else
        \thickmuskip  1\halfthickmuskip
        \medmuskip    1\halfmedmuskip
        \thinmuskip   1\halfthinmuskip
        \tinymuskip   1\halftinymuskip
        \pettymuskip  1\halfpettymuskip
    \fi
    \relpenalty     \defaultrelpenalty
    \binoppenalty   \maxdimen
    \prebinoppenalty\maxdimen
    \prerelpenalty  \maxdimen
\stopsetups

\startsetups math:spacing:fixed
    \ifcase\raggedstatus
        \thickmuskip   \halfthickmuskip
        \medmuskip     \halfmedmuskip
        \thinmuskip    \halfthinmuskip
        \tinymuskip    \halftinymuskip
        \pettymuskip   \halfpettymuskip
    \else
        \thickmuskip  1\halfthickmuskip
        \medmuskip    1\halfmedmuskip
        \thinmuskip   1\halfthinmuskip
        \tinymuskip   1\halftinymuskip
        \pettymuskip  1\halfpettymuskip
    \fi
    \relpenalty     \maxdimen
    \binoppenalty   \maxdimen
    \prebinoppenalty\maxdimen
    \prerelpenalty  \maxdimen
\stopsetups

% this will reset the spacing to default values

% \Umathspacingmode\allmathstyles\plusone % always pair driven

%D \starttyping
%D \startformula
%D f(x) = \sin x \mt{,} x
%D \stopformula
%D
%D $f(x) = \sin x \mt{,} x$
%D \stoptyping

% mu based: 18mu == quad, preferred

\newmuskip\mathinterwordmuskip

% Hans:
%
% \mathinterwordmuskip 9mu plus .45mu minus .225mu
%
% Lansburg, p. 296: "A quad---nothing less, but also nothing more---is set between all independent formulas, independent of their length,
% height or character.

\mathinterwordmuskip 18mu

\permanent\protected\def\mtp#1{\mathatom class \mathtextpunctuationcode {\hbox{#1}}} % only at the outer level (text, display)

% granular, but more clutter
%
% \newgluespec\mathinterwordtextskip
% \newgluespec\mathinterwordscriptskip
% \newgluespec\mathinterwordscriptscriptskip
%
% \appendtoks
%     \mathinterwordtextskip         \fontinterwordspace\textfont        \zerocount \fontinterwordstretch\textfont        \zerocount \fontinterwordshrink\textfont        \zerocount \relax
%     \mathinterwordscriptskip       \fontinterwordspace\scriptfont      \zerocount \fontinterwordstretch\scriptfont      \zerocount \fontinterwordshrink\scriptfont      \zerocount \relax
%     \mathinterwordscriptscriptskip \fontinterwordspace\scriptscriptfont\zerocount \fontinterwordstretch\scriptscriptfont\zerocount \fontinterwordshrink\scriptscriptfont\zerocount \relax
% \to \everymathematics
%
% \inherited\setmathspacing \mathtextpunctuationcode \mathordcode \allmathstyles         \mathinterwordtextskip
% \inherited\setmathspacing \mathtextpunctuationcode \mathordcode \allscriptstyles       \mathinterwordscriptskip
% \inherited\setmathspacing \mathtextpunctuationcode \mathordcode \allscriptscriptstyles \mathinterwordscriptscriptskip

\startsetups math:spacing:presets
    \resetmathspacing
    %
  % \inherited\setmathspacing \mathordinarycode        \mathordinarycode        \allmathstyles    \zeromuskip
    \inherited\setmathspacing \mathordinarycode        \mathoperatorcode        \allmathstyles    \thinmuskip
    \inherited\setmathspacing \mathordinarycode        \mathbinarycode          \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathordinarycode        \mathbinarycode          \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathordinarycode        \mathrelationcode        \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathordinarycode        \mathrelationcode        \allunsplitstyles \pettymuskip
  % \inherited\setmathspacing \mathordinarycode        \mathopencode            \allmathstyles    \zeromuskip
    \inherited\setmathspacing \mathordinarycode        \mathmiddlecode          \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathordinarycode        \mathmiddlecode          \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathordinarycode        \mathclosecode           \allmathstyles    \fencemuskip
  % \inherited\setmathspacing \mathordinarycode        \mathpunctuationcode     \allmathstyles    \zeromuskip
    \inherited\setmathspacing \mathordinarycode        \mathconstructcode       \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathordinarycode        \mathconstructcode       \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathordinarycode        \mathellipsiscode        \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathordinarycode        \mathellipsiscode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathordinarycode        \mathfractioncode        \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathordinarycode        \mathfractioncode        \allunsplitstyles \pettymuskip
  % \inherited\setmathspacing \mathordinarycode        \mathradicalcode         \allsplitstyles   \tinymuskip  % 220705 Results in an unwanted space
  % \inherited\setmathspacing \mathordinarycode        \mathradicalcode         \allunsplitstyles \pettymuskip % 220705 Results in an unwanted space
    %
    \inherited\setmathspacing \mathoperatorcode        \mathordinarycode        \allmathstyles    \thinmuskip
    \inherited\setmathspacing \mathoperatorcode        \mathoperatorcode        \allmathstyles    \thinmuskip
  % \inherited\setmathspacing \mathoperatorcode        \mathbinarycode          \allmathstyles    \zeromuskip
    \inherited\setmathspacing \mathoperatorcode        \mathrelationcode        \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathoperatorcode        \mathrelationcode        \allunsplitstyles \pettymuskip
  % \inherited\setmathspacing \mathoperatorcode        \mathopencode            \allmathstyles    \zeromuskip
    \inherited\setmathspacing \mathoperatorcode        \mathmiddlecode          \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathoperatorcode        \mathmiddlecode          \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathoperatorcode        \mathclosecode           \allmathstyles    \fencemuskip
  % \inherited\setmathspacing \mathoperatorcode        \mathpunctuationcode     \allmathstyles    \zeromuskip
    \inherited\setmathspacing \mathoperatorcode        \mathconstructcode       \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathoperatorcode        \mathconstructcode       \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathoperatorcode        \mathellipsiscode        \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathoperatorcode        \mathellipsiscode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathoperatorcode        \mathfractioncode        \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathoperatorcode        \mathfractioncode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathoperatorcode        \mathradicalcode         \allmathstyles    \thinmuskip
    %
    \inherited\setmathspacing \mathbinarycode          \mathordinarycode        \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathbinarycode          \mathordinarycode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathbinarycode          \mathoperatorcode        \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathbinarycode          \mathoperatorcode        \allunsplitstyles \pettymuskip
 %% \inherited\setmathspacing \mathbinarycode          \mathbinarycode          \allmathstyles    \zeromuskip
 %% \inherited\setmathspacing \mathbinarycode          \mathrelationcode        \allmathstyles    \zeromuskip
    \inherited\setmathspacing \mathbinarycode          \mathopencode            \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathbinarycode          \mathopencode            \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathbinarycode          \mathmiddlecode          \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathbinarycode          \mathmiddlecode          \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathbinarycode          \mathclosecode           \allmathstyles    \fencemuskip
    \inherited\setmathspacing \mathbinarycode          \mathpunctuationcode     \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathbinarycode          \mathpunctuationcode     \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathbinarycode          \mathconstructcode       \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathbinarycode          \mathconstructcode       \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathbinarycode          \mathellipsiscode        \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathbinarycode          \mathellipsiscode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathbinarycode          \mathfractioncode        \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathbinarycode          \mathfractioncode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathbinarycode          \mathradicalcode         \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathbinarycode          \mathradicalcode         \allunsplitstyles \pettymuskip
    %
    \inherited\setmathspacing \mathrelationcode        \mathordinarycode        \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathrelationcode        \mathordinarycode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathrelationcode        \mathoperatorcode        \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathrelationcode        \mathoperatorcode        \allunsplitstyles \pettymuskip
 %% \inherited\setmathspacing \mathrelationcode        \mathbinarycode          \allmathstyles    \zeromuskip
  % \inherited\setmathspacing \mathrelationcode        \mathrelationcode        \allmathstyles    \zeromuskip
    \inherited\setmathspacing \mathrelationcode        \mathopencode            \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathrelationcode        \mathopencode            \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathrelationcode        \mathmiddlecode          \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathrelationcode        \mathmiddlecode          \allunsplitstyles \thinmuskip
    \inherited\setmathspacing \mathrelationcode        \mathclosecode           \allmathstyles    \fencemuskip
    \inherited\setmathspacing \mathrelationcode        \mathpunctuationcode     \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathrelationcode        \mathpunctuationcode     \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathrelationcode        \mathconstructcode       \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathrelationcode        \mathconstructcode       \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathrelationcode        \mathellipsiscode        \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathrelationcode        \mathellipsiscode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathrelationcode        \mathfractioncode        \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathrelationcode        \mathfractioncode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathrelationcode        \mathradicalcode         \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathrelationcode        \mathradicalcode         \allunsplitstyles \pettymuskip
    %
    \inherited\setmathspacing \mathopencode            \mathordinarycode        \allmathstyles    \fencemuskip
    \inherited\setmathspacing \mathopencode            \mathoperatorcode        \allmathstyles    \fencemuskip
    \inherited\setmathspacing \mathopencode            \mathbinarycode          \allmathstyles    \fencemuskip
    \inherited\setmathspacing \mathopencode            \mathrelationcode        \allmathstyles    \fencemuskip
    \inherited\setmathspacing \mathopencode            \mathopencode            \allmathstyles    \fencemuskip
    \inherited\setmathspacing \mathopencode            \mathmiddlecode          \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathopencode            \mathclosecode           \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathopencode            \mathpunctuationcode     \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathopencode            \mathconstructcode       \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathopencode            \mathellipsiscode        \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathopencode            \mathradicalcode         \allmathstyles    \fencemuskip
    \inherited\setmathspacing \mathopencode            \mathfractioncode        \allsplitstyles   \pettymuskip
    \inherited\setmathspacing \mathopencode            \mathfractioncode        \allunsplitstyles \pettymuskip
    %
    \inherited\setmathspacing \mathclosecode           \mathordinarycode        \allmathstyles    \tinymuskip
    \inherited\setmathspacing \mathclosecode           \mathoperatorcode        \allmathstyles    \thinmuskip
    \inherited\setmathspacing \mathclosecode           \mathbinarycode          \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathclosecode           \mathbinarycode          \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathclosecode           \mathrelationcode        \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathclosecode           \mathrelationcode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathclosecode           \mathopencode            \alltextstyles    \tinymuskip
    \inherited\setmathspacing \mathclosecode           \mathopencode            \alldisplaystyles \thinmuskip
    \inherited\setmathspacing \mathclosecode           \mathopencode            \allunsplitstyles \pettymuskip
%
% todo: see asciimath or at least to be checked
%
% \inherited\setmathspacing \mathclosecode \mathmiddlecode                    \alldisplaystyles   \thickmuskip
% \inherited\setmathspacing \mathclosecode \mathmiddlecode                    \allunsplitstyles   \pettymuskip
%
  % \inherited\setmathspacing \mathclosecode           \mathmiddlecode          \allmathstyles    \zeromuskip
    \inherited\setmathspacing \mathclosecode           \mathclosecode           \allmathstyles    \fencemuskip
  % \inherited\setmathspacing \mathclosecode           \mathpunctuationcode     \allmathstyles    \zeromuskip
    \inherited\setmathspacing \mathclosecode           \mathconstructcode       \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathclosecode           \mathconstructcode       \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathclosecode           \mathfactorialcode       \allmathstyles    \zeromuskip
    \inherited\setmathspacing \mathclosecode           \mathellipsiscode        \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathclosecode           \mathellipsiscode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathclosecode           \mathfractioncode        \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathclosecode           \mathfractioncode        \allunsplitstyles \pettymuskip
  % \inherited\setmathspacing \mathclosecode           \mathradicalcode         \allmathstyles    \zeromuskip
    %
    \inherited\setmathspacing \mathpunctuationcode     \mathordinarycode        \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathpunctuationcode     \mathordinarycode        \allunsplitstyles \tinymuskip
    \inherited\setmathspacing \mathpunctuationcode     \mathoperatorcode        \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathpunctuationcode     \mathoperatorcode        \allunsplitstyles \tinymuskip
  % \inherited\setmathspacing \mathpunctuationcode     \mathbinarycode          \allmathstyles    \zeromuskip
    \inherited\setmathspacing \mathpunctuationcode     \mathrelationcode        \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathpunctuationcode     \mathrelationcode        \allunsplitstyles \tinymuskip
    \inherited\setmathspacing \mathpunctuationcode     \mathopencode            \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathpunctuationcode     \mathopencode            \allunsplitstyles \tinymuskip
    \inherited\setmathspacing \mathpunctuationcode     \mathmiddlecode          \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathpunctuationcode     \mathmiddlecode          \allunsplitstyles \tinymuskip
    \inherited\setmathspacing \mathpunctuationcode     \mathclosecode           \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathpunctuationcode     \mathclosecode           \allunsplitstyles \tinymuskip
    \inherited\setmathspacing \mathpunctuationcode     \mathpunctuationcode     \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathpunctuationcode     \mathpunctuationcode     \allunsplitstyles \tinymuskip
    \inherited\setmathspacing \mathpunctuationcode     \mathconstructcode       \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathpunctuationcode     \mathconstructcode       \allunsplitstyles \tinymuskip
    \inherited\setmathspacing \mathpunctuationcode     \mathellipsiscode        \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathpunctuationcode     \mathellipsiscode        \allunsplitstyles \tinymuskip
    \inherited\setmathspacing \mathpunctuationcode     \mathfractioncode        \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathpunctuationcode     \mathfractioncode        \allunsplitstyles \tinymuskip
    \inherited\setmathspacing \mathpunctuationcode     \mathradicalcode         \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathpunctuationcode     \mathradicalcode         \allunsplitstyles \tinymuskip
    %
    \inherited\setmathspacing \mathconstructcode       \mathordinarycode        \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathconstructcode       \mathordinarycode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathconstructcode       \mathoperatorcode        \allmathstyles    \thinmuskip
    \inherited\setmathspacing \mathconstructcode       \mathbinarycode          \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathconstructcode       \mathbinarycode          \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathconstructcode       \mathrelationcode        \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathconstructcode       \mathrelationcode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathconstructcode       \mathopencode            \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathconstructcode       \mathopencode            \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathconstructcode       \mathmiddlecode          \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathconstructcode       \mathmiddlecode          \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathconstructcode       \mathclosecode           \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathconstructcode       \mathpunctuationcode     \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathconstructcode       \mathpunctuationcode     \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathconstructcode       \mathconstructcode       \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathconstructcode       \mathconstructcode       \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathconstructcode       \mathfractioncode        \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathconstructcode       \mathfractioncode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathconstructcode       \mathradicalcode         \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathconstructcode       \mathradicalcode         \allunsplitstyles \pettymuskip
    %
    \inherited\setmathspacing \mathellipsiscode        \mathordinarycode        \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathellipsiscode        \mathordinarycode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathellipsiscode        \mathoperatorcode        \allmathstyles    \thinmuskip
    \inherited\setmathspacing \mathellipsiscode        \mathbinarycode          \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathellipsiscode        \mathbinarycode          \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathellipsiscode        \mathrelationcode        \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathellipsiscode        \mathrelationcode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathellipsiscode        \mathopencode            \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathellipsiscode        \mathopencode            \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathellipsiscode        \mathmiddlecode          \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathellipsiscode        \mathmiddlecode          \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathellipsiscode        \mathclosecode           \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathellipsiscode        \mathpunctuationcode     \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathellipsiscode        \mathpunctuationcode     \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathellipsiscode        \mathconstructcode       \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathellipsiscode        \mathconstructcode       \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathellipsiscode        \mathellipsiscode        \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathellipsiscode        \mathellipsiscode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathellipsiscode        \mathfractioncode        \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathellipsiscode        \mathfractioncode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathellipsiscode        \mathradicalcode         \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathellipsiscode        \mathradicalcode         \allunsplitstyles \pettymuskip
    %
    \inherited\setmathspacing \mathfractioncode        \mathordinarycode        \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathfractioncode        \mathordinarycode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathfractioncode        \mathoperatorcode        \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathfractioncode        \mathoperatorcode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathfractioncode        \mathbinarycode          \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathfractioncode        \mathbinarycode          \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathfractioncode        \mathrelationcode        \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathfractioncode        \mathrelationcode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathfractioncode        \mathopencode            \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathfractioncode        \mathopencode            \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathfractioncode        \mathmiddlecode          \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathfractioncode        \mathmiddlecode          \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathfractioncode        \mathclosecode           \allmathstyles    \pettymuskip
    % \inherited\setmathspacing \mathfractioncode        \mathclosecode           \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathfractioncode        \mathpunctuationcode     \allsplitstyles   \tinymuskip
    \inherited\setmathspacing \mathfractioncode        \mathpunctuationcode     \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathfractioncode        \mathtextpunctuationcode \allmathstyles    \tinymuskip
    \inherited\setmathspacing \mathfractioncode        \mathconstructcode       \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathfractioncode        \mathconstructcode       \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathfractioncode        \mathellipsiscode        \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathfractioncode        \mathellipsiscode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathfractioncode        \mathfractioncode        \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathfractioncode        \mathfractioncode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathfractioncode        \mathradicalcode         \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathfractioncode        \mathradicalcode         \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathfractioncode        \mathdifferentialcode    \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathfractioncode        \mathdifferentialcode    \allunsplitstyles \pettymuskip
    %
    \inherited\setmathspacing \mathradicalcode         \mathordinarycode        \allsplitstyles   \tinymuskip
    \inherited\setmathspacing \mathradicalcode         \mathordinarycode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathradicalcode         \mathoperatorcode        \allmathstyles    \thinmuskip
    \inherited\setmathspacing \mathradicalcode         \mathbinarycode          \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathradicalcode         \mathbinarycode          \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathradicalcode         \mathrelationcode        \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathradicalcode         \mathrelationcode        \allunsplitstyles \pettymuskip
  % \inherited\setmathspacing \mathradicalcode         \mathopencode            \allmathstyles    \zeromuskip
    \inherited\setmathspacing \mathradicalcode         \mathmiddlecode          \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathradicalcode         \mathmiddlecode          \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathradicalcode         \mathclosecode           \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathradicalcode         \mathpunctuationcode     \allsplitstyles   \pettymuskip
    \inherited\setmathspacing \mathradicalcode         \mathpunctuationcode     \allunsplitstyles \tinymuskip
    \inherited\setmathspacing \mathradicalcode         \mathconstructcode       \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathradicalcode         \mathconstructcode       \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathradicalcode         \mathellipsiscode        \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathradicalcode         \mathellipsiscode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathradicalcode         \mathfractioncode        \allsplitstyles   \tinymuskip
    \inherited\setmathspacing \mathradicalcode         \mathfractioncode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathradicalcode         \mathradicalcode         \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathradicalcode         \mathradicalcode         \allunsplitstyles \pettymuskip
    %
    \inherited\setmathspacing \mathmiddlecode          \mathordinarycode        \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathmiddlecode          \mathordinarycode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathmiddlecode          \mathoperatorcode        \allmathstyles    \thickmuskip
    \inherited\setmathspacing \mathmiddlecode          \mathbinarycode          \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathmiddlecode          \mathbinarycode          \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathmiddlecode          \mathrelationcode        \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathmiddlecode          \mathrelationcode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathmiddlecode          \mathopencode            \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathmiddlecode          \mathopencode            \allscriptstyles  \pettymuskip
    \inherited\setmathspacing \mathmiddlecode          \mathmiddlecode          \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathmiddlecode          \mathmiddlecode          \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathmiddlecode          \mathclosecode           \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathmiddlecode          \mathclosecode           \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathmiddlecode          \mathpunctuationcode     \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathmiddlecode          \mathpunctuationcode     \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathmiddlecode          \mathconstructcode       \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathmiddlecode          \mathconstructcode       \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathmiddlecode          \mathellipsiscode        \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathmiddlecode          \mathellipsiscode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathmiddlecode          \mathfractioncode        \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathmiddlecode          \mathfractioncode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathmiddlecode          \mathradicalcode         \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathmiddlecode          \mathradicalcode         \allmathstyles    \pettymuskip
    %
    \inherited\setmathspacing \mathclosecode           \mathdifferentialcode    \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathclosecode           \mathdifferentialcode    \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathordinarycode        \mathdifferentialcode    \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathordinarycode        \mathdifferentialcode    \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathfactorialcode       \mathordinarycode        \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathfactorialcode       \mathordinarycode        \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathfactorialcode       \mathfactorialcode       \allmathstyles    \zeromuskip
    %
    \inherited\setmathspacing \mathopencode            \mathconstructcode       \allmathstyles    \thinmuskip
    \inherited\setmathspacing \mathconstructcode       \mathclosecode           \allmathstyles    \thinmuskip
    %
    \inherited\setmathspacing \mathdimensioncode       \mathdimensioncode       \allmathstyles    \zeromuskip
    \inherited\setmathspacing \mathordinarycode        \mathdimensioncode       \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathordinarycode        \mathdimensioncode       \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathdigitcode           \mathdimensioncode       \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathdigitcode           \mathdimensioncode       \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathclosecode           \mathdimensioncode       \allsplitstyles   \thinmuskip
    \inherited\setmathspacing \mathclosecode           \mathdimensioncode       \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathfunctioncode        \mathbinarycode          \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathfunctioncode        \mathbinarycode          \allunsplitstyles \pettymuskip
    %
    % A bit more spacing before parentheses
    %
    \inherited\setmathspacing \mathfunctioncode        \mathopencode            \allsplitstyles    \pettymuskip
    \inherited\setmathspacing \mathdifferentialcode    \mathopencode            \allsplitstyles    \pettymuskip
    %
    % integral inherited from operator, with the differences below
    %
    \inherited\setmathspacing \mathintegralcode        \mathordinarycode        \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathintegralcode        \mathdigitcode           \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathintegralcode        \mathoperatorcode        \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathintegralcode        \mathdifferentialcode    \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathintegralcode        \mathexponentialcode     \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathintegralcode        \mathimaginarycode       \allmathstyles    \pettymuskip
    %
    % \im{1\unit{hour} 20 \unit{minute} 56 \unit{second}}
    %
    \inherited\setmathspacing \mathdimensioncode       \mathdigitcode           \allmathstyles    \thickmuskip
    \inherited\setmathspacing \mathdimensioncode       \mathbinarycode          \allsplitstyles   \medmuskip
    \inherited\setmathspacing \mathdimensioncode       \mathbinarycode          \allunsplitstyles \pettymuskip
    \inherited\setmathspacing \mathdimensioncode       \mathrelationcode        \allsplitstyles   \thickmuskip
    \inherited\setmathspacing \mathdimensioncode       \mathrelationcode        \allunsplitstyles \pettymuskip
    %
    \inherited\setmathspacing \mathfakecode            \mathallcode             \allmathstyles    \tinymuskip
    \inherited\setmathspacing \mathallcode             \mathfakecode            \allmathstyles    \tinymuskip
    %
    \inherited\setmathspacing \mathtextpunctuationcode \mathordinarycode        \allmathstyles    \mathinterwordmuskip
    \inherited\setmathspacing \mathtextpunctuationcode \mathoperatorcode        \allmathstyles    \mathinterwordmuskip
    \inherited\setmathspacing \mathtextpunctuationcode \mathbinarycode          \allmathstyles    \mathinterwordmuskip
    \inherited\setmathspacing \mathtextpunctuationcode \mathrelationcode        \allmathstyles    \mathinterwordmuskip
    \inherited\setmathspacing \mathtextpunctuationcode \mathopencode            \allmathstyles    \mathinterwordmuskip
    \inherited\setmathspacing \mathtextpunctuationcode \mathmiddlecode          \allmathstyles    \mathinterwordmuskip
    \inherited\setmathspacing \mathtextpunctuationcode \mathclosecode           \allmathstyles    \mathinterwordmuskip
    \inherited\setmathspacing \mathtextpunctuationcode \mathpunctuationcode     \allmathstyles    \mathinterwordmuskip
    \inherited\setmathspacing \mathtextpunctuationcode \mathconstructcode       \allmathstyles    \mathinterwordmuskip
    \inherited\setmathspacing \mathtextpunctuationcode \mathellipsiscode        \allmathstyles    \mathinterwordmuskip
    \inherited\setmathspacing \mathtextpunctuationcode \mathfractioncode        \allmathstyles    \mathinterwordmuskip
    \inherited\setmathspacing \mathtextpunctuationcode \mathradicalcode         \allmathstyles    \mathinterwordmuskip
    \inherited\setmathspacing \mathtextpunctuationcode \mathdifferentialcode    \allmathstyles    \mathinterwordmuskip
    \inherited\setmathspacing \mathtextpunctuationcode \mathpunctuationcode     \allmathstyles    \mathinterwordmuskip
    %
    \inherited\setmathspacing \mathordinarycode        \mathtextpunctuationcode \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathoperatorcode        \mathtextpunctuationcode \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathbinarycode          \mathtextpunctuationcode \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathrelationcode        \mathtextpunctuationcode \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathopencode            \mathtextpunctuationcode \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathmiddlecode          \mathtextpunctuationcode \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathclosecode           \mathtextpunctuationcode \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathpunctuationcode     \mathtextpunctuationcode \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathconstructcode       \mathtextpunctuationcode \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathellipsiscode        \mathtextpunctuationcode \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathfractioncode        \mathtextpunctuationcode \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathradicalcode         \mathtextpunctuationcode \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathdifferentialcode    \mathtextpunctuationcode \allmathstyles    \pettymuskip
    \inherited\setmathspacing \mathpunctuationcode     \mathtextpunctuationcode \allmathstyles    \pettymuskip
    %
    % todo: check with relation and see where it differs
    %
    \inherited\setmathspacing \mathimplicationcode     \mathordinarycode        \alldisplaystyles \thickermuskip
    \inherited\setmathspacing \mathimplicationcode     \mathbinarycode          \alldisplaystyles \thickermuskip
    \inherited\setmathspacing \mathimplicationcode     \mathdigitcode           \alldisplaystyles \thickermuskip
    \inherited\setmathspacing \mathordinarycode        \mathimplicationcode     \alldisplaystyles \thickermuskip
    \inherited\setmathspacing \mathbinarycode          \mathimplicationcode     \alldisplaystyles \thickermuskip
    \inherited\setmathspacing \mathdigitcode           \mathimplicationcode     \alldisplaystyles \thickermuskip
    \inherited\setmathspacing \mathclosecode           \mathimplicationcode     \alldisplaystyles \thickermuskip
    \inherited\setmathspacing \mathradicalcode         \mathimplicationcode     \alldisplaystyles \thickermuskip
    \inherited\setmathspacing \mathfractioncode        \mathimplicationcode     \alldisplaystyles \thickermuskip
    \inherited\setmathspacing \mathfunctioncode        \mathimplicationcode     \alldisplaystyles \thickermuskip
    \inherited\setmathspacing \mathoperatorcode        \mathimplicationcode     \alldisplaystyles \thickermuskip
    \inherited\setmathspacing \mathellipsiscode        \mathimplicationcode     \alldisplaystyles \thickermuskip
    \inherited\setmathspacing \mathconstructcode       \mathimplicationcode     \alldisplaystyles \thickermuskip
    \inherited\setmathspacing \mathghostcode           \mathimplicationcode     \alldisplaystyles \thickermuskip
    \inherited\setmathspacing \mathwrappedcode         \mathimplicationcode     \alldisplaystyles \thickermuskip
\stopsetups

\directsetup{math:spacing:default}
\directsetup{math:spacing:presets}

% \dorecurse{80}{test \m[i:tight]{\red \fakeformula} test }

%setupmathematics            [\c!setups=math:spacing:default]

\definemathematics[i:default][\c!setups=math:spacing:equal]
\definemathematics[i:half]   [\c!setups=math:spacing:half]
\definemathematics[i:tight]  [\c!setups=math:spacing:tight]
\definemathematics[i:fixed]  [\c!setups=math:spacing:fixed]

% Normally the next is applied to only one character.
%
% $ABC$ $\cal ABC$ $\mathaltcal ABC$

% todo: only in mmode
% these commands are semi-public but should not be used directly (lua names wil change)

%permanent\protected\def\setmathattribute  #1#2{\ifmmode\clf_setmathattribute{#1}{#2}\fi}
%permanent\protected\def\setmathalphabet     #1{\ifmmode\clf_setmathalphabet{#1}\fi}
%permanent\protected\def\setmathfontstyle    #1{\ifmmode\clf_setmathstyle{#1}\fi}
%permanent\protected\def\setmathfontalternate#1{\ifmmode\clf_setmathalternate{#1}\fi}

\installcorenamespace{mathstylealternative} % might become a setuphandler

\permanent\protected\def\setmathfontstylealternate#1%
  {\ifcsname\??mathstylealternative\fontclass:#1\endcsname
     \expandafter\setmathfontalternate\lastnamedcs
   \orelse\ifcsname\??mathstylealternative#1\endcsname
     \expandafter\setmathfontalternate\lastnamedcs
   \fi}

\permanent\tolerant\protected\def\setupmathrendering[#1]#*[#S#2]% the name might change
  {\ifparameter#2\or
     \getparameters[\??mathstylealternative#1:][#2]%
   \else
     \getparameters[\??mathstylealternative][#1]%
   \fi}

\appendtoks
    \edef\p_stylealternative{\mathematicsparameter\c!stylealternative}%
    \ifempty\p_stylealternative\else
        \presetmathfontalternate{\p_stylealternative}%
    \fi
\to \everymathematics

% if there were many features we could have a feature pass over math nodes but it makes no
% sense now so we have commands to deal with it

% \enabletrackers[math.alternates]
% \setupbodyfont[lucidaot]
%
% \startTEXpage
%     \setupmathematics[stylealternative={reset}]$x+\mathcal A$\par
%     \setupmathematics[stylealternative={reset,calligraphic}]$x+\mathcal A$\par
%     \setupmathematics[stylealternative={reset,italic}]$x+\mathcal A$\par
%     \setupmathematics[stylealternative={reset,calligraphic,italic}]$x+\mathcal A$
% \stopTEXpage

% no longer needed now we have enforce so the next few lines will go

% \pushoverloadmode
%     \enforced\let\dotlessi\dotlessi
%     \enforced\let\dotlessj\dotlessj
% \popoverloadmode

\permanent\protected\def\mathaltcalligraphic{\setmathfontalternate{calligraphic}\cal}          % set via goody file
\permanent\protected\def\mathaltitalic      {\setmathfontalternate{italic}}                    % set via goody file
\permanent\protected\def\mathslashedzero    {\begingroup\setmathfontalternate{zero}∅\endgroup} % set via goody file or automatic
\permanent\protected\def\mathdotless        {\setmathfontalternate{dotless}}                   % set via goody file or automatic
\permanent\protected\def\mathdotfull        {\setmathfontalternate{-dotless}}
\permanent\protected\def\mathdotlessi       {\begingroup\mathdotless i\endgroup}
\permanent\protected\def\mathdotlessj       {\begingroup\mathdotless j\endgroup}

\aliased\let\mathaltcal\mathaltcalligraphic
\aliased\let\mathaltit \mathaltitalic

%aliased\let\textslashedzero\slashedzero \permanent\protected\def\autoslashedzero{\mathortext\mathslashedzero\textslashedzero}
\aliased\let\textdotlessi   \dotlessi    \permanent\protected\def\autodotlessi   {\mathortext\mathdotlessi   \textdotlessi}
\aliased\let\textdotlessj   \dotlessj    \permanent\protected\def\autodotlessj   {\mathortext\mathdotlessj   \textdotlessj}

\appendtoks
    %enforced\let\slashedzero\autoslashedzero
    \enforced\let\dotlessi\autodotlessi
    \enforced\let\dotlessj\autodotlessj
\to \everymathematics

\aliased\let\setmathfontalternative     \setmathfontalternate
\aliased\let\setmathfontstylealternative\setmathfontstylealternate
\aliased\let\mathalternate              \setmathfontalternate

\permanent\protected\def\math_upright     {\setmathattribute\s!regular\s!tf\setmathfontstylealternate\s!tf}
\permanent\protected\def\math_italic      {\setmathattribute\s!regular\s!it\setmathfontstylealternate\s!it}
%permanent\protected\def\math_script      {\setmathalphabet \s!script      \setmathfontstylealternate\s!script\setmathvariant\s!handwriting}
%permanent\protected\def\math_calligraphic{\setmathalphabet \s!script      \setmathfontstylealternate\s!script\setmathvariant\s!calligraphy}
\permanent\protected\def\math_script      {\setmathalphabet \s!script      \setmathfontstylealternate\s!script}
\permanent\protected\def\math_calligraphic{\setmathalphabet \s!calligraphic\setmathfontstylealternate\s!calligraphic}
\permanent\protected\def\math_fraktur     {\setmathalphabet \s!fraktur     \setmathfontstylealternate\s!fraktur}
\permanent\protected\def\math_blackboard  {\setmathalphabet \s!blackboard  \setmathfontstylealternate\s!blackboard}

\permanent\protected\def\mathupright     {\mathgroupedcommandcs\math_upright     }
\permanent\protected\def\mathitalic      {\mathgroupedcommandcs\math_italic      }
\permanent\protected\def\mathscript      {\mathgroupedcommandcs\math_script      }
\permanent\protected\def\mathcalligraphic{\mathgroupedcommandcs\math_calligraphic}
\permanent\protected\def\mathfraktur     {\mathgroupedcommandcs\math_fraktur     }
\permanent\protected\def\mathblackboard  {\mathgroupedcommandcs\math_blackboard  }

\permanent\protected\def\math_rm{\setmathattribute\s!rm\s!tf\setmathfontstylealternate\s!tf}
\permanent\protected\def\math_ss{\setmathattribute\s!ss\s!tf\setmathfontstylealternate\s!tf}
\permanent\protected\def\math_tt{\setmathattribute\s!tt\s!tf\setmathfontstylealternate\s!tf}

\permanent\protected\def\math_tf{\setmathfontstyle\s!tf\setmathfontstylealternate\s!tf}
\permanent\protected\def\math_sl{\setmathfontstyle\s!it\setmathfontstylealternate\s!it} % no sl
\permanent\protected\def\math_it{\setmathfontstyle\s!it\setmathfontstylealternate\s!it}

\permanent\protected\def\math_bf{\setmathfontstyle\s!bf\setmathfontstylealternate\s!bf}
\permanent\protected\def\math_bs{\setmathfontstyle\s!bi\setmathfontstylealternate\s!bi} % no sl
\permanent\protected\def\math_bi{\setmathfontstyle\s!bi\setmathfontstylealternate\s!bi}

\permanent\protected\def\mathrm{\mathgroupedcommandcs\math_rm} % \relax not needed
\permanent\protected\def\mathss{\mathgroupedcommandcs\math_ss}
\permanent\protected\def\mathtt{\mathgroupedcommandcs\math_tt}

\permanent\protected\def\mathtf{\mathgroupedcommandcs\math_tf}
\permanent\protected\def\mathsl{\mathgroupedcommandcs\math_sl}
\permanent\protected\def\mathit{\mathgroupedcommandcs\math_it}

\permanent\protected\def\mathbf{\mathgroupedcommandcs\math_bf}
\permanent\protected\def\mathbs{\mathgroupedcommandcs\math_bs}
\permanent\protected\def\mathbi{\mathgroupedcommandcs\math_bi}

\aliased\let\math_default\math_italic
\aliased\let\mathdefault \math_italic

\appendtoks
    \ifcstok{\mathematicsparameter\c!default}\v!normal
      \enforced\let\mathdefault \math_upright
      \enforced\let\math_default\math_upright
    \else
      \enforced\let\mathdefault \math_italic
      \enforced\let\math_default\math_italic
    \fi
% \to \everysetupmathematics
\to \everyswitchmathematics

\setupmathematics
  [\c!default=\v!italic]

\aliased\let\tfmath\mathtf % maybe a grouped command
\aliased\let\slmath\mathsl
\aliased\let\itmath\mathit

\aliased\let\bfmath\mathbf
\aliased\let\bsmath\mathbs
\aliased\let\bimath\mathbi

\aliased\let\Bbb\mathblackboard

\permanent\protected\def\frak      {\ifmmode\expandafter\mathfraktur     \fi}
\permanent\protected\def\cal       {\ifmmode\expandafter\mathcalligraphic\fi}
\permanent\protected\def\bbd       {\ifmmode\expandafter\mathblackboard  \fi}
\permanent\protected\def\blackboard{\ifmmode\expandafter\mathblackboard  \fi}
\permanent\protected\def\fraktur   {\ifmmode\expandafter\mathfraktur     \fi}
\permanent\protected\def\gothic    {\ifmmode\expandafter\mathfraktur     \fi}

\aliased\let\mathcal \mathcalligraphic % for AMS compatibility
\aliased\let\mathscr \mathscript       % for AMS compatibility
\aliased\let\mathfrak\mathfraktur      % for AMS compatibility
\aliased\let\mathbb  \mathblackboard   % for AMS compatibility

\ifdefined\normaltf \else \permanent\let\normaltf\tf \fi \permanent\protected\def\tf{\ifmmode\expandafter\mathtf\else\expandafter\normaltf\fi}
\ifdefined\normalbf \else \permanent\let\normalbf\bf \fi \permanent\protected\def\bf{\ifmmode\expandafter\mathbf\else\expandafter\normalbf\fi}
\ifdefined\normalit \else \permanent\let\normalit\it \fi \permanent\protected\def\it{\ifmmode\expandafter\mathit\else\expandafter\normalit\fi}
\ifdefined\normalsl \else \permanent\let\normalsl\sl \fi \permanent\protected\def\sl{\ifmmode\expandafter\mathsl\else\expandafter\normalsl\fi}
\ifdefined\normalbi \else \permanent\let\normalbi\bi \fi \permanent\protected\def\bi{\ifmmode\expandafter\mathbi\else\expandafter\normalbi\fi}
\ifdefined\normalbs \else \permanent\let\normalbs\bs \fi \permanent\protected\def\bs{\ifmmode\expandafter\mathbs\else\expandafter\normalbs\fi}

\permanent\protected\def\rm{\ifmmode\expandafter\mathrm\else\expandafter\normalrm\fi}
\permanent\protected\def\ss{\ifmmode\expandafter\mathss\else\expandafter\normalss\fi}
\permanent\protected\def\tt{\ifmmode\expandafter\mathtt\else\expandafter\normaltt\fi}

\ifdefined\mr \else \let\mr\relax \fi % hm ... permanent
\ifdefined\mb \else \let\mb\relax \fi % hm ... permanent

% 1: $\setmathattribute{ss}{bf}3$
% 2: $\setmathattribute{ss}{bf}\setmathfontstylealternate{bf}3$
% 3: $\setmathattribute{ss}{bf}\setmathfontstyle{bf}3$
% 4: $\setmathattribute{ss}{bf}\setmathfontstyle{bf}\setmathfontstylealternate{bf}3$
% 5: $e=mc^2 \quad \mb e=mc^2$

\prependtoks
    \math_default
\to \everymathematics

%D We could set the rendering attribute at the \LUA\ end but as there can be many
%D small math snippets we keep track of the state at the \TEX\ end (mapping is
%D export safe).
%D
%D \starttyping
%D \startformula
%D     \reals {\mathbf R} \utfchar{"0211D} \utfchar{"1D411}
%D \stopformula
%D
%D \setupmathematics
%D   [symbolset=blackboard-to-bold]
%D
%D \startformula
%D     \reals {\mathbf R} \utfchar{"0211D} \utfchar{"1D411}
%D \stopformula
%D \stoptyping

\newinteger\c_math_renderings_attribute

\appendtoks
    \c_math_renderings_attribute\clf_mathrenderset{\mathematicsparameter\c!symbolset}\relax
% \to \everysetupmathematics % only in mathematics
\to \everyswitchmathematics

\appendtoks
    \ifcase\c_math_renderings_attribute\else
        \c_attr_mathrendering\c_math_renderings_attribute
    \fi
\to \everymathematics

\setupmathematics
  [\c!symbolset=]

%D \macros
%D   {boldsymbol}
%D
%D To be done.

\mutable\let\mathboldsymbol\relax % yet unsupported, will be

\permanent\protected\def\boldsymbol
  {\mathortext\mathboldsymbol\bold}

%D Helpers (defined at the \LUA\ end):

% \utfmathclass          #1
% \utfmathstretch        #1
% \utfmathcommand        #1
% \utfmathfiller         #1
%
% \utfmathcommandabove   #1..
% \utfmathcommandbelow   #1..
% \utfmathcommandfiller  #1..
%
% \doifelseutfmathaccent #1#2#3
% \doifelseutfmathabove  #1#2#3
% \doifelseutfmathbelow  #1#2#3
% \doifelseutfmathfiller #1#2#3
% \doifelseutfmathlimop  #1#2#3

\aliased\let\doifutfmathaccentelse \doifelseutfmathaccent
\aliased\let\doifutfmathaboveelse  \doifelseutfmathabove
\aliased\let\doifutfmathbelowelse  \doifelseutfmathbelow
\aliased\let\doifutfmathfillerelse \doifelseutfmathfiller
\aliased\let\doifutfmathlimopelse  \doifelseutfmathlimop

%D Not used that much:

\permanent\protected\def\mathlimop#1{\normalmathop{#1}} %no \limits
\permanent\protected\def\mathbox  #1{\dontleavehmode\hbox\Ustartmath\mathsurround\zeropoint#1\Ustopmath}
\permanent\protected\def\mathnolop#1{\normalmathop{#1}\nolimits}

% \permanent\protected\def\mathlimop#1{\mathatom \mathoperatorcode options "C0000 {#1}} % auto "40000 + "80000
% \permanent\protected\def\mathnolop#1{\mathatom \mathoperatorcode options "80000 {#1}}

% \aliased\let\mathnothing\firstofoneunexpanded
% \aliased\let\mathalpha  \firstofoneunexpanded

\ifdefined\mathop    \else \aliased\let\mathop   \normalmathoperator    \aliased\let\normalmathop   \normalmathoperator    \fi
\ifdefined\mathord   \else \aliased\let\mathord  \normalmathordinary    \aliased\let\normalmathord  \normalmathordinary    \fi
\ifdefined\mathbin   \else \aliased\let\mathbin  \normalmathbinary      \aliased\let\normalmathbin  \normalmathbinary      \fi
\ifdefined\mathrel   \else \aliased\let\mathrel  \normalmathrelation    \aliased\let\normalmathrel  \normalmathrelation    \fi
\ifdefined\mathpunct \else \aliased\let\mathpunct\normalmathpunctuation \aliased\let\normalmathpunct\normalmathpunctuation \fi

\ifdefined\underline \else \aliased\let\underline\normalmathunderline   \aliased\let\normalunderline\normalmathunderline   \fi
\ifdefined\overline  \else \aliased\let\overline \normalmathoverline    \aliased\let\normaloverline \normalmathoverline    \fi

\permanent\def\mathcodechecked#1%
  {\numexpr
     \ifempty{#1}%
       \mathordinarycode
     \orelse\ifchknumber#1\or
       \lastchknumber
     \orelse\ifchknumber\begincsname math#1code\endcsname\or % maybe some day a hash for this
       \lastchknumber
     \else
       \mathordinarycode
     \fi
   \relax}

\permanent\def\mathcodenumber#1%
  {\the\mathcodechecked{#1}}

\permanent\protected\def\mathcodecommand#1%
  {\mathatom \s!class \mathcodechecked{#1}}

\permanent\protected\def\mathcodeallcommand#1#2%
  {\mathatom \s!class \mathcodechecked{#1} \s!all \mathcodechecked{#2}}

\def\math_class_by_parameter    #1#2{\expanded{\noexpand\mathcodechecked{#1#2}}}
\def\math_atom_by_parameter       #1{\expanded{\noexpand\math_atom_by_parameter_indeed{#1\c!mathclass}}}
\def\math_atom_by_parameter_indeed#1{\mathatom \s!class \mathcodechecked{#1}}

% \startlines
% $\mathopnolimits{\rm d}x$
% $\mathopnolimits{\kern\zeropoint \rm d}x$
% $\mathcodecommand{nolop}{\rm d}x$
% $\mathcodecommand{nolop}{\kern\zeropoint\rm d}x$
% \blank
% $\mathcodecommand{nolop}{\mr d}x$
% $\mathcodecommand{nolop}{\kern\zeropoint\mr d}x$
% $\mathop{\kern\zeropoint\mr d}x$
% $\mathopnolimits{\kern\zeropoint d}x$
% \stoplines

\installcorenamespace{mathcommand}

\permanent\tolerant\protected\def\definemathcommand[#1]#*[#2]#*[#3]#:#*#4% command class args meaning
  {\ifparameter#3\or
     \ifcstok{#3}\v!one
       \frozen\protected\defcsname\??mathcommand#1\endcsname##1{\mathcodecommand{#2}{#4{##1}}}%
     \orelse\ifcstok{#3}\v!two
       \frozen\protected\defcsname\??mathcommand#1\endcsname##1##2{\mathcodecommand{#2}{#4{##1}{##2}}}%
     \orelse\ifchknum\mathcodechecked{#3}\or
       \frozen\protected\defcsname\??mathcommand#1\endcsname{\mathcodeallcommand{#2}{#3}{#4}}%
     \else
       \frozen\protected\defcsname\??mathcommand#1\endcsname{\mathcodecommand{#2}{#4}}%
     \fi
   \orelse\ifparameter#2\or
     \frozen\protected\defcsname\??mathcommand#1\endcsname{\mathcodecommand{#2}{#4}}%
   \else
     \frozen\protected\defcsname\??mathcommand#1\endcsname{#4}%
   \fi
   \ifparameter#1\or % safeguard
     \letcsname#1\expandafter\endcsname\csname\??mathcommand#1\endcsname
   \fi}

\permanent\protected\def\mathcommand#1%
  {\begincsname\??mathcommand#1\endcsname}

% \definemathsymbol[wedontlikethisone][3]["2979]
% \definemathsymbol[wedontlikethisone][relation]["2979]

\permanent\tolerant\protected\def\definemathsymbol[#1]#*[#2]#*[#3]%
  {\frozen\expandafter\Umathchardef\csname#1\endcsname
     \ifparameter#3\or
        \mathcodechecked{#2}%
        \zerocount
        \numexpr#3% \relax
    \else
        \zerocount
        \zerocount
        \numexpr#2% \relax
    \fi\relax}

%D Let's define a few comands here:

%definemathcommand [mathstrut]               {\vphantom{(}}
%definemathcommand [joinrel]                 {\mathrel{\mkern-3mu}}
%definemathcommand [joinrel]   [\s!relation] {\mkern-3mu}

\permanent\integerdef\c_math_strut_default "28

\permanent\chardef\c_math_strut\c_math_strut_default

%D For the evolution of these struts see the git repositories and older code in
%D \MKIV\ and \MKI\ (commented code removed end April 2022).

\let\math_strut_math_style\normalmathstyle

% using \s!font \mathstylefontid\mathstyle\fam would needs expansion and guesswork

\appendtoks
    \Umathruleheight\allmainstyles        \strutheightfactor\fontspecifiedsize\textfont        \zerocount
    \Umathruledepth \allmainstyles        \strutdepthfactor \fontspecifiedsize\textfont        \zerocount
    \Umathruleheight\allscriptstyles      \strutheightfactor\fontspecifiedsize\scriptfont      \zerocount
    \Umathruledepth \allscriptstyles      \strutdepthfactor \fontspecifiedsize\scriptfont      \zerocount
    \Umathruleheight\allscriptscriptstyles\strutheightfactor\fontspecifiedsize\scriptscriptfont\zerocount
    \Umathruledepth \allscriptscriptstyles\strutdepthfactor \fontspecifiedsize\scriptscriptfont\zerocount
\to \everybodyfont

% The unset height and depth default to this sig nal that then tells the engine
% what to apply from the char dimensions.

\protected\def\math_strut
  {\normalsrule
     %s!width \zeropoint
     \s!fam   \fam
     \s!char  \c_math_strut
   \relax}

\permanent\protected\def\math_strut_height
  {\normalsrule
     %s!width \zeropoint
     \s!depth \zeropoint
     \s!fam   \fam
     \s!char  \c_math_strut
   \relax}

\permanent\protected\def\math_strut_depth
  {\normalsrule
     %s!width \zeropoint
     \s!height\zeropoint
     \s!fam   \fam
     \s!char  \c_math_strut
   \relax}

\appendtoks
    \enforced\chardef\c_math_strut\mathstrutcode\c_math_strut_default
\to \everymathematics

\permanent\protected\def\showmathstruts % let's not overload \math_strut_normal
  {\showmakeup[strut]}

\pushoverloadmode
    \permanent\protected\def\mathstrut      {\math_strut}
    \permanent\protected\def\mathheightstrut{\math_strut_height}
    \permanent\protected\def\mathdepthstrut {\math_strut_depth}
\popoverloadmode

% \permanent\protected\def\topstrut{\normalsrule\s!width\zeropoint\s!height\strutht  \s!depth\zeropoint\relax}
% \permanent\protected\def\botstrut{\normalsrule\s!width\zeropoint\s!height\zeropoint\s!depth\strutdp  \relax}

\permanent\protected\def\topstrut{\normalsrule\s!height\strutht\relax}
\permanent\protected\def\botstrut{\normalsrule\s!depth \strutdp\relax}

% \newdimension\mathstrutht % see top
% \newdimension\mathstrutdp % see top

\appendtoks
    \mathstrutht\strutht
    \mathstrutdp\strutdp
  % \writestatus{!!!!!!}{\the\mathstrutht,\the\mathstrutdp}%
\to \everymathematics

%D We could have a arg variant \unknown\ but not now.

\permanent\protected\def\mathopwithlimits#1#2{\mathop{#1{#2}}\limits}
\permanent\protected\def\stackrel        #1#2{\mathrel{\mathop{#2}\limits^{#1}}}

%D Moved from font-ini.mkiv:
%D
%D \macros
%D   {mf,mbox,enablembox,mathop}
%D
%D Todo:

\permanent\protected\def\mf{\begincsname\fontalternative\endcsname} % todo: \frozen

% \let\normalmathop\mathop % already defined

\permanent\protected\def\normalmbox
  {\normalhbox\bgroup
   \usemathematicsstyleandcolor\c!textstyle\c!textcolor % new
   \dowithnextboxcs\math_mbox_finish\normalhbox}

\def\math_mbox_finish
  {\flushnextbox
   \egroup}

\permanent\protected\def\mbox % we cannot add \dontleavehmode ... else no \setbox0\mbox possible
  {\ifmmode\normalmbox\else\normalhbox\fi}

\permanent\protected\def\enablembox
  {\toksapp\everymathematics{\math_enable_mbox}}

\permanent\def\math_enable_mbox % brrrr
  {\enforced\let\hbox\mbox}

\permanent\protected\def\snappedmath#1% sort of \struttedbox
  {\dontleavehmode
   \begingroup
   \setbox\scratchbox\normalhbox\bgroup
     \startimath#1\stopimath
   \egroup
   \ht\scratchbox\strutht
   \dp\scratchbox\strutdp
   \box\scratchbox
   \endgroup}

\permanent\protected\def\mtext#1%
  {\begingroup
   \currentmathblobnesting\minusone
   \dostarttaggednodetail\t!mtext
   \text{\usemathematicsstyleandcolor\c!textstyle\c!textcolor#1}%
   \dostoptagged
   \endgroup}

% \protected\permanent\def\textmathematics#1%
%   {\begingroup
%    \currentmathblobnesting\minusone
%    \mathematics{#1}%
%    \endgroup}

\protected\permanent\def\math_text_indeed#1%
  {\begingroup
   \currentmathblobnesting\minusone#1%
   \endgroup}

\protected\permanent\def\textmathematics
  {\ifmmode
     \expandafter\firstofoneargument
   \else
     \expandafter\math_text_indeed
   \fi}

%D The next hack is needed needed for sine, cosine etc.

\aliased\let\mathfunction\firstofoneunexpanded

\let\math_tags_function         \firstofoneunexpanded
\let\math_tags_functionlabeltext\mathlabeltext

% \let\math_tags_mo\firstofoneunexpanded
% \let\math_tags_mi\firstofoneunexpanded

% \protected\def\math_tags_mn#1{\begingroup\math_upright\math_set_o_both#1\endgroup}
% \protected\def\math_tags_ms#1{\begingroup\math_upright\math_set_p_both#1\endgroup} % why not just \text

% Once this is stable we can store the number at the tex end which is
% faster. Functions getnumbers >= 1000.

% \setupmathematics[functionstyle=normal] % will give ligatures and kerning

\setupmathematics
  [\c!textstyle=,     % rm ss etc i.e. known alternatives, otherwise math
   \c!textcolor=,
   \c!functionstyle=, % rm ss etc i.e. known alternatives, otherwise math
   \c!functioncolor=]

% in char-def:
%
%
% \Umathcode"2061 = \mathghostcode \zerocount "2061 % \applyfunction
% \Umathcode"2062 = \mathghostcode \zerocount "2062 % \invisibletimes
% \Umathcode"2063 = \mathghostcode \zerocount "2063 % \invisiblecomma
% \Umathcode"2064 = \mathghostcode \zerocount "2063 % \invisibleplus

%D For previous variants of the function styling you can check the git repository
%D end April 2022. We dropped the optional apply feature.

% \startTEXpage[offset=1dk]
%                           $\sin(x) = 10$
%     \m[functionstyle=sans]{\sin(x) = 10}
%     \startformula                     \sin(x) = 10 \stopformula
%     \startformula[functionstyle=sans] \sin(x) = 10 \stopformula
% \stopTEXpage

\installcorenamespace{mathfunction}

\installcommandhandler \??mathfunction {mathfunction} \??mathfunction

\appendtoks
    \protected\frozen\instance\edefcsname\currentmathfunction\endcsname{\math_function_handle\plusone{\currentmathfunction}{}}% \instance
\to \everydefinemathfunction

\aliased\let\setupmathfunctions\setupmathfunction

\setupmathfunctions
  [\c!color=\mathematicsparameter\c!functioncolor,
   \c!style=\mathematicsparameter\c!functionstyle,
   \s!class=function]

\newconstant\c_function_method

\def\math_function_handle_normal#1#2#3%
  {\begingroup
   \mathdotfull
   \cdef\currentmathfunction{#2}%
   \setupcurrentmathfunction[#3]%
   \edef\p_limits{\mathfunctionparameter\c!mathlimits}%
   \edef\p_left{\mathfunctionparameter\c!left}%
   \edef\p_right{\mathfunctionparameter\c!right}%
   \c_function_method
     \ifempty\p_left
       \ifempty\p_right
         \zerocount % prefix no argument
       \else
         \plustwo % postfix with argument
       \fi
     \orelse\ifempty\p_right
       \plusone % prefix with argument
     \else
       \plusthree % pre- and postfix with argument
     \fi
   \ifcase\c_function_method
     \expandafter\math_function_handle_normal_string
   \else
     \expandafter\math_function_handle_normal_symbol
   \fi#1} % constant

\def\math_function_handle_normal_string#1%
  {\dostarttagged\t!mfunction\currentmathfunction% todo: pass lab id
   \math_tags_mfunctionlab\plusone{\currentmathfunction}{\mathfunctionparameter\c!method}%
   \mathatom
     mathfont
     single % behave like a character
     class \mathcodechecked{\mathfunctionparameter\s!class}
     \ifx\p_limits\v!no
       nolimits
     \orelse\ifx\p_limits\v!yes
       limits
     \orelse\ifx\p_limits\v!auto
       nolimits
       limits
     \fi
 % \ifcstok{\mathfunctionparameter\c!mathlimits}\v!no
 %   nolimits
 % \orelse\iflastnamedcs\v!yes
 %   limits
 % \orelse\iflastnamedcs\v!auto
 %   nolimits
 %   limits
 % \fi
   \bgroup % textfont but can be anything
   \usemathfunctioncolorparameter\c!color
   \edef\p_functionstyle{\mathfunctionparameter\c!style}%
   % no need for \expandafter here
   \ifempty\p_functionstyle
     \expandafter\math_upright
   \orelse\ifcsname\??alternativestyle\p_functionstyle\endcsname
     \expandafter\lastnamedcs
   \else
     \expandafter\p_functionstyle
   \fi
%    \ifcase#1\or % so #1 can go away
     \mathlabeltext{\currentmathfunction}%
     % needed for StixTwo Diff
     \scratchdimen\rightmathkern{\currentmathfunction}%
     \ifzeropt\scratchdimen\else\hkern\scratchdimen\fi
%    \fi
   \egroup
   \dostoptagged
   \endgroup}

\definesystemattribute[mathstack][public]

\newinteger\c_mathfunctionstack

\def\math_function_handle_normal_symbol#1#2%
  {\global\advanceby\c_mathfunctionstack\plusone
   \attribute\mathstackattribute\c_mathfunctionstack
   \math_tags_mfunctionlab\plusone{\currentmathfunction}{\mathfunctionparameter\c!method}%
   \dostarttagged\t!mfunctionstack\currentmathfunction
   \mathghost carryover \bgroup
      \p_left
      \begingroup
      \attribute\mathstackattribute\attributeunsetvalue
      #2%
      \endgroup
      \p_right
   \egroup
   \dostoptagged
   \endgroup}

\def\math_function_handle_language_indeed#1#2#3%
  {\cdef\currentmathfunction{#2}%
   \setupcurrentmathfunction[#3]%
   \edef\p_command{\mathfunctionparameter\c!command}%
   \ifempty\p_command
     \endgroup\math_function_handle_normal#1{#2}{#3}%
   \else
     \expanded{\endgroup\p_command\expandafter}%
   \fi}

\def\math_function_handle_language#1#2%
  {\begingroup
   \let\math_function_handle\math_function_handle_language_indeed
   \csname\currentmainlanguage:#2\endcsname}

\tolerant\protected\def\math_function_handle#1#2#3%
  {\ifcsname\currentmainlanguage:#2\endcsname
     \expandafter\math_function_handle_language
   \else
     \expandafter\math_function_handle_normal
   \fi#1{#2}{#3}}

\permanent\tolerant\protected\def\mfunctionlabeltext[#1]%
  {\math_function_handle\plusone{#1}{}}

% \mfunction [settings][name]  [settings]{name}  [name]  {name}

\permanent\tolerant\protected\def\mfunction[#1]%
  {\ifhastok={#1}%
     \expandafter\mfunction_yes
   \orelse\ifparameter#1\or
     \expandafter\mfunction_nop
   \else
     \expandafter\mfunction_yop
   \fi{#1}}

\permanent\tolerant\protected\def\mfunction_yes#1#*[#2]#;#3{\math_function_handle\zerocount{#2#3}{#1}}
\permanent\protected\def\mfunction_nop                   #1{\math_function_handle\zerocount{#1}{}}
\permanent\protected\def\mfunction_yop                 #1#2{\math_function_handle\zerocount{#2}{}}

\appendtoks
%     \edef\p_functionstyle{\formulaparameter\c!functionstyle}%
%     \ifempty\p_functionstyle\else
%         \letmathematicsparameter\c!functionstyle\p_functionstyle
%     \fi
%     \edef\p_functioncolor{\formulaparameter\c!functioncolor}%
%     \ifempty\p_functioncolor\else
%         \letmathematicsparameter\c!functioncolor\p_functioncolor
%     \fi
\to \everybeforedisplayformula

\let\math_tags_mfunctionlab         \gobblethreearguments
\def\math_tags_mfunctionlabattribute#-#-#-{\zerocount}

% \permanent\protected\def\math_tags_mo_indeed#1{\begingroup             \c_attr_mathcategory\plusone                  #1\endgroup}
% \permanent\protected\def\math_tags_mi_indeed#1{\begingroup             \c_attr_mathcategory\plustwo                  #1\endgroup}
% \permanent\protected\def\math_tags_mn_indeed#1{\begingroup\math_upright\c_attr_mathcategory\plusthree\math_set_o_both#1\endgroup}
% \permanent\protected\def\math_tags_ms_indeed#1{\begingroup\math_upright\c_attr_mathcategory\plusfour \math_set_p_both#1\endgroup} % todo: mathoptext

\permanent\protected\def\math_tags_mo#1{\mathatom \s!class \mathoperatorcode        {#1}}
\permanent\protected\def\math_tags_mi#1{\mathatom \s!class \mathordinarycode        {#1}}
%permanent\protected\def\math_tags_mn#1{\mathatom \s!class \mathdigitcode           {\math_upright #1}}
\permanent\protected\def\math_tags_ms#1{\mathatom \s!class \mathtextpunctuationcode {\math_upright #1}}

\permanent\protected\def\math_tags_mn#1%
  {\dostarttaggednodetail\t!mdigits
   \mathatom \s!class \mathdigitcode {\math_upright #1}%
   \dostoptagged}

\newconditional\c_apply_function

\ifdefined\apply \else \aliased\let\apply\relax \fi

\mutable\let\mo\relax
\mutable\let\mi\relax
\mutable\let\mn\relax
\mutable\let\ms\relax

\appendtoks
    \enforced\let\math_tags_mfunctionlab         \clf_tagmfunctionlab
    \enforced\let\math_tags_mfunctionlabattribute\clf_tagmfunctionlabattribute
\to \everyenableelements

\permanent\protected\def\registermathfunction[#1]% experimental
  {\begingroup
   \scratchcounter\clf_tagmfunctionlabattribute
     \plusone
     {#1}%
     {}%
   \endgroup}

% domain language name meaning
% language name meaning
% name meaning

\permanent\protected\def\registermathsymbol[#1]#*[#2]#*[#3]#*[#4]% experimental
  {\ifparameter#4\or
     \clf_registerverbosemathlabel{#1}{#2}{#3}{#4}%
   \orelse\ifparameter#3\or
     \clf_registerverbosemathlabel{\s!default}{#1}{#2}{#3}%
   \else
     \clf_registerverbosemathlabel{\s!default}{\s!en}{#1}{#2}%
   \fi}

\permanent\lettonothing\math_tags_apply

\appendtoks
    \enforced\let\mo   \math_tags_mo
    \enforced\let\mi   \math_tags_mi
    \enforced\let\mn   \math_tags_mn
    \enforced\let\ms   \math_tags_ms
    \enforced\let\apply\math_tags_apply
\to\everymathematics

\mutable\def\currentmscaledstyle{rm} % will be plugged into the typeface text=ss option

\permanent\protected\def\mscaledtext#1%
  {\mathchoice
     {\hbox{\csname\currentmscaledstyle\endcsname\tf  #1}}
     {\hbox{\csname\currentmscaledstyle\endcsname\tf  #1}}
     {\hbox{\csname\currentmscaledstyle\endcsname\tfx #1}}
     {\hbox{\csname\currentmscaledstyle\endcsname\tfxx#1}}}

\permanent\protected\def\setmathfunctionstyle#1%
  {\setupmathematics[\c!functionstyle=#1]} % for old times sake

%D Usage:
%D
%D \starttyping
%D \setmathfunctionstyle\fontstyle % or {rm} or {ss} or ..
%D \rm test $\sin{(x^{\sin(x^{\sin(x)})})}$ test
%D \ss test $\sin{(x^{\sin(x^{\sin(x)})})}$ test
%D \tt test $\sin{(x^{\sin(x^{\sin(x)})})}$ test
%D \stoptyping

%D \macros
%D   {nonknuthmode, donknuthmode}
%D
%D The underscore is frequently used in manuals but unfortunately \TEX\ prefers
%D it to be a math specific character. And since computer modern fonts didn't
%D have an underscore, one had to use commands to fake one. Nowadays we do
%D have underscores in latin modern, and since all other fonts have them, we
%D decided to get away from the restriction to use the underscore character in
%D text mode.
%D
%D \starttyping
%D \def\test#1{#1}
%D
%D \nonknuthmode $x_2$ x_2 \test{$x_2$} \test{x_2}
%D
%D \donknuthmode $x_2$ x_2 \test{$x_2$} \test{x_2}
%D \stoptyping
%D
%D The result is as expected: the first line typesets ok, while the second one
%D triggers an error message.

% \setnewconstant\activemathcharcode "8000
%
% \newtoks\activatedmathcharacters
%
% \permanent\protected\def\activatemathcharacter#1%
%   {\appendtoks
%      \global\mathcode#1=\activemathcharcode
%    \to \activatedmathcharacters}
%
% \permanent\def\activatemathcharacters
%   {\the\activatedmathcharacters}
%
% % beware, not runtime, so has to happen at format generation
%
% \activatemathcharacter\circumflexasciicode
% \activatemathcharacter\underscoreasciicode
% %activatemathcharacter\ampersandasciicode

% % already done in catc-def.mkxl:
%
% \amcode \circumflexasciicode \superscriptcatcode
% \amcode \underscoreasciicode \subscriptcatcode
% \amcode \barasciicode        \othercatcode
% \amcode \tildeasciicode      \othercatcode

% \Umathcode\circumflexasciicode="0 "0 \circumflexasciicode
% \Umathcode\underscoreasciicode="0 "0 \underscoreasciicode

% \permanent\def\normalmathaligntab{&}
%
% \appendtoks
%     \edef\p_ampersand{\mathematicsparameter\s!ampersand}%
%     \ifx\p_ampersand\v!normal
%         \enforced\let\specialmathaligntab\normalmathaligntab
%     \else
%         \enforced\let\specialmathaligntab\mathampersand
%     \fi
% \to \everysetupmathematics
% \to \everyswitchmathematics

%D A simplified version of this code is:
%D
%D \starttyping
%D \catcode"26=12
%D
%D \bgroup
%D     \global\mathcode"26="8000
%D
%D     \catcode"26=4
%D
%D     \xdef\normalmathaligntab{&}
%D
%D     \catcode"26=13
%D
%D     \global\everymath{\def&{\normalmathaligntab}}
%D \egroup
%D \stoptyping
%D
%D The following works okay:
%D
%D \starttyping
%D A & B
%D \stoptyping
%D
%D As does:
%D
%D \starttyping
%D $A \Umathchar"2"0"26 B$
%D \stoptyping
%D
%D But the next code:
%D
%D \starttyping
%D $A \char"26 B$
%D \stoptyping
%D
%D fails with: \type{Misplaced alignment tab character &} and here is the reason.
%D
%D When we have a letter or other category a check happens for an active character
%D and when it has one then it gets expanded and fed back into the scanner (sort
%D of).
%D
%D A \type {\char} is also fed back as raw character and again when it's letter of
%D other goes through the same process.
%D
%D This means that we cannot have a definition like:
%D
%D \starttyping
%D \def\AND{\char"26\relax}
%D \stoptyping
%D
%D that can be used in math mode, which is why the cweb macros do:
%D
%D \starttyping
%D \def\AND{\def\AND{\mathchar"2026\relax}\AND}
%D \stoptyping
%D
%D Maybe we need an option to treat chars like chars.

%D The commented prime related code (dating from \MKII\ times has been removed in
%D April 2022 but it's in the archives. In \LUAMETATEX\ primes are part of the
%D machinery and additional magic (as in \MKIV) happens elsewhere. There is no
%D need to remember old stuff because \MKII\ times are long gone.

\ifdefined \prime \else
    \Umathchardef\prime "0 "0 "2032
\fi

%D We also dropped the option to let ampersands be alignment tabs. That has never
%D been a \CONTEXT\ feature|/|habit anyway.

% \bgroup
%
%     \catcode\underscoreasciicode\activecatcode
%     \catcode\circumflexasciicode\activecatcode
%
%     \aliased\glet\specialmathaligntab\normalmathaligntab
%
%     \permanent\protected\gdef\obeymathcatcodes{%
%         \enforced\let _\normalsubscript
%         \enforced\let ^\normalsuperscript
%     }
%
%     \gtoksapp\everymathematics{\obeymathcatcodes}%
%
% \egroup

%D We keep this, just for the fun of it:

\newtoks\everydonknuthmode
\newtoks\everynonknuthmode

\newconditional \knuthmode

\aliased\let\nonknuthmode\relax % no longer needed in MkIV
\aliased\let\donknuthmode\relax % no longer needed in MkIV

% \def\nonknuthmode
%   {\pushcatcodetable
%    \setcatcodetable\ctxcatcodes
%    \expand\everynonknuthmode
%    \let\nonknuthmode\relax
%    \popcatcodetable}
%
% \def\donknuthmode
%   {\pushcatcodetable
%    \setcatcodetable\ctxcatcodes
%    \expand\everydonknuthmode
%    \popcatcodetable}
%
% \bgroup
%
%     \catcode\underscoreasciicode\activecatcode
%     \catcode\circumflexasciicode\activecatcode
%     \catcode\ampersandasciicode \activecatcode
%
%     \global \everynonknuthmode {\appendtoks
%         \let_\normalsubscript
%         \let^\normalsuperscript
%         \let&\normalmathaligntab % use \def when it's \aligntab
%     \to \everymathematics}
%
% \egroup
%
% \appendtoks
%     \knuthmode\conditionalfalse
%     \catcode\underscoreasciicode\othercatcode
%     \catcode\circumflexasciicode\othercatcode
%     \catcode\ampersandasciicode \othercatcode
% \to \everynonknuthmode
%
% \appendtoks
%     \knuthmode\conditionaltrue
%     \catcode\underscoreasciicode\subscriptcatcode
%     \catcode\circumflexasciicode\superscriptcatcode
%     \catcode\ampersandasciicode \alignmentcatcode
% \to \everydonknuthmode
%
% \appendtoks
%     \startextendcatcodetable\ctxcatcodes
%         \catcode\underscoreasciicode\othercatcode
%         \catcode\circumflexasciicode\othercatcode
%         \catcode\ampersandasciicode \othercatcode
%     \stopextendcatcodetable
% \to \everynonknuthmode
%
% \appendtoks
%     \startextendcatcodetable\ctxcatcodes
%         \catcode\underscoreasciicode\subscriptcatcode
%         \catcode\circumflexasciicode\superscriptcatcode
%         \catcode\ampersandasciicode \alignmentcatcode
%     \stopextendcatcodetable
% \to \everydonknuthmode

%D Even more drastic (this code will move as nonknuthmode is default now)

% \protected\def\enableasciimode
%   {\ctxlua{resolvers.macros.enablecomment()}%
%    \glet\enableasciimode\relax}
%
% \protected\def\asciimode
%   {\catcodetable\txtcatcodes
%    \enableasciimode
%    \nonknuthmode}
%
% \protected\def\startasciimode
%   {\pushcatcodetable
%    \catcodetable\txtcatcodes
%    \enableasciimode
%    \nonknuthmode}
%
% \protected\def\stopasciimode
%   {\popcatcodetable
%    \ifconditional\knuthmode\else\donknuthmode\fi}

\permanent\protected\def\enableasciimode
  {\clf_enableasciimode} % relaxes itself

\permanent\protected\def\asciimode
  {\catcodetable\txtcatcodes
   \clf_enableasciimode}

\permanent\protected\def\startasciimode
  {\pushcatcodetable
   \catcodetable\txtcatcodes
   \clf_enableasciimode}

\permanent\protected\def\stopasciimode
  {\popcatcodetable}

%D Needed for unicode:

\permanent\def\nulloperator{\mathortext{\mathop{\emptyhbox}}{\emptyhbox}}

%D Memory saver:

\def\math_basics_check_compact
  {\ifcstok{\mathematicsparameter\c!compact}\v!yes
     \expandafter\enabledirectives
   \else
     \expandafter\disabledirectives
   \fi
   [math.virtual.optional]}

\appendtoks
    \ifempty\currentmathematics
        \math_basics_check_compact % less tracing
    \fi
% \to \everysetupmathematics
\to \everyswitchmathematics

\setupmathematics
  [\c!compact=\v!no]

% \enabletrackers[typesetters.directions.math]

%D Right||to||left typesetting in math is supported by the \type {align} parameter
%D with as option the \type {bidi} parameter. Of course support for special symbols
%D like square roots depends on the font as well. We probably need to mirror a few
%D more characters.
%D
%D \startbuffer
%D     \removeunwantedspaces
%D     \m{   (  1 =   1)   }\quad
%D     \m{   (123 = 123)   }\quad
%D     \m{ a (  1 =   1) b }\quad
%D     \m{ a (123 = 123) b }\quad
%D     \m{ x = 123 y + (1 / \sqrt {x}) }
%D \stopbuffer
%D
%D \typebuffer
%D
%D \starttabulate[|T|T||]
%D \HL
%D \NC align \NC bidi \NC                                                  \NC \NR
%D \HL
%D \NC l2r   \NC no   \NC \setupmathematics[bidi=no]            \getbuffer \NC \NR
%D \NC l2r   \NC yes  \NC \setupmathematics[bidi=yes]           \getbuffer \NC \NR
%D \NC r2l   \NC no   \NC \setupmathematics[align=r2l,bidi=no]  \getbuffer \NC \NR
%D \NC r2l   \NC yes  \NC \setupmathematics[align=r2l,bidi=yes] \getbuffer \NC \NR
%D \HL
%D \stoptabulate

% We will use proper constants when we go numbers instead of XXX.

\newconditional\c_math_right_to_left

\installcorenamespace{mathaligndirection}

\defcsname\??mathaligndirection           r2l\endcsname{\c_math_right_to_left\conditionaltrue}
\defcsname\??mathaligndirection\v!righttoleft\endcsname{\c_math_right_to_left\conditionaltrue}

\appendtoks
    \ifcsname\??mathaligndirection\mathematicsparameter\c!align\endcsname
      \lastnamedcs
    \else
      \c_math_right_to_left\conditionalfalse
    \fi
\to \everyswitchmathematics

\protected\def\math_basics_synchronize_direction
  {\mathdirection\ifconditional\c_math_right_to_left\directionrighttoleft\else\directionlefttoright\fi}

% Not \everymathematics as it comes too late and I'm not in the mood for a mixed mode
% kludge now (should be a property of beginmath nodes and passed to callbacks).

\appendtoks
    \math_basics_synchronize_direction
\to \everyswitchmathematics

% experimental (needed for an article) .. this is is no longer neded

% \installcorenamespace {mathbidi}
%
% \newcount\c_math_bidi
%
% \def\math_bidi_enable {\clf_setmathdirection\plusone  \relax\c_math_bidi\plusone}
% \def\math_bidi_disable{\clf_setmathdirection\zerocount\relax\c_math_bidi\attributeunsetvalue}
%
% \letcsname\??mathbidi\v!yes\endcsname\math_bidi_enable
% \letcsname\??mathbidi\v!no \endcsname\math_bidi_disable
%
% \appendtoks
%     \edef\p_bidi{\mathematicsparameter\c!bidi}% still needed ?
%     \ifcsname\??mathbidi\p_bidi\endcsname\lastnamedcs\else\math_bidi_disable\fi
% \to \everysetupmathematics
% \to \everyswitchmathematics
%
% \appendtoks
%     \c_attr_mathbidi\ifconditional\c_math_right_to_left\c_math_bidi\else\attributeunsetvalue\fi
% \to \everyswitchmathematics

%D Delayed: greek.
%D
%D \starttyping
%D \usetypescript[cambria]\setupbodyfont[cambria]
%D \startTEXpage
%D     $\alpha \mathgreekupright \alpha \mathgreekitalic \alpha$
%D \stopTEXpage
%D \stoptyping

% [lc uc] normal (upright) = 2, italic = 3, none = 0/1

% We can move the setting to the lua end and use abstract numbers instead
% if funny ones here.

\installcorenamespace{mathgreek}

\newconstant\c_math_greek_attribute

\defcsname\??mathgreek\v!none  \endcsname{1}
\defcsname\??mathgreek\v!normal\endcsname{2}
\defcsname\??mathgreek\v!italic\endcsname{3}

% \appendtoks
%     \edef\p_sygreek{\mathematicsparameter\s!sygreek}% still needed ?
%     \edef\p_lcgreek{\mathematicsparameter\s!lcgreek}% still needed ?
%     \edef\p_ucgreek{\mathematicsparameter\s!ucgreek}% still needed ?
%     \c_math_greek_attribute"% hex digits
%       \ifcsname\??mathgreek\p_sygreek\endcsname\lastnamedcs\else1\fi
%       \ifcsname\??mathgreek\p_lcgreek\endcsname\lastnamedcs\else1\fi
%       \ifcsname\??mathgreek\p_ucgreek\endcsname\lastnamedcs\else1\fi
%     \relax
%     \ifcase\c_math_greek_attribute
%       \c_math_greek_attribute\attributeunsetvalue
%     \fi
% \to \everyswitchmathematics

\appendtoks
    \c_math_greek_attribute"% hex digits
      \ifcsname\??mathgreek\mathematicsparameter\s!sygreek\endcsname\lastnamedcs\else1\fi
      \ifcsname\??mathgreek\mathematicsparameter\s!lcgreek\endcsname\lastnamedcs\else1\fi
      \ifcsname\??mathgreek\mathematicsparameter\s!ucgreek\endcsname\lastnamedcs\else1\fi
    \relax
    \ifcase\c_math_greek_attribute
      \c_math_greek_attribute\attributeunsetvalue
    \fi
\to \everyswitchmathematics

% only used local

\permanent\protected\def\mathgreekupright{\c_attr_mathgreek"222\relax}
\permanent\protected\def\mathgreekitalic {\c_attr_mathgreek"333\relax}
\permanent\protected\def\mathgreekdefault{\c_attr_mathgreek"000\relax}

\aliased\let\mathgreeknormal\mathgreekupright
\aliased\let\mathgreeknone  \mathgreekdefault

\appendtoks
    \c_attr_mathgreek\c_math_greek_attribute
\to \everymathematics

\setupmathematics
  [\s!sygreek=\v!normal,
   \s!lcgreek=\v!italic,
   \s!ucgreek=\v!normal] % was: none

%D Math collapsing (ligatures)

\installcorenamespace{mathcollapsing}

\setnewconstant\c_math_collapsing_attribute\attributeunsetvalue

\permanent\protected\def\resetmathcollapsing{\c_attr_mathcollapsing\attributeunsetvalue}

\letcsname\??mathcollapsing         0\endcsname\zerocount            % enforced (primes)
\letcsname\??mathcollapsing\s!tex    \endcsname\zerocount
\letcsname\??mathcollapsing         1\endcsname\plusone              % enforced | specials
\letcsname\??mathcollapsing\v!default\endcsname\plusone
\letcsname\??mathcollapsing         2\endcsname\plustwo              % enforced | specials | mathlist
\letcsname\??mathcollapsing\v!all    \endcsname\plustwo
\letcsname\??mathcollapsing         3\endcsname\plusthree            % enforced | mathlist | specials
\letcsname\??mathcollapsing\v!list   \endcsname\plusthree
\letcsname\??mathcollapsing\v!none   \endcsname\attributeunsetvalue
\letcsname\??mathcollapsing\v!reset  \endcsname\attributeunsetvalue

\def\math_collapsing_initialize
  {\ifnum\c_math_collapsing_attribute=\attributeunsetvalue \else
     \clf_initializemathcollapsing % one time
     \glet\math_collapsing_initialize\relax
   \fi}

\appendtoks
    \edef\p_collapsing{\mathematicsparameter\s!collapsing}%
    \c_math_collapsing_attribute
        \ifcsname\??mathcollapsing\p_collapsing\endcsname\lastnamedcs\else\attributeunsetvalue\fi
    \relax
\to \everyswitchmathematics % only in mathematics

\appendtoks
    \math_collapsing_initialize
    \c_attr_mathcollapsing\c_math_collapsing_attribute
\to \everymathematics

\setupmathematics
  [\s!collapsing=1] % so that we at least do primes

%D Math kerns (experiment)

\installcorenamespace{mathkernpairs}

\setnewconstant\c_math_kernpairs_attribute\attributeunsetvalue % no real need for an extra constant

\def\math_kernpairs_initialize
  {\ifnum\c_math_kernpairs_attribute=\attributeunsetvalue \else
     \clf_initializemathkernpairs % one time
     \glet\math_kernpairs_initialize\relax
   \fi}

\appendtoks
    \edef\p_kernpairs{\mathematicsparameter\s!kernpairs}%
    \c_math_kernpairs_attribute\ifx\p_kernpairs\v!yes\plusone\else\attributeunsetvalue\fi\relax
\to \everyswitchmathematics % only in mathematics

\appendtoks
    \math_kernpairs_initialize
    \c_attr_mathkernpairs\c_math_kernpairs_attribute
\to \everymathematics

\setupmathematics
  [\s!kernpairs=\v!no]

%D \macros
%D   {enablemathpunctuation,disablemathpunctuation}
%D
%D \startbuffer
%D \enablemathpunctuation$(1,2) (1, 2) (1{,}2) \hbox{foo, not bar}$
%D \stopbuffer
%D
%D \typebuffer
%D
%D \blank{\getbuffer}\blank

% \newconditional\automathpunctuation
%
% \protected\def\enablemathpunctuation {\automathpunctuation\conditionaltrue}
% \protected\def\disablemathpunctuation{\automathpunctuation\conditionalfalse}
%
% \appendtoks
%     \ifcstok{\mathematicsparameter\c!autopunctuation}\v!yes
%       \automathpunctuation\conditionaltrue
%     \else
%       \automathpunctuation\conditionalfalse
%     \fi
% \to \everyswitchmathematics
%
% \setupmathematics
%   [\c!autopunctuation=\v!no]
%
% \def\math_punctuation_next{\ifx\nexttoken\blankspace\signalcharacter\fi}
%
% \protected\def\math_punctuation_comma {\textcomma \futurelet\nexttoken\math_punctuation_next}
% \protected\def\math_punctuation_period{\textperiod\futurelet\nexttoken\math_punctuation_next}
%
% \setnewconstant\commaasciicode  "002C
% \setnewconstant\periodasciicode "002E
% \setnewconstant\c_math_special"8000
%
% \bgroup
%
%     \catcode\commaasciicode \activecatcode
%     \catcode\periodasciicode\activecatcode
%
%     \protected\gdef\math_punctuation_initialize_indeed
%       {\mathcode\commaasciicode \c_math_special
%        \mathcode\periodasciicode\c_math_special
%        \let,\math_punctuation_comma
%        \let.\math_punctuation_period
%        \c_attr_mathpunctuation\plustwo}
%
%     \protected\gdef\math_punctuation_initialize_yes
%       {\c_attr_mathpunctuation\plustwo}
%
%     \protected\gdef\math_punctuation_initialize_nop
%       {\c_attr_mathpunctuation\plusone}
%
% \egroup
%
% \appendtoks
%     \ifconditional\automathpunctuation
%       \math_punctuation_initialize_indeed
%       \math_punctuation_initialize_yes
%       \let\enablemathpunctuation \math_punctuation_initialize_yes
%       \let\disablemathpunctuation\math_punctuation_initialize_nop
%     \fi
% \to \everymathematics

% Later I will look again into a \LUATEX\ based solution. It only makes sense
% to delegate to \LUA\ when we have more variants and need analysis (experimental
% trickery removed for a while).

% \def\math_punctuation_comma_next {\ifx\nexttoken\blankspace\mathpunct\else\mathord\fi{\textcomma }}
% \def\math_punctuation_period_next{\ifx\nexttoken\blankspace\mathpunct\else\mathord\fi{\textperiod}}
%
% \protected\def\math_punctuation_nop_comma {\mathpunct{\textcomma}}
% \protected\def\math_punctuation_nop_period{\mathord{\textperiod}}
%
% \protected\def\math_punctuation_all_comma {\futurelet\nexttoken\math_punctuation_comma_next}
% \protected\def\math_punctuation_all_period{\futurelet\nexttoken\math_punctuation_period_next}
%
%            \let\math_punctuation_yes_comma \math_punctuation_all_comma
%            \let\math_punctuation_yes_period\math_punctuation_nop_period
%
% The next one is more efficient as it produces more flat noad lists for numbers.

%D This is a dirty trick. In order to prevent a loop due to reinjection, when a
%D active one is seen, the amcode is set to other. So, afterwards we need to
%D reactivate. Eventually this feature will be dropped in favor of a more modern
%D mechanism.

%D These amcodes can be alignmenttab, superscript, subscript, letter, otherchar, or
%D active. That way we can avoid the "8000 hackery and let characters keep the
%D proper class. The code is checked when we run into an active character in math
%D mode

\def\math_activeate_comma    {\amcode\commaasciicode    \activecatcode}
\def\math_activeate_period   {\amcode\periodasciicode   \activecatcode}
\def\math_activeate_semicolon{\amcode\semicolonasciicode\activecatcode}

\def\math_set_o_comma    {\Umathcode\commaasciicode    \mathordinarycode   \zerocount\commaasciicode}
\def\math_set_p_comma    {\Umathcode\commaasciicode    \mathpunctuationcode\zerocount\commaasciicode}
\def\math_set_o_period   {\Umathcode\periodasciicode   \mathordinarycode   \zerocount\periodasciicode}
\def\math_set_p_period   {\Umathcode\periodasciicode   \mathpunctuationcode\zerocount\periodasciicode}
\def\math_set_o_semicolon{\Umathcode\semicolonasciicode\mathordinarycode   \zerocount\semicolonasciicode}
\def\math_set_p_semicolon{\Umathcode\semicolonasciicode\mathpunctuationcode\zerocount\semicolonasciicode}

\edef\math_set_o_both{\math_set_o_period\math_set_o_comma}
\edef\math_set_p_both{\math_set_p_period\math_set_p_comma}

% We cannot use \mathchardef'd variants because then are intercepted as active, so:

\protected\def\math_punctuation_nop_comma    {\begingroup\math_set_p_comma    ,\endgroup\math_activeate_comma    }
\protected\def\math_punctuation_nop_period   {\begingroup\math_set_o_period   .\endgroup\math_activeate_period   }
\protected\def\math_punctuation_nop_semicolon{\begingroup\math_set_p_semicolon;\endgroup\math_activeate_semicolon}

\def\math_punctuation_comma_next    {\begingroup\Umathcode\commaasciicode    \ifx\nexttoken\blankspace\mathpunctuationcode\else\mathordinarycode\fi\zerocount\commaasciicode    ,\endgroup\math_activeate_comma    }
\def\math_punctuation_period_next   {\begingroup\Umathcode\periodasciicode   \ifx\nexttoken\blankspace\mathpunctuationcode\else\mathordinarycode\fi\zerocount\periodasciicode   .\endgroup\math_activeate_period   }
\def\math_punctuation_semicolon_next{\begingroup\Umathcode\semicolonasciicode\ifx\nexttoken\blankspace\mathpunctuationcode\else\mathordinarycode\fi\zerocount\semicolonasciicode;\endgroup\math_activeate_semicolon}

% So, nicer is:
%
% \protected\def\math_punctuation_nop_comma    {\Umathclass\mathpunctuationcode\commaasciicode    \math_activeate_comma    }
% \protected\def\math_punctuation_nop_period   {\Umathclass\mathordinarycode   \periodasciicode   \math_activeate_period   }
% \protected\def\math_punctuation_nop_semicolon{\Umathclass\mathpunctuationcode\semicolonasciicode\math_activeate_semicolon}
%
% \def\math_punctuation_comma_next    {\Umathclass\ifx\nexttoken\blankspace\mathpunctuationcode\else\mathordinarycode\fi\commaasciicode    \math_activeate_comma    }
% \def\math_punctuation_period_next   {\Umathclass\ifx\nexttoken\blankspace\mathpunctuationcode\else\mathordinarycode\fi\periodasciicode   \math_activeate_period   }
% \def\math_punctuation_semicolon_next{\Umathclass\ifx\nexttoken\blankspace\mathpunctuationcode\else\mathordinarycode\fi\semicolonasciicode\math_activeate_semicolon}

\protected\def\math_punctuation_all_comma    {\futurelet\nexttoken\math_punctuation_comma_next}
\protected\def\math_punctuation_all_period   {\futurelet\nexttoken\math_punctuation_period_next}
\protected\def\math_punctuation_all_semicolon{\futurelet\nexttoken\math_punctuation_semicolon_next}

          \let\math_punctuation_yes_comma    \math_punctuation_all_comma
          \let\math_punctuation_yes_period   \math_punctuation_nop_period
          \let\math_punctuation_yes_semicolon\math_punctuation_all_semicolon

\installcorenamespace {mathautopunctuation}

% \bgroup
%
%     \catcode\commaasciicode    \activecatcode
%     \catcode\periodasciicode   \activecatcode
%     \catcode\semicolonasciicode\activecatcode
%
%     \gdefcsname\??mathautopunctuation\v!no\endcsname
%       {\let,\math_punctuation_nop_comma
%        \let.\math_punctuation_nop_period
%        \let;\math_punctuation_nop_semicolon}
%
%     \gdefcsname\??mathautopunctuation\v!yes\endcsname
%       {\let,\math_punctuation_yes_comma
%        \let.\math_punctuation_yes_period
%        \let;\math_punctuation_nop_semicolon}
%
%     \gdefcsname\??mathautopunctuation\v!all\endcsname
%       {\let,\math_punctuation_all_comma
%        \let.\math_punctuation_all_period
%        \let;\math_punctuation_nop_semicolon}
%
%     \gdefcsname\??mathautopunctuation comma\endcsname
%       {\let,\math_punctuation_yes_comma
%        \let.\math_punctuation_yes_period
%        \let;\math_punctuation_nop_semicolon}
%
%     \gdefcsname\??mathautopunctuation\v!yes\string,semicolon\endcsname
%       {\let,\math_punctuation_yes_comma
%        \let.\math_punctuation_yes_period
%        \let;\math_punctuation_yes_semicolon}
%
%     \gdefcsname\??mathautopunctuation comma\string,semicolon\endcsname
%       {\let,\math_punctuation_yes_comma
%        \let.\math_punctuation_yes_period
%        \let;\math_punctuation_yes_semicolon}
%
%     \gdefcsname\??mathautopunctuation\v!all\string,semicolon\endcsname
%       {\let,\math_punctuation_all_comma
%        \let.\math_punctuation_all_period
%        \let;\math_punctuation_all_semicolon}
%
% \egroup

\defcsname\??mathautopunctuation\v!no\endcsname
  {\letcharcode\commaasciicode    \math_punctuation_nop_comma
   \letcharcode\periodasciicode   \math_punctuation_nop_period
   \letcharcode\semicolonasciicode\math_punctuation_nop_semicolon}

\defcsname\??mathautopunctuation\v!yes\endcsname
  {\letcharcode\commaasciicode    \math_punctuation_yes_comma
   \letcharcode\periodasciicode   \math_punctuation_yes_period
   \letcharcode\semicolonasciicode\math_punctuation_nop_semicolon}

\defcsname\??mathautopunctuation\v!all\endcsname
  {\letcharcode\commaasciicode    \math_punctuation_all_comma
   \letcharcode\periodasciicode   \math_punctuation_all_period
   \letcharcode\semicolonasciicode\math_punctuation_nop_semicolon}

\defcsname\??mathautopunctuation comma\endcsname
  {\letcharcode\commaasciicode    \math_punctuation_yes_comma
   \letcharcode\periodasciicode   \math_punctuation_yes_period
   \letcharcode\semicolonasciicode\math_punctuation_nop_semicolon}

\defcsname\??mathautopunctuation\v!yes\string,semicolon\endcsname
  {\letcharcode\commaasciicode    \math_punctuation_yes_comma
   \letcharcode\periodasciicode   \math_punctuation_yes_period
   \letcharcode\semicolonasciicode\math_punctuation_yes_semicolon}

\defcsname\??mathautopunctuation comma\string,semicolon\endcsname
  {\letcharcode\commaasciicode    \math_punctuation_yes_comma
   \letcharcode\periodasciicode   \math_punctuation_yes_period
   \letcharcode\semicolonasciicode\math_punctuation_yes_semicolon}

\defcsname\??mathautopunctuation\v!all\string,semicolon\endcsname
  {\letcharcode\commaasciicode    \math_punctuation_all_comma
   \letcharcode\periodasciicode   \math_punctuation_all_period
   \letcharcode\semicolonasciicode\math_punctuation_all_semicolon}

% \appendtoks
%     \global\mathcode\commaasciicode    \c_math_special
%     \global\mathcode\periodasciicode   \c_math_special
%     \global\mathcode\semicolonasciicode\c_math_special
% \to \everyjob

% \activatemathcharacter\commaasciicode
% \activatemathcharacter\periodasciicode
% \activatemathcharacter\semicolonasciicode

% \appendtoks
%     \mathcode\commaasciicode    \c_math_special
%     \mathcode\periodasciicode   \c_math_special
%     \mathcode\semicolonasciicode\c_math_special
%     \begincsname\??mathautopunctuation\mathematicsparameter\c!autopunctuation\endcsname
% \to \everymathematics

\appendtoks
    \math_activeate_comma
    \math_activeate_period
    \math_activeate_semicolon
    \begincsname\??mathautopunctuation\mathematicsparameter\c!autopunctuation\endcsname
\to \everymathematics

\appendtoks
    \ifcsname\??mathautopunctuation\mathematicsparameter\c!autopunctuation\endcsname \else
        \letmathematicsparameter\c!autopunctuation\v!no
    \fi
% \to \everysetupmathematics
\to \everyswitchmathematics

\permanent\protected\def\enablemathpunctuation {\csname\??mathautopunctuation\v!no \endcsname}
\permanent\protected\def\disablemathpunctuation{\csname\??mathautopunctuation\v!yes\endcsname}

\setupmathematics
  [\c!autopunctuation=\v!no] % no | yes | all | comma | yes,semicolon | all,semicolon

%D The next replaces the above:

% [0x2E] = { 0x2E, 0x2C, 0x002E, 0x002C, 0x2008, 0x2008 },
% [0x2C] = { 0x2C, 0x2E, 0x2008, 0x2008, 0x002E, 0x002C },

% \startbuffer
%     \im{x + 1,222,333.44 + x}\par
%     \im{x + 1.222.333,44 + x}\par
%     \im{x + 1, 222, 333. 44 + x}\par
%     \im{(1.5, 1.5) + (1,5;1,5)}\par
%     \im{111 2222}\par
%     \im{f: \reals\to\reals}\par
%     \im{f : \reals\to\reals}\par
%     \im{f\colon\reals\to\reals}\par
%     \im{f \colon\reals\to\reals}\par
% \stopbuffer
%
% \startTEXpage[offset=1dk]
%     \setupmathematics[autospacing=yes] \getbuffer \blank
%     \setupmathematics[autonumbers=1]   \getbuffer \blank
%     \setupmathematics[autonumbers=2]   \getbuffer \blank
%     \setupmathematics[autonumbers=3]   \getbuffer \blank
%     \setupmathematics[autonumbers=4]   \getbuffer \blank
%     \setupmathematics[autonumbers=5]   \getbuffer \blank
%     \setupmathematics[autonumbers=6]   \getbuffer \blank
% \stopTEXpage

\installcorenamespace{autospacing}

\permanent\protected\def\enablemathautospacing
  {\attribute\mathspacingattribute\plusone
   \clf_initializemathspacing}

\permanent\protected\def\disablemathautospacing
  {\attribute\mathspacingattribute\attributeunsetvalue}

\appendtoks
    \ifcstok{\mathematicsparameter\c!autospacing}\v!yes
      \enablemathautospacing
    \else
      \disablemathautospacing
    \fi
% \to \everysetupmathematics
\to \everyswitchmathematics

\setupmathematics
  [\c!autospacing=\v!no]

\permanent\protected\def\enablemathautonumbers
  {\attribute\mathnumbersattribute\plusone
   \clf_initializemathnumbers}

\permanent\protected\def\disablemathautonumbers
  {\attribute\mathnumbersattribute\attributeunsetvalue}

\appendtoks
    \edef\p_autonumbers{\mathematicsparameter\c!autonumbers}%
    \ifchknum\p_autonumbers\or
      \enablemathautonumbers % default
      \attribute\mathnumbersattribute\p_autonumbers\relax
    \orelse\ifx\p_autonumbers\v!no
      \disablemathautonumbers
    \else
      \enablemathautonumbers % default
    \fi
% \to \everysetupmathematics
\to \everyswitchmathematics

\setupmathematics
  [\c!autonumbers=\v!no]

\installcorenamespace{autofencing}

\permanent\protected\def\enablemathautofencing
  {\attribute\mathfencingattribute\plusone
   \clf_initializemathfencing}

\permanent\protected\def\disablemathautofencing
  {\attribute\mathfencingattribute\attributeunsetvalue}

\appendtoks
    \ifcstok{\mathematicsparameter\c!autofencing}\v!yes
      \enablemathautofencing
      \autofences
    \else
      \disablemathautofencing
    \fi
% \to \everysetupmathematics
\to \everyswitchmathematics

\setupmathematics
  [\c!autofencing=\v!no]

%D The consequences of setting this are as follows:
%D
%D \def\TestA#1#2#3%
%D   {\ifnum#1=0 \type{#2}\else\setupmathematics[autopunctuation={#2}]$#3$\fi}
%D \def\TestB#1#2%
%D   {\NC \TestA{#1}{no}           {#2}
%D    \NC \TestA{#1}{yes}          {#2}
%D    \NC \TestA{#1}{yes,semicolon}{#2}
%D    \NC \TestA{#1}{all}          {#2}
%D    \NC \TestA{#1}{all,semicolon}{#2}
%D    \NC \NR}
%D \starttabulate[|c|c|c|c|c|]
%D     \TestB{0}{}
%D     \TestB{1}{(1,2)=(1, 2)}
%D     \TestB{1}{(1.2)=(1. 2)}
%D     \TestB{1}{(1;2)=(1; 2)}
%D \stoptabulate

% 0 = display
% 1 = crampeddisplay
% 2 = text
% 3 = crampedtext
% 4 = script
% 5 = crampedscript
% 6 = scriptscript
% 7 = crampedscriptscript

\permanent\def\uncramped#1%
  {\beginmathgroup
   \ifmathstyle
    \or \displaystyle      \or
    \or \textstyle         \or
    \or \scriptstyle       \or
    \or \scriptscriptstyle \fi
   #1%
   \endmathgroup}

\permanent\def\cramped#1%
  {\beginmathgroup
   \ifmathstyle
    \crampeddisplaystyle      \or \or % 0 -> 1
    \crampedtextstyle         \or \or % 2 -> 3
    \crampedscriptstyle       \or \or % 4 -> 5
    \crampedscriptscriptstyle \fi     % 6 -> 7
   #1%
   \endmathgroup}

\permanent\def\triggermathstyle#1{\givenmathstyle{\numexpr#1\relax}}
%permanent\def\mathstyletrigger#1{\numexpr#1\relax}
\permanent\let\mathstyletrigger   \firstofoneargument

\def\triggeredmathstyle#1{\givenmathstyle\numexpr\number#1\relax} % expandable

\permanent\def\triggeredmathstyleparameter#1% to bypass the relax
  {\ifcase\numexpr\normalmathstyle\relax
     #1\displaystyle             \or % 0
     #1\crampeddisplaystyle      \or % 1
     #1\textstyle                \or % 2
     #1\crampedtextstyle         \or % 3
     #1\scriptstyle              \or % 4
     #1\crampedscriptstyle       \or % 5
     #1\scriptscriptstyle        \or % 6
     #1\crampedscriptscriptstyle \else
     % error
   \fi}

\permanent\def\mathstylefont#1% #1 is number (\normalmathstyle)
  {\ifcase\numexpr#1\relax
     \textfont         \or
     \textfont         \or
     \textfont         \or
     \textfont         \or
     \scriptfont       \or
     \scriptfont       \or
     \scriptscriptfont \or
     \scriptscriptfont \else
     \textfont
   \fi\fam} % was \zerocount

\permanent\def\somemathstylefont#1% #1 is number (\normalmathstyle)
  {\ifcase\numexpr#1\relax
     \textfont         \or
     \textfont         \or
     \textfont         \or
     \textfont         \or
     \scriptfont       \or
     \scriptfont       \or
     \scriptscriptfont \or
     \scriptscriptfont \else
     \textfont
   \fi}

\permanent\def\mathsmallstylefont#1% #1 is number (\normalmathstyle)
  {\ifcase\numexpr#1\relax
     \scriptfont       \or
     \scriptfont       \or
     \scriptfont       \or
     \scriptfont       \or
     \scriptscriptfont \or
     \scriptscriptfont \or
     \scriptscriptfont \or
     \scriptscriptfont \else
     \scriptfont
   \fi\fam} % was \zerocount

\permanent\def\mathstyleface#1% #1 is number (\normalmathstyle)
  {\ifcase\numexpr#1\relax
     \textface         \or
     \textface         \or
     \textface         \or
     \textface         \or
     \scriptface       \or
     \scriptface       \or
     \scriptscriptface \or
     \scriptscriptface \else
     \textface
   \fi}

% \permanent\def\mathstyleface#1% #1 is number (\normalmathstyle)
%   {\mathstylefont#1\relax}

\permanent\def\mathsmallstyleface#1% #1 is number (\normalmathstyle)
  {\ifcase\numexpr#1\relax
     \scriptface       \or
     \scriptface       \or
     \scriptface       \or
     \scriptface       \or
     \scriptscriptface \or
     \scriptscriptface \or
     \scriptscriptface \or
     \scriptscriptface \else
     \scriptface
   \fi}

% \permanent\def\mathsmallstyleface#1% #1 is number (\normalmathstyle)
%   {\mathstylefont\ifcase\numexpr#1\relax
%      \scriptstyle       \or
%      \scriptstyle       \or
%      \scriptstyle       \or
%      \scriptstyle       \or
%      \scriptscriptstyle \or
%      \scriptscriptstyle \or
%      \scriptscriptstyle \or
%      \scriptscriptstyle \else
%      \scriptstyle
%    \fi}

\permanent\def\mathstylecommand#1#2#3%
  {\ifcase\numexpr\normalmathstyle\relax
     \expandafter#1\or
     \expandafter#1\or
     \expandafter#1\or
     \expandafter#1\or
     \expandafter#2\or
     \expandafter#2\or
     \expandafter#3\or
     \expandafter#3\else
     \expandafter#1\fi}

% \permanent\def\textstyleface#1% #1 is number (\normalmathstyle)
%   {\ifcase\numexpr#1\relax
%      \tf   \or
%      \tf   \or
%      \tf   \or
%      \tf   \or
%      \tfx  \or
%      \tfx  \or
%      \tfxx \or
%      \tfxx \else
%      \tf
%    \fi}

\permanent\protected\def\verbosemathstyle#1% #1 is number (\normalmathstyle)
  {{\expanded{\relax\darkgray\ttxx[\number#1:\ifcase\numexpr#1\relax
                display\or   % 0
         crampeddisplay\or   % 1
                   text\or   % 2
            crampedtext\or   % 3
                 script\or   % 4
          crampedscript\or   % 5
           scriptscript\or   % 6
    crampedscriptscript\else % 7
                unknown\fi]}}}

\permanent\protected\def\showmathstyle{\verbosemathstyle\normalmathstyle}

%D Handy too:

\permanent\def\mathcharwd{\scaledfontcharwd\mathstylefont\normalmathstyle}
\permanent\def\mathcharht{\scaledfontcharht\mathstylefont\normalmathstyle}
\permanent\def\mathchardp{\scaledfontchardp\mathstylefont\normalmathstyle}

%D Some dimension fun:

\aliased  \let\mathexheight \exheight                   % also in math-ini.mkiv
\permanent\def\mathemwidth {\Umathquad\normalmathstyle} % also in math-ini.mkiv

%D A plain inheritance:

\permanent\def\mathpalette#1#2%
  {\mathchoice
     {#1\displaystyle     {#2}}%
     {#1\textstyle        {#2}}%
     {#1\scriptstyle      {#2}}%
     {#1\scriptscriptstyle{#2}}}

%D \macros
%D    {cramedllap, crampedrlap, crampedclap}
%D
%D In many cases, one wants to use the \tex {clap} macro in math mode while using
%D subscripts. Normally, subscripts are in cramped mode, and these macros allow you
%D to go to cramped mode. For example:
%D
%D \startbuffer
%D \startformula
%D   \sum_{a^2 < b^2 < c^2} \quad
%D   \sum_{\clap{a^2 < b^2 < c^2}} \quad
%D   \sum_{\crampedclap{a^2 < b^2 < c^2}}
%D \stopformula
%D \stopbuffer
%D
%D \start
%D   \typebuffer
%D   \switchtobodyfont[24pt]
%D   \getbuffer
%D \stop
%D
%D This used to be in \type {supp-math.mkxl}:

\permanent\protected\def\crampedllap#1{\llap{\cramped#1}}
\permanent\protected\def\crampedrlap#1{\rlap{\cramped#1}}
\permanent\protected\def\crampedclap#1{\clap{\cramped#1}}

%D Often we can use:
%D
%D \startbuffer
%D $x^{\mathstylehbox{x^{\mathstylehbox{x}}}}$
%D \stopbuffer
%D
%D \typebuffer \getbuffer

% to be tested: {#1} but it could have side effects

\permanent\protected\def\mathstylehbox#1#% sensitive for: a \over b => {a\over b} or \frac{a}{b}
  {\math_style_hbox{#1}}

\protected\def\math_style_hbox#1#2% sensitive for: a \over b => {a\over b} or \frac{a}{b}
  {\expanded{\hbox#1\bgroup
     \startimath\triggeredmathstyle\normalmathstyle}\mathsurround\zeropoint#2\stopimath\egroup}

% adaptive variant:
%
% \protected\def\math_style_hbox#1#2% sensitive for: a \over b => {a\over b} or \frac{a}{b}
%   {\expanded{\setbox\scratchbox\hbox#1\bgroup
%   \mathbeginclass\lastrightclass
%   \startimath\givenmathstyle\the\mathstyle\relax}%
%      \mathsurround\zeropoint#2\stopimath\egroup
%      \box\scratchbox
%   \mathrightclass\lastrightclass   }

\permanent\protected\def\mathstylevbox#1%
  {\expanded{\vbox\bgroup
     \startimath\triggeredmathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup}

\permanent\protected\def\mathstylevcenter#1%
  {\expanded{\vcenter\bgroup
     \startimath\triggeredmathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup}

\permanent\protected\def\mathstylevcenteredhbox#1%
  {\expanded{\vcenter\bgroup\hbox\bgroup
     \startimath\triggeredmathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup\egroup}

\permanent\protected\def\mathstylevcenteredvbox#1%
  {\expanded{\vcenter\bgroup\vbox\bgroup
     \startimath\triggeredmathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup\egroup}

\permanent\protected\def\setmathsmalltextbox#1#2#%
  {\normalizebodyfontsize\m_math_text_choice_face{\mathsmallstyleface\normalmathstyle}%
   \setbox#1#2\bgroup
     \font_basics_switchtobodyfont\m_math_text_choice_face
     \let\next}

\permanent\protected\def\setmathtextbox#1#2#%
  {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
   \setbox#1#2\bgroup
     \font_basics_switchtobodyfont\m_math_text_choice_face
     \let\next}

%D Here is the new mechanism ... it might replace some of the above but we will do
%D that stepwise. Keep in mind that cramped only affects superscripts and even then,
%D only when in a smaller size than normal.
%D
%D \def\TestMe#1%
%D   {\NC \ttbf #1
%D    \NC \ruledhbox{$\setupmathstyle[#1]x + x_j^2 + x_i^{e^2} + \frac{1}{x}$}
%D    \NC \ruledhbox{$\setupmathstyle[#1,small]x + x_j^2 + x_i^{e^2} + \frac{1}{x}$}
%D    \NC \NR}
%D
%D \starttabulate[|l|r|l|]
%D \HL
%D \NC \NC \NC \ttbf ...,small \NC \NR
%D \HL
%D \TestMe{text}         \TestMe{text,cramped}
%D \TestMe{script}       \TestMe{script,cramped}
%D \TestMe{scriptscript} \TestMe{scriptscript,cramped}
%D \TestMe{display}      \TestMe{display,cramped}
%D \HL
%D \stoptabulate

\permanent\def\triggerdisplaystyle
  {\ifmathstyle
     \displaystyle        \or
     \crampeddisplaystyle \or
     \displaystyle        \or
     \crampeddisplaystyle \or
     \displaystyle        \or
     \crampeddisplaystyle \or
     \displaystyle        \or
     \crampeddisplaystyle \or
   \fi}

\permanent\def\triggertextstyle
  {\ifmathstyle
     \textstyle        \or
     \crampedtextstyle \or
     \textstyle        \or
     \crampedtextstyle \or
     \textstyle        \or
     \crampedtextstyle \or
     \textstyle        \or
     \crampedtextstyle \else
   \fi}

\permanent\def\triggerscriptstyle
  {\ifmathstyle
     \scriptstyle        \or
     \crampedscriptstyle \or
     \scriptstyle        \or
     \crampedscriptstyle \or
     \scriptstyle        \or
     \crampedscriptstyle \or
     \scriptstyle        \or
     \crampedscriptstyle \or
   \fi}

\permanent\def\triggerscriptscriptstyle
  {\ifmathstyle
     \scriptscriptstyle        \or
     \crampedscriptscriptstyle \or
     \scriptscriptstyle        \or
     \crampedscriptscriptstyle \or
     \scriptscriptstyle        \or
     \crampedscriptscriptstyle \or
     \scriptscriptstyle        \or
     \crampedscriptscriptstyle \or
   \fi}

\permanent\def\triggeruncrampedstyle
  {\ifmathstyle
     \currentlysetmathstyle\or
     \displaystyle         \or
     \currentlysetmathstyle\or
     \textstyle            \or
     \currentlysetmathstyle\or
     \scriptstyle          \or
     \currentlysetmathstyle\or
     \scriptscriptstyle
   \fi}

\permanent\def\triggercrampedstyle
  {\ifmathstyle
     \crampeddisplaystyle     \or
     \currentlysetmathstyle   \or
     \crampedtextstyle        \or
     \currentlysetmathstyle   \or
     \crampedscriptstyle      \or
     \currentlysetmathstyle   \or
     \crampedscriptscriptstyle\or
     \currentlysetmathstyle
   \fi}

\permanent\def\triggersmallstyle
  {\ifmathstyle
     \scriptstyle              \or
     \crampedscriptstyle       \or
     \scriptstyle              \or
     \crampedscriptstyle       \or
     \scriptscriptstyle        \or
     \crampedscriptscriptstyle \or
     \scriptscriptstyle        \or
     \crampedscriptscriptstyle \or
    \fi}

\permanent\def\triggeruncrampedsmallstyle
  {\ifmathstyle
     \scriptstyle       \or
     \scriptstyle       \or
     \scriptstyle       \or
     \scriptstyle       \or
     \scriptscriptstyle \or
     \scriptscriptstyle \or
     \scriptscriptstyle \or
     \scriptscriptstyle \or
    \fi}

\permanent\def\triggercrampedsmallstyle
  {\ifmathstyle
     \crampedscriptstyle       \or
     \crampedscriptstyle       \or
     \crampedscriptstyle       \or
     \crampedscriptstyle       \or
     \crampedscriptscriptstyle \or
     \crampedscriptscriptstyle \or
     \crampedscriptscriptstyle \or
     \crampedscriptscriptstyle \or
    \fi}

\permanent\def\triggerbigstyle
  {\ifmathstyle
     \displaystyle        \or
     \crampeddisplaystyle \or
     \textstyle           \or
     \crampedtextstyle    \or
     \textstyle           \or
     \crampedtextstyle    \or
     \scriptstyle         \or
     \crampedscriptstyle  \or
    \fi}

\permanent\def\triggeruncrampedbigstyle
  {\ifmathstyle
     \displaystyle \or
     \displaystyle \or
     \textstyle    \or
     \textstyle    \or
     \textstyle    \or
     \textstyle    \or
     \scriptstyle  \or
     \scriptstyle  \or
    \fi}

\permanent\def\triggercrampedbigstyle
  {\ifmathstyle
     \crampeddisplaystyle \or
     \crampeddisplaystyle \or
     \crampedtextstyle    \or
     \crampedtextstyle    \or
     \crampedtextstyle    \or
     \crampedtextstyle    \or
     \crampedscriptstyle  \or
     \crampedscriptstyle  \or
    \fi}

\newinteger\c_math_saved_style

\permanent\protected\def\pushmathstyle % assumes begingroup .. endgroup
  {\c_math_saved_style\mathstyle}

\permanent\protected\def\popmathstyle
  {\ifnum\mathstyle=\c_math_saved_style\else
     \triggermathstyle\c_math_saved_style
   \fi}

\installcorenamespace{mathstylecommand}
\installcorenamespace{mathstylecachem}
\installcorenamespace{mathstylecachet}

\newconstant\c_math_styles_state_style
\newconstant\c_math_styles_state_cramped
\newconstant\c_math_styles_state_size

\def\math_style_add_to_cache_choice {%
  \ifcase\c_math_styles_state_size
    \ifcase\c_math_styles_state_style
        \ifcase\c_math_styles_state_cramped
        \currentlysetmathstyle\or
        \triggeruncrampedstyle\or
        \triggercrampedstyle  \fi
    \or\ifcase\c_math_styles_state_cramped
        \ifmode\triggerdisplaystyle\else\displaystyle\fi
        \or\displaystyle\or\crampeddisplaystyle\fi
    \or\ifcase\c_math_styles_state_cramped
        \ifmode\triggertextstyle\else\textstyle\fi
        \or\textstyle\or\crampedtextstyle\fi
    \or\ifcase\c_math_styles_state_cramped
        \ifmode\triggerscriptstyle\else\scriptstyle\fi
        \or\scriptstyle\or\crampedscriptstyle\fi
    \or\ifcase\c_math_styles_state_cramped
        \ifmode\triggerscriptscriptstyle\else\scriptscriptstyle\fi
        \or\scriptscriptstyle\or\crampedscriptscriptstyle\fi
    \fi
  \or % small
    \ifcase\c_math_styles_state_style
        \ifcase\c_math_styles_state_cramped
        \triggersmallstyle         \or
        \triggeruncrampedsmallstyle\or
        \triggercrampedsmallstyle  \fi
    \or\ifcase\c_math_styles_state_cramped
        \ifmode\triggerscriptstyle\else\scriptstyle\fi
        \or\scriptstyle\or\crampedscriptstyle\fi
    \or\ifcase\c_math_styles_state_cramped
        \ifmode\triggerscriptstyle\else\scriptstyle\fi
        \or\scriptstyle\or\crampedscriptstyle\fi
    \or\ifcase\c_math_styles_state_cramped
        \ifmode\triggerscriptscriptstyle\else\scriptscriptstyle\fi
        \or\scriptscriptstyle\or\crampedscriptscriptstyle\fi
    \or\ifcase\c_math_styles_state_cramped
        \ifmode\triggerscriptscriptstyle\else\scriptscriptstyle\fi
        \or\scriptscriptstyle\or\crampedscriptscriptstyle\fi
    \fi
  \or % large
    \ifcase\c_math_styles_state_style
        \ifcase\c_math_styles_state_cramped
        \triggerbigstyle         \or
        \triggeruncrampedbigstyle\or
        \triggercrampedbigstyle  \fi
    \or\ifcase\c_math_styles_state_cramped
        \ifmode\triggerdisplaystyle\else\displaystyle\fi
        \or\displaystyle\or\crampeddisplaystyle\fi
    \or\ifcase\c_math_styles_state_cramped
        \ifmode\triggertextstyle\else\textstyle\fi
        \or\textstyle\or\crampedtextstyle\fi
    \or\ifcase\c_math_styles_state_cramped
        \ifmode\triggertextstyle\else\textstyle\fi
        \or\textstyle\or\crampedtextstyle\fi
    \or\ifcase\c_math_styles_state_cramped
        \ifmode\triggerscriptstyle\else\scriptstyle\fi
        \or\scriptstyle\or\crampedscriptstyle\fi
    \fi
  \else
    \currentlysetmathstyle
  \fi
  % % fails in alignment
  % \ifcase\c_math_styles_state_style\or
  %   \noexpand\localcontrol{\indisplaymath\conditionaltrue }\or
  %   \noexpand\localcontrol{\indisplaymath\conditionaltrue }\else
  %   \noexpand\localcontrol{\indisplaymath\conditionalfalse}%
  % \fi}
  % % okay in alignment (styles-001.tex)
  % \noexpand\beginlocalcontrol
  % \ifcase\c_math_styles_state_style\or
  %   \indisplaymath\conditionaltrue \or
  %   \indisplaymath\conditionaltrue \else
  %   \indisplaymath\conditionalfalse
  % \fi
  % \noexpand\endlocalcontrol}
  % % more efficient
  \ifcase\c_math_styles_state_style\or
    \noexpand\beginlocalcontrol\indisplaymath\conditionaltrue \noexpand\endlocalcontrol\or
    \noexpand\beginlocalcontrol\indisplaymath\conditionaltrue \noexpand\endlocalcontrol\else
    \noexpand\beginlocalcontrol\indisplaymath\conditionalfalse\noexpand\endlocalcontrol
  \fi}

\permanent\def\installmathstyle#1#2%
  {\ifcsname\??mathstylecommand#1\endcsname \else
     \defcsname\??mathstylecommand#1\endcsname{#2}%
   \fi}

\def\math_style_collect#1%
  {\csname\??mathstylecommand#1\endcsname}

% \defcsname\??mathstylecommand\s!display     \endcsname{\indisplaymath\conditionaltrue \c_math_styles_state_style\plusone}
% \defcsname\??mathstylecommand\s!text        \endcsname{\indisplaymath\conditionalfalse\c_math_styles_state_style\plustwo}
% \defcsname\??mathstylecommand\s!script      \endcsname{\indisplaymath\conditionalfalse\c_math_styles_state_style\plusthree}
% \defcsname\??mathstylecommand\s!scriptscript\endcsname{\indisplaymath\conditionalfalse\c_math_styles_state_style\plusfour}

\defcsname\??mathstylecommand\s!display     \endcsname{\c_math_styles_state_style\plusone}
\defcsname\??mathstylecommand\s!text        \endcsname{\c_math_styles_state_style\plustwo}
\defcsname\??mathstylecommand\s!script      \endcsname{\c_math_styles_state_style\plusthree}
\defcsname\??mathstylecommand\s!scriptscript\endcsname{\c_math_styles_state_style\plusfour}

\defcsname\??mathstylecommand\s!uncramped   \endcsname{\c_math_styles_state_cramped\plusone}
\defcsname\??mathstylecommand\s!cramped     \endcsname{\c_math_styles_state_cramped\plustwo}
\defcsname\??mathstylecommand\v!normal      \endcsname{\c_math_styles_state_cramped\plusone}
\defcsname\??mathstylecommand\v!packed      \endcsname{\c_math_styles_state_cramped\plustwo}

\defcsname\??mathstylecommand\v!small       \endcsname{\c_math_styles_state_size\plusone}
\defcsname\??mathstylecommand\v!big         \endcsname{\c_math_styles_state_size\plustwo}

% \def\math_styles_check_style_parameter#1#2%
%    {\ifempty{#1\c!mathstyle}%
%       \expanded{#2{\c!mathstyle}{\currentverbosemathstyle}}%
%     \fi}

\permanent\def\currentverbosemathstyle
  {\ifmathstyle \s!display
   \or          \s!text
   \or          \s!text,\s!cramped
   \or          \s!script
   \or          \s!script,\s!cramped
   \or          \s!scriptscript
   \or          \s!scriptscript,\s!cramped
   \fi}

%D A \type {mathstyle} is a set of:
%D
%D \starttabulate[|lT|lT|]
%D \BC style   \NC display text script scriptscript \NC \NR
%D \BC variant \NC uncramped cramped normal packed \NC \NR
%D \BC size    \NC small big \NC \NR
%D \stoptabulate
%D
%D \startbuffer
%D \m{x\foo}
%D \m[mathstyle=text]{x\foo}
%D \m[mathstyle={cramped,text}]{x\foo}
%D \m[mathstyle=scriptscript]{x\foo \scriptstyle\foo}
%D \stopbuffer
%D
%D \typebuffer \getbuffer
%D
%D \startbuffer
%D \definemathstyle[mystyle][scriptscript]
%D
%D $text\startmathstyle[mystyle]scriptscript\stopmathstyle text$
%D \stopbuffer
%D
%D \typebuffer \blank \start \getbuffer \stop \blank

% maybe move this to the lua end ...

\installcorenamespace {mathstyle}

\letcsname\??mathstyle      \endcsname\empty
%letcsname\??mathstylecachem\endcsname\empty
%letcsname\??mathstylecachet\endcsname\empty

\lettonothing\m_math_style_asked

%D test case:
%D
%D \starttyping
%D \startformula
%D \frac{1}{2} + \sqrt{\frac{1}{2} + 1}
%D \stopformula%
%D \stoptyping

% \permanent\def\expandedmathstyleparameter#1#2%
%   {\beginlocalcontrol
%    \edef\m_math_style_asked{#1#2}%
%    \edef\m_math_style_asked{\math_style_set_expanded\m_math_style_asked}%
%    \endlocalcontrol
%    \ifempty\m_math_style_asked
%      \mathstyle
%    \else
%      \m_math_style_asked
%    \fi}

\permanent\def\expandedmathstyleparameter#1#2%
  {\ifcstok{#1#2}\emptytoks
     \mathstyle
   \else
     \expandafter\math_style_set_expanded\expandafter{\lastnamedcs}%
   \fi}

\def\math_style_set_expanded#1% in caller: \math_style_set_main
  {\ifcsname\??mathstyle#1\endcsname
     \lastnamedcs
   \orelse\ifcsname\ifmmode\??mathstylecachem\the\mathstyle:\else\??mathstylecachet\fi#1\endcsname
     \lastnamedcs
   \else
     \math_style_set_mathstyle_mathstylecache{#1}%
   \fi}

\def\math_style_set_main{\indisplaymath\ifcase\mathstyle\conditionaltrue\else\conditionalfalse\fi} % for fractions

\def\math_style_set_indeed
  {\ifcsname\??mathstyle\m_math_style_asked\endcsname
     \lastnamedcs
   \orelse\ifcsname\ifmmode\??mathstylecachem\the\mathstyle:\else\??mathstylecachet\fi\m_math_style_asked\endcsname
     \lastnamedcs
   \else
     \math_style_set_mathstyle_mathstylecache\m_math_style_asked
   \fi
   \math_style_set_main}

\permanent\protected\def\usemathstyleparameter#1#2%
  {\edef\m_math_style_asked{#1#2}%
   \ifempty\m_math_style_asked \else
     \math_style_set_indeed
   \fi}

\permanent\tolerant\protected\def\setmathstyle[#1]#;#=% so we accept [] and {}
  {\edef\m_math_style_asked{#1#2\c!mathstyle}%
   \ifempty\m_math_style_asked \else
     \math_style_set_indeed
   \fi}

\permanent\protected\def\setupmathstyle[#1]%
  {\edef\m_math_style_asked{#1}%
   \ifempty\m_math_style_asked \else
     \math_style_set_indeed
   \fi}

\def\math_style_set_mathstyle_mathstylecache#1%
  {\beginlocalcontrol % so we can expand
   \edef\m_math_style_asked{#1}%
   \c_math_styles_state_style  \zerocount
   \c_math_styles_state_cramped\zerocount
   \c_math_styles_state_size   \zerocount
   \rawprocesscommacommand[\m_math_style_asked]\math_style_collect
   \gletcsname\ifmmode\??mathstylecachem\the\mathstyle:\else\??mathstylecachet\fi\m_math_style_asked\expanded
     {\endcsname\math_style_add_to_cache_choice}%
   \endlocalcontrol
   \csname\ifmmode\??mathstylecachem\the\mathstyle:\else\??mathstylecachet\fi\m_math_style_asked\endcsname
   \math_style_set_main}

% \letcsname\??mathstyle     \??mathstyle     \endcsname\math_style_set_mathstyle_mathstyle      % still needed?
% \letcsname\??mathstylecache\??mathstylecache\endcsname\math_style_set_mathstyle_mathstylecache % still needed?

%D \startbuffer
%D $x\begingroup\setupmathstyle[script]x\endgroup x$
%D $x{\setupmathstyle[script]x}x$
%D $x\startmathstyle[script]x\stopmathstyle x$
%D \stopbuffer
%D
%D \typebuffer \getbuffer

\permanent\protected\def\startmathstyle[#1]%
  {\edef\m_math_style_asked{#1}%
   \ifempty\m_math_style_asked
     \enforced\aliased\let\stopmathstyle\relax
   \else
     \beginmathgroup % \bgroup
     \math_style_set_indeed
     \enforced\aliased\let\stopmathstyle\endmathgroup % \egroup
   \fi}

\aliased\let\stopmathstyle\relax

\permanent\protected\def\startusemathstyleparameter#1#2%
  {\edef\m_math_style_asked{#1#2}%
   \ifempty\m_math_style_asked
     \enforced\let\stopusemathstyleparameter\relax
   \else
     \beginmathgroup % \bgroup
     \math_style_set_indeed
     \enforced\let\stopusemathstyleparameter\endmathgroup % \egroup
   \fi}

\aliased\let\stopusemathstyleparameter\relax

%D Something similar can be used in the (re|)|definition of \type {\text}. This
%D version is a variation on the one in the math module (see \type{m-math} and|/|or
%D \type {m-newmat}).

\let\m_math_text_choice_face\relax

%D We accept a low level box specification so that one can make helpers:
%D
%D \startbuffer
%D \startformula
%D     \startalign[m=2,align={middle}]
%D         \NC \text to 6cm{One\hfill}           \NC a = 1 \NR
%D         \NC \text to 6cm{One Two\hfill}       \NC b = 2 \NR
%D         \NC \text to 6cm{One Two Three\hfill} \NC c = 3 \NR
%D     \stopalign
%D \stopformula
%D \stopbuffer
%D
%D \typebuffer \getbuffer

% %mathscriptboxmode    \plusthree % lists and boxes with \boundary=1 (also for testing and demo)
% %mathscriptboxmode    \plusone   % collapsed and then removed, now control option
% %mathscriptcharmode   \plusone   % idem
%
% %mathrulethicknessmode\plusone   % adaptive

% We keep this as reference:
%
% \def\math_text_choice_font#1#2#%
%   {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
%    \hbox#2\bgroup
%    \bgroup
%    \aftergroup\hss
%    \aftergroup\egroup
%    \hss
%    \font_basics_switchtobodyfont\m_math_text_choice_face
%    #1%
%    \let\next}
%
% \def\math_text_choice_word#1#2#%
%   {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
%    \hbox#2\bgroup
%    \bgroup
%    \aftergroup\hss
%    \aftergroup\egroup
%    \hss
%    \font_basics_switchtobodyfont\m_math_text_choice_face
%    #1%
%    \nospacing % \normalnospaces\plusone
%    \let\next}
%
% % \ruledhbox{$\mathtext{abc ffi}$}
% % \ruledhbox{$\mathword{abc ffi}$}
%
% \permanent\protected\def\mathtext  {\mathortext{\math_text_choice_font\relax}\hbox}
% \permanent\protected\def\mathword  {\mathortext{\math_text_choice_word\relax}\hbox}
%
% \permanent\protected\def\mathtexttf{\mathortext{\math_text_choice_font\tf}\hbox}
% \permanent\protected\def\mathtextit{\mathortext{\math_text_choice_font\it}\hbox}
% \permanent\protected\def\mathtextsl{\mathortext{\math_text_choice_font\sl}\hbox}
% \permanent\protected\def\mathtextbf{\mathortext{\math_text_choice_font\bf}\hbox}
% \permanent\protected\def\mathtextbi{\mathortext{\math_text_choice_font\bi}\hbox}
% \permanent\protected\def\mathtextbs{\mathortext{\math_text_choice_font\bs}\hbox}
%
% \permanent\protected\def\mathwordtf{\mathortext{\math_text_choice_word\tf}\hbox}
% \permanent\protected\def\mathwordit{\mathortext{\math_text_choice_word\it}\hbox}
% \permanent\protected\def\mathwordsl{\mathortext{\math_text_choice_word\sl}\hbox}
% \permanent\protected\def\mathwordbf{\mathortext{\math_text_choice_word\bf}\hbox}
% \permanent\protected\def\mathwordbi{\mathortext{\math_text_choice_word\bi}\hbox}
% \permanent\protected\def\mathwordbs{\mathortext{\math_text_choice_word\bs}\hbox}

%D The split option is sort or a gimmick but one never knows how it might come in
%D handy. It was also an interesting test for how easy we can get this done (an extra
%D option as well as cheating in the line break function). And it was a good excuse
%D to add options to glue (which was pending). Actually, the main reason for this
%D trickery was that unrolling lists into the main math list could have strange side
%D effects, due to glue being ignored in math in the libereak routine, so better get
%D it working than explaining why if could have side effects.

%D The fact that one can pass e.g \type {to 4cm} before the content is an old and
%D probably never used feature that we keep in order to remain compatible.

\installcorenamespace{mathtext}

\installcommandhandler \??mathtext {mathtext} \??mathtext

\setupmathtext
  [\s!leftclass=\mathtextparameter\s!class,
   \s!rightclass=\mathtextparameter\s!class,
   \s!class=\mathordinarycode]

\appendtoks
    \frozen\protected\edefcsname\currentmathtext\endcsname{\math_text_handle{\currentmathtext}}
\to \everydefinemathtext

\newtoks\everymathtext

\tolerant\protected\def\math_text_handle_indeed#1#*[#S#2]#:#3#%
  {\begingroup
   \cdef\currentmathtext{#1}%
   \setupcurrentmathtext[#2]%
   \normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
   \ifcstok{\mathtextparameter\c!alternative}\v!split
     \mathatom
       unroll
       class      \mathcodechecked{\mathtextparameter\s!class}
       leftclass  \mathcodechecked{\mathtextparameter\s!leftclass}
       rightclass \mathcodechecked{\mathtextparameter\s!rightclass}
       \bgroup
     \hbox#3\bgroup
     \aftergroup\egroup
     \aftergroup\endgroup
   \else
     \hbox#3\bgroup
     \atendofgroup\hss
     \aftergroup\endgroup
     \ifcstok{\mathtextparameter\c!alternative}\v!word
       \nospacing % \normalnospaces\plusone
     \fi
     \hss
   \fi
   \font_basics_switchtobodyfont\m_math_text_choice_face
   \usemathtextstyleandcolor\c!style\c!color
   \expand\everymathtext\relax
   \let\next}

\protected\def\math_text_handle#1%
   {\mathortext{\math_text_handle_indeed{#1}}\hbox}

\definemathtext[mathtext]
\definemathtext[mathtexttf][mathtext][\c!style=\tf]
\definemathtext[mathtextit][mathtext][\c!style=\it]
\definemathtext[mathtextsl][mathtext][\c!style=\sl]
\definemathtext[mathtextbf][mathtext][\c!style=\bf]
\definemathtext[mathtextbi][mathtext][\c!style=\bi]
\definemathtext[mathtextbs][mathtext][\c!style=\bs]

\definemathtext[mathword]  [mathtext][\c!alternative=\v!word]
\definemathtext[mathwordtf][mathword][\c!style=\tf]
\definemathtext[mathwordit][mathword][\c!style=\it]
\definemathtext[mathwordsl][mathword][\c!style=\sl]
\definemathtext[mathwordbf][mathword][\c!style=\bf]
\definemathtext[mathwordbi][mathword][\c!style=\bi]
\definemathtext[mathwordbs][mathword][\c!style=\bs]

\definemathtext[mathsplit]  [mathtext] [\c!alternative=\v!split]
\definemathtext[mathsplittf][mathsplit][\c!style=\tf]
\definemathtext[mathsplitit][mathsplit][\c!style=\it]
\definemathtext[mathsplitsl][mathsplit][\c!style=\sl]
\definemathtext[mathsplitbf][mathsplit][\c!style=\bf]
\definemathtext[mathsplitbi][mathsplit][\c!style=\bi]
\definemathtext[mathsplitbs][mathsplit][\c!style=\bs]

% \startbuffer
%     $
%     {    x\! \neq x!} \quad {\ss     x\! \neq x!} \qquad
%     {\it x\! \neq x!} \quad {\ss \it x\! \neq x!} \qquad
%     {\bf x\! \neq x!} \quad {\ss \bf x\! \neq x!} \qquad
%     {\bi x\! \neq x!} \quad {\ss \bi x\! \neq x!}
%     $
% \stopbuffer
%
% \startTEXpage[offset=1dk]
%     \getbuffer \par \automathtext \getbuffer
% \stopTEXpage

\newconditional\c_mathtextauto % we need aproper key: \c_mathtextauto\conditionaltrue

\permanent\protected\def\automathtext{\c_mathtextauto\conditionaltrue}

\let\currentmathalphabet \s!rm
\let\currentmathfontstyle\s!tf

\permanent\protected\def\mathtextauto#1#2%
  {\ifconditional\c_mathtextauto
     \mathortext
       {\mathpunct
          {\begincsname\currentmathalphabet\endcsname
           \begincsname mathtext\currentmathfontstyle\endcsname
           {#1}}}%
       {#1}%
   \else
     #2%
   \fi}

%D Actually in spac-hor.mkxl we defined them using \suggestedalias which redefines
%D these so basically we now make that sort of obsolete.
%D
%D \starttyping
%D $x\, x$\quad\automathtext$x\, x$
%D \stoptyping

\pushoverloadmode
    \permanent\protected\def\.{\mathtextauto{.}{.}}
    \permanent\protected\def\,{\mathtextauto{,}{\thinspace }}
    \permanent\protected\def\:{\mathtextauto{:}{\medspace  }}
    \permanent\protected\def\;{\mathtextauto{;}{\thickspace}}
    \permanent\protected\def\!{\mathtextauto{!}{\negthinspace}}
    \permanent\protected\def\?{\mathtextauto{?}{?}}
\popoverloadmode

\appendtoks \obeydiscretionaries   \to \everymathtext
\appendtoks \ignorediscretionaries \to \everymathematics

%D Safeguard against redefinitions:

\appendtoks
    \enforced\let\_\normalunderscore % is textunderscore or fakeunderscore
\to \everymathematics

%D Because we may overload \type {\text} in other (structuring) macros, we say:

\appendtoks
    \enforced\let\text\mathtext
\to \everymathematics

\newinteger\interdisplaylinepenalty \interdisplaylinepenalty\plushundred

%D Text in math:

\permanent\protected\def\mathortext
  {\ifmmode
     \expandafter\firstoftwoarguments
   \else
     \expandafter\secondoftwoarguments
   \fi}

% \defineactivecharacter _ {\mathortext{_}{\_}} text_text  $a^2$

% force text mode, will be overloaded later

\ifdefined\text\else \aliased\let\text\hbox \fi

% \protected\def\mathoptext#1{\mathop{\text{#1}}}

\newtoks\everymathoptext

\appendtoks
    \let|\textbar
\to \everymathoptext

\permanent\protected\def\mathoptext
  {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
  %\showmathstyle
   \dowithnextbox
     {\mathop{\box\nextbox}}%
     \hbox\bgroup
     \expandtoks\everymathoptext
     \font_basics_switchtobodyfont
     \m_math_text_choice_face
     \let\next}

% new:

% \startsetups math:morespacing
%     \Umathordordspacing\textstyle 1mu plus .5mu minus .25mu\relax
% \stopsetups
%
% \setupmathematics
%   [setups=math:morespacing]

\appendtoks
    \edef\p_setups{\mathematicsparameter\c!setups}%
    \ifempty\p_setups\else
        \directsetup\p_setups
    \fi
%to \everyswitchmathematics
\to \everyinsidemathematics

% new:

\permanent\protected\def\smallmathsymbol#1%
  {\mathematics{\mathbin{\expanded{\raise.15\exheight\hbox{\normalstartimath
     \triggeredmathstyle{\the\numexpr\normalmathstyle+2\relax}#1%
   \normalstopimath}}}}}

% this should be a primitive:

%permanent\def\mathextensiblecode#1#2{\clf_extensiblecode{#1}{#2}} % at lua end
%permanent\def\mathhorizontalcode#1#2{\clf_horizontalcode{#1}{#2}} % at lua end

% experimental:

%D \starttyping
%D \enabletrackers[math.openedup]
%D
%D \dorecurse{10}{\dorecurse{#1}{whatever }}
%D
%D \startitemize[packed]
%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
%D \stopitemize
%D \startitemize[packed,columns]
%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
%D \stopitemize
%D
%D \dorecurse{5}{\dorecurse{#1}{whatever }\openedupimath{\frac{1}{2}} }
%D
%D \startitemize[packed,columns]
%D     \startitem whatever \openedupimath{1+2} whatever
%D     \startitem whatever \openedupimath{1+2} whatever
%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
%D     \startitem whatever \openedupimath{1+2} whatever
%D     \startitem whatever \openedupimath{1+2} whatever
%D \stopitemize
%D
%D \dorecurse{5}{\dorecurse{#1}{whatever }\openedupimath{1+2} }
%D
%D \startitemize[packed]
%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
%D     \startitem whatever \openedupimath{\frac{1}{2}} whatever
%D \stopitemize
%D
%D \dorecurse{10}{whatever }
%D \dorecurse {5}{\dorecurse{#1}{whatever }\openedupimath{\frac{1}{2}} }
%D \dorecurse{10}{whatever }
%D \stoptyping

% \def\m_math_inline_openup_ht{\dimexpr\ifinsidecolumns\strutdp\else\lineheight\fi/\plusfour\relax}
% \def\m_math_inline_openup_dp{\dimexpr\ifinsidecolumns\strutdp\else\lineheight\fi/\plusfour\relax}

\def\m_math_inline_openup_ht{(\ifinsidecolumns\strutdp\else\lineheight\fi/\plusfour)}
\def\m_math_inline_openup_dp{(\ifinsidecolumns\strutdp\else\lineheight\fi/\plusfour)}

% \def\m_math_inline_openup_ht{\dimexpr\lineheight/\ifinsidecolumns\pluseight\else\plusfour\fi\relax}
% \def\m_math_inline_openup_dp{\dimexpr\lineheight/\ifinsidecolumns\pluseight\else\plusfour\fi\relax}

\installtextracker
  {math.openedup}
  {\let\math_inline_openup_start_yes\math_inline_openup_traced_start}
  {\let\math_inline_openup_start_yes\math_inline_openup_normal_start}

\protected\def\math_inline_openup_normal_start
  {\scratchheight{\ht\scratchbox+\m_math_inline_openup_ht}%
   \scratchdepth {\dp\scratchbox+\m_math_inline_openup_dp}%
   \vrule\s!width\zeropoint\s!height\scratchheight\s!depth\scratchdepth\relax
   \begingroup
   \let\math_inline_openup_stop\math_inline_openup_normal_stop}

\protected\def\math_inline_openup_normal_stop
   {\endgroup
    \vrule\s!width\zeropoint\s!height\scratchheight\s!depth\scratchdepth\relax}

\protected\def\math_inline_openup_traced_start
  {\scratchtopoffset   \ht\scratchbox
   \scratchbottomoffset\dp\scratchbox
   \scratchheight      {\scratchtopoffset   +\m_math_inline_openup_ht}%
   \scratchdepth       {\scratchbottomoffset+\m_math_inline_openup_dp}%
   \vrule\s!width\zeropoint\s!height\scratchheight\s!depth\scratchdepth\relax
   \begingroup
     \dousecolorparameter{darkred}%
     \vrule\s!width\emwidth\s!height\scratchheight\s!depth-\scratchtopoffset\relax
   \endgroup
   \kern-\emwidth
   \begingroup
   \let\math_inline_openup_stop\math_inline_openup_traced_stop}

\protected\def\math_inline_openup_traced_stop
  {\endgroup
   \kern-\emwidth
   \begingroup
     \dousecolorparameter{darkblue}%
     \vrule\s!width\emwidth\s!height-\scratchbottomoffset\s!depth\scratchdepth\relax
   \endgroup
   \vrule\s!width\zeropoint\s!height\scratchheight\s!depth\scratchdepth\relax}

\let\math_inline_openup_start_yes\math_inline_openup_normal_start
\let\math_inline_openup_stop     \relax

\def\math_inline_openup_start_nop
  {\let\math_inline_openup_stop\relax}

\permanent\protected\def\openedupimath
  {\dontleavehmode
   \begingroup
   \ifmmode
     \expandafter\openedupimath_math
   \else
     \expandafter\openedupimath_text
   \fi}

\protected\def\openedupimath_math#1%
  {\setbox\scratchbox\mathstylehbox{#1}%
   \ifdim\ht\scratchbox>\strutht
     \math_inline_openup_start_yes
   \orelse\ifdim\dp\scratchbox>\strutdp
     \math_inline_openup_start_yes
   \else
     \math_inline_openup_start_nop
   \fi
   #1%
   \math_inline_openup_stop
   \endgroup}

\protected\def\openedupimath_text#1%
  {\setbox\scratchbox\hbox{\startimath#1\stopimath}%
   \ifdim\ht\scratchbox>\strutht
     \math_inline_openup_start_yes
   \orelse\ifdim\dp\scratchbox>\strutdp
     \math_inline_openup_start_yes
   \else
     \math_inline_openup_start_nop
   \fi
   \startimath
   #1%
   \stopimath
   \math_inline_openup_stop
   \endgroup}

% Also handy, especially for units:
%
% 0x002B=plus 0x2212=minus 0x2013=endash

\permanent\protected\def\mathplus     {+}
\permanent\protected\def\mathminus    {\ifmmode –\orelse\iffontchar\font`−−\else –\fi}
\permanent\protected\def\mathplusminus{±}

%D Experiment, replaced by dictionaries but for now we keep the code as the domain key
%D might come back.
%
% \newinteger\c_math_domain_attribute
%
% \def\math_domain_initialize
%   {\ifnum\c_math_domain_attribute=\attributeunsetvalue \else
%      \clf_initializemathdomain % one time
%      \glet\math_domain_initialize\relax
%    \fi}
%
% \appendtoks
%     \edef\p_domain{\mathematicsparameter\c!domain}%
%     \ifempty\p_domain
%         \c_math_domain_attribute\attributeunsetvalue
%     \else
%         \c_math_domain_attribute\clf_getmathdomain\p_domain\relax
%         \math_domain_initialize
%     \fi
% \to \everyswitchmathematics % only in mathematics
%
% \appendtoks
%     \c_attr_mathdomain\c_math_domain_attribute
% \to \everymathematics

\newinteger\c_math_domain_attribute

\appendtoks
    \edef\p_domain{\mathematicsparameter\c!domain}%
    \ifempty\p_domain
        \c_math_domain_attribute\attributeunsetvalue
    \else
        \c_math_domain_attribute\clf_domainattribute{\p_domain}\relax
    \fi
\to \everyswitchmathematics % only in mathematics

\appendtoks
    \c_attr_mathdomain\c_math_domain_attribute
\to \everymathematics

%D For special purposes (koeieletters) we set this one:

\installcorenamespace{mathrules}

\permanent\protected\def\enablemathrules{\gletcsname\??mathrules\fontclass\endcsname\plusone}

\appendtoks
    \mathrulesmode\ifcsname\??mathrules\fontclass\endcsname
      \lastnamedcs
    \else
      \zerocount
    \fi
    \mathrulesfam\zerocount
\to \everymathematics

%D Maybe:

% \starttabulate[|||c|c|]
% \BC positive                            \BC negative                               \BC text                           \BC math \NC \NR
% \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
% \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
% \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
% \NC \tex {f4} \tex {thickspace}         \NC \tex {b4} \tex {negthickspace}         \NC {\darkred\vl}\f4{\darkblue\vl} \NC ${\darkred\vl}\f4{\darkblue\vl}$ \NC \NR
% \NC \tex {f5} \tex {enspace}            \NC \tex {b5}                              \NC {\darkred\vl}\f5{\darkblue\vl} \NC ${\darkred\vl}\f5{\darkblue\vl}$ \NC \NR
% \NC \tex {f6} \tex {emspace}            \NC \tex {b6}                              \NC {\darkred\vl}\f6{\darkblue\vl} \NC ${\darkred\vl}\f6{\darkblue\vl}$ \NC \NR
% \stoptabulate

% \protected\def\negenspace{\kern-.5\emwidth}
% \protected\def\negemspace{\kern-  \emwidth}
%
% \protected\def\math_f#1%
%   {\ifcase#1\or
%      \hairspace
%    \or
%      \thinspace
%    \or
%      \medspace
%    \or
%      \thickspace
%    \or
%      \enspace
%    \or
%      \emspace
%    \fi}
%
% \protected\def\math_b#1%
%   {\ifcase#1\or
%      \neghairspace
%    \or
%      \negthinspace
%    \or
%      \negmedspace
%    \or
%      \negthickspace
%    \or
%      \negenspace
%    \or
%      \negemspace
%    \fi}
%
% \appendtoks
%     \let\f\math_f
%     \let\b\math_b
% \to \everymathematics

%D Experiment

\permanent\protected\def\math_scripts_stack
  {\c_attr_mathunstack\attributeunsetvalue}

\permanent\protected\def\math_scripts_unstack
  {\clf_enablescriptunstacking
   \c_attr_mathunstack\plustwo} % \plusone for the other way around

\ifdefined\stackscripts   \else \aliased\let\stackscripts  \relax \fi
\ifdefined\unstackscripts \else \aliased\let\unstackscripts\relax \fi

\appendtoks
    \enforced\let\stackscripts  \math_scripts_stack
    \enforced\let\unstackscripts\math_scripts_unstack
\to \everymathematics

%D Expensive (tracing and inject) but a primitive (using factors) is tricky as we
%D want this frozen support.

% \def\math_openup_parameter#1#2%
%   {\ifzeropt#1\displaystyle            \orelse\ifdim#1\displaystyle            =\maxdimen\else\frozen#1\displaystyle            #2#1\displaystyle            \fi
%    \ifzeropt#1\crampeddisplaystyle     \orelse\ifdim#1\crampeddisplaystyle     =\maxdimen\else\frozen#1\crampeddisplaystyle     #2#1\crampeddisplaystyle     \fi
%    \ifzeropt#1\textstyle               \orelse\ifdim#1\textstyle               =\maxdimen\else\frozen#1\textstyle               #2#1\textstyle               \fi
%    \ifzeropt#1\crampedtextstyle        \orelse\ifdim#1\crampedtextstyle        =\maxdimen\else\frozen#1\crampedtextstyle        #2#1\crampedtextstyle        \fi
%    \ifzeropt#1\scriptstyle             \orelse\ifdim#1\scriptstyle             =\maxdimen\else\frozen#1\scriptstyle             #2#1\scriptstyle             \fi
%    \ifzeropt#1\crampedscriptstyle      \orelse\ifdim#1\crampedscriptstyle      =\maxdimen\else\frozen#1\crampedscriptstyle      #2#1\crampedscriptstyle      \fi
%    \ifzeropt#1\scriptscriptstyle       \orelse\ifdim#1\scriptscriptstyle       =\maxdimen\else\frozen#1\scriptscriptstyle       #2#1\scriptscriptstyle       \fi
%    \ifzeropt#1\crampedscriptscriptstyle\orelse\ifdim#1\crampedscriptscriptstyle=\maxdimen\else\frozen#1\crampedscriptscriptstyle#2#1\crampedscriptscriptstyle\fi}

% \def\mdim#1#2%
%   {\ifcase\ifzeropt#1#2\plusone\orelse\ifdim#1#2=\maxdimen\plusone\else\zerocount\fi}
%
% \def\mdim
%   {\afterassignment\mmdim\scratchdimen}
%
% \def\mmdim
%   {\ifcase\ifzeropt\scratchdimen\plusone\orelse\ifdim\scratchdimen=\maxdimen\plusone\else\zerocount\fi}
%
% \def\math_openup_parameter#1#2%
%   {\ifcondition\mdim#1\displaystyle            \frozen#1\displaystyle            #2\dimexpr#1\displaystyle            \relax\fi
%    \ifcondition\mdim#1\crampeddisplaystyle     \frozen#1\crampeddisplaystyle     #2\dimexpr#1\crampeddisplaystyle     \relax\fi
%    \ifcondition\mdim#1\textstyle               \frozen#1\textstyle               #2\dimexpr#1\textstyle               \relax\fi
%    \ifcondition\mdim#1\crampedtextstyle        \frozen#1\crampedtextstyle        #2\dimexpr#1\crampedtextstyle        \relax\fi
%    \ifcondition\mdim#1\scriptstyle             \frozen#1\scriptstyle             #2\dimexpr#1\scriptstyle             \relax\fi
%    \ifcondition\mdim#1\crampedscriptstyle      \frozen#1\crampedscriptstyle      #2\dimexpr#1\crampedscriptstyle      \relax\fi
%    \ifcondition\mdim#1\scriptscriptstyle       \frozen#1\scriptscriptstyle       #2\dimexpr#1\scriptscriptstyle       \relax\fi
%    \ifcondition\mdim#1\crampedscriptscriptstyle\frozen#1\crampedscriptscriptstyle#2\dimexpr#1\crampedscriptscriptstyle\relax\fi}

% \ifmathparameter : 0=zero, 1=set, 2=unset (les stracing clutter this way)

%D New stuff:
%D
%D \starttyping
%D $\mathopenupparameter\Umathradicalvgap{10.5}\sqrt[3]{x}$
%D \stoptyping

\permanent\protected\def\mathopenupparameter#1#2%
  {\ifmathparameter#1\displaystyle            \or\frozen#1\displaystyle            #2#1\displaystyle            \fi
   \ifmathparameter#1\crampeddisplaystyle     \or\frozen#1\crampeddisplaystyle     #2#1\crampeddisplaystyle     \fi
   \ifmathparameter#1\textstyle               \or\frozen#1\textstyle               #2#1\textstyle               \fi
   \ifmathparameter#1\crampedtextstyle        \or\frozen#1\crampedtextstyle        #2#1\crampedtextstyle        \fi
   \ifmathparameter#1\scriptstyle             \or\frozen#1\scriptstyle             #2#1\scriptstyle             \fi
   \ifmathparameter#1\crampedscriptstyle      \or\frozen#1\crampedscriptstyle      #2#1\crampedscriptstyle      \fi
   \ifmathparameter#1\scriptscriptstyle       \or\frozen#1\scriptscriptstyle       #2#1\scriptscriptstyle       \fi
   \ifmathparameter#1\crampedscriptscriptstyle\or\frozen#1\crampedscriptscriptstyle#2#1\crampedscriptscriptstyle\fi}

%D New stuff:
%D
%D \startbuffer
%D $x\mathopen   {!}+123+\mathclose  {!}x$
%D $x\tomathopen  ! +123+\tomathclose ! x$
%D $x\mathclose  {!}+123+\mathopen   {!}x$
%D $x\tomathclose ! +123+\tomathopen  ! x$
%D $x             ! +123+             ! x$
%D \stopbuffer
%D
%D \typebuffer
%D
%D \startlines
%D \getbuffer
%D \stoplines

\permanent\protected\def\tomathord  {\Umathclass\zerocount}
\permanent\protected\def\tomathop   {\Umathclass\plusone  } % \mathinfix
\permanent\protected\def\tomathbin  {\Umathclass\plustwo  }
\permanent\protected\def\tomathrel  {\Umathclass\plusthree}
\permanent\protected\def\tomathopen {\Umathclass\plusfour } % \mathprefix
\permanent\protected\def\tomathclose{\Umathclass\plusfive } % \mathsuffix
\permanent\protected\def\tomathpunct{\Umathclass\plussix  }

%D Prescripts. These work in \CONTEXT\ because we have the super- and subscript
%D triggers enabled as active characters but when we would have
%D
%D \starttyping
%D \catcode\underscoreasciicode\subscriptcatcode
%D \catcode\circumflexasciicode\superscriptcatcode
%D \stoptyping
%D
%D we also need the next line to disable character escaping via \type {^} in
%D math mode:
%D
%D \startbuffer
%D \blank \hbox{
%D     \ruledhbox{${\tf X} ^1 _2 ^^3 __4$}
%D     \ruledhbox{${\tf X} ^1           $}
%D     \ruledhbox{${\tf X}    _2        $}
%D     \ruledhbox{${\tf X}       ^^3    $}
%D     \ruledhbox{${\tf X}           __4$}
%D     \ruledhbox{${\tf X} ^1 _2        $}
%D     \ruledhbox{${\tf X} ^1    ^^3    $}
%D     \ruledhbox{${\tf X} ^1        __4$}
%D     \ruledhbox{${\tf X}    _2 ^^3    $}
%D     \ruledhbox{${\tf X}    _2     __4$}
%D     \ruledhbox{${\tf X} ^1 _2 ^^3    $}
%D     \ruledhbox{${\tf X} ^1 _2     __4$}
%D     \ruledhbox{${\tf X}    _2 ^^3    $}
%D     \ruledhbox{${\tf X}    _2 ^^3 __4$}
%D     \ruledhbox{${\tf X}       ^^3 __4$}
%D } \blank
%D
%D \typebuffer \getbuffer

\normalsupmarkmode\plusone % 2 also disable ^[^+] in text mode

\permanent\protected\tolerant\def\supscr[#1]#:#2%
  {\ifchkdimension#1\or\Umathopenupheight\lastchkdimension\fi
   \superscript{#2}}

\permanent\protected\tolerant\def\subscr[#1]#:#2%
  {\ifchkdimension#1\or\Umathopenupdepth\lastchkdimension\fi
   \subscript{#2}}

\permanent\protected\tolerant\def\supsubscr[#1]#:#2#3%
  {\ifchkdimension#1\or\Umathopenupheight\lastchkdimension\Umathopenupdepth\lastchkdimension\relax\fi
   \superscript{#2}\subscript{#3}}

\permanent\protected\tolerant\def\subsupscr[#1]#:#*#2#3%
  {\ifchkdimension#1\or\Umathopenupheight\lastchkdimension\Umathopenupdepth\lastchkdimension\relax\fi
   \subscript{#2}\superscript{#3}}

\permanent\protected\tolerant\def\supprescr[#1]#:#2%
  {\ifchkdimension#1\or\Umathopenupheight\lastchkdimension\fi
   \superprescript{#2}}

\permanent\protected\tolerant\def\subprescr[#1]#:#2%
  {\ifchkdimension#1\or\Umathopenupdepth\lastchkdimension\fi
   \subprescript{#2}}

\permanent\protected\tolerant\def\supsubprescr[#1]#:#2#3%
  {\ifchkdimension#1\or\Umathopenupheight\lastchkdimension\Umathopenupdepth\lastchkdimension\fi
   \superprescript{#2}\subprescript{#3}}

\permanent\protected\tolerant\def\subsupprescr[#1]#:#*#2#3%
  {\ifchkdimension#1\or\Umathopenupheight\lastchkdimension\Umathopenupdepth\lastchkdimension\fi
   \subprescript{#2}\superprescript{#3}}

%D For now (needed in asciimath):

\def\math_relax_limits{\enforced\let\limits\relax}

%D Something new:
%D
%D \starttyping
%D \definemathpreset[whatever][factor=.5,style=all,list={fraction*gap}]
%D % \presetmathematics[whatever] % less more zero
%D \stoptyping
%D
%D as well as:
%D
%D \starttyping
%D $\Umathxscale\textstyle  800 a + b + x + d + e = f $\par
%D $\Umathxscale\textstyle 1000 a + b + x + d + e = f $\par
%D $\Umathxscale\textstyle 1200 a + b + x + d + e = f $\blank
%D
%D $\showboxes\setupmathspacing[narrow] a + b + x + d + e = f $\par
%D $\showboxes\setupmathspacing[normal] a + b + x + d + e = f $\par
%D $\showboxes\setupmathspacing[wide]   a + b + x + d + e = f $\blank
%D
%D $\showboxes\setupmathspacing[tight]  x^2_1$\quad
%D $\showboxes\setupmathspacing[normal] x^2_1$\quad
%D $\showboxes\setupmathspacing[loose]  x^2_1$\blank
%D \stoptyping

\installcorenamespace{mathspacing}

\permanent\tolerant\protected\def\definemathspacing[#1]#*[#2]#*[#3]%
  {\ifcstok{#2}\v!horizontal
     \edefcsname\??mathspacing#1\endcsname
       {\Umathxscale\allmathstyles\ifchknum#3\or#3\else\plusthousand\fi\relax}%
   \orelse\ifcstok{#2}\v!vertical
     \edefcsname\??mathspacing#1\endcsname
       {\Umathyscale\allmathstyles\ifchknum#3\or#3\else\plusthousand\fi\relax}%
   \else
     \edefcsname\??mathspacing#1\endcsname
       {\Umathxscale\allmathstyles\ifchknum#2\or\number#2\else\plusthousand\fi\relax
        \Umathyscale\allmathstyles\ifchknum#3\or\number#3\orelse\ifchknum#2\or\number#2\else\plusthousand\fi\relax}%
   \fi}

\definemathspacing[\v!normal]                [1000] [1000]
\definemathspacing[\v!tight] [\c!vertical]    [900]
\definemathspacing[\v!loose] [\c!vertical]   [1100]
\definemathspacing[\v!narrow][\c!horizontal]  [900]
\definemathspacing[\v!wide]  [\c!horizontal] [1100]
\definemathspacing[\v!less]                   [900]  [900]
\definemathspacing[\v!more]                  [1100] [1100]

\permanent\protected\def\setupmathspacing[#1]%
  {\begincsname\??mathspacing#1\endcsname}

%D We're done with the double dollars:
%D
%D \startbuffer
%D     before $                  i = 1 $                   after\par
%D     before $                  i = 2 \Ustopmath{}        after\par
%D     before \Ustartmath        i = 3 $                   after\par
%D     before \Ustartmath        i = 4 \Ustopmath{}        after\par
%D     before $$                 d = 1 $$                  after\par
%D     before $$                 d = 2 \Ustopdisplaymath{} after\par
%D     before \Ustartdisplaymath d = 3 $$                  after\par
%D     before \Ustartdisplaymath d = 4 \Ustopdisplaymath{} after\par
%D \stopbuffer
%D
%D \startpacked {\mathdisplaymode\zerocount \getbuffer} \stoppacked
%D \startpacked {\mathdisplaymode\plusone   \getbuffer} \stoppacked
%D
%D So we do the next. At some point this primitive will be blocked
%D after being set do don't assume it's there.

\mathdisplaymode\plusone % expands \everydisplay
%mathdisplaymode\plustwo % expands \everymath

%D Just to be sure:

\permanent\immutable\integerdef\c_math_glyph_options_default\numexpr
    \noexpansionglyphoptioncode
   +\noprotrusionglyphoptioncode
\relax

\permanent\immutable\integerdef\c_math_glyph_options_hz\numexpr
    \noprotrusionglyphoptioncode
\relax

\appendtoks
    \ifcstok{\mathematicsparameter\c!hz}\v!yes
      \glyphoptions\c_math_glyph_options_hz
    \else
      \glyphoptions\c_math_glyph_options_default
    \fi
\to \everymathematics

%D Math italics: see \MKIV\ files for how this was done because in \LMTX\ we ditched
%D them. The flags that we set with glyphoptions no longer apply. Correction with
%D surrounding text is also set elsewhere.

% \def\math_italics_initialize
%   {\clf_initializemathitalics
%    \gdef\math_italics_initialize
%      {%bitwiseflip\discretionaryoptions-\textcheckitalicdiscoptioncode % is this really needed
%       \bitwiseflip\glyphoptions-\textcheckitalicglyphoptioncode % is this really needed
%       \bitwiseflip\glyphoptions \mathcheckitalicglyphoptioncode}%
%    \math_italics_initialize}

\def\math_italics_initialize
  {\clf_initializemathitalics % one time, so permanent
   \gdef\math_italics_initialize{\bitwiseflip\glyphoptions\mathcheckitalicglyphoptioncode}%
   \math_italics_initialize}

\appendtoks
    \ifcstok{\mathematicsparameter\s!italics}\v!yes
        \math_italics_initialize
    \fi
\to \everymathematics

\setupmathematics
  [\s!italics=\v!yes] % per 2026-04-21

%D Bonus for testing:

% styles       : regular sansserif monospaced fraktur script blackboard
% alternatives : normal bold italic bolditalic
% sets         : ucletters lcletters digits ucgreek lcgreek symbols

% \def\CheckMathHat#1{\ruledhbox{\im{\widehat{\tocharacter#1}_1^2__3^^4}}}
%
% \dontleavehmode \traversemath{regular}{bold}{digits}{\CheckMathHat{#1}\hskip1em}

\aliased\let\mathtraversecommand\relax

\permanent\protected\def\traversemath#1#2#3#4%
  {\pushmacro\mathtraversecommand
   \enforced\def\mathtraversecommand##1{#4}%
   \clf_traversemath{#1}{#2}{#3}\mathtraversecommand
   \popmacro\mathtraversecommand}

\permanent\protected\def\traverseblock#1#2%
  {\pushmacro\mathtraversecommand
   \enforced\def\mathtraversecommand##1{#2}%
   \clf_traverseblock{#1}\mathtraversecommand
   \popmacro\mathtraversecommand}

%D Just some features:
%D
%D \starttyping
%D $ x + \mathatom         class \mathordcode {xxx} \Umathphantom + x $\par
%D $ x + \mathatom         class \mathordcode {xxx} \Umathvoid    + x $\par
%D $ x + \mathatom phantom class \mathordcode {xxx}               + x $\par
%D $ x + \mathatom void    class \mathordcode {xxx}               + x $\par
%D
%D \def\rab{\Umathchar"1"00"007C }
%D
%D $
%D \color[green]{\rab\Umathadapttoright^{\black 1}_{\black 2}^^3__4}
%D \color[blue] {\mathinner{\vrule height 30mm depth 30mm width 5mm}}
%D \color[red]  {\rab\Umathadapttoleft ^5_6^^{\black 7}__{\black 8}}
%D $
%D
%D $
%D     \rab\Umathadapttoright^1_2^^3__4
%D     \mathinner{\vrule height 30mm depth 30mm width 5mm}
%D     \rab\Umathadapttoleft^5_6^^7__8
%D $
%D \stoptyping

%D Just in case someone uses it:

% \appendtoks
%     \scriptspace.05\Umathquad\textstyle % for Mikael
% \to \everymathematics

\scriptspace\zeropoint

%D New:

% \startformula
%     \mathatom class 0 all \mathbincode      {a b c d} \breakhere
%     \mathatom class 0 all \mathfractioncode {a b c d} \breakhere
%     \base    {FE03} \breakhere
%     \base[16]{FE03} \breakhere
%     \base[8] {7204}
% \stopformula

\permanent\tolerant\def\mathdigits#1%
  {\ifmmode
     \mathatom \s!class \mathdigitcode \s!all \mathdigitcode {#1}%
   \else
     #1%
   \fi}

\permanent\tolerant\protected\def\base[#1]#*#:#2%
  {\ifmmode
     \mathdigits{\tf#2}\ifparameter#1\or\subscript{\mathdigits{\tf#1}}\fi
   \else
     #2\ifparameter#1\or\low{#1}\fi
   \fi}

%D New:

\permanent\tolerant\protected\def\definemathgroupset[#1]#*[#2]%
  {\clf_registergroupset{#1}{#2}}

\permanent\tolerant\protected\def\setmathgroupset[#1]%
  {\mathdictgroup\clf_groupsetgroup{#1}\relax}

\setmathgroupset
  [every]

%D Only for testing (limited line span):
%D
%D \starttyping
%D test \im {z + \mathaxisbelow x + 2 - a = 1} test \par
%D test \im {z + \mathaxisontop x + 2 - a = 1} test
%D \stoptyping

%D \starttyping
%D $ x^2 + x_2 + x_2^2\mathaxisbelow\mathscriptbelow$\par
%D $ x^g + x_g + x_g^g\mathaxisbelow\mathscriptbelow$
%D \stoptyping

\definesystemattribute[mathaxis][public]

\def\math_axis_inject_indeed#1%
  {\srule
     \s!height {%
        (\scratchdimentwo+\scratchdimenone)*%
        \ifnum\c_math_m_scaled=\plusthousand
          \glyphscale/\plusthousand
        \else
          \c_math_m_scaled*\glyphscale/\plusthousand/\plusthousand
        \fi
     }%
     \s!depth - {%
        (\scratchdimentwo-\scratchdimenone)*%
         \ifnum\c_math_m_scaled=\plusthousand
           \glyphscale/\plusthousand
         \else
           \c_math_m_scaled*\glyphscale/\plusthousand/\plusthousand
         \fi
     }%
     \s!attr \mathaxisattribute#1%
   \relax}

\def\math_axis_inject#1#2%
  {\mathatom \s!class \mathghostcode \s!unpack {
   \showmakeup[strut]% todo: shortcut
   \ifcase#1%
     % nothing
   \or
     \scratchdimenone.5\Umathfractionrule\mathstyle
     \scratchdimentwo\Umathaxis\mathstyle
     \math_axis_inject_indeed#2%
   \or
     \scratchdimenone.25\Umathfractionrule\mathstyle
     \scratchdimentwo\Umathsupshiftup\mathstyle
     \math_axis_inject_indeed#2%
     \scratchdimentwo-\Umathsubshiftdown\mathstyle
     \math_axis_inject_indeed#2%
     \scratchdimentwo-\Umathsubsupshiftdown\mathstyle
     \math_axis_inject_indeed#2%
   % \scratchdimenone.125\Umathfractionrule\mathstyle
     \divideby\scratchdimenone\plustwo
     \scratchdimentwo\Umathprimeshiftup\mathstyle
     \math_axis_inject_indeed#2%
   \fi}}

\permanent\protected\def\mathaxisbelow  {\math_axis_inject\plusone\plusone}
\permanent\protected\def\mathaxisontop  {\math_axis_inject\plusone\plustwo}
\permanent\protected\def\mathscriptbelow{\math_axis_inject\plustwo\plusone}
\permanent\protected\def\mathscriptontop{\math_axis_inject\plustwo\plustwo}

%D \macros{kt}
%D
%D Bonus (keep together):
%D
%D \startbuffer
%D test $a + b + c +                    d + x + x + e + f  + g = h$ test
%D test $a + b + c + \keeptogether{\red d + x + x + e + f} + g = h$ test
%D \stopbuffer
%D
%D \typebuffer
%D
%D \startlines \getbuffer \stoplines

\mathinlinepenaltyfactor  = 1500 % a reasonable default
\mathdisplaypenaltyfactor = 1000

\setmathpostpenalty\mathpunctuationcode\plustenthousand

\installcorenamespace{mathnesting}

\installcommandhandler \??mathnesting {mathnesting} \??mathnesting

\appendtoks
    \protected\frozen\instance\edefcsname\currentmathnesting\endcsname{\math_nesting[\currentmathnesting]}%
\to \everydefinemathnesting

\newconstant\c_math_boundary_old
\newconstant\c_math_boundary_new

\protected\tolerant\def\math_nesting[#1]#*[#S#2]%
  {\groupedcommand
     {\cdef\currentmathnesting{#1}%
      \setupcurrentmathnesting[#2]% \ifparameter#2\or...\fi can't work here due to nesting
      \mathnestingparameter\c!left
      \c_math_boundary_old\c_math_boundary_new
      \c_math_boundary_new
        \ifconditional\indisplaymath
          \ifchknum\mathnestingparameter\c!displayfactor\or\lastnamedcs\else\mathdisplaypenaltyfactor\fi
        \else
          \ifchknum\mathnestingparameter\c!inlinefactor \or\lastnamedcs\else\mathinlinepenaltyfactor \fi
        \fi
        \relax
      \mathboundary\plustwo  \c_math_boundary_new}%
     {\mathboundary\plusthree\c_math_boundary_old
      \mathnestingparameter\c!right}}

\permanent\tolerant\protected\def\mathnesting[#1]%
  {\groupedcommand
     {\c_math_boundary_old\c_math_boundary_new
      \c_math_boundary_new\ifchknum#1\or#1\orelse\ifconditional\indisplaymath\mathdisplaypenaltyfactor\else\mathinlinepenaltyfactor\fi\relax
      \mathboundary\plustwo  \c_math_boundary_new}%
     {\mathboundary\plusthree\c_math_boundary_old}}

% \definemathnesting[triplet][left=(,right=),inlinefactor=500]
% $ (a,b,c) + \triplet{1,2,3} + (p,q,r) $

\definemathnesting[mathtogether][\c!inlinefactor=1500]
\definemathnesting[mathloose]   [\c!inlinefactor=0500]

% \nofmathvariants % defined at lua end
% \getmathvariant  % defined at lua end
% \getmathcharone  % defined at lua end
% \getmathchartwo  % defined at lua end

%D Snapping scripts:
%D
%D \startbuffer
%D \setupmathematics[snap=yes]
%D
%D \im {
%D     \mathscriptbelow \mathaxisbelow
%D     (x)^1_2 + \left(x\right)^1_2 + \left(\frac{1}{2}\right)^1_2
%D }
%D \stopbuffer
%D
%D \typebuffer
%D
%D This will align scripts as in: \inlinebuffer.

\setupmathematics % currently not implemented
  [\c!snap=\v!no]

%D Here is a new one (that abstracts the scripts being abused):
%D
%D \startbuffer
%D \startformula
%D     \showstruts
%D      \mathannotation[top=my text here,bottom=my text there]{\underbrace{x+y+z}}
%D \stopformula
%D \stopbuffer
%D
%D \typebuffer
%D
%D \getbuffer

\installcorenamespace {mathannotation}

\installcommandhandler \??mathannotation {mathannotation} \??mathannotation

\setupmathannotation
  [\c!top=,
   \c!bottom=,
   \c!strut=\v!yes,
   \c!mathclass=\mathconstructcode]

\appendtoks
    \frozen\protected\tolerant\edefcsname\currentmathannotation\endcsname{\math_annotation{\currentmathannotation}}
\to \everydefinemathannotation

\tolerant\protected\def\math_annotation#1[#S#2]#:#3%
  {\beginmathgroup
   \edef\currentmathannotation{#1}%
   \setupcurrentmathannotation[#2]%
   \edef\p_strut{\mathannotationparameter\c!strut}%
   \mathatom
      limits
      \s!class\mathcodechecked{\mathannotationparameter\c!mathclass}%
     {#3}%
   \ifempty{\mathannotationparameter\c!top}\else
     % todo: tag this differently
     \superscript{%
        \ifx\p_strut\v!yes\botstrut\fi
        \mtext{\mathannotationparameter\c!top}%
      }%
   \fi
   \ifempty{\mathannotationparameter\c!bottom}\else
     % todo: tag this differently
     \subscript{%
        \ifx\p_strut\v!yes\topstrut\fi
        \mtext{\mathannotationparameter\c!bottom}%
     }%
   \fi
   \endmathgroup}

\definemathannotation[mathannotation]

%D By default we enable proper tensor multiple script alignment:

\mathdoublescriptmode
  "\tohexadecimal\numexpr
     \inheritclassdoublescriptmodecode
   + \discardshapekerndoublescriptmodecode
   + \realignscriptsdoublescriptmodecode
   + \reorderprescriptsdoublescriptmodecode
   \relax
   \tohexadecimal\mathcontinuationcode % 2 bytes
   \tohexadecimal\mathcontinuationcode % 2 bytes
   \tohexadecimal\mathcontinuationcode % 2 bytes

\permanent\immutable\integerdef\c_math_alignscripts_bits\numexpr
    "1000000 * \realignscriptsdoublescriptmodecode
\relax

\permanent\immutable\integerdef\c_math_obeyempty_bits\numexpr
    \ignoreemptysuperscriptsmodecode
   +\ignoreemptysubscriptsmodecode
   +\ignoreemptyprimescriptsmodecode
\relax

\lettonothing\m_math_alignscripts

\def\math_update_alignscripts
  {\ifx\m_alignscripts\v!yes
     \bitwiseflip\mathdoublescriptmode \c_math_alignscripts_bits  % align
     \bitwiseflip\mathscriptsmode     -\c_math_obeyempty_bits     % obey empty
   \orelse\ifx\m_alignscripts\v!always
     \bitwiseflip\mathdoublescriptmode \c_math_alignscripts_bits  % align
     \bitwiseflip\mathscriptsmode      \c_math_obeyempty_bits     % ignore empty
   \orelse\ifx\m_alignscripts\v!empty
     \bitwiseflip\mathdoublescriptmode-\c_math_alignscripts_bits  % don't align
     \bitwiseflip\mathscriptsmode      \c_math_obeyempty_bits     % ignore empty
   \else
     \bitwiseflip\mathdoublescriptmode-\c_math_alignscripts_bits  % don't align
     \bitwiseflip\mathscriptsmode     -\c_math_obeyempty_bits     % obey empty
   \fi
   \let\m_math_alignscripts\m_alignscripts}

\appendtoks
    \cdef\m_alignscripts{\mathematicsparameter\c!alignscripts}%
    \ifx\m_math_alignscripts\m_alignscripts\else
        \math_update_alignscripts
    \fi
% \to \everysetupmathematics
\to \everyswitchmathematics

\appendtoks
    \scriptspacebetweenfactor\numericscale\mathematicsparameter\c!interscriptfactor\relax
% \to \everysetupmathematics
\to \everyswitchmathematics

\setupmathematics
  [\c!alignscripts=\v!always,
   \c!interscriptfactor=1]

%D Needed for spacing, tagging, etc.

\newinteger\c_math_intervals

\appendtoks
    \ifcstok{\mathematicsparameter\c!autointervals}\v!yes
      \c_math_intervals\plusone
    \else
      \c_math_intervals\attributeunsetvalue
    \fi
% \to \everysetupmathematics
\to \everyswitchmathematics

\appendtoks
    \attribute\mathintervalsattribute\c_math_intervals
\to \everymathematics

\setupmathematics
  [\c!autointervals=\v!yes]

%D This is needed for tagging blobs:

\definesystemattribute[mathblob][public]

% \newinteger\currentmathblob
% \newinteger\currentmathblobnesting % could be a primitive

\newconditional\overloadedmathmeaning

\permanent\protected\def\math_start_meaning
  {\begingroup
   \let\math_trace_blobs\relax
   \setbox\scratchbox\hpack\bgroup\startmathexport[math:export]%
   \startimath}

\permanent\protected\def\math_stop_meaning
  {\stopimath
   \stopmathexport
   \egroup
   \endgroup
   \global\overloadedmathmeaning\conditionaltrue}

\appendtoks
    \enforced\let\startmathmeaning\math_start_meaning
    \enforced\let\stopmathmeaning \math_stop_meaning
\to \everyenableelements

\permanent\protected\def\startmathmeaning
  {\gobbleuntil\stopmathmeaning}

\permanent\lettonothing\stopmathmeaning

\protected\def\math_bump_blob_state
  {\ifnum\currentmathblobnesting<\zerocount\else
     \ifcase\currentmathblobnesting
       \ifconditional\overloadedmathmeaning
         \global\overloadedmathmeaning\conditionalfalse
       \else
         \global\advanceby\currentmathblob\plusone
       \fi
       \attribute\mathblobattribute\currentmathblob
     \fi
     \advanceby\currentmathblobnesting\plusone
   \fi}

\appendtoks
    \math_bump_blob_state
\to \everymathematics

% \appendtoks
%    \ifcstok{\taggingparameter\c!state}\v!start
%        \clf_enablecollectingmath
%    \fi
% \to \everysetuptagging

\appendtoks
    \clf_enablecollectingmath
\to \everyenableelements

\appendtoks
    \clf_disablecollectingmath
\to \everydisableelements

% needed for verbose: \im {C \of (a,b) \neq C^2 \of (a,b)}

\permanent\protected\def\math_application_of
%  {\mathatom class \mathghostcode unpack {\Umathchar \mathghostcode \zerocount "2061}} % only lists gets upacked !
  {\mathatom class \mathghostcode unpack {\applyfunctionof}} % only lists gets upacked !

\appendtoks
    \aliased\let\of\math_application_of
\to \everymathematics

%D For manuals and testing:
%D
%D \starttyping
%D \m { \showmathstate      {CMPSrfnd} }
%D \m { \showmathstate[-1ex]{CMPSrfnd} }
%D \stoptyping

\def\math_show_math_state    {\ifconditional\indisplaymath D\else T\fi\space}
\def\math_show_math_style  #1{\the#1\space}
\def\math_show_math_variant#1{\tohexa\pluseight#1\ifconditional\indisplaymath\displaystyle\else\textstyle\fi\space}

\permanent\tolerant\protected\def\showmathstate[#1]#:#2%
  {\mathghost \bgroup
     \setbox\scratchbox\hpack to \zeropoint \bgroup
       \hss
       \smallinfofont
       \ifhastok C{#2}C:\math_show_math_state\fi
       \ifhastok M{#2}M:\math_show_math_style  \mathmainstyle  \fi
       \ifhastok P{#2}P:\math_show_math_style  \mathparentstyle\fi
       \ifhastok S{#2}S:\math_show_math_style  \mathstyle      \fi
       \ifhastok r{#2}r:\math_show_math_variant\Umathradicalvariant    \fi
       \ifhastok f{#2}f:\math_show_math_variant\Umathfractionvariant   \fi
       \ifhastok n{#2}n:\math_show_math_variant\Umathnumeratorvariant  \fi
       \ifhastok d{#2}d:\math_show_math_variant\Umathdenominatorvariant\fi
       \removeunwantedspaces
       \hss
     \egroup
     \ht\scratchbox\zeropoint
     \dp\scratchbox\zeropoint
     \ifchkdimension#1\or\lower\lastchkdimension\fi
     \box\scratchbox
   \egroup}

\permanent\protected\def\showmathstyles
  {(\the\mathmainstyle|\the\mathparentstyle|\the\mathstyle)}

%D I need to verify if this indeed will make it into \type {math-ini.mkiv}, that is:
%D does Alan use it?

\ifdefined\t \else \permanent\protected\def\t{\mathortext\text\mathtext} \fi
\ifdefined\w \else \permanent\protected\def\w{\mathortext\word\mathword} \fi

\appendtoks
    \enforced\aliased\let\t\mathtext
    \enforced\aliased\let\w\mathword
\to \everymathematics

\protect \endinput

% % not used (yet)
%
% \newtoks \everystartimath
% \newtoks \everystopimath
%
% \protected\def\startimath{\Ustartmath\expand\everystartimath}
% \protected\def\stopimath {\expand\everystopimath\Ustopmath}
%
% \protected\def\m%
%   {\relax
%    \ifmmode\expandafter\math_m_stay\else\expandafter\math_m_math\fi}
%
% \protected\def\math_m_math#1%
%   {\startimath#1\stopimath}
%
% \let\math_m_stay\firstofoneargument

% Maybe
%
% % \showmakeup[mathglue] \mathspacingmode1
% % \im{x \not< M}
% % \im{x + x \not+ M + M}
% % \im{x + x \not+ M + M}
% % \im{x + x \not [\not ] M}
%
% \protected\def\abnormalnot#1%
%   {\ifcsname\csstring\not\csstring#1\endcsname
%      \lastnamedcs
%    \else
%      \begingroup
%      \aliased\let\not\normalnot % else weird recursion and even a crash (stack probably)
%      % we need to block look_ahead_for_end_class_option (todo: via boundary
%      \setbox\scratchboxone\mathstylehbox{\normalnot}%
%      \setbox\scratchboxtwo\mathstylehbox{\hbox{}#1\hbox{}}% fool the bin
%      \scratchcounterone\the\lastleftclass
%      \scratchcountertwo\the\lastrightclass
%       \mathatom leftclass \scratchcounterone rightclass \scratchcountertwo
%     {\hpack{%
%        \scratchdimenone\wd\scratchboxone
%        \scratchdimentwo\wd\scratchboxtwo
%        \kern.5\dimexpr\scratchdimentwo-\scratchdimenone\relax
%        \unhbox\scratchboxone
%        \kern-.5\dimexpr\scratchdimenone+\scratchdimentwo\relax
%        \unhbox\scratchboxtwo
%      }}%
%      \endgroup
%   \fi}
%
% \appendtoks
%   \aliased\let\normalnot\not
%   \aliased\let\not\abnormalnot
% \to \everymathematics
