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

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

\unprotect

%D We move these definitions into the format:

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

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

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

\appendtoks
    \attribute\mathmodeattribute\plusone
\to \everydisplay

\appendtoks
    \attribute\mathmodeattribute\plusone
\to \everybeforedisplayformula

\appendtoksonce
    \attribute\displaymathattribute\plusone
\to \everybeforedisplayformula

\setnewconstant\defaultmathfamily \zerocount % 255

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

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

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

\unexpanded\def\stopmathematics
  {\popmacro\currentmathematics
   \the\everyswitchmathematics}

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

% Normally this 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\ctxcommand{setmathattribute("#1","#2")}\fi}
\unexpanded\def\math_set_alphabet      #1{\ifmmode\ctxcommand{setmathalphabet("#1")}\fi}
\unexpanded\def\math_set_font_style    #1{\ifmmode\ctxcommand{setmathstyle("#1")}\fi}
\unexpanded\def\math_set_font_alternate#1{\ifmmode\ctxcommand{setmathalternate(\number\defaultmathfamily,"#1")}\fi}

\installcorenamespace{mathstylealternate} % might become a setuphandler

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

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

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

\unexpanded\def\mathaltcal{\math_set_font_alternate{cal}\cal} % ss01 in xits

\let\setmathattribute            \math_set_attribute
\let\setmathalphabet             \math_set_alphabet
\let\setmathfontstyle            \math_set_font_style
\let\setmathfontalternate        \math_set_font_alternate
\let\setmathfontstylealterternate\math_set_font_style_alterternate

\let\mathalternate               \math_set_font_alternate % obsolete

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

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

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

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

\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

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

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

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

\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\ctxcommand{mathrenderset("\mathematicsparameter\c!symbolset")}\relax
\to \everysetupmathematics % only in mathematics

