%D \module
%D   [       file=math-ini,
%D        version=2001.04.12,
%D          title=\CONTEXT\ Math Macros,
%D       subtitle=Basic Macros,
%D         author={Hans Hagen \& Taco Hoekwater},
%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.

% todo: make all definitions global since file loaded only once

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

\unprotect

\def\@ml@{@ml@} % math list (used for collection)
\def\@mf@{@mf@} % math family
%def\@mh@{@mh@} % math handler (not used)
\def\@mt@{@mt@} % math token
\def\@mc@{@mc@} % math collection

\def\@@mathlimopcomm#1{\mathop{#1}\limits}
\def\@@mathnolopcomm#1{\mathop{#1}\nolimits}
\def\@@mathboxcomm  #1{\leavevmode\hbox{$\m@th#1$}}

\chardef\mathordcode    = 0  \let\mathordcomm     \mathord
\chardef\mathopcode     = 1  \let\mathopcomm      \mathop
\chardef\mathbincode    = 2  \let\mathbincomm     \mathbin
\chardef\mathrelcode    = 3  \let\mathrelcomm     \mathrel
\chardef\mathopencode   = 4  \let\mathopencomm    \mathopen
\chardef\mathclosecode  = 5  \let\mathclosecomm   \mathclose
\chardef\mathpunctcode  = 6  \let\mathpunctcomm   \mathpunct
\chardef\mathalphacode  = 7  \let\mathalphacomm   \firstofoneargument
\chardef\mathinnercode  = 0  \let\mathinnercomm   \mathinner
\chardef\mathnothingcode= 0  \let\mathnothingcomm \firstofoneargument
\chardef\mathlimopcode  = 1  \let\mathlimopcomm   \@@mathlimopcomm
\chardef\mathnolopcode  = 1  \let\mathnolopcomm   \@@mathnolopcomm
\chardef\mathchoicecode = 0  \let\mathchoicecomm  \@@mathchoicecomm
\chardef\mathboxcode    = 0  \let\mathboxcomm     \@@mathboxcomm

\chardef\mathaccentcode = 8
\chardef\mathradicalcode= 9

\def\@@mathchoicecomm#1{[todo #1]}

\def\puremathcode#1{\the\csname math#1code\endcsname}
\def\puremathcomm#1{\csname     math#1comm\endcsname}

\newif\iftracemathcollection

% Simple variant:
%
% \beginETEX \ifcsname
%
% \def\dohandlemathtoken#1%
%   {\csname\@mt@
%      \ifcsname\@mt@\mathcollection#1\endcsname
%        \mathcollection
%      \else\ifcsname\@mt@\nomathcollection#1\endcsname
%        \nomathcollection
%      \fi\fi
%    #1\endcsname}
%
% \endETEX
%
% \beginTEX
%
% \def\dohandlemathtoken#1%
%   {\csname\@mt@
%      \@EA\ifx\csname\@mt@\mathcollection#1\endcsname\relax
%        \@EA\ifx\csname\@mt@\nomathcollection#1\endcsname\relax
%        \else
%          \nomathcollection
%        \fi
%      \else
%        \mathcollection
%      \fi
%    #1\endcsname}
%
% \endTEX

%D Because a command can have a different meaning in math
%D and in text mode, we provide a selector. We also provide
%D the pure alternatives as \type {\mathcharacter} and \type
%D {\textcharacter}.

\ifx\dohandlecommand\undefined \wait \fi % troubles !

\let\mathcharacter\dohandlemathtoken
\let\textcharacter\dohandlecommand % better \dohandletexttoken

% More clever layout:
%
% \beginETEX \ifcsname
%
% \def\dohandlemathtoken#1%
%   {\csname
%      \ifmmode
%        \ifcsname\@mt@\mathcollection#1\endcsname
%          \@mt@\mathcollection
%        \else\ifcsname\@mt@\nomathcollection#1\endcsname
%          \@mt@\nomathcollection
%        \else\ifcsname\characterencoding#1\endcsname
%          \characterencoding
%        \else
%          \nocharacterencoding
%        \fi\fi\fi
%      \else
%        \ifcsname\characterencoding#1\endcsname
%          \characterencoding
%        \else
%          \nocharacterencoding
%        \fi
%      \fi
%    #1\endcsname}
%
% \endETEX
%
% \beginTEX
%
% \def\dohandlemathtoken#1%
%   {\csname
%      \ifmmode
%        \@EA\ifx\csname\@mt@\mathcollection#1\endcsname\relax
%          \@EA\ifx\csname\@mt@\nomathcollection#1\endcsname\relax
%            \@EA\ifx\csname\characterencoding#1\endcsname\relax
%              \nocharacterencoding
%            \else
%              \characterencoding
%            \fi
%          \else
%            \@mt@\nomathcollection
%          \fi
%        \else
%          \@mt@\mathcollection
%        \fi
%      \else
%        \@EA\ifx\csname\characterencoding#1\endcsname\relax
%          \nocharacterencoding
%        \else
%          \characterencoding
%        \fi
%      \fi
%    #1\endcsname}
%
% \endTEX
%
% fallback to math when in text mode (handy for unicode vectors)

\beginETEX

\def\dohandlemathtoken#1%
  {\csname
     \ifmmode
       \ifcsname\@mt@\mathcollection#1\endcsname
         \@mt@\mathcollection
       \else\ifcsname\@mt@\nomathcollection#1\endcsname
         \@mt@\nomathcollection
       \else\ifcsname\characterencoding#1\endcsname
         \characterencoding
       \else
         \nocharacterencoding
       \fi\fi\fi
     \else
       \ifcsname\characterencoding#1\endcsname
         \characterencoding
       \else\ifcsname\nocharacterencoding#1\endcsname
         \nocharacterencoding
       \else\ifcsname\@mt@\mathcollection#1\endcsname
         \strippedcsname\mathematics\expandafter\endcsname\csname\@mt@\mathcollection
       \else\ifcsname\@mt@\nomathcollection#1\endcsname
         \strippedcsname\mathematics\expandafter\endcsname\csname\@mt@\nomathcollection
       \else
         \nocharacterencoding
       \fi\fi\fi\fi
     \fi
   #1\endcsname}

\endETEX

\beginTEX

\def\dohandlemathtoken#1%
  {\csname
     \ifmmode
       \@EA\ifx\csname\@mt@\mathcollection#1\endcsname\relax
         \@EA\ifx\csname\@mt@\nomathcollection#1\endcsname\relax
           \@EA\ifx\csname\characterencoding#1\endcsname\relax
             \nocharacterencoding
           \else
             \characterencoding
           \fi
         \else
           \@mt@\nomathcollection
         \fi
       \else
         \@mt@\mathcollection
       \fi
     \else
       \@EA\ifx\csname\characterencoding#1\endcsname\relax
         \@EA\ifx\csname\nocharacterencoding#1\endcsname\relax
           \@EA\ifx\csname\@mt@\mathcollection#1\endcsname\relax
             \@EA\ifx\csname\@mt@\nomathcollection#1\endcsname\relax
               \nocharacterencoding
             \else
                \strippedcsname\mathematics\expandafter\endcsname\csname\@mt@\nomathcollection
             \fi
           \else
             \strippedcsname\mathematics\expandafter\endcsname\csname\@mt@\mathcollection
          \fi
         \else
           \nocharacterencoding
         \fi
       \else
         \characterencoding
       \fi
     \fi
   #1\endcsname}

\endTEX

%D Now we redefine the text encoding handler.

\let\dohandlecommand\dohandlemathtoken

\def\definefamilysynonym
  {\dotripleempty\dodefinefamilysynonym}

\def\dodefinefamilysynonym[#1][#2][#3]% [mathcollection] [] []
  {\ifthirdargument
     \setvalue{\@mf@#1#2}{#3}%
   \else
     \setvalue{\@mf@  #1}{#2}%
   \fi}

\let\mathsubfamily\empty

\def\purefamily   #1{\csname    \truefamily{#1}\mathsubfamily\s!fam\endcsname}
\def\purefamilyhex#1{\csname hex\truefamily{#1}\mathsubfamily\s!fam\endcsname}

\beginETEX \ifcsname

\def\truefamily#1%
  {\ifcsname\@mf@\mathcollection#1\endcsname
     \@EA\truefamily\csname\@mf@\mathcollection#1\endcsname
   \else\ifcsname\@mf@#1\endcsname
     \@EA\truefamily\csname\@mf@#1\endcsname
   \else\ifcsname\@mf@\nomathcollection#1\endcsname
     \@EA\truefamily\csname\@mf@\nomathcollection#1\endcsname
   \else
     #1%
   \fi\fi\fi}

\endETEX

\beginTEX

\def\truefamily#1%
  {\@EA\ifx\csname\@mf@\mathcollection#1\endcsname\relax
     \@EA\ifx\csname\@mf@#1\endcsname\relax
       \@EA\ifx\csname\@mf@\nomathcollection#1\endcsname\relax
         #1%
       \else
         \@EA\truefamily\csname\@mf@\nomathcollection#1\endcsname
       \fi
     \else
       \@EA\truefamily\csname\@mf@#1\endcsname
     \fi
   \else
     \@EA\truefamily\csname\@mf@\mathcollection#1\endcsname
   \fi}

\endTEX

\newif\ifdynamicmathfamilies \dynamicmathfamiliestrue % true per 2003.11.25; needed for mixed bold math

\let\normalpurefamilyhex\purefamilyhex

% todo: reset collection (tok legen) en opnieuw laden met true

\def\definemathsymbol
  {\dosixtupleempty\dodefinemathsymbol}

\def\dodefinemathsymbol[#1][#2][#3][#4][#5][#6]%
  {\unexpanded\setgvalue{#1}{\dohandlemathtoken{#1}}%
   \ifdynamicmathfamilies \let\purefamilyhex\relax \fi
   \setevalue{\@mt@\mathcollection#1}%
     {\ifsixthargument
        \ifnum\puremathcode{#2}=\mathradicalcode
          \radical"%
        \else
          \delimiter"%
          \ifnum\puremathcode{#2}>7 0\else\puremathcode{#2}\fi
        \fi
        \purefamilyhex{#3}\uchexnumbers{#4}%
        \purefamilyhex{#5}\uchexnumbers{#6}\space
      \else\iffourthargument
        \ifnum\puremathcode{#2}=\mathaccentcode
          \mathaccent\else\mathchar
        \fi
       "\ifnum\puremathcode{#2}>7 0\else\puremathcode{#2}\fi
        \purefamilyhex{#3}\uchexnumbers{#4}\space
      \fi\fi}%
   \let\purefamilyhex\normalpurefamilyhex
   \tracemathsymbol{#1}}

\def\tracemathsymbol#1%
  {\iftracemathcollection
     {\endgraf
      \hbox{\tex{#1}~:~{\mathematics{\getvalue{#1}{}}}}
      \endgraf}%
   \fi}

\def\definemathcharacter
  {\dosixtupleempty\dodefinemathcharacter}

\def\dodefinemathcharacter[#1][#2][#3][#4][#5][#6]%
  {\setmathtoks
   \ifdynamicmathfamilies \let\purefamilyhex\relax \fi
   \doifnumberelse{#1}
     {\scratchcounter#1}
     {\scratchcounter\@EA`\string#1}%
   \appendetoks
      \ifsixthargument
        \delcode\the\scratchcounter="%
          \ifnum\puremathcode{#2}>7 0\else\puremathcode{#2}\fi
          \purefamilyhex{#3}\uchexnumbers{#4}%
          \purefamilyhex{#5}\uchexnumbers{#6}\space
      \else\iffourthargument
        \mathcode\the\scratchcounter="%
          \ifnum\puremathcode{#2}>7 0\else\puremathcode{#2}\fi
          \purefamilyhex{#3}\uchexnumbers{#4}\space
      \fi\fi\to\mathtoks
   \let\purefamilyhex\normalpurefamilyhex
   \tracemathcharacter{#1}}

\def\tracemathcharacter#1%
  {\iftracemathcollection
     {\endgraf
      \doifnumberelse{#1}
        {\hbox{\tttf\rawcharacter{#1}~:~{\mathematics{\rawcharacter{#1}}}}}
        {\hbox{\type{#1}~:~{\mathematics{#1}}}}
      \endgraf}%
   \fi}

\def\definemathcommand
  {\dotripleempty\dodefinemathcommand}

\def\dodefinemathcommand[#1][#2][#3]#4% command class args meaning
  {\unexpanded\setgvalue{#1}{\dohandlemathtoken{#1}}%
   \ifthirdargument
     \processaction
       [#3]
       [one=>\setvalue{\@mt@\mathcollection#1}##1{\puremathcomm{#2}{#4{##1}}},
        two=>\setvalue{\@mt@\mathcollection#1}##1##2{\puremathcomm{#2}{#4{##1}{##2}}}]%
   \else\ifsecondargument
     \setvalue{\@mt@\mathcollection#1}{\puremathcomm{#2}{#4}}%
   \else
     \setvalue{\@mt@\mathcollection#1}{\puremathcomm{nothing}{#4}}%
   \fi\fi
   \tracemathcommand{#1}}

\def\tracemathcommand#1%
  {\iftracemathcollection
     \endgraf\hbox{\tex{#1}~:~{\mathematics{\getvalue{#1}{}}}}\endgraf
   \fi}

\def\startmathcollection[#1]%
  {\pushmacro\mathcollection
   \setmathcollection{#1}}

\def\setmathcollection#1%
  {\edef\mathcollection{#1}%
   \doifundefined{\@ml@\mathcollection}
     {\expandafter\newtoks\csname\@ml@\mathcollection\endcsname}}

\def\stopmathcollection
  {\popmacro\mathcollection}

\def\startrawmathcollection
  {\startmathcollection}

\def\stoprawmathcollection
  {\stopmathcollection}

\newtoks\mathtoks

\def\setmathtoks
  {\@EA\let\@EA\mathtoks\csname\@ml@\mathcollection\endcsname}

\def\currentmathcollection{\mathcollection}

\let\nomathcollection\s!default

\def\enablemathcollection[#1]%
  {\doifnot{#1}\s!default
     {\setmathcollection\s!default
      \the\csname\@ml@\mathcollection\endcsname}%
   \setmathcollection{#1}%
   \the\csname\@ml@\mathcollection\endcsname}

% hook 'm into the font mechanism

\definefilesynonym[\f!mathprefix\s!default][\f!mathprefix tex]

\def\usemathcollection
  {\dodoubleempty\dousemathcollection}

\def\dousemathcollection[#1][#2]%
  {\pushmacro\fontclass
   \pushmacro\mathclass
   \ifsecondargument
     \edef\fontclass{#1}%
     \edef\mathclass{#2}%
   \else
     \edef\mathclass{#1}%
   \fi
   \doinputonce{\truefilename{\f!mathprefix\mathclass}}%
   \doifsomething\fontclass{\setevalue{\@mc@\fontclass\@mc@}{\mathclass}}%
   \popmacro\mathclass
   \popmacro\fontclass}

\let\mathclass\nomathcollection

\letvalue{\@mc@\@mc@}\nomathcollection

% \def\autoenablemathcollection
%   {\doifdefinedelse{\@mc@\fontclass\@mc@}
%      {\enablemathcollection[\getvalue{\@mc@\fontclass\@mc@}]}
%      {\enablemathcollection[\s!default]}} % ? ? ?

\def\autoenablemathcollection
  {\expanded{\enablemathcollection[\executeifdefined{\@mc@\fontclass\@mc@}\nomathcollection]}}

\appendtoks\autoenablemathcollection\to\mathstrategies

\fetchruntimecommand \showmathcharacters {\f!mathprefix\s!run}
\fetchruntimecommand \showmathtoken      {\f!mathprefix\s!run}

\def\resetmathcollection[#1]%
  {\def\mathcollection{#1}%
   \forgetdoingonce{\f!mathprefix\mathcollection}%
   \setmathtoks
   \ifx\mathtoks\relax\else\mathtoks\emptytoks\fi}

%D \macros
%D   {ifmathpunctuation, enablemathpunctuation,
%D    definemathpunctuation}
%D
%D \starttyping
%D \definemathpunctuation . mathperiod textperiod
%D \definemathpunctuation , mathcomma  textcomma
%D \stoptyping

\newif\ifmathpunctuation

\def\enablemathpunctuation{\mathpunctuationtrue}

\def\definemathpunctuation #1 #2 #3 %
  {\appendtoks
     \initializemathpunctuation{#1}{#2}{#3}%
   \to\everymath}

\def\initializemathpunctuation#1#2#3% sloowww
  {\ifmathpunctuation
     \mathcode`#1="8000
     \defineactivecharacter #1 {\dohandlemathpunctuation{#2}{#3}}%
   \fi}

\unexpanded\def\dohandlemathpunctuation#1#2% \if fails in mathml interval
  {\def\next{\csname\ifx\space\nexttoken#2\else#1\fi\endcsname}%
   \futurelet\nexttoken\next}

%D \startbuffer
%D \enablemathpunctuation$(1,2) (1, 2) (1{,}2) \hbox{foo, not bar}$
%D \stopbuffer
%D
%D \typebuffer
%D
%D \blank{\getbuffer}\blank

%D needed for sin, cos etc

\def\mfunction#1{{\mr#1}}

%D Taco posted this solution as response to a mail by Olivier, so
%D let's integrate it here.

\def\setmathfunctionstyle#1% \rm \ss \tt
  {\def\mfunction##1% no families, just scaling a la text
     {\mathchoice
        {\hbox{\csname#1\endcsname\tf  ##1}}
        {\hbox{\csname#1\endcsname\tf  ##1}}
        {\hbox{\csname#1\endcsname\tfx ##1}}
        {\hbox{\csname#1\endcsname\tfxx##1}}}}

%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

\edef\hexmrfam {0} \edef\hexbsfam {8}
\edef\hexmifam {1} \edef\hexbifam {9}
\edef\hexsyfam {2} \edef\hexscfam {A}
\edef\hexexfam {3} \edef\hextffam {B}
\edef\hexitfam {4} \edef\hexmafam {C}
\edef\hexslfam {5} \edef\hexmbfam {D}
\edef\hexbffam {6} \edef\hexmcfam {E}
\edef\hexnnfam {7} \edef\hexmdfam {F}

\definefamilysynonym [default] [letters]   [mr]
\definefamilysynonym [default] [operators] [sy]
\definefamilysynonym [default] [lcgreek]   [mi]
\definefamilysynonym [default] [ucgreek]   [mr]
\definefamilysynonym [default] [vargreek]  [mi]
\definefamilysynonym [default] [mitfamily] [mi]
\definefamilysynonym [default] [calfamily] [sy]

\definefamilysynonym [default] [0] [mr]
\definefamilysynonym [default] [1] [mi]
\definefamilysynonym [default] [2] [sy]
\definefamilysynonym [default] [3] [ex]

\enablemathcollection[default]

\usemathcollection [default] [tex]
\usemathcollection [default] [ams]
\usemathcollection [default] [uni]

\enablemathcollection[default]

%D Some goodies:

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

%D Bold math:
%D
%D \starttyping
%D \usetypescript [lucida] [texnansi]
%D
%D \definetypeface [boldmath] [rm] [serif]
%D   [lucida] [default] [encoding=texnansi]
%D \definetypeface [boldmath] [tt] [mono]
%D   [lucida] [default] [encoding=texnansi]
%D \definetypeface [boldmath] [ss] [sans]
%D   [lucida] [default] [encoding=texnansi]
%D \definetypeface [boldmath] [mm] [boldmath]
%D   [lucida] [default] [encoding=texnansi]
%D
%D \switchtobodyfont[lucida,10pt]
%D
%D \showmathtoken{Gamma} $\Gamma \Delta \alpha \delta \zeta$
%D
%D \switchtobodyfont[boldmath,10pt]
%D
%D \showmathtoken{Gamma} $\Gamma \Delta \alpha \delta \zeta$
%D \stoptyping

\protect \endinput

\tracemathcollectiontrue
                                                   \input math-tex \page
\setupbodyfont[ams] \enablemathcollection[default] \input math-ams \page
\setupbodyfont[lbr] \enablemathcollection[lbr]     \input math-lbr \page
\setupbodyfont[eul] \enablemathcollection[eul]     \input math-eul \stoptext

% to be checked, overloads supp-lan !

\def\defineactivecharacter #1 #2%
%   {\scratchcounter=\the\uccode`~
  {\scratchcounter\uccode`~\relax
   \expandafter\doifnumberelse\expandafter{\string#1}
     {\catcode #1=\@@active \uccode`~= #1\relax}
     {\catcode`#1=\@@active \uccode`~=`#1\relax}%
   \uppercase{\def\next{~}}%
  % unexpanded goes wrong in pdfdoc
  %\expandafter\unexpanded\expandafter\def\next{#2}%
  % better
  %\expandafter\def\next{#2}%
  % math aware
   \expandafter\def\next{\dohandleactivecharacter{#1}{#2}}% new
   \uccode`~=\scratchcounter}

\def\dohandleactivecharacter
  {\ifmmode
     \expandafter\dohandleactivemathcharacter
   \else
     \expandafter\secondoftwoarguments
   \fi}

\def\dohandleactivemathcharacter#1#2#3%
  {\ifundefined{@ma@\string#2}%
     \expandafter\firstofoneargument
   \else
     \getvalue{@ma@\string#2}%
     \expandafter\gobbleoneargument
   \fi{#3}}

% \def\dohandleactivemathcharacter#1#2%
%   {\ifcsname @ma@\string#1\endcsname
%      \csname @ma@\string#1\expandafter\endcsname
%      \expandafter\gobbleoneargument
%    \else
%      \expandafter\firstofoneargument
%    \fi{#2}}
