%D \module
%D   [       file=math-ext,
%D        version=2006.01.14,
%D          title=\CONTEXT\ Math Macros,
%D       subtitle=Extra Macros,
%D         author={Hans Hagen \& Taco Hoekwater \& Aditya Mahajan},
%D           date=\currentdate,
%D      copyright=\PRAGMA]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

\unprotect

%D These will be generalized!

\def\exmthfont#1{\symbolicsizedfont#1\plusone{MathExtension}}

\def\domthfrac#1#2#3#4#5#6#7%
  {\begingroup
   \mathsurround\zeropoint
   \setbox0\hbox{$#1 #6$}%
   \setbox2\hbox{$#1 #7$}%
   \dimen0\wd0
   \ifdim\wd2>\dimen0 \dimen0\wd2 \fi
   \setbox4\hbox to \dimen0{\exmthfont#2#3\leaders\hbox{#4}\hss#5}%
   \mathord{\vcenter{{\offinterlineskip
     \hbox to \dimen0{\hss\box0\hss}%
     \kern \ht4%
     \hbox to \dimen0{\hss\copy4\hss}%
     \kern \ht4%
     \hbox to \dimen0{\hss\box2\hss}}}}%
   \endgroup}

\def\domthsqrt#1#2#3#4#5%
  {\begingroup
   \mathsurround\zeropoint
   \setbox0\hbox{$#1 #5$}%
   \dimen0=1.05\ht0 \advance\dimen0 1pt  \ht0 \dimen0
   \dimen0=1.05\dp0 \advance\dimen0 1pt  \dp0 \dimen0
   \dimen0\wd0
   \setbox4\hbox to \dimen0{\exmthfont#2\leaders\hbox{#3}\hfill#4}%
   \delimitershortfall=0pt
   \nulldelimiterspace=0pt
   \setbox2\hbox{$\left\delimiter"0270370 \vrule height\ht0 depth \dp0 width0pt
                  \right.$}%
   \mathord{\vcenter{\hbox{\copy2
                           \rlap{\raise\dimexpr\ht2-\ht4\relax\copy4}\copy0}}}%
   \endgroup}

\def\mthfrac#1#2#3#4#5{\mathchoice
  {\domthfrac\displaystyle     \textface        {#1}{#2}{#3}{#4}{#5}}
  {\domthfrac\textstyle        \textface        {#1}{#2}{#3}{#4}{#5}}
  {\domthfrac\scriptstyle      \scriptface      {#1}{#2}{#3}{#4}{#5}}
  {\domthfrac\scriptscriptstyle\scriptscriptface{#1}{#2}{#3}{#4}{#5}}}

\def\mthsqrt#1#2#3{\mathchoice
  {\domthsqrt\displaystyle     \textface    {#1}{#2}{#3}}
  {\domthsqrt\textstyle        \textface    {#1}{#2}{#3}}
  {\domthsqrt\scriptstyle      \textface    {#1}{#2}{#3}}
  {\domthsqrt\scriptscriptstyle\textface    {#1}{#2}{#3}}}

% temp here

%D We next define extensible arrows. Extensible arrows are arrows that change
%D their length accoding to the width of the text to be placed above and below
%D the arrow. Since we need to define a lot of arrows, we first define some
%D helper macros. The basic idea is to measure the width of the box to be
%D placed above and below the arrow, and make the \quotation{body} of the
%D arrow as long as the bigger of the two widths.

\def\mtharrfactor{1}
\def\mtharrextra {0}

\def\domthxarr#1#2#3#4#5% hm, looks like we do a double mathrel
  {\begingroup
   \def\mtharrfactor{1}%
   \def\mtharrextra {0}%
   \processaction[#1] % will be sped up
     [  \v!none=>\def\mtharrfactor{0},
       \v!small=>\def\mtharrextra{10},
      \v!medium=>\def\mtharrextra{15},
         \v!big=>\def\mtharrextra{20},
      \v!normal=>,
     \v!default=>,
     \v!unknown=>\doifnumberelse{#1}{\def\mtharrextra{#1}}\donothing]%
   \mathsurround\zeropoint
   \muskip0=\thirdoffourarguments  #2mu
   \muskip2=\fourthoffourarguments #2mu
   \muskip4=\firstoffourarguments  #2mu
   \muskip6=\secondoffourarguments #2mu
   \muskip0=\mtharrfactor\muskip0 \advance\muskip0 \mtharrextra mu
   \muskip2=\mtharrfactor\muskip2 \advance\muskip2 \mtharrextra mu
   \setbox0\hbox{$\scriptstyle
                  \mkern\muskip4\relax
                  \mkern\muskip0\relax
                  #5\relax
                  \mkern\muskip2\relax
                  \mkern\muskip6\relax
                 $}%
   \setbox4\hbox{#3}%
   \dimen0\wd0
   \ifdim\wd4>\dimen0 \dimen0\wd4 \fi
   \setbox2\hbox{$\scriptstyle
                  \mkern\muskip4\relax
                  \mkern\muskip0\relax
                  #4\relax
                  \mkern\muskip2\relax
                  \mkern\muskip6\relax
                 $}%
   \ifdim\wd2>\dimen0 \dimen0\wd2 \fi
   \setbox4\hbox to \dimen0{#3}%
   \mathrel{\mathop{\hbox to \dimen0{\hss\copy4\hss}}\limits^{\box0}_{\box2}}
   \endgroup}

\let\domthxarrsingle\domthxarr

%D There are some arrows which are created by stacking two arrows. The next
%D macro helps in defining such \quotation{double arrows}.

\def\domthxarrdouble#1#2#3#4#5#6#7% opt l r sp rs top bot
  {\mathrel
     {\scratchdimen.22ex\relax
      \setbox0\hbox{$\domthxarr{#1}{#2}{#4}{\phantom{#6}}{#7}$}%
      \setbox2\hbox{$\domthxarr{#1}{#3}{#5}{#6}{\phantom{#7}}$}%
      \raise\scratchdimen\box0
      \kern-\wd2
      \lower\scratchdimen\box2}}

%D \macros{definematharrow}
%D Macro for defining new arrows. We can define two types of arrows|<|single
%D arrows and double arrows. Single arrows are defined as
%D \starttyping
%D \definematharrow [xrightarrow]        [0359] [\rightarrowfill]
%D \stoptyping
%D The first argument is the name of the arrow (\tex{xrightarrow} in this case.)
%D The second argument consists of a set of 4 numbers and specify the spacing
%D correction in math units~\type{mu}. These numbers define:
%D \startlines
%D   1st number: arrow||tip correction
%D   2nd number: arrow||tip correction
%D   3rd number: space (multiplied by \tex{matharrfactor} and advanced by \tex{matharrextra})
%D   4th number: space (multiplied by \tex{matharrfactor} and advanced by \tex{matharrextra})
%D \stoplines
%D 
%D The third argument is the name of the extensible fill. The third argument
%D is optional when the arrow is redefined later (this is useful for font
%D specific tweaking of the skips.) For example,
%D \startbuffer
%D \math{\xrightarrow{above}}
%D \definematharrow[xrightarrow][0000]
%D \math{\xrightarrow{above}}
%D \definematharrow[xrightarrow][55{50}{50}]
%D \math{\xrightarrow{above}}
%D \stopbuffer
%D \typebuffer gives {\getbuffer}
%D
%D The double arrows are defined as follows
%D \starttyping
%D \definematharrow [xrightleftharpoons] [3095,0359] 
%D                  [\rightharpoonupfill,\leftharpoondownfill]
%D \stoptyping
%D The second and the third set of arguments consist of comma separated
%D values. The first element of the second argument (\type{3095}) corresponds
%D to the spacing correction of top arrow fill (\tex{rightarrowupfill}).
%D Similarly, \type{0359} corresponds to bottom arrow fill
%D \tex{leftharpoondownfill}). Stacking them on top of each other we get
%D $\xrightleftharpoons[big]{above}{below}$.
%D The following math arrows are defined
%D \midaligned{\starttable[|l|m|]
%D   \NC \tex{xrightarrow        }  \NC \xrightarrow        [big]  \NC \NR
%D   \NC \tex{xleftarrow         }  \NC \xleftarrow         [big]  \NC \NR
%D   \NC \tex{xequal             }  \NC \xequal             [big]  \NC \NR
%D   \NC \tex{xRightarrow        }  \NC \xRightarrow        [big]  \NC \NR
%D   \NC \tex{xLeftarrow         }  \NC \xLeftarrow         [big]  \NC \NR
%D   \NC \tex{xLeftrightarrow    }  \NC \xLeftrightarrow    [big]  \NC \NR
%D   \NC \tex{xleftrightarrow    }  \NC \xleftrightarrow    [big]  \NC \NR
%D   \NC \tex{xmapsto            }  \NC \xmapsto            [big]  \NC \NR
%D   \NC \tex{xtwoheadrightarrow }  \NC \xtwoheadrightarrow [big]  \NC \NR
%D   \NC \tex{xtwoheadleftarrow  }  \NC \xtwoheadleftarrow  [big]  \NC \NR
%D   \NC \tex{xrightharpoondown  }  \NC \xrightharpoondown  [big]  \NC \NR
%D   \NC \tex{xrightharpoonup    }  \NC \xrightharpoonup    [big]  \NC \NR
%D   \NC \tex{xleftharpoondown   }  \NC \xleftharpoondown   [big]  \NC \NR
%D   \NC \tex{xleftharpoonup     }  \NC \xleftharpoonup     [big]  \NC \NR
%D   \NC \tex{xhookleftarrow     }  \NC \xhookleftarrow     [big]  \NC \NR
%D   \NC \tex{xhookrightarrow    }  \NC \xhookrightarrow    [big]  \NC \NR
%D   \NC \tex{xleftrightharpoons }  \NC \xleftrightharpoons [big]  \NC \NR
%D   \NC \tex{xrightleftharpoons }  \NC \xrightleftharpoons [big]  \NC \NR
%D \stoptable}

\def\definematharrow
  {\doquadrupleargument\dodefinematharrow}

\def\dodefinematharrow[#1][#2][#3][#4]% name type[none|both] template command
  {\iffourthargument
      \executeifdefined{dodefine#2arrow}\gobblethreearguments{#1}{#3}{#4}%
   \else\ifthirdargument
      \dodefinebotharrow{#1}{#2}{#3}%
   \else\ifsecondargument
      \redefinebotharrow{#1}{#2}{#3}%
   \fi\fi\fi}

\def\redefinebotharrow#1#2#3% real dirty, this overload!
  {\doifdefined{#1}
     {\pushmacro\dohandlemtharrow
      \def\dohandlemtharrow[##1][##2]{\setvalue{#1}{\dohandlemtharrow[#2][##2]}}%
      % == \def\dohandlemtharrow[##1][##2]{\dodefinebotharrow{#1}{#2}{##2}}%
      \getvalue{#1}%
      \popmacro\dohandlemtharrow}}

\def\dodefinebotharrow#1#2#3%
  {\setvalue{#1}{\dohandlemtharrow[#2][#3]}}

\def\dohandlemtharrow
  {\dotripleempty\doxmtharrow}

\def\doxmtharrow[#1][#2][#3]% #3 == optional arg
  {\def\dodoxmtharrow{\dododoxmtharrow[#1,\empty,\empty][#2,\empty,\empty][#3]}% {##1}{##2}
   \dodoublegroupempty\dodoxmtharrow}

\def\dododoxmtharrow[#1,#2,#3][#4,#5,#6][#7]#8#9% [3] is the optional arg
  {\edef\!!stringa{#2}%
   \ifx\!!stringa\empty
     \ifsecondargument
       \mathrel{\domthxarrsingle{#7}{#1}{#4}{#8}{#9}}%
     \else
       \mathrel{\domthxarrsingle{#7}{#1}{#4}{}{#8}}%
     \fi
   \else
     \ifsecondargument
       \mathrel{\domthxarrdouble{#7}{#1}{#2}{#4}{#5}{#8}{#9}}%
     \else
       \mathrel{\domthxarrdouble{#7}{#1}{#2}{#4}{#5}{}{#8}}%
     \fi
   \fi}

% Adapted from amsmath.

%D \macros{mtharrowfill,defaultmtharrowfill}
%D To extend the arrows we need to define a \quotation{math arrow fill}. This
%D command takes 7 arguments: the first four correspond the second argument of
%D \tex{definematharrow} explained above. The other three specify the tail,
%D body and head of the arrow. \tex{defaultmtharrowfill} has values tweaked to
%D match latin modern fonts. For fonts that are significantly different (e.g.
%D cows) a different set of values need to be determined.

\def\mtharrowfill#1#2#3#4#5#6#7%
  {$\mathsurround 0pt
    \thickmuskip0mu\medmuskip\thickmuskip\thinmuskip\thickmuskip
    \relax#5%
    \mkern-#1mu
    \cleaders\hbox{$\mkern -#2mu#6\mkern -#3mu$}\hfill
    \mkern-#4mu#7$}

\def\defaultmtharrowfill{\mtharrowfill 7227}

%D We now define some arrow fills that will be used for defining the arrows.
%D \tex{leftarrowfill} and \tex{rightarrowfill} are redefined using \tex{defaultmtharrowfill}.

\def\rightarrowfill       {\defaultmtharrowfill \relbar              \relbar \rightarrow       }
\def\leftarrowfill        {\defaultmtharrowfill \leftarrow           \relbar \relbar           }
\def\equalfill            {\defaultmtharrowfill \Relbar              \Relbar \Relbar           }
\def\Rightarrowfill       {\defaultmtharrowfill \Relbar              \Relbar \Rightarrow       }
\def\Leftarrowfill        {\defaultmtharrowfill \Leftarrow           \Relbar \Relbar           }
\def\Leftrightarrowfill   {\defaultmtharrowfill \Leftarrow           \Relbar \Rightarrow       }
\def\leftrightarrowfill   {\defaultmtharrowfill \leftarrow           \relbar \rightarrow       }
\def\mapstofill           {\defaultmtharrowfill {\mapstochar\relbar} \relbar \rightarrow       }
\def\twoheadrightarrowfill{\defaultmtharrowfill \relbar              \relbar \twoheadrightarrow}
\def\twoheadleftarrowfill {\defaultmtharrowfill \twoheadleftarrow    \relbar \relbar           }
\def\rightharpoondownfill {\defaultmtharrowfill \relbar              \relbar \rightharpoondown }
\def\rightharpoonupfill   {\defaultmtharrowfill \relbar              \relbar \rightharpoonup   }
\def\leftharpoondownfill  {\defaultmtharrowfill \leftharpoondown     \relbar \relbar           }
\def\leftharpoonupfill    {\defaultmtharrowfill \leftharpoonup       \relbar \relbar           }

\def\hookleftfill {\defaultmtharrowfill \leftarrow            \relbar{\relbar\joinrel\rhook}}
\def\hookrightfill{\defaultmtharrowfill{\lhook\joinrel\relbar}\relbar \rightarrow}

%D Now we define most commonly used arrows. These include arrows defined in
%D \filename{amsmath.sty}, \filename{extarrows.sty}, \filename{extpfel.sty}
%D and mathtools.sty packages for \LATEX.

\definematharrow [xrightarrow]        [0359] [\rightarrowfill]
\definematharrow [xleftarrow]         [3095] [\leftarrowfill]
\definematharrow [xequal]             [0099] [\equalfill]
\definematharrow [xRightarrow]        [0359] [\Rightarrowfill]
\definematharrow [xLeftarrow]         [3095] [\Leftarrowfill]
\definematharrow [xLeftrightarrow]    [0099] [\Leftrightarrowfill]
\definematharrow [xleftrightarrow]    [0099] [\leftrightarrowfill]
\definematharrow [xmapsto]            [3599] [\mapstofill]
\definematharrow [xtwoheadrightarrow] [5009] [\twoheadrightarrowfill]
\definematharrow [xtwoheadleftarrow]  [0590] [\twoheadleftarrowfill]
\definematharrow [xrightharpoondown]  [0359] [\rightharpoondownfill]
\definematharrow [xrightharpoonup]    [0359] [\rightharpoonupfill]
\definematharrow [xleftharpoondown]   [3095] [\leftharpoondownfill]
\definematharrow [xleftharpoonup]     [3095] [\leftharpoonupfill]

\definematharrow [xleftrightharpoons] [3399,3399] [\leftharpoonupfill,\rightharpoondownfill]
\definematharrow [xrightleftharpoons] [3399,3399] [\rightharpoonupfill,\leftharpoondownfill]

\definematharrow [xhookleftarrow]  [3095] [\hookleftfill]
\definematharrow [xhookrightarrow] [0395] [\hookrightfill]

%D These arrows can be used as folows:
%D \startbuffer
%D \startformula \xrightarrow{stuff on top}\stopformula
%D \startformula \xrightarrow{}{stuff on top}\stopformula
%D \startformula \xrightarrow{stuff below}{}\stopformula
%D \startformula \xrightarrow{stuff below}{stuff on top}\stopformula
%D
%D \startformula \xleftarrow [none]{stuff below}{stuff on top}\stopformula
%D \startformula \xleftarrow [small]{stuff below}{stuff on top}\stopformula
%D \startformula \xleftarrow [medium]{stuff below}{stuff on top}\stopformula
%D \startformula \xleftarrow [big]{stuff below}{stuff on top}\stopformula
%D \stopbuffer
%D \typebuffer which gives \getbuffer

\protect \endinput
