%D \module
%D   [       file=core-mat,
%D        version=1998.12.07,
%D          title=\CONTEXT\ Core Macros,
%D       subtitle=Math Fundamentals,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA / Hans Hagen \& Ton Otten}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

% engels maken

\writestatus{loading}{Context Core Macros / Math Fundamentals}

\unprotect

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

% force text mode, will be overloaded later

\ifx\text\undefined \let\text\hbox \fi

\newdimen\lastlinewidth

% does not work at all
%
% \def\setlastlinewidth
%   {\resetlastlinewidth
%    \ifmmode\else\ifhmode\else\ifoptimizedisplayspacing
%      \bgroup
%      \forgetdisplayskips
%      $$\global\lastlinewidth\predisplaysize$$
%      \vskip-\baselineskip
%      \egroup
%    \fi\fi\fi}

% test \par \dorecurse{10}{test } \moveformula \startformula test \stopformula test \endgraf
% test \par \dorecurse{10}{test } \startformula test \stopformula test \endgraf
% \dorecurse{30}{\bpar \dorecurse\recurselevel{test } \epar \startformula formula \stopformula}

\def\setlastlinewidth
  {\resetlastlinewidth
   \ifoptimizedisplayspacing\ifmmode\else\ifhmode
     \bgroup
     \forgetdisplayskips
     \displaywidowpenalty\widowpenalty % brrr, else widowpenalty does not work
     \everymath   \emptytoks
     \everydisplay\emptytoks
     $$\strut\global\lastlinewidth\predisplaysize$$
     \vskip-\lineheight
     \vskip\zeropoint
     \egroup
   \fi\fi\fi}

\def\resetlastlinewidth
  {\global\lastlinewidth\zeropoint\relax}

% not here: \appendtoks \setlastlinewidth \to \everyendofpar

%D moved from main-001

%\def\EveryMathPar{\EveryPar}
%
%\newevery \everymath \EveryMath

\abovedisplayskip      = \zeropoint
\abovedisplayshortskip = \zeropoint % evt. 0pt minus 3pt
\belowdisplayskip      = \zeropoint
\belowdisplayshortskip = \zeropoint % evt. 0pt minus 3pt

\predisplaypenalty     = \zerocount
\postdisplaypenalty    = \zerocount % -5000 gaat mis, zie penalty bij \paragraaf

% we don't use the skip's

\def\displayskipsize#1#2% obsolete
  {\ifdim\ctxparskip>\zeropoint
     #1\ctxparskip\!!plus#2\ctxparskip\!!minus#2\ctxparskip\relax
   \else
     #1\lineheight\!!plus#2\lineheight\!!minus#2\lineheight\relax
   \fi}

\def\displayskipfactor          {1.0} % obsolete
\def\displayshortskipfactor     {0.8} % obsolete
\def\displayskipgluefactor      {0.3} % obsolete
\def\displayshortskipgluefactor {0.2} % obsolete

\def\abovedisplayskipsize% obsolete
  {\displayskipsize\displayskipfactor\displayskipgluefactor}

\def\belowdisplayskipsize% obsolete
  {\displayskipsize\displayskipfactor\displayskipgluefactor}

\def\abovedisplayshortskipsize% obsolete
  {\displayskipsize\displayshortskipfactor\displayshortskipgluefactor}

\def\belowdisplayshortskipsize% obsolete
  {\displayskipsize\displayshortskipfactor\displayshortskipgluefactor}

