%D \module %D [ file=math-ini, %D version=2001.04.12, %D title=\CONTEXT\ Math Macros, %D subtitle=Initializations, %D author={Hans Hagen \& Taco Hoekwater}, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. \writestatus{loading}{ConTeXt Math Macros / Initializations} % 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}} %no \limits \def\@@mathnolopcomm#1{\mathop{#1}\nolimits} \def\@@mathboxcomm #1{\dontleavehmode\hbox{$\mathsurround\zeropoint#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: % % \def\dohandlemathtoken#1% % {\csname\@mt@ % \ifcsname\@mt@\mathcollection#1\endcsname % \mathcollection % \else\ifcsname\@mt@\nomathcollection#1\endcsname % \nomathcollection % \fi\fi % #1\endcsname} %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 ! but not in mkiv so ... \let\mathcharacter\dohandlemathtoken \let\textcharacter\dohandlecommand % better \dohandletexttoken % More clever layout: % % \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} % % fallback to math when in text mode (handy for unicode vectors) \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} %D Now we redefine the text encoding handler. %D A better fallback: % Just ETEX which is the default nowadays. \def\dohandlemathtoken#1% {\csname \ifmmode \ifcsname\@mt@\mathcollection:\outerencoding#1\endcsname \@mt@\mathcollection:\outerencoding \else\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\fi \else \ifcsname\characterencoding#1\endcsname \characterencoding \else\ifcsname\nocharacterencoding#1\endcsname \nocharacterencoding \else\ifcsname\@mt@\mathcollection:\outerencoding#1\endcsname \@mt@\mathcollection:\outerencoding \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 \fi #1\endcsname} \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} \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} \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}} \newtoks\mathscratchtoks \def\definemathcharacter {\chardef\mathcharactermode\zerocount \dosixtupleempty\dodefinemathcharacter} \def\redefinemathcharacter {\chardef\mathcharactermode\plusone \dosixtupleempty\dodefinemathcharacter} \def\dodefinemathcharacter[#1][#2][#3][#4][#5][#6]% {\ifcase\mathcharactermode \setmathtoks \or \let\mathtoks\mathscratchtoks \mathtoks\emptytoks \fi \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 \ifcase\mathcharactermode \expandafter\tracemathcharacter \or \the\mathtoks \mathtoks\emptytoks \expandafter\gobbleoneargument \fi{#1}} % maybe lookahead \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}.mkii}% \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.mkii}% \setmathtoks \ifx\mathtoks\relax\else\mathtoks\emptytoks\fi} %D \macros %D {ifmathpunctuation, enablemathpunctuation, %D definemathpunctuation} %D %D This will replace periods by comma's: %D %D \starttyping %D \definemathpunctuation . textcomma textperiod %D \definemathpunctuation , textcomma textcomma %D %D \appendtoks %D \redefinemathcharacter [.] [ord] [mi] ["3B]% %D \to \everymathpunctuation %D \stoptyping % \newif\ifmathpunctuation % % \def\enablemathpunctuation{\mathpunctuationtrue} % % \def\definemathpunctuation #1 #2 #3 % % {\appendtoks % \initializemathpunctuation{#1}{#2}{#3}% % \to\everymathematics} % % \def\initializemathpunctuation#1#2#3% sloowww % {\ifmathpunctuation % hm move this test to everymath, or better a separate token list % \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} \newtoks\everymathpunctuation \def\enablemathpunctuation % can be called inside math, so after \everymathematics {\relax \ifmmode \the\everymathpunctuation \fi \appendtoksonce \the\everymathpunctuation \to\everymathematics} \def\definemathpunctuation #1 #2 #3 % {\appendtoks \initializemathpunctuation{#1}{#2}{#3}% \to\everymathpunctuation} \def\initializemathpunctuation#1#2#3% sloowww {\mathcode`#1="8000 \defineactivecharacter #1 {\dohandlemathpunctuation{#2}{#3}}} \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}} % \def\mlimitsfunction #1{\mathlimopcomm{{\mr#1}} % \def\mnolimitsfunction#1{\mathnolopcomm{{\mr#1}} %D Taco posted this solution as response to a mail by Olivier, so %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}}}} \def\currentmscaledstyle{rm} % will be plugged into the typeface text=ss option \def\setmathfunctionstyle#1% rm ss tt {\doifsomething{#1} {\def\currentmscaledstyle{#1}% \def\mathopnolimits##1{\mathop{\mscaledtext{##1}}\nolimits}% \def\mfunction##1{\mscaledtext{##1}}}} \def\mscaledtext#1% {\mathchoice {\hbox{\csname\currentmscaledstyle\endcsname\tf #1}} {\hbox{\csname\currentmscaledstyle\endcsname\tf #1}} {\hbox{\csname\currentmscaledstyle\endcsname\tfx #1}} {\hbox{\csname\currentmscaledstyle\endcsname\tfxx#1}}} %D We can force the way functions are typeset by manipulating the text %D option: %D %D \starttyping %D \definetypeface[iwona][ss][sans][iwona][default][encoding=texnansi] %D \definetypeface[iwona][mm][math][iwona][default][encoding=texnansi,text=ss] %D \stoptyping %D %D This hooks into the math handler with: \appendtoks \setmathfunctionstyle\currentmathtextstyle \to \everybodyfont %D Usage: %D %D \starttyping %D \setmathfunctionstyle\fontstyle % or {rm} or {ss} or .. %D \rm test $\sin{(x^{\sin(x^{\sin(x)})})}$ test %D \ss test $\sin{(x^{\sin(x^{\sin(x)})})}$ test %D \tt test $\sin{(x^{\sin(x^{\sin(x)})})}$ test %D \stoptyping \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 %D \macros %D {nonknuthmode, donknuthmode} %D %D The underscore is frequently used in manuals but unfortunately \TEX\ prefers %D it to be a math specific character. And since computer modern fonts didn't %D have an underscore, one had to use commands to fake one. Nowadays we do %D have underscores in latin modern, and since all other fonts have them, we %D decided to get away from the restriction to use the underscore character in %D text mode. %D %D \starttyping %D \def\test#1{#1} %D %D \nonknuthmode $x_2$ x_2 \test{$x_2$} \test{x_2} %D %D \donknuthmode $x_2$ x_2 \test{$x_2$} \test{x_2} %D \stoptyping %D %D The result is as expected: the first line typesets ok, while the second %D one triggers an error message. \bgroup \ifx\normalsuber\undefined \def\normalsuber{_} \fi \ifx\normalsuper\undefined \def\normalsuper{^} \fi \catcode`_=\active \catcode`^=\active \gdef\nonknuthmode {\appendtoks\let_\normalsuber\let^\normalsuper\to\everymathematics \mathcode`_="8000 \mathcode`^="8000 \catcode`_=\@@other \catcode`^=\@@other \let\nonknuthmode\relax} \gdef\donknuthmode {\catcode`_=\@@subscript \catcode`^=\@@superscript} \egroup %D \macros %D {checkdelimiters, fakeleftdelimiter, fakerightdelimiter} %D %D Handy for non matching situations (as with mathml): %D %D \starttyping %D \checkdelimiters{... bla bla ...} %D \fakeleftdelimiter %D ... bla bla ... %D \fakerightdelimiter %D \stoptyping \newcount\delimitercount \def\leftfakedelimiter {\advance\delimitercount\minusone\gobbleoneargument}% \def\rightfakedelimiter{\advance\delimitercount\plusone \gobbleoneargument}% \def\checkdelimiters#1% {\delimitercount\zerocount \setbox\scratchbox\hbox\bgroup \let\left \leftfakedelimiter \let\right\rightfakedelimiter $#1\expandafter$\expandafter \egroup \expandafter\delimitercount\the\delimitercount\relax} \def\fakeleftdelimiter {\ifnum\delimitercount>\zerocount\left .\fi} \def\fakerightdelimiter{\ifnum\delimitercount<\zerocount\right.\fi} %D Needed for unicode: \def\nulloperator{\mathortext{\mathop{\null}}{\null}} %D To be dealt with ... \mathcode`\ ="8000 % \space \mathcode`\'="8000 % ^\prime \mathcode`\_="8000 % \_ \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