\appendtoks
    \ifcase\c_math_renderings_attribute\else
        \attribute\mathrenderingattribute\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{\ctxcommand{utfmathclass  (\!!bs#1\!!es)}}
\def\utfmathstretch#1{\ctxcommand{utfmathstretch(\!!bs#1\!!es)}}
\def\utfmathcommand#1{\ctxcommand{utfmathcommand(\!!bs#1\!!es)}}
\def\utfmathfiller #1{\ctxcommand{utfmathfiller (\!!bs#1\!!es)}}

\def\utfmathclassfiltered  #1#2{\ctxcommand{utfmathclass  (\!!bs#1\!!es,nil,"#2")}}
\def\utfmathcommandfiltered#1#2{\ctxcommand{utfmathcommand(\!!bs#1\!!es,nil,"#2")}}

\unexpanded\def\doifelseutfmathaccent          #1{\ctxcommand{doifelseutfmathaccent(\!!bs#1\!!es)}}
\unexpanded\def\doifelseutfmathaccentfiltered#1#2{\ctxcommand{doifelseutfmathaccent(\!!bs#1\!!es,"#2")}}

%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%
  {\csname\??mathcommand#1\endcsname}

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

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

\let\normalmathop\mathop

\unexpanded\def\mathop
  {\normalmathop
   \bgroup
   \let\rm\mf
   \let\nexttoken=}

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

\unexpanded\def\normalmbox
  {\normalhbox\bgroup\mf
   \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
  {\appendtoks\math_enable_mbox\to \everymathematics}
  {\everymathematics\expandafter{\the\everymathematics\math_enable_mbox}}

\def\math_enable_mbox
  {\ifdefined\normalhbox\else\let\normalhbox\hbox\fi % ?
   \let\hbox\mbox}

%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#1\endgroup}
\unexpanded\def\math_tags_ms#1{\begingroup\mathupright#1\endgroup}

\unexpanded\def\mfunction         #1{{\mathupright\math_tags_function{#1}}}
\unexpanded\def\mfunctionlabeltext#1{{\mathupright\math_tags_functionlabeltext{#1}}}

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

\expanded\def\math_tags_mathfunction_indeed         #1{\ctxcommand{taggedmathfunction("#1",false,\ifconditional\c_apply_function true\else false\fi)}}
\expanded\def\math_tags_mathfunctionlabeltext_indeed#1{\ctxcommand{taggedmathfunction("#1",true ,\ifconditional\c_apply_function true\else false\fi)}}

\expanded\def\math_tags_mo_indeed#1{\begingroup            \attribute\mathcategoryattribute\plusone  #1\endgroup}
\expanded\def\math_tags_mi_indeed#1{\begingroup            \attribute\mathcategoryattribute\plustwo  #1\endgroup}
\expanded\def\math_tags_mn_indeed#1{\begingroup\mathupright\attribute\mathcategoryattribute\plusthree#1\endgroup}
\expanded\def\math_tags_ms_indeed#1{\begingroup\mathupright\attribute\mathcategoryattribute\plusfour #1\endgroup}

\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_function         \math_tags_mathfunction_indeed
    \let\math_tags_functionlabeltext\math_tags_mathfunctionlabeltext_indeed
    \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}}

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

%D We can force the way functions are typeset by manipulating the text option:
%D
%D \starttyping
%D \definetypeface[iwona][ss][sans][iwona][default][encoding=texnansi]
%D \definetypeface[iwona][mm][math][iwona][default][encoding=texnansi,text=ss]
%D \stoptyping
%D
%D This hooks into the math handler with:

% no longer supported this way, has to be done with \setupmathematics
%
% \appendtoks
%     \setmathfunctionstyle\currentmathtextstyle
% \to \everybodyfont

%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 Some goodies:

\unexpanded\def\Angstrom{\nomathematics{\Aring}}

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

% \setnewconstant\primeasciicode 39 % '

\activatemathcharacter\circumflexasciicode
\activatemathcharacter\underscoreasciicode
\activatemathcharacter\ampersandasciicode
\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       \global\let\othercircumflextoken      ^ }
{ \catcode\circumflexasciicode\superscriptcatcode \global\let\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

\bgroup

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

    \doglobal \appendtoks
        \let _\normalsubscript
        \let ^\normalsuperscript
        \let &\normalmathaligntab % use \def when it's \aligntab
    \to \everymathematics

\egroup

\newtoks\everydonknuthmode
\newtoks\everynonknuthmode

\newconditional \knuthmode

\let\nonknuthmode\relax
\let\donknuthmode\relax

% \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
  {\ctxlua{resolvers.macros.enablecomment()}%
   \glet\enableasciimode\relax}

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

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

\unexpanded\def\stopasciimode
  {\popcatcodetable}

%D Needed for unicode:

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

%D Memory saver:

\appendtoks
    \ifx\currentmathematics\empty
        \doifelse{\mathematicsparameter\c!compact}\v!yes\enabledirectives\disabledirectives[math.virtual.optional]%
    \fi
\to \everysetupmathematics

\setupmathematics
  [\c!compact=no]

%D Arabic:

\newconditional\c_math_right_to_left

\appendtoks
    \doifelse{\mathematicsparameter\c!align}{r2l}\settrue\setfalse\c_math_right_to_left
\to \everyswitchmathematics

\unexpanded\def\math_basics_synchronize_direction
  {\mathdir T\ifconditional\c_math_right_to_left R\else L\fi T}

\appendtoks
    \math_basics_synchronize_direction
%to \everymathematics % comes too late and I'm not in the mood for a mixed mode kludge now
\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

% only used local

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

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

\appendtoks
    \attribute\mathgreekattribute\c_math_greek_attribute
\to \everymathematics

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

%D Math italics (experiment)

% we need keys

\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

\def\math_italics_initialize
  {\ifnum\c_math_italics_attribute=\attributeunsetvalue \else
     \ctxcommand{setmathitalics()}% one time
     \global\let\math_italics_initialize\relax
   \fi}

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

\appendtoks
    \math_italics_initialize
    \attribute\mathitalicsattribute\c_math_italics_attribute
\to \everymathematics

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

% 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 \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\v!autopunctuation}\v!yes\settrue\setfalse\automathpunctuation
% \to \everyswitchmathematics
%
% \setupmathematics
%   [\v!autopunctuation=\v!no]
%
% \def\math_punctuation_next{\ifx\nexttoken\blankspace\char\zerocount\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
%        \attribute\mathpunctuationattribute\plustwo}
%
%     \unexpanded\gdef\math_punctuation_initialize_yes
%       {\attribute\mathpunctuationattribute\plustwo}
%
%     \unexpanded\gdef\math_punctuation_initialize_nop
%       {\attribute\mathpunctuationattribute\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{\textcomma }\else\mathord{\textcomma }\fi}
\def\math_punctuation_period_next{\ifx\nexttoken\blankspace \mathpunct{\textperiod}\else\mathord{\textperiod}\fi}

\unexpanded\def\math_punctuation_nop_comma {\mathpunct{\textcomma}}
\unexpanded\def\math_punctuation_all_comma {\futurelet\nexttoken\math_punctuation_comma_next}
           \let\math_punctuation_yes_comma \math_punctuation_all_comma

\unexpanded\def\math_punctuation_nop_period{\mathord{\textperiod}}
\unexpanded\def\math_punctuation_all_period{\futurelet\nexttoken\math_punctuation_period_next}
           \let\math_punctuation_yes_period\math_punctuation_nop_period

\setnewconstant\c_math_comma  "002C
\setnewconstant\c_math_period "002E
\setnewconstant\c_math_special"8000

\installcorenamespace {mathautopunctuation}

\bgroup

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

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

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

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

\egroup

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

\appendtoks
    \mathcode\c_math_comma \c_math_special
    \mathcode\c_math_period\c_math_special
    \csname\??mathautopunctuation\mathematicsparameter\v!autopunctuation\endcsname
\to \everymathematics

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

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

\setupmathematics
  [\v!autopunctuation=\v!no] % no | yes | all

%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
     \crampeddisplaystyle      \or
     \textstyle                \or
     \crampedtextstyle         \or
     \scriptstyle              \or
     \crampedscriptstyle       \or
     \scriptscriptstyle        \or
     \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\zerocount} % hm, can ie other value as well

\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\zerocount} % hm, can ie other value as well

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