\def\setdisplayskip#1#2#3% obsolete
  {#1=#2\relax
   \advance#1 -\parskip
   \advance#1 -#3\relax}

\def\setdisplayskips % obsolete
  {\setdisplayskip\abovedisplayskip     \abovedisplayskipsize     \zeropoint
   \setdisplayskip\belowdisplayskip     \belowdisplayskipsize     \zeropoint
   \setdisplayskip\abovedisplayshortskip\abovedisplayshortskipsize\baselineskip
   \setdisplayskip\belowdisplayshortskip\belowdisplayshortskipsize\baselineskip}

% so far for unused stuff

\def\forgetdisplayskips % to do
  {\abovedisplayskip     \zeropoint
   \belowdisplayskip     \zeropoint
   \abovedisplayshortskip\zeropoint
   \belowdisplayshortskip\zeropoint}

\definenumber % \definelabel
  [\v!formula]
  [\c!text=\v!formula,
   \c!way=\@@fmway,
   \c!blockway=\@@fmblockway,
   \c!location=\v!intext]

\def\setupformulas
  {\dodoubleargument\getparameters[\??fm]}

\newconditional\handleformulanumber
\newconditional\incrementformulanumber

\def\dododoformulanumber#1#2#3#4% (#1,#2)=outer(ref,sub) (#3,#4)=inner(ref,sub)
  {\hbox\bgroup
   \ifconditional\handleformulanumber
     \ifconditional\incrementformulanumber
       \incrementnumber[\v!formula]%
     \fi
     \maakhetnummer[\v!formula]%
     \setbox0\hbox{\ignorespaces#2\unskip}%
     \ifdim\wd0>\zeropoint
       \edef\hetsubnummer{#2}%
     \else
       \let\hetsubnummer\empty
     \fi
     \doifsomething{#1}{\rawreference{\s!for}{#1}{\hetnummer\hetsubnummer}}%
     \setbox0\hbox{\ignorespaces#4\unskip}%
     \ifdim\wd0>\zeropoint
       \edef\hetsubnummer{#4}%
     \fi
     \doifsomething{#3}{\rawreference\s!for{#3}{\hetnummer\hetsubnummer}}%
     \rm % nodig ?
     \@@fmnumbercommand
       {\dostartattributes\??fm\c!numberstyle\c!numbercolor
        \strut
        \@@fmleft
        \preparethenumber\??fm\hetnummer\preparednumber
        \labeltexts\v!formula
          {\ignorespaces\preparednumber\ignorespaces\hetsubnummer\unskip}%
        \@@fmright
        \dostopattributes}%
   \fi
   \egroup}

\def\dodoformulanumber[#1][#2][#3]%
  {\doquadruplegroupempty\dododoformulanumber{#1}{#2}{#3}}

\def\doformulanumber
  {\dotripleempty\dodoformulanumber}

\setvalue{\e!start\v!formula}{\dostartformula{}}
\setvalue{\e!stop \v!formula}{\dostopformula}

\def\definieerformule
  {\dodoubleempty\dodefinieerformule}

\def\dodefinieerformule[#1][#2]%
  {\doifsomething{#1}
     {\copyparameters
        [\??fm#1][\??fm]
        [\c!spacebefore,\c!spaceafter,\c!grid,
         \c!leftmargin,\c!rightmargin,\c!margin,
         \c!indentnext,\c!alternative,
         \c!strut,\c!align,\c!distance]%
      \setupformulas[#1][#2]%
      \setvalue{\e!start#1\v!formula}{\dostartformula{#1}}%
      \setvalue{\e!stop #1\v!formula}{\dostopformula}}}

\newtoks \everysetupformulas \relax % we need a hook for extensions in modules

\def\setupformulas
  {\dodoubleempty\dosetupformulas}

\def\dosetupformulas[#1][#2]%
  {\ifsecondargument
     \getparameters[\??fm#1][#2]%
   \else
     \getparameters[\??fm][#1]%
   \fi
   \the\everysetupformulas}

\def\formulaparameter#1%
  {\csname\??fm\currentformula#1\endcsname}

\setupformulas
  [\c!way=\@@nrway,
   \c!blockway=,
   \c!sectionnumber=\@@nrsectionnumber,
   \c!location=\v!right,
   \c!left=(,
   \c!right=),
   \c!spacebefore=,
   \c!spaceafter=\@@fmspacebefore,
   \c!leftmargin=\!!zeropoint,
   \c!rightmargin=\!!zeropoint,
   \c!margin=,
   \c!indentnext=\v!no,
   \c!alternative=\s!default,
   \c!align=,
   \c!strut=\v!no,
   \c!separator=\@@koseparator,
   \c!distance=1em]

\def\currentformula          {}
\def\predisplaysizethreshhold{2em} % was 3em

\def\leftdisplayskip    {\leftskip}
\def\rightdisplayskip   {\rightskip}
\def\leftdisplaymargin  {\formulaparameter\c!leftmargin}
\def\rightdisplaymargin {\formulaparameter\c!rightmargin}
\def\displaygridsnapping{\formulaparameter\c!grid}

\def\beforedisplayspace
  {\doifnot{\formulaparameter\c!spacebefore}\v!none{\blank[\formulaparameter\c!spacebefore]}}

\def\afterdisplayspace
  {\doifnot{\formulaparameter\c!spaceafter  }\v!none{\blank[\formulaparameter\c!spaceafter  ]}}

\def\setpredisplaysize#1%
  {\predisplaysize#1\relax
   \ifdim\predisplaysize<\maxdimen
     \ifdim\predisplaysize>\zeropoint
       \advance\predisplaysize \predisplaysizethreshhold
     \fi
     \advance\predisplaysize \displayindent % needed ?
     \ifdim\predisplaysize>\hsize
       \predisplaysize\hsize
     \fi
   \else
     \predisplaysize\zeropoint
   \fi}

\def\setdisplaydimensions
  {\displayindent\leftdisplayskip
   \advance\displayindent\leftdisplaymargin
   \displaywidth\hsize
   \ifdim\hangindent>\zeropoint
     \advance\displayindent\hangindent
   \else
     \advance\displaywidth\hangindent
   \fi
   \advance\displaywidth-\displayindent
   \advance\displaywidth-\rightdisplayskip
   \advance\displaywidth-\rightdisplaymargin}

\newif\ifoptimizedisplayspacing

\def\dostartformula#1%
  {\dodoubleempty\dodostartformula[#1]}

\newskip\formulaparskip
\newskip\formulastrutht
\newskip\formulastrutdp

% hm, invoke otr in hmode in order to move skips to mvl, could be an option

\def\dodostartformula[#1][#2]% setting leftskip adaption is slow !
  {% todo: test first
   %
   % \ifdim\lastskip>\zeropoint
   %   \resetlastlinewidth % else problems with in between stuff without \epar
   % \fi
   \bgroup
   \formulaparskip\parskip
   \formulastrutdp\strutdepth
   \formulastrutht\strutheight
   \switchtoformulabodyfont[#2]%
   \parskip\formulaparskip
   \def\currentformula{#1}%
   \doifsomething{\formulaparameter\c!margin}% so we test first
     {\dosetleftskipadaption{\formulaparameter\c!margin}%
      \edef\leftdisplaymargin{\the\leftskipadaption}}% overloaded
   \long\def\dostartformula##1{\bgroup\let\dostopformula\egroup}%
   \freezedimenmacro\leftdisplayskip
   \freezedimenmacro\rightdisplayskip
   \freezedimenmacro\leftdisplaymargin
   \freezedimenmacro\rightdisplaymargin
   \freezedimenmacro\predisplaysizethreshhold
   \forgetdisplayskips
   \let\setdisplayskips\relax
   \ifoptimizedisplayspacing
     \ifdim\lastlinewidth>\zeropoint
       \abovedisplayshortskip-\strutht\relax
     \fi
   \else
     \resetlastlinewidth
   \fi
   \getvalue{\e!start\formulaparameter\c!alternative\v!formula}}

\def\switchtoformulabodyfont{\switchtobodyfont}

\setvalue{\v!formula}{\dosingleempty\doformula}

\def\doformula[#1]#2%
  {\begingroup
   \switchtoformulabodyfont[#1]%
   % not : \def\doformula[##1]##2{\mathematics{##2}}%
   \mathematics{#2}%
   \endgroup}

\let\doplaceformulanumber\empty

\def\dostopformula
  {\doplaceformulanumber
   \getvalue{\e!stop\formulaparameter\c!alternative\v!formula}%
   \resetlastlinewidth
   \nonoindentation
   \dochecknextindentation{\??fm\currentformula}%
   \egroup}

\newif\ifinformula

% \def\startdisplaymath
%   {\ifgridsnapping
%      \beforedisplayspace
%      \snapmathtogrid\vbox
%      \bgroup
%      \informulatrue
%     %\forgetall % breaks side floats
%    \else
%      \bgroup
%      \informulatrue
%     %\forgetall % otherwise backgrounds fail
%      \ifdim\lastskip<\zeropoint\else
%        \par
%        \ifvmode \ifdim\parskip>\zeropoint\relax
%          \vskip-\parskip
%        \fi \fi
%      \fi
%      \doif\displaygridcorrection{-\v!boven}{\kern-\strutht}% new, currently only option/default
%      \beforedisplayspace
%      \par
%      \ifvmode
%        \verticalstrut
%        \vskip-\struttotal
%        \vskip-\baselineskip
%      \fi
%    \fi
%    $$\setdisplaydimensions
%    \setpredisplaysize\lastlinewidth
%    \startinnermath}

% \def\stopdisplaymath
%   {\stopinnermath
%    $$%
%    \ifgridsnapping
%      \egroup
%      \afterdisplayspace
%    \else
%      \par\ifvmode\ifdim\parskip>\zeropoint\vskip-\parskip\fi\fi
%      \afterdisplayspace
%      \egroup
%    \fi
%    \globallet\displaylinecorrection\empty
%    \gdef\displaygridcorrection{\displaygridsnapping}}

\def\startdisplaymath
  {\ifgridsnapping
     \beforedisplayspace
     \snapmathtogrid\vbox
     \bgroup
     \informulatrue
    %\forgetall % breaks side floats
   \else
     \bgroup
     \parskip\formulaparskip % ! !
     \informulatrue
    %\forgetall % otherwise backgrounds fail
     \ifdim\lastskip<\zeropoint\else
       \par
         \ifvmode \ifdim\parskip>\zeropoint\relax
           \whitespace \vskip-\parskip % kind of forces and cancels again
         \fi \fi
     \fi
     \doif\displaygridcorrection{-\v!top}{\kern-\strutht}% new, currently only option/default
     \beforedisplayspace
     \par
     \ifvmode
       \verticalstrut
       \vskip-\struttotal
       \vskip-\baselineskip
     \fi
   \fi
   $$\setdisplaydimensions
   \setpredisplaysize\lastlinewidth
   \startinnermath}

\def\stopdisplaymath
  {\stopinnermath
   $$%
   \ifgridsnapping
     \egroup
     \afterdisplayspace
   \else
     \par\ifvmode\ifdim\parskip>\zeropoint\whitespace\vskip-\parskip\fi\fi
     \afterdisplayspace
     \egroup
   \fi
   \globallet\displaylinecorrection\empty
   \gdef\displaygridcorrection{\displaygridsnapping}}

\newif\ifclipdisplaymath \clipdisplaymathtrue
\def\displaymathclipfactor{1.1}

\def\snapmathtogrid % to do \dp
  {\dowithnextbox
     {\bgroup
      \donefalse
      \ifclipdisplaymath
        \ifdim\nextboxht<\displaymathclipfactor\lineheight
          \donetrue
        \fi
      \fi
      \ifdone
        \nextboxht\lineheight
      \else
        \getnoflines\nextboxht
        \setbox\nextbox\vbox to \noflines\lineheight
          {\vfill\flushnextbox\vfill}%
        \setbox\nextbox\hbox{\lower\strutdepth\flushnextbox}%
      \fi
      \snaptogrid[\displaygridcorrection]\hbox{\flushnextbox}%
      \egroup}}

\def\displaygridcorrection{\displaygridsnapping}
\let\displaygridcorrection\empty

\def\moveformula
  {\dosingleempty\domoveformula}

% \def\domoveformula[#1]% brr gaat mogelijk fout
%   {\ifgridsnapping
%      \iffirstargument
%        \xdef\displaygridcorrection{#1}%
%      \else
%        \gdef\displaygridcorrection{-\v!boven}% handy with short preline
%      \fi
%    \else
%      \gdef\displaygridcorrection{\displaygridsnapping}%
%    \fi}

\def\domoveformula[#1]% brr gaat mogelijk fout
  {\iffirstargument
     \xdef\displaygridcorrection{#1}%
   \else
     \gdef\displaygridcorrection{-\v!top}% handy with short preline
   \fi
   \globallet\displaylinecorrection\displaygridcorrection}

\let\startinnermath\empty
\let\stopinnermath \empty

\def\defineformulaalternative
  {\dotripleargument\dodefineformulaalternative}

\def\dodefineformulaalternative[#1][#2][#3]%
  {\setvalue{\e!start#1\v!formula}{#2}%
   \setvalue{\e!stop #1\v!formula}{#3}}

\defineformulaalternative[\s!default][\startdisplaymath][\stopdisplaymath]

% sp = single line paragraph  sd = single line display
% mp = multi  line paragraph  md = multy  line display

\defineformulaalternative[single][\startdisplaymath][\stopdisplaymath]
\defineformulaalternative[multi] [\startdisplaymath][\stopdisplaymath]

\definieerformule
  [sp]
  [\c!spacebefore=\v!none,\c!spaceafter=\v!none,
   \c!indentnext=\v!no,
   \c!alternative=single]

\definieerformule
  [sd]
  [\c!spacebefore=\v!none,\c!spaceafter=\v!none,
   \c!indentnext=\v!yes,
   \c!alternative=single]

\definieerformule
  [mp]
  [\c!indentnext=\v!no,
   \c!alternative=multi]

\definieerformule
  [md]
  [\c!indentnext=\v!yes,
   \c!alternative=multi]

% in m-math
%
% \defineformulaalternative[multi][\begindmath][\enddmath]
%
% \fakewords{20}{40}\epar
% \plaatsformule {a} $$              \fakespacingformula $$
% \fakewords{20}{40}\epar
% \plaatsformule {b} \startformule   \fakespacingformula \stopformule
% \plaatsformule {b} \startformule   \fakespacingformula \stopformule
% \fakewords{20}{40}\epar
% \plaatsformule {c} \startmdformule \fakespacingformula \stopmdformule
% \plaatsformule {c} \startmdformule \fakespacingformula \stopmdformule
% \fakewords{20}{40}\epar
% \plaatsformule {d} \startmpformule \fakespacingformula \stopmpformule
% \plaatsformule {d} \startmpformule \fakespacingformula \stopmpformule
% \fakewords{20}{40}\epar
% \plaatsformule {e} \startsdformule \fakespacingformula \stopsdformule
% \plaatsformule {e} \startsdformule \fakespacingformula \stopsdformule
% \fakewords{20}{40}\epar
% \plaatsformule {f} \startspformule \fakespacingformula \stopspformule
% \plaatsformule {f} \startspformule \fakespacingformula \stopspformule
% \fakewords{20}{40}

% \convertcommand\next\to\ascii \getfirstcharacter\ascii
% \ifx\firstcharacter\letterbackslash % a \cs

\def\placeformula
  {\settrue\incrementformulanumber
   \dodoubleempty\doplaceformula}

\def\placesubformula
  {\setfalse\incrementformulanumber
   \dodoubleempty\doplaceformula}

\def\doplaceformula[#1][#2]% #2 = dummy, gobbles spaces
  {\def\redoplaatsformule
     {\bgroup\def\dostartformula####1{\relax}%
      \ifx\next\bgroup
        \@EA\moreplaatsformule % [ref]{}
      \else
        \expandafter\convertargument\e!start\to\asciiA
        \expandafter\convertargument\next   \to\asciiB
        \ExpandBothAfter\doifincsnameelse\asciiA\asciiB
          {\egroup \@EA\dodoplaceformula}% [ref]\start
          {\egroup \@EA\dispplaatsformule}% [ref]$$
      \fi[#1]{}}%
   \futurelet\next\redoplaatsformule}

\long\def\moreplaatsformule[#1]#2#3#4% #2 dummy #4 gobbles spaces
  {\def\redoplaatsformule
     {\expandafter\convertargument\e!start\to\asciiA
      \expandafter\convertargument\next   \to\asciiB
      \ExpandBothAfter\doifincsnameelse\asciiA\asciiB
        {\egroup \dodoplaceformula}% [ref]\start
        {\egroup \dispplaatsformule}% [ref]$$
      [#1]{#3}}%
   \futurelet\next\redoplaatsformule#4}

\def\dispplaatsformule[#1]#2$$#3$$%
  {\dodoplaceformula[#1]{#2}\dostartformula{}#3\dostopformula}

\let\normalreqno\eqno
\let\normalleqno\leqno

\def\dodoplaceformula[#1]#2% messy, needs a clean up
  {\doifelse{#1}{-}
     {\setfalse\handleformulanumber}
     {\doifelse{#2}{-}
        {\setfalse\handleformulanumber}
        {\settrue\handleformulanumber}}%
   \ifconditional\handleformulanumber
     \def\formulanumber
       {%\global\let\subformulanumber\doformulanumber % no, bug
        \doformulanumber[#1][#2]}%
     \def\subformulanumber
       {\setfalse\incrementformulanumber
        \formulanumber}%
     \gdef\doplaceformulanumber
       {\global\let\doplaceformulanumber\empty
        \doifelse\@@fmlocation\v!left
          {\normalleqno{\doformulanumber[#1][#2][]{}}}
          {\normalreqno{\doformulanumber[#1][#2][]{}}}}%
   \else
     \def\formulanumber{\doformulanumber[#1][#2]}%
     \global\let\subformulanumber\doformulanumber
     \global\let\doplaceformulanumber\empty
   \fi}

%D We need a hook into the plain math alignment macros
%D
%D \starttyping
%D \displaylines
%D \eqalignno
%D \eqalignno
%D \stoptyping
%D
%D Otherwise we get a missing \type {$$} error reported.

\def\resetdisplaymatheq
  {\let\normalleqno\relax \let\leqno\relax
   \let\normalreqno\relax \let\eqno \relax
   \let\doplaceformulanumber\relax}

\let\normaldispl@y\displ@y

\def\displ@y{\resetdisplaymatheq\normaldispl@y}

%D Here we implement a basic math alignment mechanism. Numbers
%D are also handled. The macros \type {\startinnermath} and
%D \type {\stopinnermath} can be overloaded in specialized
%D modules.

\def\startinnermath
  {\getvalue{\e!start\??fm\formulaparameter\c!align}}

\def\stopinnermath
  {\getvalue{\e!stop \??fm\formulaparameter\c!align}}

\def\mathinnerstrut
  {\doif{\formulaparameter\c!strut}\v!yes\strut}

\long\def\defineinnermathhandler#1#2#3%
  {\setvalue{\e!start\??fm#1}{#2}%
   \setvalue{\e!stop \??fm#1}{#3}}

\newif\iftracemath

\def\mathhbox
  {\iftracemath\ruledhbox\else\hbox\fi}

\def\startmathbox#1#2%
  {\hsize\displaywidth
   \global\let\@eqno \empty \def\eqno {\gdef\@eqno }%
   \global\let\@leqno\empty \def\leqno{\gdef\@leqno}%
   % added
   \let\normalreqno\eqno
   \let\normalleqno\leqno
   % added
   \doplaceformulanumber
   \mathhbox to \displaywidth\bgroup
     \mathinnerstrut
     $\displaystyle
     \ifx\@leqno\empty\else \ifcase#2
       \rlap{\@leqno}%
     \else
       \@leqno\hskip\formulaparameter\c!distance
     \fi \fi
     #1}

\def\stopmathbox#1#2%
  {$#1%
   \ifx\@eqno\empty\else \ifcase#2
     \llap{\@eqno}%
   \else
     \hskip\formulaparameter\c!distance\@eqno
   \fi \fi
   \egroup}

\defineinnermathhandler\v!right{\startmathbox\empty1}{\stopmathbox\hfill0}
\defineinnermathhandler\v!left {\startmathbox\hfill0}{\stopmathbox\empty1}
\defineinnermathhandler\v!middle{\startmathbox\hfill0}{\stopmathbox\hfill0}

%D [The examples below are in english and don't process in the
%D  documentation style, which will be english some day.]
%D
%D Normally a formula is centered, but in case you want to
%D align it left or right, you can set up formulas to behave
%D that way. Normally a formula will adapt is left indentation
%D to the environment:
%D
%D \startbuffer
%D \fakewords{20}{40}\epar
%D \startitemize
%D \item \fakewords{20}{40}\epar
%D       \placeformula \startformula \fakeformula \stopformula
%D \item \fakewords{20}{40}\epar
%D \stopitemize
%D \fakewords{20}{40}\epar
%D \stopbuffer
%D
%D % \getbuffer
%D
%D In the next examples we explicitly align formulas to the
%D left (\type {\raggedleft}), center and right (\type
%D {\raggedright}):
%D
%D \startbuffer
%D \setupformulas[align=left]
%D \startformula\fakeformula\stopformula
%D \setupformulas[align=middle]
%D \startformula\fakeformula\stopformula
%D \setupformulas[align=right]
%D \startformula\fakeformula\stopformula
%D \stopbuffer
%D
%D \typebuffer
%D
%D Or in print:
%D
%D % {\getbuffer}
%D
%D With formula numbers these formulas look as follows:
%D
%D \startbuffer
%D \setupformulas[align=left]
%D \placeformula \startformula\fakeformula\stopformula
%D \setupformulas[align=middle]
%D \placeformula \startformula\fakeformula\stopformula
%D \setupformulas[align=right]
%D \placeformula \startformula\fakeformula\stopformula
%D \stopbuffer
%D
%D % {\getbuffer}
%D
%D This was keyed in as:
%D
%D \typebuffer
%D
%D When tracing is turned on (\type {\tracemathtrue}) you can
%D visualize the bounding box of the formula,
%D
%D % {\tracemathtrue\getbuffer}
%D
%D As you can see, the dimensions are the natural ones, but if
%D needed you can force a normalized line:
%D
%D \startbuffer
%D \setupformulas[strut=yes]
%D \placeformula \startformula \fakeformula \stopformula
%D \stopbuffer
%D
%D \typebuffer
%D
%D This time we get a more spacy result.
%D
%D % {\tracemathtrue\getbuffer}
%D
%D We will now show a couple of more settings and combinations
%D of settings. In centered formulas, the number takes no space
%D
%D \startbuffer
%D \setupformulas[align=middle]
%D \startformula \fakeformula \stopformula
%D \placeformula \startformula \fakeformula \stopformula
%D \stopbuffer
%D
%D \typebuffer % {\tracemathtrue\getbuffer}
%D
%D You can influence the placement of the whole box with the
%D parameters \type {leftmargin} and \type {rightmargin}.
%D
%D \startbuffer
%D \setupformulas[align=right,leftmargin=3em]
%D \startformula \fakeformula \stopformula
%D \placeformula \startformula \fakeformula \stopformula
%D
%D \setupformulas[align=left,rightmargin=1em]
%D \startformula \fakeformula \stopformula
%D \placeformula \startformula \fakeformula \stopformula
%D \stopbuffer
%D
%D \typebuffer % {\tracemathtrue\getbuffer}
%D
%D You can also inherit the margin from the environment.
%D
%D \startbuffer
%D \setupformulas[align=right,margin=standard]
%D \startformula \fakeformula \stopformula
%D \placeformula \startformula \fakeformula \stopformula
%D \stopbuffer
%D
%D \typebuffer % {\tracemathtrue\getbuffer}
%D
%D The distance between the formula and the number is only
%D applied when the formula is left or right aligned.
%D
%D \startbuffer
%D \setupformulas[align=left,distance=2em]
%D \startformula \fakeformula \stopformula
%D \placeformula \startformula \fakeformula \stopformula
%D \stopbuffer
%D
%D \typebuffer % {\tracemathtrue\getbuffer}

%D \macros
%D   {big..}
%D
%D Because they are related to the bodyfontsize, we redefine
%D some \PLAIN\ macros.

\def\@@dobig#1#2%
  {{\hbox{$\left#2\vbox\!!to#1\bodyfontsize{}\right.\n@space$}}}

\def\big {\@@dobig{0.85}}
\def\Big {\@@dobig{1.15}}
\def\bigg{\@@dobig{1.45}}
\def\Bigg{\@@dobig{1.75}}

%D \macros
%D   {bordermatrix}
%D
%D We already redefined \type {\bordermatrix} in \type
%D {font-ini}.

%D \macros
%D   {setuptextformulas}
%D
%D This command sets up in||line math. Most features deals
%D with grid snapping and are experimental.

\newevery \everysetuptextformulas \relax

\def\setuptextformulas
  {\dosingleempty\dosetuptextformulas}

\def\dosetuptextformulas[#1]%
  {\getparameters[\??mt][#1]%
   \the\everysetuptextformulas}

%D \macros
%D   {super, sub}
%D
%D \TEX\ uses \type{^} and \type{_} for entering super- and
%D subscript mode. We want however a bit more control than
%D normally provided, and therefore provide \type {\super}
%D and \type{sub}.

\global\let\normalsuper=^
\global\let\normalsuber=_

\newcount\supersubmode

\newevery\everysupersub \EverySuperSub

\appendtoks \advance\supersubmode \plusone \to \everysupersub

% \def\dodosuper#1{\normalsuper{\the\everysupersub#1}}
% \def\dodosuber#1{\normalsuber{\the\everysupersub#1}}
%
% \def\dosuper{\ifx\next\bgroup\expandafter\dodosuper\else\normalsuper\fi}
% \def\dosuber{\ifx\next\bgroup\expandafter\dodosuber\else\normalsuber\fi}
%
% \def\super{\futurelet\next\dosuper}
% \def\suber{\futurelet\next\dosuber}
%
% \def\super#1{\normalsuper{\the\everysupersub#1}}
% \def\suber#1{\normalsuber{\the\everysupersub#1}}

\appendtoks
  \gridsupsubstyle
\to \everysupersub

\appendtoks
  \doifelse\@@mtsize\v!small
    {\let\gridsupsubstyle    \scriptscriptstyle
     \let\gridsupsubbodyfont \setsmallbodyfont}%
    {\let\gridsupsubstyle    \scriptstyle
     \let\gridsupsubbodyfont \relax}%
\to \everysetuptextformulas

\setuptextformulas
  [\c!size=\v!normal]

\def\dogridsupsub#1#2%
  {\begingroup
   \setbox\nextbox\iftracegridsnapping\ruledhbox\else\hbox\fi
     {\gridsupsubbodyfont
      $\strut^{\the\everysupersub#1}_{\the\everysupersub#2}$}%
   \nextboxht\strutheight
   \nextboxdp\strutdepth
   \flushnextbox
   \endgroup}

\def\gridsupsub
  {\ifconditional\crazymathsnapping
     \ifgridsnapping
       \@EAEAEA\dogridsupsub
     \else
       \@EAEAEA\normalsupsub
     \fi
   \else
     \@EA\normalsupsub
   \fi}

\def\normalsupsub#1#2%
  {^{\the\everysupersub#1}_{\the\everysupersub#2}}

\appendtoks
  \let\gridsupsubstyle   \relax
  \let\gridsupsubbodyfont\relax
  \let\gridsupsub        \normalsupsub
\to \everydisplay

\def\super#1{^{\the\everysupersub#1}}
\def\suber#1{_{\the\everysupersub#1}}
\def\supsub#1#2{\super{#1}\suber{#2}}
\def\subsup#1#2{\suber{#1}\super{#2}}

%\def\super#1{\gridsupsub{#1}{}} %
%\def\suber#1{\gridsupsub{}{#1}} %
%
%\def\supsub#1#2{\gridsupsub{#1}{#2}}
%\def\subsup#1#2{\gridsupsub{#2}{#1}}

\def\gridsuper#1{\gridsupsub{#1}{}}
\def\gridsuber#1{\gridsupsub{}{#1}}

% \let\sup\super % math char
% \let\sub\suber

% test set:
%
% \startbuffer
% \sform{x\frac{1}{2}}
% \sform{x\sup{\frac{1}{2}} + x\sup{2} + 2}
% \sform{x\supsub{\frac{1}{2}}{\frac{1}{2}} + x\sup{2} + 2}
% \stopbuffer
%
% \typebuffer
%
% \startlines
% \getbuffer
% \stoplines
%
% \startbuffer
% $x\frac{1}{2}$
% $x\sup{\frac{1}{2}} + x^2 + 2$
% $x\supsub{\frac{1}{2}}{\frac{1}{2}} + x^2 + 2$
% \stopbuffer
%
% \typebuffer
%
% \start
% \enablesupersub
% \enableautomath
% \startlines
% \getbuffer
% \stoplines
% \stop

%D \macros
%D   {enablesupersub,enablesimplesupersub}
%D
%D We can let \type {^} and \type {_} act like \type {\super}
%D and \type {\sub} by saying \type {\enablesupersub}.

\bgroup
\catcode`\^=\@@active
\catcode`\_=\@@active
\gdef\enablesupersub
  {\catcode`\^=\@@active
   \def^{\ifmmode\expandafter\super\else\expandafter\normalsuper\fi}%
   \catcode`\_=\@@active
   \def_{\ifmmode\expandafter\suber\else\expandafter\normalsuber\fi}}
\egroup
%D \macros
%D   {enableautomath}
%D
%D The next one can be dangerous, but handy in controlled
%D situations.

\bgroup \catcode`\$=\active

\gdef\enableautomath
  {\catcode`\$=\active
   \def$##1${\snappedinlineformula{##1}}}

% \gdef\enableautomath
%   {\catcode`\$=\active
%    \def${\doifnextcharelse$\doautodmath\doautoimath}%
%    \def\doautoimath##1${\snappedinlineformula{##1}}%
%    \def\doautodmath$##1$${\startformula##1\stopformula}}

\egroup

%D \macros
%D   {...}
%D
%D New and experimental: snapping big inline math!

\newconditional\halfcrazymathlines % \settrue\halfcrazymathlines
\newconditional\crazymathsnapping  % \settrue\crazymathsnapping

% \appendtoks
%  \doifelse\@@mtgrid\v!ja
%    {\settrue \crazymathsnapping }{\setfalse\crazymathsnapping}%
%  \doifelse\@@mtstap\v!halveregel
%    {\settrue \halfcrazymathlines}{\setfalse\halfcrazymathlines}%
% \to \everysetuptextformulas

\appendtoks
 \doifelse\@@mtgrid\v!yes        \settrue\setfalse\crazymathsnapping
 \doifelse\@@mtstep\v!halfline\settrue\setfalse\halfcrazymathlines
\to \everysetuptextformulas

\setuptextformulas
  [\c!grid=\v!yes,
   \c!step=\v!line]

\newcount\crazymathhack

\let\lastcrazymathline     \!!zeropoint
\let\lastcrazymathpage     \!!zerocount
\let\lastcrazymathprelines \!!zerocount
\let\lastcrazymathpostlines\!!zerocount

\def\crazymathtag{amh:\the\crazymathhack}
\def\crazytexttag{\v!text:\lastcrazymathpage}

\def\crazymathindent{\hskip\MPx\crazymathtag\hskip-\MPx\crazytexttag}

\def\flushcrazymathbox
  {\nextboxht\strutheight
   \nextboxdp\strutdepth
   \hbox{\iftracegridsnapping\ruledhbox\fi{\flushnextbox}}}

% possible pdftex bug:
%
% \dorecurse{100}{gest \vadjust     {\strut} \par} \page
% \dorecurse{100}{gest \vadjust pre {\strut} \par} \page
%
% duplicate depth compensation with pre

\def\snappedinlineformula
  {\dosingleempty\dosnappedinlineformula}

%D \starttabulate[|Tl|l|]
%D \NC - \NC half lines        \NC \NR
%D \NC + \NC full lines        \NC \NR
%D \NC = \NC force             \NC \NR
%D \NC < \NC force, minus pre  \NC \NR
%D \NC > \NC force, minus post \NC \NR
%D \stoptabulate

\newif\if!!donee
\newif\if!!donef

\def\inlinemathmargin{1pt}

\settrue\autocrazymathsnapping

% FROM NOW ON, CHANGES AS OPTIONS

% TODO: SKYLINE (PREV LINE POS SCAN)

\def\dosnappedinlineformula[#1]#2%
  {\ifvmode\dontleavehmode\fi % tricky
   \strut % prevents funny space at line break
   \begingroup % interesting: \bgroup can make \vadjust disappear
   \ifconditional\crazymathsnapping
     \ifgridsnapping
       \ifx\pdftexversion\undefined
         \donefalse
       \else
         \checktextbackgrounds % we need pos tracking, to be made less redundant
         \donetrue
       \fi
     \else
       \donefalse
     \fi
   \else
     \donefalse
   \fi
   \!!doneafalse % forced or not auto
   \!!donebfalse % too heigh
   \!!donecfalse % too low
   \!!donedfalse % less before
   \!!doneefalse % less after
   \ifdone
     \setbox\nextbox\hbox{$#2$}%
     \iftracegridsnapping
       \setbox\nextbox\ruledhbox
         {\incolortrue\localcolortrue
          \backgroundline[gray]{\showstruts\strut\flushnextbox}}%
     \fi
     \def\docommando##1%
       {\doif{##1}-{\settrue \halfcrazymathlines}%
        \doif{##1}+{\setfalse\halfcrazymathlines}%
        \doif{##1}={\!!doneatrue}%
        \doif{##1}<{\!!donedtrue}%
        \doif{##1}>{\!!doneetrue}}%
     \processcommalist[#1]\docommando
\if!!doneb
  \if!!donec \else
    \setfalse\halfcrazymathlines
  \fi
\else
  \if!!donec
    \setfalse\halfcrazymathlines
  \fi
\fi
     \donefalse
     \if!!donea
       \donetrue
\scratchdimen \nextboxht
\advance\scratchdimen .5\lineheight
\nextboxht\scratchdimen
\scratchdimen \nextboxdp
\advance\scratchdimen .5\lineheight
\nextboxdp\scratchdimen
     \else\ifdim\nextboxht>\strutht
       \donetrue
     \else\ifdim\nextboxdp>\strutdp
       \donetrue
     \fi\fi\fi
     \ifconditional\autocrazymathsnapping \else \if!!donea \else
       % don't compensate, just snap to strut
       \donefalse
       % signal for next else, snap line to strut
       \!!doneatrue
     \fi \fi
   \fi
   \ifdone
     % analyze height
     \scratchdimen\inlinemathmargin
     \advance\scratchdimen \strutht
     \ifdim\nextboxht<\scratchdimen \else \!!donebtrue \fi
     % analyze depth
     \scratchdimen\inlinemathmargin
     \advance\scratchdimen \strutdp
     \ifdim\nextboxdp<\scratchdimen \else \!!donectrue \fi
     % analyzed or forced
     \ifdone
       \global\advance\crazymathhack\plusone
       \donefalse
       \ifnum\MPp\crazymathtag=\lastcrazymathpage\relax
         \ifdim\MPy\crazymathtag=\lastcrazymathline\relax
           \donetrue
         \fi
       \fi
       \ifnum\MPp\crazymathtag=\zerocount \donefalse \fi
       \ifdim\MPy\crazymathtag=\zeropoint \donefalse \fi
       \ifdone
         % same page and same line
       \else
         \global\let\lastcrazymathprelines \!!zerocount
         \global\let\lastcrazymathpostlines\!!zerocount
         \xdef\lastcrazymathpage{\MPp\crazymathtag}%
         \xdef\lastcrazymathline{\MPy\crazymathtag}%
       \fi
       \if!!doneb
       % \getrawnoflines\nextboxht
         \scratchdimen\nextboxht
         \advance\scratchdimen-\strutht
         \getnoflines\scratchdimen
         \if!!doned \advance\noflines\minusone \fi
         \scratchcounter\noflines
         \advance\noflines-\lastcrazymathprelines\relax
         \ifnum\noflines>\zerocount
           \xdef\lastcrazymathprelines{\the\scratchcounter}%
           \scratchdimen\noflines\lineheight
           \ifconditional\halfcrazymathlines
             \advance\scratchdimen-.5\lineheight
           \fi
           \advance\scratchdimen-\strutdepth
           \setbox\scratchbox\null
           \wd\scratchbox2\bodyfontsize
           \ht\scratchbox\scratchdimen
           \dp\scratchbox\strutdepth
           %%% top correction code (see below)
           \normalvadjust pre
             {%\allowbreak % sometimes breaks spacing
              \forgetall
              \crazymathindent
              \iftracegridsnapping
                \setbox\scratchbox\hbox
                  {\incolortrue\localcolortrue\green
                   \ruledhbox{\box\scratchbox}}%
              \fi
              \box\scratchbox
              \endgraf
              \nobreak}%
         \else\ifnum\scratchcounter>\zerocount
           \normalvadjust pre
             {\nobreak}%
         \fi\fi
       \fi
       \if!!donec
       % \getrawnoflines\nextboxdp
         \scratchdimen\nextboxdp
         \advance\scratchdimen-\strutdp
         \getnoflines\scratchdimen
         \if!!donee \advance\noflines\minusone \fi
         \scratchcounter\noflines
         \advance\noflines-\lastcrazymathpostlines\relax
         \ifnum\noflines>\zerocount
           \donetrue
         \else\ifnum\lastcrazymathpostlines=\zerocount
           \donetrue
         \else
           \donefalse
         \fi\fi
       \else
         \donefalse
       \fi
       \ifdone
         \xdef\lastcrazymathpostlines{\the\scratchcounter}%
         \ifnum\lastcrazymathpostlines=\zerocount
           \global\let\lastcrazymathpostlines\!!plusone
         \fi
         \hbox{\setposition\crazymathtag\flushcrazymathbox}%
         \scratchdimen\noflines\lineheight
         \advance\scratchdimen-\lineheight
         \advance\scratchdimen+\strutheight
\ifdim\scratchdimen>\zeropoint \else
  \scratchdimen=\strutheight % todo : test for half lines
\fi
         \ifconditional\halfcrazymathlines
           \advance\scratchdimen-.5\lineheight
         \fi
         \setbox\scratchbox\null
         \wd\scratchbox2\bodyfontsize
         \ht\scratchbox\scratchdimen
         \dp\scratchbox\strutdepth
         \normalvadjust
           {\forgetall
            \crazymathindent
            \iftracegridsnapping
              \setbox\scratchbox\hbox
                {\incolortrue\localcolortrue\blue
                 \ruledhbox{\box\scratchbox}}%
            \fi
            \box\scratchbox
            \endgraf
            % precaution: else we stick below the text bottom
            \ifconditional\halfcrazymathlines
              \allowbreak
            \else
              \vskip-\lineheight
              \vskip \lineheight
           \fi}%
       \else
         \hbox{\setposition\crazymathtag\flushcrazymathbox}%
       \fi
     \else
       \flushcrazymathbox
     \fi
   \else\if!!donea
     \flushcrazymathbox
   \else
     \mathematics{#2}%
   \fi\fi
   \endgroup}


%%% top correction code
%%%
%%% correct for fuzzy top of page situations
%
% \scratchdimen\lastcrazymathprelines\lineheight
% \advance\scratchdimen\MPy\crazymathtag
% \advance\scratchdimen\lineheight
% \advance\scratchdimen\topskip
% \advance\scratchdimen-\strutheight
% \dimen0=\MPy\crazytexttag
% \advance\dimen0 \MPh\crazytexttag
% \advance\scratchdimen-\dimen0\relax
% % do we need correction at all
% \ifdim\scratchdimen>\strutdepth\relax
%   \donefalse
% \else\ifdim\scratchdimen<\zeropoint
%   \donefalse
% \else
%   \donetrue
% \fi\fi
% % analysis done
% \donefalse
% \ifdone
%   \edef\crazymathcorrection{\the\scratchdimen}%
%   \advance\scratchdimen-\dp\scratchbox
%   \dp\scratchbox-\scratchdimen
% \else
%   \let\crazymathcorrection\zeropoint
% \fi
%
%%%
%%% keep the previous code
%%%

\let\tform\mathematics
\let\gform\snappedinlineformula

% test set:
%
% \startbuffer
% Crazy math \gform {1+x} or \gform {\dorecurse {100} {1+} 1 =
% 101} and even gore crazy \gform {2^{2^2}_{1_1}}
% again\dorecurse {20} { and again} \gform {\sqrt {\frac
% {x^{5^5}} {\frac {1} {2}}}} even gore\dorecurse {50} { and
% gore} \tform {\dorecurse {12} {\gform {\sqrt {\frac
% {x^{5^5}} {3}}}+\gform {\sqrt {\frac {x^{5^5}} {\frac {1}
% {2}}}}+}x=10}\dorecurse{20} { super crazy math}: \tform
% {\dorecurse {30} {\gform {\sqrt {\frac {x^{5^5}} {3}}}+
% \gform {\sqrt {\frac {x^{5^5}} {\frac {1} {2}}}}+ }x = 10},
% and we're\dorecurse {20} { done}!
% \stopbuffer
%
% \setupcolors[state=start] \setuppapersize[S6][S6]
%
% \showgrid \tracegridsnappingtrue \showstruts
%
% \starttext
% \setuplayout[grid=yes,lines=15]\getbuffer \page
% \setuplayout[grid=yes,lines=16]\getbuffer \page
% \setuplayout[grid=yes,lines=17]\getbuffer \page
% \setuplayout[grid=yes,lines=18]\getbuffer \page
% \setuplayout[grid=yes,lines=19]\getbuffer \page
% \stoptext
%
% test
%
% \startregels
% \gform[<]{35 \cdot p^{\frac{3}{4}} = 70}
% \gform{12{,}4 \cdot d^3 = 200}
% \gform{a \cdot x^b}.
% \gform{12x^6 \cdot \negative 3x^4}
% \gform{\frac{12x^6}{\negative 3x^4}}
% \gform{(4x^2)^3}
% \gform{4x \sqrt{x} \cdot 3x^2}
% \gform{\frac{2x^4}{4x \sqrt{x}}}
% \gform{y = a \cdot x^b}.
% \gform{y_1 = \frac{15x^2}{x}}
% \gform{y_2 = x \cdot \sqrt{x}}
% \gform{y_3 = \frac{6x^3}{x^2}}
% \gform[<]{y_4 = \left(2x^2\right)^{\frac{1}{2}}}
% \gform{y_1 = \frac{4x^5}{x^2}}
% \gform{y_2 = 4 \cdot \sqrt{x}}
% \gform{y_3 = 4x^3}
% \gform{y_4 = \frac{100x}{\sqrt{x}}}
% \gform[<]{y_5 = 4 \cdot x^{\frac{1}{2}}}
% \gform{y_6 = \frac{1}{2} x \cdot 4x^2}
% \gform{y_7 = 2 \cdot x^3}
% \gform{y_8 = 100 \cdot x^{\frac{1}{2}}}
% \gform{4x^8 \cdot 8x^3}
% \gform{\frac{4x^8}{8x^3}}
% \gform{\left(\negative3x^4\right)^3}
% \gform{x^3 \sqrt{x} \cdot 3x^2}
% \gform{\frac{6x^3}{x^2 \sqrt{x}}}
% \gform{\frac{6}{2x^4}}
% \gform{\frac{1}{3x^6}}
% \gform{\frac{12x^8}{4x^{10}}}
% \gform{\frac{4}{\sqrt{x}}}
% \gform{\frac{1}{2x \sqrt{x}}}
% \gform{\frac{2{,}25}{p} = 0{,}35}
% \gform{4{,}50 + \frac{300}{k} = 4{,}70}
% \gform{\frac{1200}{k+12} - 42 = 6}
% \stopregels

%D \macros
%D   {restoremathstyle}
%D
%D We can pick up the current math style by calling \type
%D {\restoremathstyle}.

\def\restoremathstyle
  {\ifmmode
     \ifcase\supersubmode
       \textstyle
     \or
       \scriptstyle
     \else
       \scriptscriptstyle
     \fi
   \fi}

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

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

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

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

\def\domathtext#1%
  {\mathchoice
     {\dodomathtext\displaystyle\textface        {#1}}%
     {\dodomathtext\textstyle   \textface        {#1}}%
     {\dodomathtext\textstyle   \scriptface      {#1}}%
     {\dodomathtext\textstyle   \scriptscriptface{#1}}}

\def\dodomathtext#1#2#3% no \everymath !
 %{\hbox{\everymath{#1}\switchtobodyfont  [#2]#3}} % 15 sec
  {\hbox{\everymath{#1}\setcurrentfontbody{#2}#3}} %  3 sec (no math)

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

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

%D \macros
%D   {frac, xfrac, xxfrac}
%D
%D This is another one Tobias asked for. It replaces the
%D primitive \type {\over}. We also take the opportunity to
%D handle math style restoring, which makes sure units and
%D chemicals come out ok.
%D
%D \starttyping
%D \def\frac#1#2%
%D   {\relax
%D    \ifmmode
%D       {{\mathstyle{#1}}\over{\mathstyle{#2}}}%
%D    \else
%D       $\frac{#1}{#2}$%
%D    \fi}
%D \stoptyping
%D
%D Better is:
%D
%D \starttyping
%D \def\frac#1#2%
%D   {\relax\mathematics{{{\mathstyle{#1}}\over{\mathstyle{#2}}}}}
%D \stoptyping
%D
%D The \type {\frac} macro kind of replaces the awkward \type
%D {\over} primitive. Say that we have the following formulas:
%D
%D \startbuffer[sample]
%D test $\frac  {1}{2}$ test $$1 + \frac  {1}{2} = 1.5$$
%D test $\xfrac {1}{2}$ test $$1 + \xfrac {1}{2} = 1.5$$
%D test $\xxfrac{1}{2}$ test $$1 + \xxfrac{1}{2} = 1.5$$
%D \stopbuffer
%D
%D \typebuffer[sample]
%D
%D With the most straightforward definitions, we get:
%D
%D \startbuffer[code]
%D \def\dofrac#1#2#3{\relax\mathematics{{{#1{#2}}\over{#1{#3}}}}}
%D
%D \def\frac  {\dofrac\mathstyle}
%D \def\xfrac {\dofrac\scriptstyle}
%D \def\xxfrac{\dofrac\scriptscriptstyle}
%D \stopbuffer
%D
%D \typebuffer[code] \getbuffer[code,sample]
%D
%D Since this does not work well, we can try:
%D
%D \startbuffer[code]
%D \def\xfrac #1#2{\hbox{$\dofrac\scriptstyle      {#1}{#2}$}}
%D \def\xxfrac#1#2{\hbox{$\dofrac\scriptscriptstyle{#1}{#2}$}}
%D \stopbuffer
%D
%D \typebuffer[code] \getbuffer[code,sample]
%D
%D This for sure looks better than:
%D
%D \startbuffer[code]
%D \def\xfrac #1#2{{\scriptstyle      \dofrac\relax{#1}{#2}}}
%D \def\xxfrac#1#2{{\scriptscriptstyle\dofrac\relax{#1}{#2}}}
%D \stopbuffer
%D
%D \typebuffer[code] \getbuffer[code,sample]
%D
%D So we stick to the next definitions (watch the local
%D overloading of \type {\xfrac}).

\def\dofrac#1#2#3{\relax\mathematics{{{#1{#2}}\over{#1{#3}}}}}

\def\frac      {\dofrac\mathstyle}
\def\xfrac #1#2{\begingroup
                \let\xfrac\xxfrac
                \dofrac\scriptstyle{#1}{#2}%
                \endgroup}
\def\xxfrac#1#2{\begingroup
                \dofrac\scriptscriptstyle{#1}{#2}%
                \endgroup}

%D The \type {xx} variant looks still ugly, so maybe it's
%D best to say:

\def\xxfrac#1#2{\begingroup
                \dofrac\scriptscriptstyle
                  {#1}{\raise.25ex\hbox{$\scriptscriptstyle#2$}}%
                \endgroup}

%D Something low level for scientific calculator notation:

\def\scinot#1#2%
  {#1\times10^{#2}}

%D The next macro, \type {\ch}, is \PPCHTEX\ aware. In
%D formulas one can therefore best use \type {\ch} instead of
%D \type {\chemical}, especially in fractions.

\ifx\mathstyle\undefined
  \let\mathstyle\relax
\fi

\def\ch#1%
  {\ifx\@@chemicalletter\undefined
     \mathstyle{\rm#1}%
   \else
     \dosetsubscripts
     \mathstyle{\@@chemicalletter{#1}}%
     \doresetsubscripts
   \fi}

%D \macros
%D   {/}
%D
%D Just to be sure, we restore the behavior of some typical
%D math characters.

\bgroup

\catcode`\/=\@@other    \global           \let\normalforwardslash/
\catcode`\/=\@@active \doglobal\appendtoks\let/\normalforwardslash\to\everymathematics

\egroup

%D These macros were first needed by Frits Spijker (also
%D known as Gajes) for typesetting the minus sign that is
%D keyed into scientific calculators.

% This is the first alternative, which works okay for the
% minus, but less for the plus.
%
% \def\dodoraisedmathord#1#2#3%
%   {\mathord{{#2\raise.#1ex\hbox{#2#3}}}}
%
% \def\doraisedmathord#1%
%   {\mathchoice
%      {\dodoraisedmathord5\tf  #1}%
%      {\dodoraisedmathord5\tf  #1}%
%      {\dodoraisedmathord4\tfx #1}%
%      {\dodoraisedmathord3\tfxx#1}}
%
% \def\negative{\doraisedmathord-}
% \def\positive{\doraisedmathord+}
%
% So, now we use the monospaced signs, that we also
% define as symbol, so that they can be overloaded.

\def\dodoraisedmathord#1#2#3%
  {\mathord{{#2\raise.#1ex\hbox{#2\symbol[#3]}}}}

\def\doraisedmathord#1%
  {\mathchoice
     {\dodoraisedmathord5\tf {#1}}%
     {\dodoraisedmathord5\tf {#1}}%
     {\dodoraisedmathord4\tx {#1}}%
     {\dodoraisedmathord3\txx{#1}}}

\def\dodonumbermathord#1#2%
  {\setbox\scratchbox\hbox{0}%
   \mathord{\hbox to \wd\scratchbox{\hss#1\symbol[#2]\hss}}}

\def\donumbermathord#1%
  {\mathchoice
     {\dodonumbermathord\tf {#1}}%
     {\dodonumbermathord\tf {#1}}%
     {\dodonumbermathord\tx {#1}}%
     {\dodonumbermathord\txx{#1}}}

\definesymbol[positive]  [\getglyph{Mono}{+}]
\definesymbol[negative]  [\getglyph{Mono}{-}]
\definesymbol[zeroamount][\getglyph{Mono}{-}]

\def\negative  {\doraisedmathord{negative}}
\def\positive  {\doraisedmathord{positive}}
\def\zeroamount{\donumbermathord{zeroamount}}

%D How negative such a symbol looks is demonstrated in:
%D $\negative 10^{\negative 10^{\negative 10}}$.

\setupformulas
  [\c!way=\@@nrway,
   \c!blockway=,
   \c!sectionnumber=\@@nrsectionnumber,
   \c!location=\v!right,
   \c!left=(,
   \c!right=),
   \c!numberstyle=,
   \c!numbercolor=,
   \c!numbercommand=,
   \c!spacebefore=\v!big,
   \c!spaceafter=\@@fmspacebefore,
   \c!grid=]

\protect \endinput
