%D \module %D [ file=supp-num, %D version=1998.05.15, %D title=\CONTEXT\ Support Macros, %D subtitle=Numbers, %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. \writestatus{loading}{ConTeXt Support Macros / Numbers} \unprotect %D \macros %D {digits, setdigitmode, setdigitsign} %D %D Depending on the digit mode the command \type {\digits} %D normalizes number patterns depending on the language set. %D %D \starttyping %D This will never be a \digits{1.000.000} seller. %D \stoptyping %D %D or %D %D \starttyping %D I will never grow longer than \digits 1.86 \Meter. %D \stoptyping %D %D The different modes are shown in: %D %D \startbuffer %D \setdigitmode 1 \digits 12.345,90 \digits 12.345.000 \digits 1,23 %D \setdigitmode 2 \digits 12.345,90 \digits 12.345.000 \digits 1,23 %D \setdigitmode 3 \digits 12.345,90 \digits 12.345.000 \digits 1,23 %D \setdigitmode 4 \digits 12.345,90 \digits 12.345.000 \digits 1,23 %D \setdigitmode 5 \digits 12.345,90 \digits 12.345.000 \digits 1,23 %D \setdigitmode 6 \digits 12.345,90 \digits 12.345.000 \digits 1,23 %D \stopbuffer %D %D \typebuffer %D %D This is typset as: %D %D \startlines %D \getbuffer %D \stoplines %D %D The sign can be typeset as is or within the space of a %D digit. %D %D \startbuffer %D \setdigitsign 0 \digits +12.345,90 %D \setdigitmode 1 \digits +12.345,90 %D \setdigitmode 2 \digits +12.345,90 %D \setdigitmode 3 \digits +12.345,90 %D \stopbuffer %D %D \typebuffer %D %D This is typset as: %D %D \startlines %D \getbuffer %D \stoplines \chardef\digitoutputmode=1 % 0..6 \chardef\digitsignmode =0 % 0..3 \def\setdigitmode{\chardef\digitoutputmode} \def\setdigitsign{\chardef\digitsignmode} %D The digit modes are: %D %D \startitemize[packed] %D \item periods \& comma %D \item commas \& period %D \item thinmuskips \& comma %D \item thinmuskips \& period %D \item thickmuskips \& comma %D \item thickmuskips \& period %D \stopitemize \let\collecteddigits \empty \chardef\digitinputmode =1 \let\saveddigits \empty \chardef\skipdigit =0 \let\savedpowerdigits\empty \chardef\powerdigits =0 %D The first stage of the \type {\digit} macro takes care of %D the grouped call, the other branch handles the fuzzy %D delimited calls. \ifx\mbox\undefined \let\mbox\normalhbox \fi % \unexpanded\def\digits % {\bgroup\let~@\doifnextbgroupelse\dodigits\grabdigit} \unexpanded\def\digits {\bgroup \let~@% \doifnextbgroupelse\dodigits{\doifnextcharelse\normalmathshift\domathdigits\grabdigit}} \def\dodigits#1% {\grabdigit#1\relax} \def\domathdigits$#1$% {\mbox{\grabdigit#1\relax}} % adding $ $ goes wrong in tabulate \def\grabdigit {\futurelet\next\scandigit} %D Watch the test for \type {\nextobeyedline}, because the %D endofline token can be \type {\def'd}, not \type {\let}'d, %D we need to do an indirect test (see \type {verb-ini.tex}) %D for details. %D %D \starttyping %D \def ^^M{\obeyedline} %D \def\nextbeyedline{\obeyedline} %D \stoptyping \ifx\normalmathshift\undefined \let\normalmathshift=$ \fi \def\scandigit {\ifx\next\blankspace \let\next\handledigits \else\ifx\next\nextobeyedline % the indirect one \let\next\handledigits \else\ifx\next\bgroup \let\next\handledigits \else\ifx\next\egroup \let\next\handledigits \else\ifx\next\normalmathshift \let\next\handledigits \else \let\next\collectdigit \fi\fi\fi\fi\fi \next} %D We store the power||of||ten (to be signaled by \type {^}, %D \type {e} or~\type {E}) in a seperate macro so that we can %D typeset it in superscript. The space placeholders are %D replaced by a \type {@}. \def\savedigit#1#2% {\edef#1{#1\saveddigits#2}\let\saveddigits\empty} \long\def\collectdigit#1% {\ifx#1~% \savedigit\collecteddigits @% \else\if#1_% \savedigit\collecteddigits @% \else\if\noexpand#1\relax \let\grabdigit\handledigits \else\ifcase\powerdigits \if#1E% \chardef\powerdigits\plusone \else\if#1e% \chardef\powerdigits\plusone \else\if#1^% \chardef\powerdigits\plusone \else \savedigit\collecteddigits#1% %\doifnumberelse{#1} % {\savedigit\collecteddigits#1} % {\def\saveddigits{#1}}% \fi\fi\fi \else \savedigit\savedpowerdigits#1% %\doifnumberelse{#1} % {\savedigit\savedpowerdigits#1} % {\def\saveddigits{#1}}% \fi\fi\fi\fi \grabdigit} \let\handlemathdigits\firstofoneargument \let\handletextdigits\mathematics \def\handledigits {%\ifcase\powerdigits % \edef\collecteddigits{\collecteddigits\saveddigits}% %\else % \edef\savedpowerdigits{\savedpowerdigits\saveddigits}% %\fi \ifmmode \handlemathdigits{\dohandledigits}% \else \dontleavehmode\hbox{\handletextdigits{\dohandledigits}}% \fi \egroup} %D Although we could do with one pass, a second pass for %D handling the stored sequence is more readable. \startmode[mkiv] \def\dohandledigits {\mathcode`\,="003B \mathcode`\.="003A % pretty hard coded \expandafter\handletokens\collecteddigits\with\scandigits \ifcase\powerdigits\else\digitpowerseparator^{\savedpowerdigits}\fi} \stopmode \startnotmode[mkiv] \def\dohandledigits {\mathcode`\,="013B \mathcode`\.="013A % pretty hard coded \expandafter\handletokens\collecteddigits\with\scandigits \ifcase\powerdigits\else\digitpowerseparator^{\savedpowerdigits}\fi} \stopnotmode \def\doscandigit#1% {\ifcase\skipdigit\@EA\hbox\else\@EA\hphantom\fi\bgroup \mathematics % brr, needed because of stored punctuation {\ifnum\digitinputmode=#1\relax \ifcase\digitoutputmode \or .% \or ,% \or \mskip\thinmuskip \or \mskip\thinmuskip \or \mskip\thickmuskip \or \mskip\thickmuskip \fi \else \ifodd\digitoutputmode,\else.\fi \fi}% \egroup} %D The signs can be made smaller and sqeezed into the width %D of a digit. Watch the \type {\mathaxisheight} trickery (this %D font related register stored the math axis). % \def\scandigits#1% % {\if#1.\doscandigit1\chardef\skipdigit0\else % \if#1,\doscandigit2\chardef\skipdigit0\else % \if#1@\hphantom{0}\chardef\skipdigit1\else % \if#1_\hphantom{0}\chardef\skipdigit1\else % \if#1/\digitsgn{\hphantom{+}}\chardef\skipdigit0\else % \if#1-\digitsgn-\chardef\skipdigit0\else % \if#1+\digitsgn+\chardef\skipdigit0\else % \if#1=\digitsgn\zeroamount\chardef\skipdigit0\else % \if#1s\digitsgn{\hphantom{\positive}}\chardef\skipdigit0\else % \if#1p\digitsgn\positive\chardef\skipdigit0\else % \if#1m\digitsgn\negative\chardef\skipdigit0\else % \if#1n\digitsgn\negative\chardef\skipdigit0\else % #1\chardef\skipdigit0\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi} % \def\digitsep#1% % {\doscandigit#1\chardef\skipdigit0} % % \def\digitnop % {\hphantom{0}\chardef\skipdigit1} % 0,= % 0,== second = results in delta(00,=) % 0,- is invalid, should be = % 0,-- is invalid, should be == \def\digitzeroamount {\digitsgn\zeroamount \def\digitzeroamount {\hphantom {00\setbox\scratchbox\hbox{$\zeroamount$}% \hskip-\wd\scratchbox}% \let\digitzeroamount\empty}} \def\scandigits#1% {\if#1.\digitsep1\else \if#1,\digitsep2\else \if#1@\digitnop \else \if#1_\digitnop \else \if#1/\digitsgn{\hphantom{+}}\chardef\skipdigit0\else \if#1-\ifcase\skipdigit\digitsgn-\else \box\digitsepbox\digitzeroamount \fi\chardef\skipdigit0\else \if#1+\digitsgn+\chardef\skipdigit0\else \if#1=\box\digitsepbox\digitzeroamount \chardef\skipdigit0\else \if#1s\digitsgn{\hphantom{\positive}}\chardef\skipdigit0\else \if#1p\digitsgn\positive\chardef\skipdigit0\else \if#1m\digitsgn\negative\chardef\skipdigit0\else \if#1n\digitsgn\negative\chardef\skipdigit0\else \box\digitsepbox #1\chardef\skipdigit0\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi} \newbox\digitsepbox \chardef\autodigitmode=1 \def\digitsep#1% {\ifcase\autodigitmode \doscandigit#1% \else \setbox\digitsepbox\hbox{\doscandigit#1}% \fi \chardef\skipdigit0\relax} % strange, does not work % % \def\digitnop % {\hphantom{\box\digitsepbox}% % \hphantom{0}\chardef\skipdigit1\relax} % % while this works \def\digitnop {\hbox{\hphantom{\box\digitsepbox}}% \hphantom{0}\chardef\skipdigit1\relax} % but this doesn't % % \def\digitnop % {\hphantom{\box\digitsepbox0}% % \chardef\skipdigit1\relax} \def\digitsgn#1% {\ifcase\digitsignmode#1\else \hbox {\setbox\scratchbox\hbox{0}% \scratchdimen\mathaxisheight\textfont2 \def\digitsgn##1##2% {\advance\scratchdimen-\mathaxisheight##12 \raise\scratchdimen \hbox to \wd\scratchbox{\hss$##2#1$\hss}}% \ifcase\digitsignmode\or \digitsgn\textfont \textstyle \or \digitsgn\scriptfont \scriptstyle \or \digitsgn\scriptscriptfont\scriptscriptstyle\fi}% \fi} \ifx\undefined\zeroamount \def\zeroamount{-} \fi \ifx\undefined\positive \def\positive {+} \fi \ifx\undefined\negative \def\negative {-} \fi %D The digit parser handles a bunch of special characters as %D well as different formats. We strongly suggest you to use %D the grouped call. %D %D \starttabulate[|l|l|l|] %D \NC \type{.} \NC , . \NC comma or period \NC \NR %D \NC \type{,} \NC , . \NC comma or period \NC \NR %D \NC \type{@} \NC \NC invisible space \NC \NR %D \NC \type{_} \NC \NC invisible space \NC \NR %D \NC \type{/} \NC \NC invisible sign \NC \NR %D \NC \type{-} \NC $-$ \NC minus sign \NC \NR %D \NC \type{+} \NC $+$ \NC plus sign \NC \NR %D \NC \type{s} \NC \NC invisible high sign \NC \NR %D \NC \type{p} \NC $\positive$ \NC high plus sign \NC \NR %D \NC \type{m} \NC $\negative$ \NC high minus sign \NC \NR %D \NC \type{n} \NC $\negative$ \NC high minus (negative) sign \NC \NR %D \NC \type{=} \NC $\zeroamount$ \NC zero padding \NC \NR %D \stoptabulate %D %D These triggers are used in the following examples. %D %D \startbuffer %D \digits 12 %D \digits{~~~.~~~.~~~.68.712,34} %D \digits ~~~.~~~.~~~.68.712,34 %D \digits ___.___.111.68.712,34 %D \digits 111.111.111.68.712,34 %D \digits 12.345,90 %D \digits 12.345.000 %D \digits 12,34 %D \digits{392.857.230.68.712,34} %D {\digits1234} %D \digits{1234} %D \digits 1234\relax %D $\digits 123.222,00$ %D \digits 123.222,00 %D \digits 123.222,== %D \digits 123.222,00^10 %D \digits 123.222,00e10 %D \digits /123.222,00e-12 %D \digits -123.222,00e-12 %D \digits +123.222,00e-12 %D \digits n123.222,00e-12 %D \digits s123.222,00e-12 %D \digits p123.222,00e-12 %D \stopbuffer %D %D \typebuffer %D %D \startlines %D \getbuffer %D \stoplines %D \macros %D {Digits} %D %D We also permit: \let\Digits=\digits %D These macros are complicated by the fact that we also %D have to support cases like: %D %D \starttyping %D {\digits1234} %D \digits{1234} %D \digits 1234\whatever %D $\digits 123.222,00$ %D \digits 123.222,00. %D \stoptyping %D %D The latter case shows us that trailing non digits are to %D be passed untreated. %D %D Another interesting case is: %D %D \starttyping %D \digits 123.222,00^10 %D \stoptyping %D %D The separator is defined as: % \def\digitpowerseparator% % {\cdot10} % {\times10} \def\digitpowerseparator {\ifx\collecteddigits\empty\else\cdot\fi10} %D \macros %D {digittemplate} %D %D Users can specify the way they enter those digits by saying %D something like: %D %D \starttyping %D \digittemplate 12.000.000,00 % \digittemplate ., %D \stoptyping \def\digittemplate #1 % {\chardef\digitinputmode\zerocount \handletokens#1\with\scandigittemplate} \def\scandigittemplate#1% {\if #1.\ifcase\digitinputmode\chardef\digitinputmode1 \fi% period \else\if#1,\ifcase\digitinputmode\chardef\digitinputmode2 \fi% comma \fi\fi} \protect \endinput