%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

\unexpanded\def\mathstylehbox#1%
  {\normalexpanded{\hbox\bgroup
     \startimath\triggermathstyle\normalmathstyle}\mathsurround\zeropoint#1\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}

\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
%   {\ifcsname\??mathstyle\m_math_style_asked\endcsname
%      \csname\??mathstyle\m_math_style_asked\endcsname
%    \else
%      \math_style_set_indeed_cached
%    \fi}
%
% \def\math_style_set_indeed_cached
%   {\ifcsname\??mathstylecache\m_math_style_asked\endcsname
%      % already in cache
%    \else
%      \math_style_add_to_cache
%    \fi
%    \csname\??mathstylecache\m_math_style_asked\endcsname}
%
% \def\math_style_add_to_cache
%   {\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
%    \global\expandafter\let\csname\??mathstylecache\m_math_style_asked\normalexpanded{\endcsname\math_style_add_to_cache_choice}}
%
% ugly but more efficient (as called often)

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

%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}).

\unexpanded\def\mathtext
  {\mathortext\math_text_choice\hbox}

% \def\math_text_choice#1%
%   {\mathchoice
%      {\math_text_choice_indeed\displaystyle\textface        {#1}}%
%      {\math_text_choice_indeed\textstyle   \textface        {#1}}%
%      {\math_text_choice_indeed\textstyle   \scriptface      {#1}}%
%      {\math_text_choice_indeed\textstyle   \scriptscriptface{#1}}}
%
% \def\math_text_choice_indeed#1#2#3% no \everymath !
%   {\hbox{\everymath{#1}\switchtobodyfont[#2]#3}} % 15 sec

% \let\m_math_text_choice_style\relax
%
% \def\math_text_choice#1%
%   {\edef\m_math_text_choice_style{\normalmathstyle}%
%    \hbox\bgroup
%    % \everymath{\triggermathstyle\m_math_text_choice_style}%
%      \normalizebodyfontsize\m_math_text_choice_style{\mathstylefont\m_math_text_choice_style}%
%      \font_basics_switchtobodyfont\m_math_text_choice_style
%      #1%
%    \egroup}

\let\m_math_text_choice_face \relax

% \def\math_text_choice#1% if needed we can get rid of the normalize (predo in font code)
%   {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
%    \hbox{\font_basics_switchtobodyfont\m_math_text_choice_face#1}}

\def\math_text_choice% if needed we can get rid of the normalize (predo in font code)
  {\normalizebodyfontsize\m_math_text_choice_face{\mathstyleface\normalmathstyle}%
   \hbox\bgroup\font_basics_switchtobodyfont\m_math_text_choice_face\let\next}

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

\appendtoks
    \resetdisplaymatheq % moved to here
\to \mathdisplayaligntweaks

\unexpanded\def\math_display_align_hack % I don't like the global, maybe we should push and pop
  {\global\let\math_display_align_hack_indeed\math_display_align_hack_remove_skip
   \openup\displayopenupvalue % was \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
   \global\let\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}}}

% 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{$\triggermathstyle{\the\numexpr\normalmathstyle+2\relax}#1$}}}}}

% this should be a primitive:

% \def\mathextensiblecode#1#2%
%   {\cldcontext{mathematics.extensiblecode(\number#1,\number#2)}}

\def\mathextensiblecode#1#2{\ctxcommand{extensiblecode(\number#1,\number#2)}}
\def\mathhorizontalcode#1#2{\ctxcommand{horizontalcode(\number#1,\number#2)}}

\protect \endinput
