%D \module
%D   [       file=math-ini,
%D        version=2008.01.02,
%D          title=\CONTEXT\ Math Macros,
%D       subtitle=Initializations,
%D         author=Hans Hagen,
%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}

% todo: hpack as we skip math anyway
%
% todo: 0x2061 : function application
% todo: 0x2062 : invisible times
% todo: 0x2063 : invisible comma

% a bit tricky way to set ... no (pseudo) registers but math hash values:
%
% \normalexpanded{\Umathlimitabovevgap\displaystyle=40\dimexpr\the\Umathlimitabovevgap\displaystyle\relax}

% Todo in luatex maincontrol.w: also accept a number here:
%
%    case set_math_param_cmd:
%        p = cur_chr;
%        get_token();
%        if (cur_cmd != math_style_cmd) {
%
% plus two new math styles: larger/smaller
%
% \unexpanded\def\Umathshow#1%
%   {\hbox{\infofont(\string#1:\the#1\textstyle,\the#1\scriptstyle,\the#1\scriptscriptstyle)}}

%D This module provides namespaces for math fonts, thereby permitting mixed usage of
%D math fonts. Although not strictly needed, we also provide a family name mapping
%D mechanism as used in the (original) AMS math definition files, but here these
%D names can recursively be remapped and if needed, dynamically be changed. We've
%D tried to minimize the number of definition commands and use plain \TEX\
%D definitions as fallback. We've tried to follow a couple of conventions from plain
%D and AMS math in order to achieve backward compatinility. We also kept an eye on
%D future usage of these modules in the perspective of MathML and unicode fonts.

%D There is a subtle issue with grouping: the \type {\begingroup} method will not
%D restore a changed mathstyle so best avoid that one. However, there are cases where
%D we really need to use such grouping.

% Weird, these fail, maybe amp is solved in a later state from char noads (needs a
% fix in luatex):
%
% $\char"26$
% $\a$
% $\string&$

% mathop applied to characters centers it vertically

\unprotect

%D We move these definitions into the format:

% test  [[\char948 \cldcontext{utf.char(948)}]]
% test $[[\char948 \cldcontext{utf.char(948)}]]$

\registerctxluafile{math-ini}{}
\registerctxluafile{math-dim}{}
\registerctxluafile{math-act}{}
\registerctxluafile{math-ext}{}
\registerctxluafile{math-vfu}{}
\registerctxluafile{math-ttv}{}
\registerctxluafile{math-map}{optimize}
\registerctxluafile{math-ren}{}
\registerctxluafile{math-noa}{optimize}
\registerctxluafile{math-tag}{}
\registerctxluafile{math-fbk}{}
\registerctxluafile{math-dir}{}
\registerctxluafile{math-spa}{}

%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

\newcount\mathnestinglevel

\appendtoks
    \advance\mathnestinglevel\plusone
\to \everymathematics

%D A few compatibility helpers:

\def\Umathbotaccent{\Umathaccent \s!bottom }
\def\Umathtopaccent{\Umathaccent \s!top    }
\def\Umathaccents  {\Umathaccent \s!both   }

\ifdefined\Umathcharclass \else
    \def\Umathcharclass{\numexpr\cldcontext{tex.getmathcode(token.scan_int())[1]}\relax}
    \def\Umathcharfam  {\numexpr\cldcontext{tex.getmathcode(token.scan_int())[2]}\relax}
    \def\Umathcharslot {\numexpr\cldcontext{tex.getmathcode(token.scan_int())[3]}\relax}
\fi

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

\definesystemattribute[mathalphabet]   [public]
\definesystemattribute[mathsize]       [public]
\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[displaymath]    [public]

\mathflattenmode 31

\ifdefined\ordlimits\else
    \let\ordlimits\limits
\fi

\appendtoks
    \c_attr_mathmode\plusone
\to \everydisplay

\appendtoks
    \c_attr_mathmode   \plusone
    \c_attr_displaymath\plusone
\to \everybeforedisplayformula

\setnewconstant\defaultmathfamily \zerocount % 255

\unexpanded\def\resetmathattributes{\clf_resetmathattributes}

% handy

\newconditional\indisplaymath

\appendtoks
    \setfalse\indisplaymath
\to \everymath

\appendtoks
    \settrue\indisplaymath
\to \everydisplay

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

\unexpanded\def\forcedisplaymath
  {\ifmmode
     \displaystyle
     \settrue\indisplaymath
   \fi}

\unexpanded\def\startforceddisplaymath
  {\startimath
   \displaystyle
   \begingroup
   \settrue\indisplaymath}

\unexpanded\def\stopforceddisplaymath
  {\endgroup
   \stopimath}

\unexpanded\def\startpickupmath % for the moment private
  {\ifconditional\indisplaymath
     \startforceddisplaymath
     \let\stoppickupmath\stopforceddisplaymath
   \else
     \startimath
     \let\stoppickupmath\stopimath
   \fi}

\let\stoppickupmath\relax

% \unexpanded\def\rawmathcharacter#1% slow but only for tracing
%   {\begingroup
%    \ifmmode
%      \resetmathattributes\Uchar#1%
%    \else
%      \startimath\resetmathattributes\Uchar#1\stopimath
%    \fi
%    \endgroup}

\unexpanded\def\rawmathematics#1% slow but only for tracing
  {\begingroup
   \ifmmode
     \clf_resetmathattributes#1%
   \else
     \startimath\clf_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

\unexpanded\def\startmathematics % no grouping, if ever then also an optional second
  {\doifelsenextoptionalcs\math_mathematics_start_yes\math_mathematics_start_nop}

\installmacrostack\currentmathematics

\unexpanded\def\math_mathematics_start_yes[#1]%
  {\push_macro_currentmathematics
   \edef\currentmathematics{#1}% check for valid
   \the\everyswitchmathematics}

\unexpanded\def\math_mathematics_start_nop
  {\push_macro_currentmathematics
   \let\currentmathematics\empty
   \the\everyswitchmathematics}

\unexpanded\def\stopmathematics
  {\pop_macro_currentmathematics
   \the\everyswitchmathematics}

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

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

\unexpanded\def\mathematics
  {\doifelsenextoptionalcs\math_m_yes\math_m_nop}

\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}

% \def\math_m_yes_text[#1]%
%   {\begingroup
%    \doifassignmentelse{#1}%
%      {\setupcurrentmathematics[#1]}%
%      {\edef\currentmathematics{#1}}% check for valid
%    \edef\p_openup{\mathematicsparameter\c!openup}%
%    \ifx\p_openup\v!yes
%      \expandafter\math_m_yes_text_openedup
%    \else
%      \expandafter\math_m_yes_text_normal
%    \fi}

\def\math_m_yes_text[#1]%
  {\begingroup
   \ifcondition\validassignment{#1}%
     \setupcurrentmathematics[#1]%
   \else
     \edef\currentmathematics{#1}% check for valid
   \fi
   \edef\p_openup{\mathematicsparameter\c!openup}%
   \ifx\p_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
      \the\everyswitchmathematics\relax
      \normalstartimath
      #1%
      \normalstopimath
   \egroup
   \ifdim\ht\scratchbox>\strutht
     \math_inline_openup_start_yes
   \else\ifdim\dp\scratchbox>\strutdp
     \math_inline_openup_start_yes
   \else
     \math_inline_openup_start_nop
   \fi\fi
   \unhbox\scratchbox % \normalstartimath#1\normalstopimath
   \math_inline_openup_stop
   \endgroup}

\def\math_m_yes_text_normal#1%
  {\the\everyswitchmathematics\relax
   \normalstartimath
   #1%
   \normalstopimath
   \endgroup}

\def\math_m_nop#1%
  {\relax
   \ifmmode
     #1%
   \else
     \normalstartimath
     #1%
     \normalstopimath
   \fi}

\let\m   \mathematics
\let\math\mathematics

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

\newmuskip\defaultthickmuskip \defaultthickmuskip 5mu plus 5mu
\newmuskip\defaultmedmuskip   \defaultmedmuskip   4mu plus 2mu minus 4mu
\newmuskip\defaultthinmuskip  \defaultthinmuskip  3mu

\newmuskip\halfthickmuskip \halfthickmuskip 2.5mu plus 2.5mu
\newmuskip\halfmedmuskip   \halfmedmuskip   2.0mu plus 1.0mu minus 2.0mu
\newmuskip\halfthinmuskip  \halfthinmuskip  1.5mu

\newcount \defaultrelpenalty        \defaultrelpenalty         500
\newcount \defaultbinoppenalty      \defaultbinoppenalty       700
\newcount \defaultprerelpenalty     \defaultprerelpenalty     -100
\newcount \defaultprebinoppenalty   \defaultprebinoppenalty   -100
\newcount \defaultdisplayprepenalty \defaultdisplayprepenalty  -10

% For the moment this way:

% \appendtoks
%     \setmathprepenalty \mathbinarycode         \defaultdisplayprepenalty
%   % \setmathpostpenalty\mathbinarycode         \zerocount
%     \setmathprepenalty \mathrelationcode       \defaultdisplayprepenalty
%   % \setmathpostpenalty\mathrelationcode       \zerocount
%     \setmathpostpenalty\mathtextpunctuationcode\defaultdisplayprepenalty
%   % \setmathprepenalty \mathtextpunctuationcode\zerocount
% \to \everybeforedisplayformula

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

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

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

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

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

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

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

\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)

\unexpanded\def\math_set_attribute   #1#2{\ifmmode\clf_setmathattribute{#1}{#2}\fi}
\unexpanded\def\math_set_alphabet      #1{\ifmmode\clf_setmathalphabet{#1}\fi}
\unexpanded\def\math_set_font_style    #1{\ifmmode\clf_setmathstyle{#1}\fi}
\unexpanded\def\math_set_font_alternate#1{\ifmmode\clf_setmathalternate\defaultmathfamily{#1}\fi}

\installcorenamespace{mathstylealternative} % might become a setuphandler

\unexpanded\def\math_set_font_style_alternate#1%
  {\ifcsname\??mathstylealternative\fontclass:#1\endcsname
    %\expandafter\math_set_font_alternate\csname\??mathstylealternate\fontclass:#1\endcsname
     \expandafter\math_set_font_alternate\lastnamedcs
   \else\ifcsname\??mathstylealternative#1\endcsname
    %\expandafter\math_set_font_alternate\csname\??mathstylealternate#1\endcsname
     \expandafter\math_set_font_alternate\lastnamedcs
   \fi\fi}

\unexpanded\def\setupmathrendering % the name might change
  {\dodoubleargument\math_setup_rendering}

\def\math_setup_rendering[#1][#2]%
  {\ifsecondargument
     \getparameters[\??mathstylealternative#1:][#2]%
   \else
     \getparameters[\??mathstylealternative][#1]%
   \fi}

\appendtoks
    \edef\p_stylealternative{\mathematicsparameter\c!stylealternative}%
    \ifx\p_stylealternative\empty\else
        \clf_presetmathalternate\defaultmathfamily{\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

\unexpanded\def\mathaltcalligraphic{\math_set_font_alternate{calligraphic}\cal}          % set via goody file
\unexpanded\def\mathaltitalic      {\math_set_font_alternate{italic}}                    % set via goody file
\unexpanded\def\mathslashedzero    {\begingroup\math_set_font_alternate{zero}∅\endgroup} % set via goody file or automatic
\unexpanded\def\mathdotless        {\math_set_font_alternate{dotless}}                   % set via goody file or automatic
\unexpanded\def\mathdotlessi       {\begingroup\mathdotless i\endgroup}
\unexpanded\def\mathdotlessj       {\begingroup\mathdotless j\endgroup}

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

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

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

\let\setmathattribute           \math_set_attribute
\let\setmathalphabet            \math_set_alphabet
\let\setmathfontstyle           \math_set_font_style
\let\setmathfontalternate       \math_set_font_alternate
\let\setmathfontalternative     \math_set_font_alternate
\let\setmathfontstylealternate  \math_set_font_style_alternate
\let\setmathfontstylealternative\math_set_font_style_alternate

\let\mathalternate              \math_set_font_alternate

\unexpanded\def\mathupright   {\math_set_attribute\s!regular\s!tf\math_set_font_style_alternate\s!tf}
\unexpanded\def\mathitalic    {\math_set_attribute\s!regular\s!it\math_set_font_style_alternate\s!it}
\unexpanded\def\mathscript    {\math_set_alphabet \s!script      \math_set_font_style_alternate\s!script}
\unexpanded\def\mathfraktur   {\math_set_alphabet \s!fraktur     \math_set_font_style_alternate\s!fraktur}
\unexpanded\def\mathblackboard{\math_set_alphabet \s!blackboard  \math_set_font_style_alternate\s!blackboard}

\unexpanded\def\mathrm        {\math_set_attribute\s!rm\s!tf     \math_set_font_style_alternate\s!tf}
\unexpanded\def\mathss        {\math_set_attribute\s!ss\s!tf     \math_set_font_style_alternate\s!tf}
\unexpanded\def\mathtt        {\math_set_attribute\s!tt\s!tf     \math_set_font_style_alternate\s!tf}

\unexpanded\def\mathtf        {\math_set_font_style\s!tf         \math_set_font_style_alternate\s!tf}
\unexpanded\def\mathsl        {\math_set_font_style\s!it         \math_set_font_style_alternate\s!it} % no sl
\unexpanded\def\mathit        {\math_set_font_style\s!it         \math_set_font_style_alternate\s!it}

\unexpanded\def\mathbf        {\math_set_font_style\s!bf         \math_set_font_style_alternate\s!bf}
\unexpanded\def\mathbs        {\math_set_font_style\s!bi         \math_set_font_style_alternate\s!bi} % no sl
\unexpanded\def\mathbi        {\math_set_font_style\s!bi         \math_set_font_style_alternate\s!bi}

\let\mathdefault\mathitalic

\appendtoks
    \edef\p_default{\mathematicsparameter\c!default}%
    \ifx\p_default\v!normal
      \let\mathdefault\mathupright
    \else
      \let\mathdefault\mathitalic
    \fi
\to \everysetupmathematics

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

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

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

\let\Bbb\mathblackboard

\unexpanded\def\frak      {\ifmmode\expandafter\mathfraktur   \fi}
\unexpanded\def\cal       {\ifmmode\expandafter\mathscript    \fi}
\unexpanded\def\bbd       {\ifmmode\expandafter\mathblackboard\fi}
\unexpanded\def\blackboard{\ifmmode\expandafter\mathblackboard\fi}
\unexpanded\def\fraktur   {\ifmmode\expandafter\mathfraktur   \fi}
\unexpanded\def\gothic    {\ifmmode\expandafter\mathfraktur   \fi}

\unexpanded\def\mathcal #1{{\mathscript    #1}}  % for AMS compatibility
\unexpanded\def\mathfrak#1{{\mathfraktur   #1}}  % for AMS compatibility
\unexpanded\def\mathbb  #1{{\mathblackboard#1}}  % for AMS compatibility

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

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

\ifdefined\mr \else \let\mr\relax \fi
\ifdefined\mb \else \let\mb\relax \fi

% 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
    \mathdefault
\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

\newcount\c_math_renderings_attribute

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

\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.

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

\unexpanded\def\boldsymbol
  {\mathortext\mathboldsymbol\bold}

%D Helpers

\def\utfmathclass  #1{\clf_utfmathclass  {#1}}
\def\utfmathstretch#1{\clf_utfmathstretch{#1}}
\def\utfmathcommand#1{\clf_utfmathcommand{#1}}
\def\utfmathfiller #1{\clf_utfmathfiller {#1}}

\def\utfmathcommandabove #1{\clf_utfmathcommandabove {#1}}
\def\utfmathcommandbelow #1{\clf_utfmathcommandbelow {#1}}
\def\utfmathcommandfiller#1{\clf_utfmathcommandfiller{#1}}

\unexpanded\def\doifelseutfmathaccent#1{\clf_doifelseutfmathaccent{#1}}
\unexpanded\def\doifelseutfmathabove #1{\clf_doifelseutfmathabove {#1}}
\unexpanded\def\doifelseutfmathbelow #1{\clf_doifelseutfmathbelow {#1}}
\unexpanded\def\doifelseutfmathfiller#1{\clf_doifelseutfmathfiller{#1}}
\unexpanded\def\doifelseutfmathlimop #1{\clf_doifelseutfmathlimop {#1}}

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

%D Not used that much:

\installcorenamespace{mathcodecommand}

\unexpanded\def\mathlimop#1{\mathop{#1}} %no \limits
\unexpanded\def\mathbox  #1{\dontleavehmode\hbox\Ustartmath\mathsurround\zeropoint#1\Ustopmath}
\unexpanded\def\mathnolop#1{\mathop{#1}\nolimits}

\let\mathnothing\firstofoneunexpanded
\let\mathalpha  \firstofoneunexpanded

\setnewconstant\mathordcode     \zerocount  \letvalue{\??mathcodecommand     ord}\mathord
\setnewconstant\mathopcode      \plusone    \letvalue{\??mathcodecommand      op}\mathop
\setnewconstant\mathbincode     \plustwo    \letvalue{\??mathcodecommand     bin}\mathbin
\setnewconstant\mathrelcode     \plusthree  \letvalue{\??mathcodecommand     rel}\mathrel
\setnewconstant\mathopencode    \plusfour   \letvalue{\??mathcodecommand    open}\mathopen
\setnewconstant\mathclosecode   \plusfive   \letvalue{\??mathcodecommand   close}\mathclose
\setnewconstant\mathpunctcode   \plussix    \letvalue{\??mathcodecommand   punct}\mathpunct
\setnewconstant\mathalphacode   \plusseven  \letvalue{\??mathcodecommand   alpha}\mathalpha
\setnewconstant\mathinnercode   \zerocount  \letvalue{\??mathcodecommand   inner}\mathinner
\setnewconstant\mathnothingcode \zerocount  \letvalue{\??mathcodecommand nothing}\mathnothing
\setnewconstant\mathlimopcode   \plusone    \letvalue{\??mathcodecommand   limop}\mathlimop
\setnewconstant\mathnolopcode   \plusone    \letvalue{\??mathcodecommand   nolop}\mathnolop
\setnewconstant\mathboxcode     \zerocount  \letvalue{\??mathcodecommand     box}\mathbox
\setnewconstant\mathchoicecode  \zerocount  %letvalue{\??mathcodecommand  choice}\mathnothing

\setnewconstant\mathaccentcode  \pluseight
\setnewconstant\mathradicalcode \plusnine

           \def\mathcodenumber #1{\the\csname math#1code\endcsname}
\unexpanded\def\mathcodecommand#1{\csname\??mathcodecommand#1\endcsname}

% \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}

\unexpanded\def\definemathcommand
  {\dotripleempty\math_define_command}

\def\math_define_command[#1][#2][#3]#4% command class args meaning
  {\ifthirdargument
     \edef\nofmathcommandarguments{#3}%
     \ifx\nofmathcommandarguments\v!one
       \setuvalue{\??mathcommand#1}##1{\mathcodecommand{#2}{#4{##1}}}%
     \else\ifx\nofmathcommandarguments\v!two
       \setuvalue{\??mathcommand#1}##1##2{\mathcodecommand{#2}{#4{##1}{##2}}}%
     \else
       \setuvalue{\??mathcommand#1}{\mathcodecommand{#2}{#4}}%
     \fi\fi
   \else\ifsecondargument
     \setuvalue{\??mathcommand#1}{\mathcodecommand{#2}{#4}}%
   \else
     \setuvalue{\??mathcommand#1}{\mathcodecommand{nothing}{#4}}%
   \fi\fi
   \letcsnamecsname\csname#1\endcsname\csname\??mathcommand#1\endcsname}

\unexpanded\def\mathcommand#1%
  {\begincsname\??mathcommand#1\endcsname}

%D Let's define a few comands here:

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

\chardef\c_math_strut"28

\unexpanded\def\math_strut_htdp#1%
  {\s!height\fontcharht#1\c_math_strut
   \s!depth \fontchardp#1\c_math_strut}

\unexpanded\def\math_strut_normal
  {\vrule
      \normalexpanded{\math_strut_htdp{\mathstylefont\normalmathstyle}}%
      \s!width \zeropoint
   \relax}

\unexpanded\def\math_strut_visual
  {\hskip-.01\emwidth
   \vrule
      \normalexpanded{\math_strut_htdp{\mathstylefont\normalmathstyle}}%
      \s!width .02\emwidth
   \relax
   \hskip-.01\emwidth}

\unexpanded\def\showmathstruts % let's not overload \math_strut_normal
  {\let\math_strut\math_strut_visual}

\let\math_strut\math_strut_normal

% \unexpanded\def\mathstrut{\mathcodecommand{nothing}{\math_strut}}

\definemathcommand [mathstrut] {\math_strut}

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

\unexpanded\def\mathopwithlimits#1#2{\mathop{#1{#2}}\limits}
\unexpanded\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:

\unexpanded\def\mf
  {\begincsname\fontalternative\endcsname}

% \let\normalmathop\mathop % already defined

% no longer needed as we no longer switch fonts
%
% \unexpanded\def\mathop
%   {\normalmathop
%    \bgroup
%   % no: \let\rm\mf
%    \afterassignment\math_op\let\nexttoken=}
%
% \def\math_op{\ifx\nexttoken\bgroup\else\nexttoken\egroup\fi}

% this one too: \letvalue{\??mathcodecommand op}\mathop ?

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

\def\math_mbox_finish
  {\flushnextbox
   \egroup}

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

\unexpanded\def\enablembox
  {\toksapp\everymathematics{\math_enable_mbox}}

\def\math_enable_mbox
  {\let\hbox\mbox}

\unexpanded\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}

\unexpanded\def\mtext#1%
  {\text{\usemathematicsstyleandcolor\c!textstyle\c!textcolor#1}}

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

\let\mathfunction\firstofoneunexpanded

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

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

\unexpanded\def\math_tags_mn#1{\begingroup\mathupright\math_set_o_both#1\endgroup}
\unexpanded\def\math_tags_ms#1{\begingroup\mathupright\math_set_p_both#1\endgroup}

% 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=]

\unexpanded\def\math_mfunction_styled
  {\begingroup
   \usemathematicscolorparameter\c!functioncolor
   \edef\p_functionstyle{\mathematicsparameter\c!functionstyle}%
   \ifx\p_functionstyle\empty
     \expandafter\math_mfunction_styled_none
   \else\ifcsname\??alternativestyle\p_functionstyle\endcsname
     \doubleexpandafter\math_mfunction_styled_text
   \else
     \doubleexpandafter\math_mfunction_styled_math
   \fi\fi}

\unexpanded\def\math_mfunction_styled_text#1%
 %{\mathoptext{\csname\??alternativestyle\p_functionstyle\endcsname#1}%
  {\expandafter\mathoptext\expandafter{\lastnamedcs#1}%
   \endgroup}

\unexpanded\def\math_mfunction_styled_math#1%
  {\p_functionstyle
   #1%
   \endgroup}

\unexpanded\def\math_mfunction_styled_none#1%
  {\mathupright
   #1%
   \endgroup}

\unexpanded\def\mfunction#1%
  {\begingroup
   \math_tags_mfunctiontxt{#1}\c_apply_function
   \math_mfunction_styled{#1}%
   \endgroup}

\unexpanded\def\mfunctionlabeltext#1%
  {\begingroup
   \math_tags_mfunctionlab{#1}\c_apply_function
   \math_mfunction_styled{\mathlabeltext{#1}}%
   \endgroup}

\let\math_tags_mfunctiontxt\gobbletwoarguments
\let\math_tags_mfunctionlab\gobbletwoarguments

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

\newconditional\c_apply_function

\unexpanded\def\math_tags_apply#1#2%
  {\begingroup
   \settrue\c_apply_function
   #1%
   \endgroup
   \begingroup
   % todo: auto ()
   #2%
   \endgroup}

\appendtoks
    \let\math_tags_mfunctiontxt\clf_tagmfunctiontxt
    \let\math_tags_mfunctionlab\clf_tagmfunctionlab
    \let\math_tags_mo          \math_tags_mo_indeed
    \let\math_tags_mi          \math_tags_mi_indeed
    \let\math_tags_mn          \math_tags_mn_indeed
    \let\math_tags_ms          \math_tags_ms_indeed
\to \everyenableelements

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

% \def\mlimitsfunction  #1{\mathlimopcomm{{\mr#1}}
% \def\mnolimitsfunction#1{\mathnolopcomm{{\mr#1}}

% %D Taco posted this solution as response to a mail by Olivier, so let's integrate
% %D it here.
%
% \def\currentmscaledstyle{rm} % will be plugged into the typeface text=ss option
%
% \unexpanded\def\math_function_style_opnolimits        #1{\mathop{\mscaledtext{#1}}\nolimits}
% \unexpanded\def\math_function_style_mfunction         #1{\mscaledtext{\math_tags_function{#1}}}
% \unexpanded\def\math_function_style_mfunctionlabeltext#1{\mscaledtext{\math_tags_functionlabeltext{#1}}}
%
% \unexpanded\def\setmathfunctionstyle#1% rm ss tt (can be made faster if needed)
%   {\doifsomething{#1}
%      {\def\currentmscaledstyle{#1}%
%       \let\mathopnolimits    \math_function_style_opnolimits
%       \let\mfunction         \math_function_style_mfunction
%       \let\mfunctionlabeltext\math_function_style_mfunctionlabeltext}}

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

\unexpanded\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}}}

\unexpanded\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
%D one triggers an error message.

\setnewconstant\activemathcharcode "8000

\newtoks\activatedmathcharacters

\unexpanded\def\activatemathcharacter#1%
  {\appendtoks
     \global\mathcode#1=\activemathcharcode
   \to \activatedmathcharacters}

\def\activatemathcharacters
  {\the\activatedmathcharacters}

% beware, not runtime, so has to happen at format generation

\activatemathcharacter\circumflexasciicode
\activatemathcharacter\underscoreasciicode
\activatemathcharacter\ampersandasciicode

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

%D \starttyping
%D \setupmathematics[ampersand=normal]
%D $\eqalign{a&=a'\cr}$
%D \stoptyping

%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
%D reason.
%D
%D When we have a letter or other category a check happens for an active
%D character and when it has one then it gets expanded and fed back into the
%D scanner (sort of).
%D
%D A \type {\char} is also fed back as raw character and again when it's letter
%D of 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.

% \activatemathcharacter\primeasciicode

% not used:
%
% \mathcode\spaceasciicode\activemathcharcode
%
% not used:
%
% \bgroup
%     \catcode\underscoreasciicode\activecatcode
%     \doglobal\appendtoks
%         \mathcode\underscoreasciicode\activemathcharcode
%         \let_\activemathunderscore
%     \to \everymathematics
% \egroup

% Here follows some plain legacy: primes.
%
% The \let\prime\math_prime_indeed might become an obsolete as we have \doubleprime
% and \tripleprime and collapsing can nicely handle the script then.
%
% Collapsing to 0x2033 and 0x2034 happens elsewhere.
%
% \switchtobodyfont[modern]
% \switchtobodyfont[cambria]
% \switchtobodyfont[xits]
% \switchtobodyfont[minion]
% \setupbodyfont[dejavu]
%
% \startbuffer
% \def\SampleLine#1{%
%    \NC#1
%    \NC\switchtobodyfont[#1]$f^2$                       %  1
%    \NC\switchtobodyfont[#1]$f\prime^2$                 %  2
%    \NC\switchtobodyfont[#1]$f\prime\prime^2$           %  3
%    \NC\switchtobodyfont[#1]$f\prime\prime\prime^2$     %  4
%    \NC\switchtobodyfont[#1]$f{\prime}^2$               %  5
%    \NC\switchtobodyfont[#1]$f{\prime\prime}^2$         %  6
%    \NC\switchtobodyfont[#1]$f{\prime\prime\prime}^2$   %  7
%    \NC\switchtobodyfont[#1]$f'(x)$                     %  8
%    \NC\switchtobodyfont[#1]$f''(x)$                    %  9
%    \NC\switchtobodyfont[#1]$f'''(x)$                   % 10
%    \NC\NR
% }
%
% \starttabulate[|Tl|Tc|Tc|Tc|Tc|Tc|Tc|Tc|Tc|Tc|Tc|]
%     \NC\NC1\NC2\NC3\NC4\NC5\NC6\NC7\NC8\NC9\NC10\NC\NR
%     \SampleLine{modern}
%     \SampleLine{cambria}
%     \SampleLine{xits}
%     \SampleLine{minion}
% \stoptabulate
% \stopbuffer
%
% \typebuffer \getbuffer

% most math fonts have messed up primes, just test this: $\prime^{\prime^{\prime}}$

{ \catcode\circumflexasciicode\othercatcode       \glet\othercircumflextoken      ^ }
{ \catcode\circumflexasciicode\superscriptcatcode \glet\superscriptcircumflextoken^ }

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

% \let\math_prime_indeed_normal\prime
%
% \appendtoks
%     \let\math_prime_indeed_normal\prime    % gets defined later
%     \let\mathfontprime\prime               % for tracing
%     \let\prime\math_prime_indeed           % so this is needed
% \to \everydump
%
% \unexpanded\def\math_prime_indeed
%   {\iffontchar\textfont\zerocount"FE325\relax
%     ^\bgroup
%      \expandafter\math_prime_indeed_virtual % virtual mess (using funny signal)
%    \else
%    % \expandafter\math_prime_indeed_normal  % gets collapsed
%      \expandafter\math_prime_indeed_crapped  % gets collapsed
%    \fi}
%
% \def\math_prime_indeed_crapped
%   {{^{\math_prime_indeed_normal}}}
%
% % \let\prime\math_prime_indeed
%
% \def\math_prime_indeed_virtual
%   {\math_prime_indeed_normal
%    \futurelet\nexttoken\math_prime_indeed_choice}
%
% \installcorenamespace{mathprime}
%
% \def\math_prime_indeed_choice
%   {\csname\??mathprime
%      \ifx                          '\nexttoken a\else
%      \ifx  \math_prime_indeed_normal\nexttoken a\else
%      \ifx                     \prime\nexttoken a\else
%      \ifx\superscriptcircumflextoken\nexttoken b\else
%      \ifx\othercircumflextoken      \nexttoken b\else
%                                                c\fi\fi\fi\fi\fi
%    \endcsname}
%
% \setvalue{\??mathprime a}#1{\math_prime_indeed_virtual}
% \setvalue{\??mathprime b}#1#2{#2\egroup}
% \setvalue{\??mathprime c}{\egroup}
%
% \let\activemathprime\math_prime_indeed
%
% \bgroup
%
%     \catcode\primeasciicode\activecatcode
%
%     \global\everymathematics\expandafter{\the\everymathematics\let'\math_prime_indeed} % todo: do this at the lua end
%
% \egroup

% $\char26$ gives an error because it expands to an active character that
% then becomes an & which is then seen as an alignment character; anyway,
% even when we switch like this the diufferen tmeaning only happens when
% we're in math mode which can be delayed till we're in a cell

\bgroup

    \catcode\underscoreasciicode\activecatcode
    \catcode\circumflexasciicode\activecatcode
    \catcode\ampersandasciicode \activecatcode

    \glet\specialmathaligntab\normalmathaligntab

    \unexpanded\gdef\obeymathcatcodes
      {\let _\normalsubscript
       \let ^\normalsuperscript
       \def &\specialmathaligntab
       }

    \doglobal \appendtoks
        \let _\normalsubscript
        \let ^\normalsuperscript
        \let &\specialmathaligntab
   \to \everymathematics

  % \unexpanded\gdef\normalmathampersands
  %   {\let\specialmathaligntab\mathampersand}

\egroup

\newtoks\everydonknuthmode
\newtoks\everynonknuthmode

\newconditional \knuthmode

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

% \def\nonknuthmode
%   {\pushcatcodetable
%    \setcatcodetable\ctxcatcodes
%    \the\everynonknuthmode
%    \let\nonknuthmode\relax
%    \popcatcodetable}
%
% \def\donknuthmode
%   {\pushcatcodetable
%    \setcatcodetable\ctxcatcodes
%    \the\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
%     \setfalse\knuthmode
%     \catcode\underscoreasciicode\othercatcode
%     \catcode\circumflexasciicode\othercatcode
%     \catcode\ampersandasciicode \othercatcode
% \to \everynonknuthmode
%
% \appendtoks
%     \settrue\knuthmode
%     \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)

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

\unexpanded\def\enableasciimode
  {\clf_enableasciimode} % relaxes itself

\unexpanded\def\asciimode
  {\catcodetable\txtcatcodes
   \clf_enableasciimode}

\unexpanded\def\startasciimode
  {\pushcatcodetable
   \catcodetable\txtcatcodes
   \clf_enableasciimode}

\unexpanded\def\stopasciimode
  {\popcatcodetable}

%D Needed for unicode:

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

%D Memory saver:

\def\math_basics_check_compact
  {\doifelse{\mathematicsparameter\c!compact}\v!yes
     \enabledirectives\disabledirectives[math.virtual.optional]}

\appendtoks
    \ifx\currentmathematics\empty
        \math_basics_check_compact % less tracing
    \fi
\to \everysetupmathematics

\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}

\setvalue{\??mathaligndirection           r2l}{\settrue\c_math_right_to_left}
\setvalue{\??mathaligndirection\v!righttoleft}{\settrue\c_math_right_to_left}

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

\unexpanded\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)

\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}

\letvalue{\??mathbidi\v!yes}\math_bidi_enable
\letvalue{\??mathbidi\v!no }\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

\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

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

% \appendtoks
%     \edef\p_sygreek{\mathematicsparameter\s!sygreek}%
%     \edef\p_lcgreek{\mathematicsparameter\s!lcgreek}%
%     \edef\p_ucgreek{\mathematicsparameter\s!ucgreek}%
%     \c_math_greek_attribute"% hex digits
%       \csname\??mathgreek\ifcsname\??mathgreek\p_sygreek\endcsname\p_sygreek\else\v!none\fi\endcsname
%       \csname\??mathgreek\ifcsname\??mathgreek\p_lcgreek\endcsname\p_lcgreek\else\v!none\fi\endcsname
%       \csname\??mathgreek\ifcsname\??mathgreek\p_ucgreek\endcsname\p_ucgreek\else\v!none\fi\endcsname
%     \relax
%     \ifcase\c_math_greek_attribute
%       \c_math_greek_attribute\attributeunsetvalue
%     \fi
% \to \everyswitchmathematics

\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

% only used local

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

\let\mathgreeknormal\mathgreekupright
\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

\letvalue{\??mathcollapsing       1}\plusone              % specials
\letvalue{\??mathcollapsing       2}\plustwo              % specials + mathlist
\letvalue{\??mathcollapsing       3}\plusthree            % mathlist + specials
\letvalue{\??mathcollapsing\v!none }\attributeunsetvalue
\letvalue{\??mathcollapsing\v!reset}\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 italics (experiment)

%D We need keys but what names to use and because we have hardcoded solution
%D we can stick to numbers.

\installcorenamespace{mathitalics}

\setnewconstant\c_math_italics_attribute\attributeunsetvalue

\letvalue{\??mathitalics       1}\plusone              % fontitalics
\letvalue{\??mathitalics       2}\plustwo              % fontdata
\letvalue{\??mathitalics       3}\plusthree            % quad based
\letvalue{\??mathitalics       4}\plusfour             % combination of 1 and 3
\letvalue{\??mathitalics\v!none }\attributeunsetvalue
\letvalue{\??mathitalics\v!reset}\attributeunsetvalue

\def\math_italics_initialize
  {\ifnum\c_math_italics_attribute=\attributeunsetvalue \else
     \clf_initializemathitalics % one time
     \glet\math_italics_initialize\relax
   \fi}

\appendtoks
    \edef\p_italics{\mathematicsparameter\s!italics}%
    \c_math_italics_attribute
        \ifcsname\??mathitalics\p_italics\endcsname\lastnamedcs\else\attributeunsetvalue\fi
    \relax
  % \math_italics_initialize
\to \everyswitchmathematics % only in mathematics

\appendtoks
    \math_italics_initialize
    \c_attr_mathitalics\c_math_italics_attribute
\to \everymathematics

% \setupmathematics % done later
%   [\s!italics=3] % 4 is probably better

% looks nicer but can generate bogus csnames
%
% \setvalue{\??mathitalics1}{\math_italics_initialize\c_math_italics_attribute\plusone  } % fontitalics
% \setvalue{\??mathitalics2}{\math_italics_initialize\c_math_italics_attribute\plustwo  } % fontdata
% \setvalue{\??mathitalics3}{\math_italics_initialize\c_math_italics_attribute\plusthree} % quad based
% \setvalue{\??mathitalics4}{\math_italics_initialize\c_math_italics_attribute\plusfour } % combination of 1 and 3
%
% \appendtoks
%     \c_math_italics_attribute\attributeunsetvalue
%     \csname\??mathitalics\mathematicsparameter\s!italics\endcsname
% \to \everyswitchmathematics % only in mathematics

%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
%
% \unexpanded\def\enablemathpunctuation {\settrue \automathpunctuation}
% \unexpanded\def\disablemathpunctuation{\setfalse\automathpunctuation}
%
% \appendtoks
%     \doifelse{\mathematicsparameter\c!autopunctuation}\v!yes\settrue\setfalse\automathpunctuation
% \to \everyswitchmathematics
%
% \setupmathematics
%   [\c!autopunctuation=\v!no]
%
% \def\math_punctuation_next{\ifx\nexttoken\blankspace\signalcharacter\fi}
%
% \unexpanded\def\math_punctuation_comma {\textcomma \futurelet\nexttoken\math_punctuation_next}
% \unexpanded\def\math_punctuation_period{\textperiod\futurelet\nexttoken\math_punctuation_next}
%
% \setnewconstant\c_math_comma  "002C
% \setnewconstant\c_math_period "002E
% \setnewconstant\c_math_special"8000
%
% \bgroup
%
%     \catcode\c_math_comma \activecatcode
%     \catcode\c_math_period\activecatcode
%
%     \unexpanded\gdef\math_punctuation_initialize_indeed
%       {\mathcode\c_math_comma \c_math_special
%        \mathcode\c_math_period\c_math_special
%        \let,\math_punctuation_comma
%        \let.\math_punctuation_period
%        \c_attr_mathpunctuation\plustwo}
%
%     \unexpanded\gdef\math_punctuation_initialize_yes
%       {\c_attr_mathpunctuation\plustwo}
%
%     \unexpanded\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}}
%
% \unexpanded\def\math_punctuation_nop_comma {\mathpunct{\textcomma}}
% \unexpanded\def\math_punctuation_nop_period{\mathord{\textperiod}}
%
% \unexpanded\def\math_punctuation_all_comma {\futurelet\nexttoken\math_punctuation_comma_next}
% \unexpanded\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.

\setnewconstant\c_math_comma    "002C
\setnewconstant\c_math_period   "002E
%setnewconstant\c_math_colon    "003A
\setnewconstant\c_math_semicolon"003B
\setnewconstant\c_math_special  "8000

\def\math_set_o_comma    {\Umathcode\c_math_comma    \mathordcode  \zerocount\c_math_comma}
\def\math_set_p_comma    {\Umathcode\c_math_comma    \mathpunctcode\zerocount\c_math_comma}
\def\math_set_o_period   {\Umathcode\c_math_period   \mathordcode  \zerocount\c_math_period}
\def\math_set_p_period   {\Umathcode\c_math_period   \mathpunctcode\zerocount\c_math_period}
\def\math_set_o_semicolon{\Umathcode\c_math_semicolon\mathordcode  \zerocount\c_math_semicolon}
\def\math_set_p_semicolon{\Umathcode\c_math_semicolon\mathpunctcode\zerocount\c_math_semicolon}

\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}

\unexpanded\def\math_punctuation_nop_comma    {\begingroup\math_set_p_comma    ,\endgroup}
\unexpanded\def\math_punctuation_nop_period   {\begingroup\math_set_o_period   .\endgroup}
\unexpanded\def\math_punctuation_nop_semicolon{\begingroup\math_set_p_semicolon;\endgroup}

\unexpanded\def\math_punctuation_all_comma    {\futurelet\nexttoken\math_punctuation_comma_next}
\unexpanded\def\math_punctuation_all_period   {\futurelet\nexttoken\math_punctuation_period_next}
\unexpanded\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

\def\math_punctuation_comma_next    {\begingroup\Umathcode\c_math_comma    \ifx\nexttoken\blankspace\mathpunctcode\else\mathordcode\fi\zerocount\c_math_comma    ,\endgroup}
\def\math_punctuation_period_next   {\begingroup\Umathcode\c_math_period   \ifx\nexttoken\blankspace\mathpunctcode\else\mathordcode\fi\zerocount\c_math_period   .\endgroup}
\def\math_punctuation_semicolon_next{\begingroup\Umathcode\c_math_semicolon\ifx\nexttoken\blankspace\mathpunctcode\else\mathordcode\fi\zerocount\c_math_semicolon;\endgroup}

\installcorenamespace {mathautopunctuation}

\bgroup

    \catcode\c_math_comma    \activecatcode
    \catcode\c_math_period   \activecatcode
    \catcode\c_math_semicolon\activecatcode

    \setgvalue{\??mathautopunctuation\v!no}%
      {\let,\math_punctuation_nop_comma
       \let.\math_punctuation_nop_period
       \let;\math_punctuation_nop_semicolon}

  %  more efficient list:
  %
  %  \setgvalue{\??mathautopunctuation\v!no}%
  %    {\Umathcode\c_math_period\mathordcode  \zerocount\c_math_period
  %     \Umathcode\c_math_comma \mathpunctcode\zerocount\c_math_comma }

    \setgvalue{\??mathautopunctuation\v!yes}%
      {\let,\math_punctuation_yes_comma
       \let.\math_punctuation_yes_period
       \let;\math_punctuation_nop_semicolon}

    \setgvalue{\??mathautopunctuation\v!all}%
      {\let,\math_punctuation_all_comma
       \let.\math_punctuation_all_period
       \let;\math_punctuation_nop_semicolon}

    \setgvalue{\??mathautopunctuation comma}%
      {\let,\math_punctuation_yes_comma
       \let.\math_punctuation_yes_period
       \let;\math_punctuation_nop_semicolon}

    \setgvalue{\??mathautopunctuation\v!yes\string,semicolon}%
      {\let,\math_punctuation_yes_comma
       \let.\math_punctuation_yes_period
       \let;\math_punctuation_yes_semicolon}

    \setgvalue{\??mathautopunctuation comma\string,semicolon}%
      {\let,\math_punctuation_yes_comma
       \let.\math_punctuation_yes_period
       \let;\math_punctuation_yes_semicolon}

    \setgvalue{\??mathautopunctuation\v!all\string,semicolon}%
      {\let,\math_punctuation_all_comma
       \let.\math_punctuation_all_period
       \let;\math_punctuation_all_semicolon}

\egroup

% \appendtoks
%     \global\mathcode\c_math_comma    \c_math_special
%     \global\mathcode\c_math_period   \c_math_special
%     \global\mathcode\c_math_semicolon\c_math_special
% \to \everyjob

% \activatemathcharacter\c_math_comma
% \activatemathcharacter\c_math_period
% \activatemathcharacter\c_math_semicolon

\appendtoks
    \mathcode\c_math_comma    \c_math_special
    \mathcode\c_math_period   \c_math_special
    \mathcode\c_math_semicolon\c_math_special
    \begincsname\??mathautopunctuation\mathematicsparameter\c!autopunctuation\endcsname
\to \everymathematics

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

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

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

%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

%D \macros
%D   {mathstyle}
%D
%D If one want to be sure that something is typeset in the appropriate style, \type
%D {\mathstyle} can be used:
%D
%D \starttyping
%D \mathstyle{something}
%D \stoptyping

% \def\mathstyle#1%
%   {\mathchoice
%      {\displaystyle     #1}%
%      {\textstyle        #1}%
%      {\scriptstyle      #1}%
%      {\scriptscriptstyle#1}}
%
% We now have a primitive operation for this. As the macro overloads a new
% primitive introduced in \LUATEX, we need to use \type {\normalmathstyle} when we
% consult the current math style.
%
% \let \mathstyle \Ustack % spoils cramped
%
% \let \mathstyle \firstofoneargument
%
% 0 = display
% 1 = crampeddisplay
% 2 = text
% 3 = crampedtext
% 4 = script
% 5 = crampedscript
% 6 = scriptscript
% 7 = crampedscriptscript

\def\uncramped#1%
  {{\ifcase\normalmathstyle
    \or \displaystyle      \or
    \or \textstyle         \or
    \or \scriptstyle       \or
    \or \scriptscriptstyle \fi
    #1}}

\def\cramped#1%
  {{\ifcase\normalmathstyle
    \crampeddisplaystyle      \or \or % 0 -> 1
    \crampedtextstyle         \or \or % 2 -> 3
    \crampedscriptstyle       \or \or % 4 -> 5
    \crampedscriptscriptstyle \fi     % 6 -> 7
    #1}}

\def\triggermathstyle#1% #1 is number
  {\ifcase\numexpr#1\relax
     \displaystyle             \or % 0
     \crampeddisplaystyle      \or % 1
     \textstyle                \or % 2
     \crampedtextstyle         \or % 3
     \scriptstyle              \or % 4
     \crampedscriptstyle       \or % 5
     \scriptscriptstyle        \or % 6
     \crampedscriptscriptstyle \else
     % error
   \fi}

\let\mathstyletrigger\triggermathstyle

\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}

\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

\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}

\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

\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}

\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}

\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}

% \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}

\unexpanded\def\verbosemathstyle#1% #1 is number (\normalmathstyle)
  {{\normalexpanded{\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]}}}

\unexpanded\def\showmathstyle{\verbosemathstyle\normalmathstyle}

%D Handy too:

\def\mathcharwd{\fontcharwd\mathstylefont\normalmathstyle}
\def\mathcharht{\fontcharht\mathstylefont\normalmathstyle}
\def\mathchardp{\fontchardp\mathstylefont\normalmathstyle}

%D Some dimension fun:

\def\mathexheight
  {\fontdimen
     \plusfive
     \ifcase\numexpr\normalmathstyle\relax
       \textfont         \or % 0
       \textfont         \or % 1
       \textfont         \or % 2
       \textfont         \or % 3
       \scriptfont       \or % 4
       \scriptfont       \or % 5
       \scriptscriptfont \or % 6
       \scriptscriptfont \else
       \textfont
     \fi
     \zerocount}

\def\mathemwidth
  {\fontdimen
     \plussix
     \ifcase\numexpr\normalmathstyle\relax
       \textfont         \or % 0
       \textfont         \or % 1
       \textfont         \or % 2
       \textfont         \or % 3
       \scriptfont       \or % 4
       \scriptfont       \or % 5
       \scriptscriptfont \or % 6
       \scriptscriptfont \else
       \textfont
     \fi
     \zerocount}

%D A plain inheritance:

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

%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

% \unexpanded\def\mathstylehbox#1% sensitive for: a \over b => {a\over b} or \frac{a}{b}
%   {\normalexpanded{\hbox\bgroup
%      \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup}

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

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

\unexpanded\def\mathstylevbox#1%
  {\normalexpanded{\vbox\bgroup
     \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup}

\unexpanded\def\mathstylevcenter#1%
  {\normalexpanded{\vcenter\bgroup
     \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup}

\unexpanded\def\mathstylevcenteredhbox#1%
  {\normalexpanded{\vcenter\bgroup\hbox\bgroup
     \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup\egroup}

\unexpanded\def\mathstylevcenteredvbox#1%
  {\normalexpanded{\vcenter\bgroup\vbox\bgroup
     \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\stopimath\egroup\egroup}

\unexpanded\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}

\unexpanded\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

\def\triggerdisplaystyle
  {\ifcase\normalmathstyle\relax
     \displaystyle        \or
     \crampeddisplaystyle \or
     \displaystyle        \or
     \crampeddisplaystyle \or
     \displaystyle        \or
     \crampeddisplaystyle \or
     \displaystyle        \or
     \crampeddisplaystyle \or
   \fi}

\def\triggertextstyle
  {\ifcase\normalmathstyle\relax
     \textstyle        \or
     \crampedtextstyle \or
     \textstyle        \or
     \crampedtextstyle \or
     \textstyle        \or
     \crampedtextstyle \or
     \textstyle        \or
     \crampedtextstyle \else
   \fi}

\def\triggerscriptstyle
  {\ifcase\normalmathstyle\relax
     \scriptstyle        \or
     \crampedscriptstyle \or
     \scriptstyle        \or
     \crampedscriptstyle \or
     \scriptstyle        \or
     \crampedscriptstyle \or
     \scriptstyle        \or
     \crampedscriptstyle \or
   \fi}

\def\triggerscriptscriptstyle
  {\ifcase\normalmathstyle\relax
     \scriptscriptstyle        \or
     \crampedscriptscriptstyle \or
     \scriptscriptstyle        \or
     \crampedscriptscriptstyle \or
     \scriptscriptstyle        \or
     \crampedscriptscriptstyle \or
     \scriptscriptstyle        \or
     \crampedscriptscriptstyle \or
   \fi}

\def\triggeruncrampedstyle
  {\ifcase\normalmathstyle\relax
    \or \displaystyle      \or
    \or \textstyle         \or
    \or \scriptstyle       \or
    \or \scriptscriptstyle \fi}

\def\triggercrampedstyle
  {\ifcase\normalmathstyle\relax
   \crampeddisplaystyle      \or \or
   \crampedtextstyle         \or \or
   \crampedscriptstyle       \or \or
   \crampedscriptscriptstyle \fi}

\def\triggersmallstyle
  {\ifcase\normalmathstyle\relax
     \scriptstyle              \or
     \crampedscriptstyle       \or
     \scriptstyle              \or
     \crampedscriptstyle       \or
     \scriptscriptstyle        \or
     \crampedscriptscriptstyle \or
     \scriptscriptstyle        \or
     \crampedscriptscriptstyle \or
    \fi}

\def\triggeruncrampedsmallstyle
  {\ifcase\normalmathstyle\relax
     \scriptstyle       \or
     \scriptstyle       \or
     \scriptstyle       \or
     \scriptstyle       \or
     \scriptscriptstyle \or
     \scriptscriptstyle \or
     \scriptscriptstyle \or
     \scriptscriptstyle \or
    \fi}

\def\triggercrampedsmallstyle
  {\ifcase\normalmathstyle\relax
     \crampedscriptstyle       \or
     \crampedscriptstyle       \or
     \crampedscriptstyle       \or
     \crampedscriptstyle       \or
     \crampedscriptscriptstyle \or
     \crampedscriptscriptstyle \or
     \crampedscriptscriptstyle \or
     \crampedscriptscriptstyle \or
    \fi}

\def\triggerbigstyle
  {\ifcase\normalmathstyle\relax
     \displaystyle        \or
     \crampeddisplaystyle \or
     \textstyle           \or
     \crampedtextstyle    \or
     \textstyle           \or
     \crampedtextstyle    \or
     \scriptstyle         \or
     \crampedscriptstyle  \or
    \fi}

\def\triggeruncrampedbigstyle
  {\ifcase\normalmathstyle\relax
     \displaystyle \or
     \displaystyle \or
     \textstyle    \or
     \textstyle    \or
     \textstyle    \or
     \textstyle    \or
     \scriptstyle  \or
     \scriptstyle  \or
    \fi}

\def\triggercrampedbigstyle
  {\ifcase\normalmathstyle\relax
     \crampeddisplaystyle \or
     \crampeddisplaystyle \or
     \crampedtextstyle    \or
     \crampedtextstyle    \or
     \crampedtextstyle    \or
     \crampedtextstyle    \or
     \crampedscriptstyle  \or
     \crampedscriptstyle  \or
    \fi}

\newcount\c_math_saved_style

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

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

\installcorenamespace{mathstylecommand}
\installcorenamespace{mathstylecache}

\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
        \relax                               \or
        \noexpand\triggeruncrampedstyle      \or
        \noexpand\triggercrampedstyle        \fi
    \or\ifcase\c_math_styles_state_cramped
        \noexpand\triggerdisplaystyle        \or
        \displaystyle                        \or
        \crampeddisplaystyle                 \fi
    \or\ifcase\c_math_styles_state_cramped
        \noexpand\triggertextstyle           \or
        \textstyle                           \or
        \crampedtextstyle                    \fi
    \or\ifcase\c_math_styles_state_cramped
        \noexpand\triggerscriptstyle         \or
        \scriptstyle                         \or
        \crampedscriptstyle                  \fi
    \or\ifcase\c_math_styles_state_cramped
        \noexpand\triggerscriptscriptstyle   \or
        \scriptscriptstyle                   \or
        \crampedscriptscriptstyle            \fi
    \fi
  \or % small
    \ifcase\c_math_styles_state_style
        \ifcase\c_math_styles_state_cramped
        \noexpand\triggersmallstyle          \or
        \noexpand\triggeruncrampedsmallstyle \or
        \noexpand\triggercrampedsmallstyle   \fi
    \or\ifcase\c_math_styles_state_cramped
        \noexpand\triggerscriptstyle         \or
        \scriptstyle                         \or
        \crampedscriptstyle                  \fi
    \or\ifcase\c_math_styles_state_cramped
        \noexpand\triggerscriptstyle         \or
        \scriptstyle                         \or
        \crampedscriptstyle                  \fi
    \or\ifcase\c_math_styles_state_cramped
        \noexpand\triggerscriptscriptstyle   \or
        \scriptscriptstyle                   \or
        \crampedscriptscriptstyle            \fi
    \or\ifcase\c_math_styles_state_cramped
        \noexpand\triggerscriptscriptstyle   \or
        \scriptscriptstyle                   \or
        \crampedscriptscriptstyle            \fi
    \fi
  \or % large
    \ifcase\c_math_styles_state_style
        \ifcase\c_math_styles_state_cramped
        \noexpand\triggerbigstyle            \or
        \noexpand\triggeruncrampedbigstyle   \or
        \noexpand\triggercrampedbigstyle     \fi
    \or\ifcase\c_math_styles_state_cramped
        \noexpand\triggerdisplaystyle        \or
        \displaystyle                        \or
        \crampeddisplaystyle                 \fi
    \or\ifcase\c_math_styles_state_cramped
        \noexpand\triggertextstyle           \or
        \textstyle                           \or
        \crampedtextstyle                    \fi
    \or\ifcase\c_math_styles_state_cramped
        \noexpand\triggertextstyle           \or
        \textstyle                           \or
        \crampedtextstyle                    \fi
    \or\ifcase\c_math_styles_state_cramped
        \noexpand\triggerscriptstyle         \or
        \scriptstyle                         \or
        \crampedscriptstyle                  \fi
    \fi
  \fi
}

\unexpanded\def\math_style_set#1%
  {\edef\m_math_style_asked{#1}%
   \ifx\m_math_style_asked\empty \else
     \math_style_set_indeed
   \fi}

\let\setmathstyle\math_style_set

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

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

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

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

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

\unexpanded\def\setupmathstyle[#1]%
  {\edef\m_math_style_asked{#1}%
   \ifx\m_math_style_asked\empty \else
     \math_style_set_indeed
   \fi}

\unexpanded\def\usemathstyleparameter#1% faster local variant
  {\edef\m_math_style_asked{#1\c!mathstyle}%
   \ifx\m_math_style_asked\empty \else
     \math_style_set_indeed
   \fi}

%D \startbuffer
%D \definemathstyle[mystyle][scriptscript]
%D
%D $text\startmathstyle[mystyle]scriptscript\stopmathstyle text$
%D \stopbuffer
%D
%D \typebuffer \blank \start \getbuffer \stop \blank

\installcorenamespace {mathstyle}

\unexpanded\def\definemathstyle
  {\dodoubleargument\math_style_define}

\def\math_style_define[#1][#2]%
  {\c_math_styles_state_style  \zerocount
   \c_math_styles_state_cramped\zerocount
   \c_math_styles_state_size   \zerocount
   \rawprocesscommacommand[#2]\math_style_collect
   \expandafter\let\csname\??mathstyle#1\normalexpanded{\endcsname\math_style_add_to_cache_choice}}

% \def\math_style_set_indeed
%   {\csname\??mathstyle
%      \ifcsname\??mathstyle\m_math_style_asked\endcsname
%        \m_math_style_asked
%      \else
%        \??mathstyle
%      \fi
%    \endcsname}
%
% \setvalue{\??mathstyle\??mathstyle}%
%   {\csname\??mathstylecache
%      \ifcsname\??mathstylecache\m_math_style_asked\endcsname
%        \m_math_style_asked
%      \else
%        \??mathstylecache
%      \fi
%    \endcsname}
%
% \setvalue{\??mathstylecache\??mathstylecache}%
%   {\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
%    \expandafter\glet\csname\??mathstylecache\m_math_style_asked\normalexpanded{\endcsname\math_style_add_to_cache_choice}%
%    \csname\??mathstylecache\m_math_style_asked\endcsname}

\def\math_style_set_indeed
  {\ifcsname\??mathstyle\m_math_style_asked\endcsname
     \lastnamedcs
   \else
     \math_style_set_mathstyle_mathstyle
   \fi}

\def\math_style_set_mathstyle_mathstyle
  {\ifcsname\??mathstylecache\m_math_style_asked\endcsname
     \lastnamedcs
   \else
     \math_style_set_mathstyle_mathstylecache
   \fi}

\def\math_style_set_mathstyle_mathstylecache
  {\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
   \expandafter\glet\csname\??mathstylecache\m_math_style_asked\normalexpanded{\endcsname\math_style_add_to_cache_choice}%
   \csname\??mathstylecache\m_math_style_asked\endcsname}

\letvalue{\??mathstyle     \??mathstyle     }\math_style_set_mathstyle_mathstyle      % still needed?
\letvalue{\??mathstylecache\??mathstylecache}\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

\unexpanded\def\startmathstyle[#1]%
  {\edef\m_math_style_asked{#1}%
   \ifx\m_math_style_asked\empty
     \let\stopmathstyle\relax
   \else
     \bgroup
     \math_style_set_indeed
     \let\stopmathstyle\egroup
   \fi}

\let\stopmathstyle\relax

\unexpanded\def\startusemathstyleparameter#1%
  {\edef\m_math_style_asked{#1\c!mathstyle}%
   \ifx\m_math_style_asked\empty
     \let\stopusemathstyleparameter\relax
   \else
     \bgroup
     \math_style_set_indeed
     \let\stopusemathstyleparameter\egroup
   \fi}

\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

% if needed we can get rid of the normalize (predo in font code)

% \def\math_text_choice_font#1#2#%
%   {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
%    \hbox#2\bgroup
%    \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
%    \font_basics_switchtobodyfont\m_math_text_choice_face
%    #1%
%    \nospacing % \normalnospaces\plusone
%    \let\next}

%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

\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}$}

% I need to decide:
%
%mathscriptboxmode    \zerocount % no kerning
%mathscriptboxmode    \plusone   % lists
\mathscriptboxmode    \plustwo   % lists and boxes
\mathscriptcharmode   \plusone   % lists and boxes
%mathscriptboxmode    \plusthree % lists and boxes with \boundary=1 (also for testing and demo)
\mathrulethicknessmode\plusone   % adaptive

\unexpanded\def\mathtext  {\mathortext{\math_text_choice_font\relax}\hbox}
\unexpanded\def\mathword  {\mathortext{\math_text_choice_word\relax}\hbox}

\unexpanded\def\mathtexttf{\mathortext{\math_text_choice_font\tf}\hbox}
\unexpanded\def\mathtextit{\mathortext{\math_text_choice_font\it}\hbox}
\unexpanded\def\mathtextsl{\mathortext{\math_text_choice_font\sl}\hbox}
\unexpanded\def\mathtextbf{\mathortext{\math_text_choice_font\bf}\hbox}
\unexpanded\def\mathtextbi{\mathortext{\math_text_choice_font\bi}\hbox}
\unexpanded\def\mathtextbs{\mathortext{\math_text_choice_font\bs}\hbox}

\unexpanded\def\mathwordtf{\mathortext{\math_text_choice_word\tf}\hbox}
\unexpanded\def\mathwordit{\mathortext{\math_text_choice_word\it}\hbox}
\unexpanded\def\mathwordsl{\mathortext{\math_text_choice_word\sl}\hbox}
\unexpanded\def\mathwordbf{\mathortext{\math_text_choice_word\bf}\hbox}
\unexpanded\def\mathwordbi{\mathortext{\math_text_choice_word\bi}\hbox}
\unexpanded\def\mathwordbs{\mathortext{\math_text_choice_word\bs}\hbox}

%D Safeguard against redefinitions:

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

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

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

%D The next code is derived from plain \TEX. The names will change!

\newcount\interdisplaylinepenalty \interdisplaylinepenalty\plushundred

% Actually, not using an if saves one macro so there is no penalty
% for splitting up this macro.
%
% \newif\ifdt@p
%
% \def\displ@y
%   {\global\dt@ptrue
%    \math_openup\displayopenupvalue % was \openup\jot
%    \everycr
%      {\noalign
%         {\ifdt@p
%            \global\dt@pfalse
%            \ifdim\prevdepth>-\thousandpoint
%              \vskip-\lineskiplimit
%              \vskip\normallineskiplimit
%            \fi
%          \else
%            \penalty\interdisplaylinepenalty
%          \fi}}}

\newtoks\mathdisplayaligntweaks

% this can become an option:

\unexpanded\def\math_display_align_hack % I don't like the global, maybe we should push and pop
  {\glet\math_display_align_hack_indeed\math_display_align_hack_remove_skip
   \math_openup\displayopenupvalue % was \math_openup\jot
   \everycr{\noalign{\math_display_align_hack_indeed}}}

\def\math_display_align_hack_remove_skip
  {\ifdim\prevdepth>-\thousandpoint
     \vskip\dimexpr-\lineskiplimit+\normallineskiplimit\relax
   \fi
   \glet\math_display_align_hack_indeed\math_display_align_hack_insert_penalty}

\def\math_display_align_hack_insert_penalty
  {\penalty\interdisplaylinepenalty}

\appendtoks
    \math_display_align_hack
\to \mathdisplayaligntweaks

%D Text in math:

\unexpanded\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 \let\text\hbox \fi

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

\unexpanded\def\mathoptext
  {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
  %\showmathstyle
   \dowithnextbox
     {\mathop{\box\nextbox}}%
     \hbox\bgroup\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}%
    \ifx\p_setups\empty\else
        \directsetup\p_setups
    \fi
\to \everyswitchmathematics

% new:

\unexpanded\def\smallmathsymbol#1%
  {\mathematics{\mathbin{\normalexpanded{\raise.15\exheight\hbox{\normalstartimath
     \triggermathstyle{\the\numexpr\normalmathstyle+2\relax}#1%
   \normalstopimath}}}}}

% this should be a primitive:

\def\mathextensiblecode#1#2{\clf_extensiblecode\numexpr#1\relax\numexpr#2\relax}
\def\mathhorizontalcode#1#2{\clf_horizontalcode\numexpr#1\relax\numexpr#2\relax}

% 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{\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}

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

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

\unexpanded\def\math_inline_openup_traced_start
  {\scratchtopoffset   \ht\scratchbox
   \scratchbottomoffset\dp\scratchbox
   \scratchheight      \dimexpr\scratchtopoffset   +\m_math_inline_openup_ht\relax
   \scratchdepth       \dimexpr\scratchbottomoffset+\m_math_inline_openup_dp\relax
   \vrule\s!width\zeropoint\s!height\scratchheight\s!depth\scratchdepth\relax
   \begingroup
     \dofastcoloractivation{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}

\unexpanded\def\math_inline_openup_traced_stop
  {\endgroup
   \kern-\emwidth
   \begingroup
     \dofastcoloractivation{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}

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

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

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

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

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

%D The \type {\displaywidth} is only known inside a display formula, so we need to catch
%D it when still zero.

\def\checkeddisplaywidth % hsize if zero
  {\dimexpr
     \ifzeropt\displaywidth
       \hsize
     \else
       \displaywidth
     \fi
   \relax}

\def\maximizeddisplaywidth % larger than zero but within hsize
  {\dimexpr
     \ifzeropt\displaywidth
       \hsize
     \else\ifdim\displaywidth>\hsize
        \hsize
     \else
       \displaywidth
     \fi\fi
   \relax}

%D Experiment: (todo: same switch as italic, using \type {\everyswitchmathematics}).

\newcount\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}%
    \ifx\p_domain\empty
        \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

\setupmathematics
  [\s!italics=3] % for the moment only this one makes sense .. still experimental

%D For special purposed we set this one:

\installcorenamespace{mathrules}

\unexpanded\def\enablemathrules{\letgvalue{\??mathrules\fontclass}\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

% \unexpanded\def\negenspace{\kern-.5\emwidth}
% \unexpanded\def\negemspace{\kern-  \emwidth}
%
% \unexpanded\def\math_f#1%
%   {\ifcase#1\or
%      \hairspace
%    \or
%      \thinspace
%    \or
%      \medspace
%    \or
%      \thickspace
%    \or
%      \enspace
%    \or
%      \emspace
%    \fi}
%
% \unexpanded\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

\unexpanded\def\math_scripts_stack
  {\c_attr_mathunstack\attributeunsetvalue}

\unexpanded\def\math_scripts_unstack
  {\clf_enablescriptunstacking
   \c_attr_mathunstack\plusone}

\appendtoks
    \let\stackscripts  \math_scripts_stack
    \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            \else\ifdim#1\displaystyle            =\maxdimen\else\frozen#1\displaystyle            #2#1\displaystyle            \fi\fi
   \ifzeropt#1\crampeddisplaystyle     \else\ifdim#1\crampeddisplaystyle     =\maxdimen\else\frozen#1\crampeddisplaystyle     #2#1\crampeddisplaystyle     \fi\fi
   \ifzeropt#1\textstyle               \else\ifdim#1\textstyle               =\maxdimen\else\frozen#1\textstyle               #2#1\textstyle               \fi\fi
   \ifzeropt#1\crampedtextstyle        \else\ifdim#1\crampedtextstyle        =\maxdimen\else\frozen#1\crampedtextstyle        #2#1\crampedtextstyle        \fi\fi
   \ifzeropt#1\scriptstyle             \else\ifdim#1\scriptstyle             =\maxdimen\else\frozen#1\scriptstyle             #2#1\scriptstyle             \fi\fi
   \ifzeropt#1\crampedscriptstyle      \else\ifdim#1\crampedscriptstyle      =\maxdimen\else\frozen#1\crampedscriptstyle      #2#1\crampedscriptstyle      \fi\fi
   \ifzeropt#1\scriptscriptstyle       \else\ifdim#1\scriptscriptstyle       =\maxdimen\else\frozen#1\scriptscriptstyle       #2#1\scriptscriptstyle       \fi\fi
   \ifzeropt#1\crampedscriptscriptstyle\else\ifdim#1\crampedscriptscriptstyle=\maxdimen\else\frozen#1\crampedscriptscriptstyle#2#1\crampedscriptscriptstyle\fi\fi}

\unexpanded\def\mathopenupparameter#1#2%
  {\ifdim#2\points=\zeropoint\else
     \math_openup_parameter#1{#2}%
   \fi}

%D For now (needed in asciimath):

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

\protect \endinput

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