%D \module
%D   [       file=math-rad,
%D        version=2013.07.13,
%D          title=\CONTEXT\ Math Macros,
%D       subtitle=Radicals,
%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 / Radicals}

\unprotect

%D \starttyping
%D $\sqrt[3]{10}$
%D \stoptyping
%D
%D This root command will be overloaded later:

%D Old stuff:

% \def\rootradical{\Uroot    0 "221A } % can be done in char-def
% \def\surdradical{\Uradical 0 "221A } % can be done in char-def

% \protected\def\sqrt{\doifelsenextoptionalcs\rootwithdegree\rootwithoutdegree} % will be redefined

% \permanent\protected\def\styledrootradical#1#2% so that \text works ok ... \rootradical behaves somewhat weird
%   {\normalexpanded{\math_radical_common
%      {\normalunexpanded{#1}}%
%      {\noexpand\triggermathstyle{\number\normalmathstyle}%
%       \normalunexpanded{#2}}}}

% experimental new keyword: (maybe keywords should come after the symbol)
%
% \permanent\protected\def\styledrootradical#1#2% so that \text works ok ... \rootradical behaves somewhat weird
%   {\Uroot style \normalmathstyle "0 "221A {#1}{#2}}

% \permanent\protected\def\rootwithdegree[#1]{\math_radical_common{#1}}
% \permanent\protected\def\rootwithoutdegree {\math_radical_common  {}}

%D Even older stuff:

% % is now a ordinary character
%
% \let\normalsurd\surd % \Uradical "0 "221A
% \permanent\protected\def\surd{\normalsurd{}}

%D The real thing. If needed one can control matters with one of the many
%D \type {\Umath...} parameters.
%D
%D \starttyping
%D \def\R {\Umathradicaldegreeafter\textstyle0pt}
%D \def\RR{\Umathradicaldegreeafter\textstyle\dimexpr
%D    \Umathradicaldegreeafter\textstyle+.1em\relax}
%D \def\RRR{\frozen\Umathradicaldegreeafter\textstyle\dimexpr
%D    \Umathradicaldegreeafter\textstyle+.2em\relax}
%D
%D $    \sqrt[3]{5}   \RR\sqrt[3]{5}  \sqrt[3]{5} $\par
%D $    \sqrt[3]{5} {\RRR\sqrt[3]{5}} \sqrt[3]{5} $\par
%D $ \RR\sqrt[3]{5} {\RRR\sqrt[3]{5}} \sqrt[3]{5} $\par
%D
%D \def\R  {\Umathradicaldegreeafter\textstyle
%D            0pt}
%D \def\RR {\Umathradicaldegreeafter\textstyle
%D            0.95\Umathradicaldegreeafter\textstyle}
%D \def\RRR{\frozen\Umathradicaldegreeafter\textstyle
%D            0.9\Umathradicaldegreeafter\textstyle}
%D
%D $    \sqrt[3]{5}   \RR\sqrt[3]{5}  \sqrt[3]{5} $\par
%D $    \sqrt[3]{5} {\RRR\sqrt[3]{5}} \sqrt[3]{5} $\par
%D $ \RR\sqrt[3]{5} {\RRR\sqrt[3]{5}} \sqrt[3]{5} $\par
%D
%D \def\RR {\mathopenupparameter\Umathradicaldegreeafter{.1}}
%D
%D $ \sqrt[3]{5}  \RR\sqrt[3]{5}  \sqrt[3]{5} $\par
%D $ \sqrt[3]{5} {\RR\sqrt[3]{5}} \sqrt[3]{5} $\par
%D \stoptyping
%D
%D And:
%D
%D \starttyping
%D \definemathradical[lsqrt][strut=yes]
%D \definemathradical[msqrt][strut=math]
%D \definemathradical[xsqrt][height=3ex,depth=2ex]
%D
%D $\sqrt[strut=no][3]{y}$
%D $\sqrt[strut=no,n=5]{y}$
%D $\sqrt[strut=no,n=5][6]{y}$
%D $\sqrt[strut=math]{y}$
%D $\sqrt[3]{y}$
%D \stoptyping

\installcorenamespace{mathradical}
\installcorenamespace{mathradicalalternative}

\installcommandhandler \??mathradical {mathradical} \??mathradical

\setupmathradical
  [\c!alternative=\v!normal,
   \c!mpoffset=.25\exheight,
   \c!height=\zeropoint,
   \c!depth=\zeropoint,
   \c!strut=\v!height,
 % \c!mindepth=\zeropoint,
   \c!mindepth=.20\exheight, % a reasonable default for: \im { \sqrt{1+x} + \sqrt{1-x} }
   \c!source=\zerocount,
   \c!left="221A,
   \c!mathstyle=\v!normal,
   \c!right=\zerocount,
   \c!leftmargin=\zeropoint,
   \c!rightmargin=\zeropoint]

\appendtoks
    \frozen\protected\instance\edefcsname\currentmathradical\endcsname{\math_radical_handle{\currentmathradical}}
\to \everydefinemathradical

\mutable\lettonothing\currentmathradical
\mutable\lettonothing\currentmathradicaldegree

\setmathignore\Umathradicaldegreebefore\plusone

\installcorenamespace{mathwhateverstrut}

\defcsname\??mathwhateverstrut\v!height\endcsname{\mathheightstrut}
\defcsname\??mathwhateverstrut\v!depth \endcsname{\mathdepthstrut}
\defcsname\??mathwhateverstrut\v!math  \endcsname{\mathstrut}
\defcsname\??mathwhateverstrut\v!yes   \endcsname{\strut}
%letcsname\??mathwhateverstrut\v!no    \endcsname\relax

\tolerant\protected\def\math_radical_handle#tag#*[#S#settings]#*[#degree]#:#body%
  {\begingroup
   \cdef\currentmathradical{#tag}%
   \ifhastok={#settings}%
     \lettonothing\currentmathradicaldegree
     \setupcurrentmathradical[#settings]%
     \ifparameter#degree\or
        \edef\currentmathradicaldegree{#degree}%
     \else
        \edef\currentmathradicaldegree{\mathradicalparameter\c!n}%
     \fi
   \else
     \edef\currentmathradicaldegree{#settings}%
   \fi
   \ifempty\currentmathradicaldegree
     \let\currentmathradicaldegree\m_math_no_degree
   \fi
   \ifcase\mathradicalparameter\c!right\else
     \let\currentmathradicaldegree\m_math_no_degree
   \fi
   \math_radical_alternative{%
     \begincsname\??mathwhateverstrut\mathradicalparameter\c!strut\endcsname
     \scratchdimen\mathradicalparameter\c!leftmargin \relax\ifzeropt\scratchdimen\else\kern\scratchdimen\fi
     #body%
     \scratchdimen\mathradicalparameter\c!rightmargin\relax\ifzeropt\scratchdimen\else\kern\scratchdimen\fi
   }%
   \endgroup}

\def\m_math_no_degree{{}}

% for every font
%
% \appendtoks
%    \Umathradicaldegreebefore\allmathstyles\zeropoint
% \to \everymathematics

% style width [options: left middle right]

%D \starttyping
%D \definemathradical[esqrt][sqrt][height=\maxdimen,depth=\maxdimen]
%D \definemathradical[fsqrt][sqrt][height=3ex,depth=2ex]
%D \definemathradical[ssqrt][sqrt][height=-.5pt,depth=-.5pt]
%D
%D \def\TestSqrt#1%
%D   {test $      #1{x}           + #1{\sin(x)}                         $ test\par
%D    test $      #1{x}           + #1{\sin(x)} + #1{\frac{1}{x}}       $ test\par
%D    test $      #1{x} + #1{x^2}                                       $ test\par
%D    test $\left(#1{x} + #1{x^2}                                \right)$ test\par}
%D
%D \TestSqrt\sqrt \blank % dynamic
%D \TestSqrt\esqrt\blank % equal
%D \TestSqrt\fsqrt\blank % fixed
%D \TestSqrt\ssqrt\blank % squeezed
%D \stoptyping

\def\math_radical_alternative{\csname\??mathradicalalternative\mathradicalparameter\c!alternative\endcsname}

% We use a strut in the degree because not all fonts have the right gaps set up but
% as struts are sort of predictable we can now fix all fonts in the lfg file.

\protected\def\math_radical_common#degree#body%
  {\scratchcounter\ifcstok{\mathradicalparameter\c!rule}\v!symbol
     \mathradicalparameter\c!top\relax
   \else
     \zerocount
   \fi
   \edef\xxx{\expandedmathstyleparameter\mathradicalparameter\c!mathstyle}
   \Urooted
     \s!height\dimexpr\ifcstok{\mathradicalparameter\c!height}\v!none\scaledpoint\else\mathradicalparameter\c!height\fi\relax
     \s!depth \dimexpr\ifcstok{\mathradicalparameter\c!depth }\v!none\scaledpoint\else\mathradicalparameter\c!depth \fi\relax
     \s!source\numexpr\namedboxanchor{\mathradicalparameter\c!source}\relax
     \s!style \normalmathstyle % not needed
     \ifzeronum\scratchcounter\else
       top % \s!top
     \fi
     \ifcstok{\mathradicalparameter\c!rule}\v!no
        norule
     \orelse\ifcstok{\lastnamedcs}\v!bottom
        reflected %
     \fi
     \zerocount \mathradicalparameter\c!left
     \zerocount \mathradicalparameter\c!right
     \ifzeronum\scratchcounter\else
        \zerocount\scratchcounter
     \fi
     \relax
   {\mathstrut#degree}%
   {% we need to also adapt the strut
    \expandedmathstyleparameter\mathradicalparameter\c!mathstyle
    #body}}

\protected\def\math_radical_mindepth
  {\scratchdepth\mathradicalparameter\c!mindepth\relax
   \ifzerodim\scratchdepth\else
     \srule \s!depth\scratchdepth\s!height\zeropoint\s!width\zeropoint\relax
   \fi}

\defcsname\??mathradicalalternative\v!default\endcsname#body%
  {\math_radical_common{\currentmathradicaldegree}{\math_radical_mindepth#body}}

\defcsname\??mathradicalalternative\v!normal\endcsname#body%
  {\edef\p_color{\mathradicalparameter\c!color}%
   \ifempty\p_color
     \math_radical_common{\currentmathradicaldegree}{\math_radical_mindepth#body}% {} really needed as \rootradical expands first
   \orelse\ifempty\currentmathradicaldegree
     \pushcolor[\p_color]%
     \math_radical_common{}%
     {\popcolor\math_radical_mindepth#body}%
   \else
     \pushcolor[\p_color]%
     \math_radical_common{\popcolor\currentmathradicaldegree\pushcolor[\p_color]}%
     {\popcolor\math_radical_mindepth#body}%
   \fi}

\startMPextensions
    vardef math_radical_simple(expr w,h,d,o) =
        (-h/2-o,h/2-o) --
        (-h/4-o,-d-o)  --
        (-o,h+o)       --
        (w+o,h+o)      --
        (w+o,h-h/10+o)
    enddef ;
\stopMPextensions

\startuniqueMPgraphic{minifun::math:radical:default}%{...}
    draw
        math_radical_simple(OverlayWidth,OverlayHeight,OverlayDepth,OverlayOffset)
      % withpen pencircle xscaled (2OverlayLineWidth) yscaled (3OverlayLineWidth/4) rotated 30
        withpen pencircle scaled OverlayLineWidth
      % dashed evenly
        withcolor OverlayLineColor ;
\stopuniqueMPgraphic

% todo: spacing .. this is just an experiment (article driven)

\defcsname\??mathradicalalternative\v!mp\endcsname#body% we could use dowithnextbox
  {\begingroup
   \scratchoffset\mathradicalparameter\c!mpoffset
   \setbox\nextbox\mathstylehbox{#body}%
   % we use the \overlay variables as these are passes anyway and
   % it's more efficient than using parameters
   \d_overlay_width    \wd\nextbox
   \d_overlay_height   \ht\nextbox
   \d_overlay_depth    \dp\nextbox
   \d_overlay_offset   \scratchoffset
   \d_overlay_linewidth\the\dimexpr\triggeredmathstyleparameter\Umathfractionrule
   %
   \edef\overlaylinecolor{\mathradicalparameter\c!color}%
   %
   \edef\p_mp{\mathradicalparameter\c!mp}%
   %
   \setbox\scratchbox\hpack\bgroup % todo: tag this box as sqrt
     \uniqueMPgraphic
       {\p_mp}%
      %{...}%
   \egroup
   \scratchdimen       \wd\scratchbox
   \scratchtopoffset   \dimexpr\scratchoffset+\dp\nextbox\relax
   \scratchbottomoffset\dimexpr\scratchoffset+\ht\nextbox/2\relax
   \hpack to \scratchdimen{\hss\box\nextbox\kern\scratchoffset}%
   \kern-\scratchdimen
   \lower\dimexpr\scratchtopoffset\box\scratchbox%
   \ifx\currentmathradicaldegree\empty \else
     \setbox\scratchbox\mathstylehbox{\scriptscriptstyle\currentmathradicaldegree\hss}%
     \wd\scratchbox\scratchdimen
     \kern-\scratchdimen
     \raise\dimexpr\scratchbottomoffset\box\scratchbox
   \fi
   \endgroup}

\pushoverloadmode

\definemathradical[root][mp=minifun::math:radical:default]
\definemathradical[sqrt][root]

\popoverloadmode

% \setupmathradical[sqrt][alternative=normal,color=darkblue]
% \setupmathradical[sqrt][alternative=mp,color=darkgreen]

%D Because I wanted to illustrate some more fun stuff another mechanism
%D is provided as well ... let's put some dangerous tools in the hand of
%D math jugglers like Aditya.

\installcorenamespace{mathornament}
\installcorenamespace{mathornamentalternative}

\installcommandhandler \??mathornament {mathornament} \??mathornament

\setupmathornament
  [\c!alternative=\v!mp, % currently mp only .. maybe some day layer too
   \c!mpoffset=.25\exheight]

\appendtoks
    \frozen\protected\instance\edefcsname\currentmathornament\endcsname
      {\math_ornament_handle{\currentmathornament}}%
\to \everydefinemathornament

\protected\def\math_ornament_handle#tag#body%
  {\begingroup
   \cdef\currentmathornament{#tag}%
   \csname\??mathornamentalternative\mathornamentparameter\c!alternative\endcsname{#body}%
   \endgroup}

\defcsname\??mathornamentalternative\v!mp\endcsname#body% we could use dowithnextbox
  {\begingroup
   \scratchoffset\mathornamentparameter\c!mpoffset
   \setbox\nextbox\mathstylehbox{#body}%
   \d_overlay_width    \wd\nextbox
   \d_overlay_height   \ht\nextbox
   \d_overlay_depth    \dp\nextbox
   \d_overlay_offset   \scratchoffset
   \d_overlay_linewidth\linewidth
   \edef\overlaylinecolor{\mathornamentparameter\c!color}%
   \edef\p_mp{\mathornamentparameter\c!mp}%
   % the width of the graphic determines the width of the final result
   \setbox\scratchbox\hpack{\uniqueMPgraphic{\p_mp}}% todo: add code key + tag
   \hpack to \wd\scratchbox{\hss\box\nextbox\hss}%
   \kern-\wd\scratchbox
   \box\scratchbox
   \endgroup}

% \startMPextensions
%     vardef math_ornament_hat(expr w,h,d,o,l) =
%         image ( path p ; p :=
%             (w/2,h + 10l) --
%             (o + w,h + o) --
%             (w/2,h + 7l) --
%             (-o,h + o) --
%             cycle ;
%             fill p ;
%             setbounds currentpicture to (-o,0) -- (w+o,0) -- (w+o,h+2o) -- (-o,h+2o) -- cycle ;
%         )
%     enddef ;
% \stopMPextensions
%
% \startuniqueMPgraphic{math:ornament:hat}
%     draw
%         math_ornament_hat(
%             OverlayWidth,
%             OverlayHeight,
%             OverlayDepth,
%             OverlayOffset,
%             OverlayLineWidth
%         )
%     withpen
%         pencircle
%             xscaled (2OverlayLineWidth)
%             yscaled (3OverlayLineWidth/4)
%             rotated 30
%     withcolor
%         OverlayLineColor ;
%         draw boundingbox currentpicture;
% \stopuniqueMPgraphic
%
% \definemathornament [mathhat] [mp=math:ornament:hat]
%
% \dorecurse{8}{$\mathhat{\blackrule[width=#1ex,color=gray]}$ }

% \annuity {(x+1)} \tocharacter"20E7

\integerdef\radicalbarextenderuc\privatecharactercode{radical bar extender}

\integerdef\delimitedleftannuitylonguc  \privatecharactercode{delimited left annuity long}
\integerdef\delimitedleftannuityshortuc \privatecharactercode{delimited left annuity short}
\integerdef\delimitedrightannuitylonguc \privatecharactercode{delimited right annuity long}
\integerdef\delimitedrightannuityshortuc\privatecharactercode{delimited right annuity short}

\integerdef\delimitedbottomleftannuitylonguc  \privatecharactercode{delimited bottom left annuity long}
\integerdef\delimitedbottomleftannuityshortuc \privatecharactercode{delimited bottom left annuity short}
\integerdef\delimitedbottomrightannuitylonguc \privatecharactercode{delimited bottom right annuity long}
\integerdef\delimitedbottomrightannuityshortuc\privatecharactercode{delimited bottom right annuity short}

%D We now default to nice bars:

\setupmathradical
  [\c!rule=\v!symbol,
   \c!top=\radicalbarextenderuc]

\definemathradical
  [rannuity]
  [\c!rule=\v!yes,
   \c!left=\zerocount,
   \c!right=\delimitedrightannuitylonguc,
   \c!rightmargin=.05\emwidth]

\definemathradical
  [lannuity]
  [\c!rule=\v!yes,
   \c!left=\delimitedleftannuitylonguc,
   \c!right=\zerocount,
   \c!leftmargin=.05\emwidth]

\definemathradical
  [lrannuity]
  [\c!rule=\v!yes,
   \c!left=\delimitedleftannuityshortuc,
   \c!right=\delimitedrightannuitylonguc,
   \c!leftmargin=.05\emwidth,
   \c!rightmargin=.05\emwidth]

\definemathradical
  [rlannuity]
  [\c!rule=\v!yes,
   \c!left=\delimitedleftannuitylonguc,
   \c!right=\delimitedrightannuityshortuc,
   \c!leftmargin=.05\emwidth,
   \c!rightmargin=.05\emwidth]

\definemathradical
  [annuity]
  [rannuity]

\definemathradical
  [lbannuity]
  [lannuity]
  [\c!rule=\v!bottom,
   \c!left=\delimitedbottomleftannuitylonguc]

\definemathradical
  [rbannuity]
  [rannuity]
  [\c!rule=\v!bottom,
   \c!right=\delimitedbottomrightannuitylonguc]

\definemathradical
  [rlbannuity]
  [rlannuity]
  [\c!rule=\v!bottom,
   \c!left=\delimitedbottomleftannuityshortuc,
   \c!right=\delimitedbottomrightannuitylonguc]

\definemathradical
  [lrbannuity]
  [lrannuity]
  [\c!rule=\v!bottom,
   \c!left=\delimitedbottomleftannuitylonguc,
   \c!right=\delimitedbottomrightannuityshortuc]

\protect \endinput

