You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
733 lines
21 KiB
733 lines
21 KiB
%D \module
|
|
%D [ file=supp-mis,
|
|
%D version=2004.10.26, % 1997.01.04,
|
|
%D title=\CONTEXT\ Support Macros,
|
|
%D subtitle=Missing (For Generic Use),
|
|
%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.
|
|
|
|
%D I will clean up this module (a la supp-pdf.tex preamble).
|
|
|
|
%D Some support modules are more or less independant. This
|
|
%D module, which is not part of plain \CONTEXT, provides the
|
|
%D missing macros and declarations of registers.
|
|
|
|
\ifx \undefined \writestatus \else \expandafter \endinput \fi
|
|
|
|
%D Because \LATEX\ has no safe package loading mechanism, we
|
|
%D need to take care of possible interference.
|
|
|
|
\def\StartLatexHack % replace this by the one in supp-pdf
|
|
{\edef\StopLatexHack
|
|
{\catcode\string`\noexpand/=\the\catcode\string`/
|
|
\catcode\string`\noexpand-=\the\catcode\string`-
|
|
\catcode\string`\noexpand:=\the\catcode\string`:
|
|
\catcode\string`\noexpand;=\the\catcode\string`;
|
|
\catcode\string`\noexpand"=\the\catcode\string`"
|
|
\catcode\string`\noexpand<=\the\catcode\string`<
|
|
\catcode\string`\noexpand>=\the\catcode\string`>
|
|
\catcode\string`\noexpand`=\the\catcode\string``}%
|
|
\catcode\string`/=12 \catcode\string`-=12
|
|
\catcode\string`:=12 \catcode\string`;=12
|
|
\catcode\string`"=12 \catcode\string`<=12
|
|
\catcode\string`>=12 \catcode\string``=12 }
|
|
|
|
%D This hack is needed especially for \LATEX\ users who use
|
|
%D the Babel package. The Germans have active \type {"}'s, the
|
|
%D Poles have \type {/}, while the French have \type {:} and
|
|
%D \type {;} defines as command (thanks to Daniel Flipo for
|
|
%D pointing that out and testing). Potentially active \type
|
|
%D {?}'s and \type {!}'s are less dangerous since they are
|
|
%D handled by the \type {\protect} and \type {\unprotect}
|
|
%D macros.
|
|
|
|
\StartLatexHack
|
|
|
|
%D \macros
|
|
%D {ifnocontextobject}
|
|
%D
|
|
%D First we take care of redundant defining. The next set of
|
|
%D macros are a bit complicated by the fact that Plain
|
|
%D \TEX\ defines the \type{\new}||macros as being outer.
|
|
%D Furthermore nested \type{\if}'s can get us into
|
|
%D trouble.
|
|
|
|
\def\definecontextobject
|
|
{\iftrue}
|
|
|
|
\def\gobblecontextobject
|
|
{\setbox0\hbox
|
|
\bgroup
|
|
\long\def\gobblecontextobject##1\fi{\egroup}%
|
|
\expandafter\gobblecontextobject\string}
|
|
|
|
\long\def\ifnocontextobject#1\do
|
|
{\ifx#1\undefined
|
|
\expandafter\definecontextobject
|
|
\else
|
|
%\writestatus{system}{beware of conflicting \string#1}%
|
|
\expandafter\gobblecontextobject
|
|
\fi}
|
|
|
|
%D \macros
|
|
%D {beginETEX,beginTEX}
|
|
%D
|
|
%D Outside \CONTEXT\ we will not be \ETEX||aware.
|
|
|
|
\long\def\beginETEX #1\endETEX {}
|
|
|
|
\let\beginTEX\relax \let\endTEX\relax
|
|
|
|
%D \macros
|
|
%D {writestatus}
|
|
%D
|
|
%D We start each module with a message. Normally the output is
|
|
%D formatted, but here we keep things simple.
|
|
|
|
\ifnocontextobject \writestatus \do
|
|
|
|
\def\writestatus#1#2{\immediate\write16{#1 : #2}}
|
|
|
|
\fi
|
|
|
|
%D Let's see if it works.
|
|
|
|
\writestatus{loading}{ConTeXt Support Macros / Miscellaneous (2004.10.26)}
|
|
|
|
%D \macros
|
|
%D {protect,unprotect}
|
|
%D
|
|
%D Next we present a poor mans alternative for \type{\protect}
|
|
%D and \type{\unprotect}, two commands that enable us to use
|
|
%D the characters \type{@}, \type{!} and \type{?} in macro
|
|
%D names.
|
|
|
|
\ifnocontextobject \protect \do
|
|
|
|
\let\protect\relax
|
|
|
|
\fi
|
|
|
|
\newcount\protectiondepth
|
|
|
|
\ifnocontextobject \unprotect \do
|
|
|
|
\def\unprotect
|
|
{\advance\protectiondepth 1
|
|
\ifnum\protectiondepth=1
|
|
\let\normalprotect=\protect
|
|
\def\protect
|
|
{\ifnum\protectiondepth>0
|
|
\advance\protectiondepth -1
|
|
\ifnum\protectiondepth=0
|
|
\doprotect
|
|
\let\protect=\normalprotect
|
|
\fi
|
|
\fi}
|
|
\edef\doprotect
|
|
{\catcode`\noexpand @=\the\catcode`@\relax
|
|
\catcode`\noexpand !=\the\catcode`!\relax
|
|
\catcode`\noexpand ?=\the\catcode`?\relax}
|
|
\catcode`@=11
|
|
\catcode`!=11
|
|
\catcode`?=11
|
|
\fi}
|
|
|
|
\fi
|
|
|
|
%D We start using this one it at once.
|
|
|
|
\unprotect
|
|
|
|
%D \macros
|
|
%D {scratch...,if...,next...}
|
|
%D
|
|
%D We need some scratch registers. Users are free to use them,
|
|
%D but can never be sure of their value once another macro is
|
|
%D called. We only allocate things when they are yet
|
|
%D undefined. This way we can't mess up other macro packages,
|
|
%D but of course previous definitions can mess up our modules.
|
|
|
|
\ifnocontextobject \donetrue \do \newif\ifdone \fi
|
|
|
|
% no time now, will do a better test later (based on dimendef)
|
|
|
|
\def\!!stringa{plain} \ifx\!!stringa\fmtname \donetrue \else
|
|
\def\!!stringa{eplain} \ifx\!!stringa\fmtname \donetrue \else
|
|
\def\!!stringa{babel-plain} \ifx\!!stringa\fmtname \donetrue \else
|
|
\donefalse \fi \fi \fi
|
|
|
|
\ifdone
|
|
% plain defines some 15 dimens, so we need to define a few
|
|
% dummies in order to get out of the scratch area
|
|
\newdimen\scratchdimen % 16
|
|
\newdimen\scratchdimen % 17
|
|
\newdimen\scratchdimen % 18
|
|
\newdimen\scratchdimen % 19
|
|
\newdimen\scratchdimen % 20
|
|
\newdimen\scratchdimen % 21
|
|
\fi
|
|
|
|
\def\stripnewabove#1%
|
|
{\ifnum10<9#1 #1\else\expandafter\stripnewabove\fi}%
|
|
|
|
\def\newabove\csname#1\endcsname#2% \dimen \name
|
|
{\csname#1\endcsname#2%
|
|
\ifnum\expandafter\stripnewabove\meaning#2>20\else
|
|
\newabove\csname#1\endcsname#2%
|
|
\fi}
|
|
|
|
\ifnocontextobject \scratchcounter \do \newabove \csname newcount\endcsname \scratchcounter \fi
|
|
\ifnocontextobject \scratchtoks \do \newabove \csname newtoks\endcsname \scratchtoks \fi
|
|
\ifnocontextobject \scratchdimen \do \newabove \csname newdimen\endcsname \scratchdimen \fi
|
|
\ifnocontextobject \scratchskip \do \newabove \csname newskip\endcsname \scratchskip \fi
|
|
\ifnocontextobject \scratchmuskip \do \newabove \csname newmuskip\endcsname \scratchmuskip \fi
|
|
\ifnocontextobject \scratchbox \do \csname newbox\endcsname \scratchbox \fi
|
|
\ifnocontextobject \scratchread \do \csname newread\endcsname \scratchread \fi
|
|
\ifnocontextobject \scratchwrite \do \csname newwrite\endcsname \scratchwrite \fi
|
|
|
|
%D Watch out, in the past we ran into troubles with \type {\onepoint}
|
|
%D (and others) mening something different in \LATEX\ then here. In
|
|
%D such situations clashes are bound to happen. For this reason the
|
|
%D assignments are no inside the test. We try to catch those situations
|
|
%D but we cannot keep ahead of the future.
|
|
|
|
\ifnocontextobject \zeropoint \do \newdimen \zeropoint \zeropoint = 0pt \fi % else problems with dimen12
|
|
\ifnocontextobject \onepoint \do \newdimen \onepoint \onepoint = 1pt \fi
|
|
\ifnocontextobject \onebasepoint \do \newdimen \onebasepoint \onebasepoint = 1bp \fi
|
|
\ifnocontextobject \zerocount \do \chardef \zerocount = 0 \fi
|
|
\ifnocontextobject \plusone \do \chardef \plusone = 1 \fi
|
|
\ifnocontextobject \minusone \do \newcount \minusone \minusone = -1 \fi
|
|
\ifnocontextobject \thousandpoint \do \newdimen \thousandpoint \thousandpoint = 1000pt \fi
|
|
\ifnocontextobject \onerealpoint \do \newdimen \onerealpoint \onerealpoint = 1pt \fi % latex has a funny \onepoint
|
|
|
|
\ifnocontextobject \emptytoks \do \newtoks \emptytoks \fi
|
|
\ifnocontextobject \nextbox \do \newbox \nextbox \fi
|
|
\ifnocontextobject \nextdepth \do \newdimen \nextdepth \fi
|
|
|
|
\ifnocontextobject \CONTEXTtrue \do \newif\ifCONTEXT \fi
|
|
\ifnocontextobject \eightbitcharacterstrue \do \newif\ifeightbitcharacters \fi
|
|
\ifnocontextobject \MPdrawingdonetrue \do \newif\ifMPdrawingdone \fi
|
|
|
|
\ifnocontextobject \ifzeropt \do \let\ifzeropt\ifcase \fi
|
|
|
|
%D \macros
|
|
%D {@@...}
|
|
%D
|
|
%D We use symbolic name for \CATCODES. They can only be used
|
|
%D when we are in unprotected state.
|
|
|
|
\ifnocontextobject \@@escape \do \chardef\@@escape = 0 \fi
|
|
\ifnocontextobject \@@begingroup \do \chardef\@@begingroup = 1 \fi
|
|
\ifnocontextobject \@@endgroup \do \chardef\@@endgroup = 2 \fi
|
|
\ifnocontextobject \@@endofline \do \chardef\@@endofline = 5 \fi
|
|
\ifnocontextobject \@@ignore \do \chardef\@@ignore = 9 \fi
|
|
\ifnocontextobject \@@space \do \chardef\@@space = 10 \fi
|
|
\ifnocontextobject \@@letter \do \chardef\@@letter = 11 \fi
|
|
\ifnocontextobject \@@other \do \chardef\@@other = 12 \fi
|
|
\ifnocontextobject \@@active \do \chardef\@@active = 13 \fi
|
|
\ifnocontextobject \@@comment \do \chardef\@@comment = 14 \fi
|
|
|
|
\def\s!sp{sp}
|
|
\def\s!pt{pt}
|
|
\def\s!bp{bp}
|
|
|
|
%D \macros
|
|
%D {@EA,expanded,expandoneargafter,expandtwoargsafter}
|
|
%D
|
|
%D Also needed:
|
|
|
|
\let\@EA=\expandafter \let\@@expanded\empty
|
|
|
|
\def\expanded#1%
|
|
{\long\xdef\@@expanded{\noexpand#1}\@@expanded}
|
|
|
|
\def\expandoneargafter#1#2%
|
|
{\@EA#1\@EA{#2}}
|
|
|
|
\def\expandtwoargsafter#1#2#3%
|
|
{\@EA\@EA\@EA#1\@EA\@EA\@EA{\@EA#2\@EA}\@EA{#3}}
|
|
|
|
\def\@EAEAEA{\@EA\@EA\@EA}
|
|
|
|
%D \macros
|
|
%D {everyline,EveryLine,EveryPar}
|
|
%D
|
|
%D In \CONTEXT\ we use \type{\everypar} for special purposes
|
|
%D and provide \type{\EveryPar} as an alternative. The same
|
|
%D goes for \type{\everyline} and \type{\EveryLine}.
|
|
|
|
\ifnocontextobject \everyline \do \newtoks\everyline \fi
|
|
\ifnocontextobject \EveryPar \do \let\EveryPar =\everypar \fi
|
|
\ifnocontextobject \EveryLine \do \let\EveryLine=\everyline \fi
|
|
|
|
%D \macros
|
|
%D {globallet}
|
|
|
|
\def\globallet{\global\let}
|
|
|
|
%D \macros
|
|
%D {!!...}
|
|
%D
|
|
%D We reserve ourselves some scratch strings (i.e. macros)
|
|
%D and some more counters.
|
|
|
|
\ifnocontextobject \!!stringa \do \def\!!stringa {} \fi
|
|
\ifnocontextobject \!!stringb \do \def\!!stringb {} \fi
|
|
\ifnocontextobject \!!stringc \do \def\!!stringc {} \fi
|
|
\ifnocontextobject \!!stringd \do \def\!!stringd {} \fi
|
|
|
|
\ifnocontextobject \!!counta \do \newcount\!!counta {} \fi
|
|
\ifnocontextobject \!!countb \do \newcount\!!countb {} \fi
|
|
|
|
%D \macros
|
|
%D {!!...}
|
|
%D
|
|
%D The next set of definitions speed up processing a bit.
|
|
%D Furthermore it saves memory.
|
|
|
|
\ifnocontextobject \!!zeropoint \do \def\!!zeropoint {0pt} \fi
|
|
\ifnocontextobject \!!zerocount \do \def\!!zerocount {0} \fi
|
|
\ifnocontextobject \!!tenthousand \do \def\!!tenthousand {10000} \fi
|
|
|
|
\ifnocontextobject \!!width \do \def\!!width {width} \fi
|
|
\ifnocontextobject \!!height \do \def\!!height {height} \fi
|
|
\ifnocontextobject \!!depth \do \def\!!depth {depth} \fi
|
|
|
|
\ifnocontextobject \!!plus \do \def\!!plus {plus} \fi
|
|
\ifnocontextobject \!!minus \do \def\!!minus {minus} \fi
|
|
\ifnocontextobject \!!to \do \def\!!to {to} \fi
|
|
|
|
%D \macros
|
|
%D {smashbox}
|
|
%D
|
|
%D The system modules offer a range of smashing macros, of
|
|
%D which we only copied \type{\smashbox}.
|
|
|
|
\ifnocontextobject \smashbox \do
|
|
|
|
\def\smashbox#1%
|
|
{\wd#1\zeropoint
|
|
\ht#1\zeropoint
|
|
\dp#1\zeropoint}
|
|
|
|
\fi
|
|
|
|
%D \macros
|
|
%D {dowithnextbox}
|
|
%D
|
|
%D Also without further comment, we introduce a macro that
|
|
%D gets the next box and does something usefull with it.
|
|
%D Because the \type{\afterassignment} is executed inside the
|
|
%D box, we have to use a \type{\aftergroup} too.
|
|
|
|
\ifnocontextobject \dowithnextbox \do
|
|
|
|
\def\dowithnextbox#1%
|
|
{\def\dodowithnextbox{#1}%
|
|
\afterassignment\dododowithnextbox
|
|
\setbox\nextbox}
|
|
|
|
\def\dododowithnextbox%
|
|
{\aftergroup\dodowithnextbox}
|
|
|
|
\fi
|
|
|
|
%D \macros
|
|
%D {setvalue,setevalue,setxvalue,,setgvalue,
|
|
%D getvalue,
|
|
%D letvalue,letgvalue}
|
|
%D
|
|
%D The next two macros expand their argument to
|
|
%D \type{\argument}. The first one is used to define macro's
|
|
%D the second one executes them.
|
|
|
|
\ifnocontextobject \setvalue \do
|
|
|
|
\def\setvalue #1{\expandafter\def\csname#1\endcsname}
|
|
\def\setevalue#1{\expandafter\edef\csname#1\endcsname}
|
|
\def\setgvalue#1{\expandafter\gdef\csname#1\endcsname}
|
|
\def\setxvalue#1{\expandafter\xdef\csname#1\endcsname}
|
|
\def\getvalue #1{\csname#1\endcsname}
|
|
\def\letvalue #1{\expandafter\let\csname#1\endcsname}
|
|
\def\letgvalue#1{\global\expandafter\let\csname#1\endcsname}
|
|
\fi
|
|
|
|
%D \macros
|
|
%D {unexpanded}
|
|
%D
|
|
%D The next command can be used as prefixed for commands that
|
|
%D need protection during tests and writing to files. This
|
|
%D is a very \CONTEXT\ specific one.
|
|
|
|
\ifnocontextobject \unexpanded \do
|
|
|
|
\let\unexpanded\relax
|
|
|
|
\fi
|
|
|
|
%D \macros
|
|
%D {convertargument}
|
|
%D
|
|
%D The original one offers a bit more, like global assignment, the
|
|
%D the next implementation is however a bit more byte saving.
|
|
|
|
\ifnocontextobject \convertargument \do
|
|
|
|
\def\doconvertargument#1>{}
|
|
|
|
\long\def\convertargument#1\to#2%
|
|
{\long\def\@@convertedargument{#1}%
|
|
\edef#2{\expandafter\doconvertargument\meaning\@@convertedargument}}
|
|
|
|
\fi
|
|
|
|
%D \macros
|
|
%D {forgetall}
|
|
%D
|
|
%D Sometimes we have to disable interference of whatever kind
|
|
%D of skips and mechanisms. The next macro resets some.
|
|
|
|
\ifnocontextobject \forgetall \do
|
|
|
|
\def\forgetall
|
|
{\parskip\zeropoint
|
|
\leftskip\zeropoint
|
|
\parindent\zeropoint
|
|
\everypar{}}
|
|
|
|
\fi
|
|
|
|
%D \macros
|
|
%D {withoutpt,
|
|
%D ScaledPointsToBigPoints,ScaledPointsToWholeBigPoints}
|
|
%D
|
|
%D \TEX\ lacks some real datastructure. We can however use
|
|
%D \DIMENSIONS. This kind of trickery is needed when we want
|
|
%D \TEX\ to communicate with the outside world (by means of
|
|
%D \type{\specials}).
|
|
|
|
\ifnocontextobject \withoutpt \do
|
|
|
|
{\catcode`\.=\@@other
|
|
\catcode`\p=\@@other
|
|
\catcode`\t=\@@other
|
|
\gdef\WITHOUTPT#1pt{#1}}
|
|
|
|
\def\withoutpt#1%
|
|
{\expandafter\WITHOUTPT#1}
|
|
|
|
\def\ScaledPointsToBigPoints#1#2%
|
|
{\scratchdimen=#1sp\relax
|
|
\scratchdimen=.996264\scratchdimen
|
|
\edef#2{\withoutpt{\the\scratchdimen}}}
|
|
|
|
\def\ScaledPointsToWholeBigPoints#1#2%
|
|
{\scratchdimen=#1sp
|
|
\scratchdimen=.996264\scratchdimen
|
|
\scratchcounter=\scratchdimen
|
|
\advance\scratchcounter by 32768
|
|
\divide\scratchcounter by 65536
|
|
\edef#2{\the\scratchcounter}}
|
|
|
|
\fi
|
|
|
|
%D \macros
|
|
%D {doprocessfile}
|
|
%D
|
|
%D This macro takes three arguments: the file number, the
|
|
%D filename and a macro that handles the content of a read
|
|
%D line.
|
|
|
|
\newif\iffileprocessed
|
|
|
|
\ifnocontextobject \doprocessfile \do
|
|
|
|
\def\doprocessfile#1#2#3%
|
|
{\openin#1=#2\relax
|
|
\ifeof#1%
|
|
\fileprocessedfalse
|
|
\closein#1\relax
|
|
\else
|
|
\fileprocessedtrue
|
|
\gdef\dofinishfile%
|
|
{\closein#1\relax
|
|
\global\let\doprocessline\relax}%
|
|
\gdef\doprocessline%
|
|
{\ifeof#1%
|
|
\dofinishfile
|
|
\else
|
|
\global\read#1 to \fileline
|
|
#3\relax
|
|
\expandafter\doprocessline
|
|
\fi}%
|
|
\expandafter\doprocessline
|
|
\fi}
|
|
|
|
\fi
|
|
|
|
%D \macros
|
|
%D {uncatcodespecials}
|
|
%D
|
|
%D This one is taken from the \TEX\ book. The \CONTEXT\
|
|
%D alternative is a bit different, but we hope this one works
|
|
%D here.
|
|
|
|
\ifx\dospecials\undefined
|
|
|
|
\def\dospecials
|
|
{\do\ \do\\\do\{\do\}\do\$%
|
|
\do\#\do\^\do\_\do\&\do\%%
|
|
\do\~\do\^^A\do\^^K}
|
|
|
|
\fi
|
|
|
|
\ifnocontextobject \uncatcodespecials \do
|
|
|
|
\def\uncatcodespecials
|
|
{\def\do##1{\catcode`##1=12 }\dospecials
|
|
\catcode`\ =\@@space
|
|
\catcode`\^^L=\@@ignore
|
|
\catcode`\^^M=\@@endofline
|
|
\catcode`\^^?=\@@ignore}
|
|
|
|
\fi
|
|
|
|
\ifnocontextobject \setnaturalcatcodes \do
|
|
|
|
\def\setnaturalcatcodes
|
|
{\catcode`\!=\@@other \catcode`\?=\@@other \catcode`\@=\@@other
|
|
\catcode`\#=\@@other \catcode`\&=\@@other \catcode`\|=\@@other
|
|
\catcode`\$=\@@other \catcode`\^=\@@other \catcode`\_=\@@other
|
|
\catcode`\*=\@@other \catcode`\/=\@@other
|
|
\catcode`\-=\@@other \catcode`+=\@@other
|
|
\catcode`\==\@@other \catcode`\<=\@@other \catcode`\>=\@@other
|
|
\catcode`\"=\@@other \catcode`\'=\@@other \catcode`\`=\@@other
|
|
\catcode`\:=\@@other \catcode`\;=\@@other
|
|
\catcode`\,=\@@other \catcode`\.=\@@other \catcode`\~=\@@other
|
|
\catcode`\(=\@@other \catcode`\)=\@@other
|
|
\catcode`\{=\@@other \catcode`\}=\@@other
|
|
\catcode`\\=\@@other \catcode`\%=\@@other }
|
|
|
|
\fi
|
|
|
|
%D \macros
|
|
%D {doglobal}
|
|
%D
|
|
%D Some \CONTEXT\ low level macros can have a \type{\doglobal}
|
|
%D prefix. Let's just forget about that here:
|
|
|
|
\ifnocontextobject \doglobal \do \let\doglobal\relax \fi
|
|
|
|
%D The next obscure one is needed in the generic verbatim
|
|
%D environment. When we end up with more of these, it's time
|
|
%D to load the module \type{syst-gen}.
|
|
|
|
\ifnocontextobject \doifincsnameelse \do
|
|
|
|
\def\dodoifincsnameelse#1#2%
|
|
{\def\dododoifincsnameelse##1#1##2##3\war%
|
|
{\csname\if##2@iffalse\else iftrue\fi\endcsname}%
|
|
\expandafter\dododoifincsnameelse#2#1@@\war}
|
|
|
|
\long\def\doifincsnameelse#1#2#3#4%
|
|
{\edef\@@instring{#1}%
|
|
\expandafter\dodoifincsnameelse\expandafter{\@@instring}{#2}%
|
|
#3%
|
|
\else
|
|
#4%
|
|
\fi}
|
|
|
|
\fi
|
|
|
|
%D \macros
|
|
%D {dostepwiserecurse, dorecurse, doloop, exitloop}
|
|
%D
|
|
%D The next loop macro is a real weak one, and does not offer
|
|
%D the full \CONTEXT\ functionality, let alone nesting, but
|
|
%D for simple purposes, its behaviour is acceptable.
|
|
|
|
\newcount\recursecounter
|
|
|
|
\def\dostepwiserecurse#1#2#3#4% very weak and rubishly version
|
|
{\ifnum#2<#1\relax\else\dodostepwiserecurse{#1}{#2}{#3}{#4}\fi}
|
|
|
|
\def\dodostepwiserecurse#1#2#3#4% very weak and rubishly version
|
|
{\recursecounter=#1\relax
|
|
\loop
|
|
\edef\recurselevel{\the\recursecounter}%
|
|
#4\relax
|
|
\ifnum\recursecounter<#2\relax
|
|
\advance\recursecounter by #3\relax
|
|
\repeat}
|
|
|
|
\def\dorecurse#1%
|
|
{\dostepwiserecurse{1}{#1}{1}}
|
|
|
|
\def\doloop
|
|
{\dostepwiserecurse{1}{\maxdimen}{1}}
|
|
|
|
\def\exitloop
|
|
{\recursecounter=\maxdimen}
|
|
|
|
%D \macros
|
|
%D {ifundefined,doifdefined,doifundefined,
|
|
%D doifdefinedelse,doifundefinedelse}
|
|
%D
|
|
%D These alteratives are not robust but suitable for simple
|
|
%D usage. The official ones are a bit faster.
|
|
|
|
\ifnocontextobject \doifdefined \do
|
|
|
|
\def\ifundefined#1%
|
|
{\expandafter\ifx\csname#1\endcsname\relax}
|
|
|
|
\def\doifdefinedelse#1#2#3%
|
|
{\expandafter\ifx\csname#1\endcsname\relax#3\else#2\fi}
|
|
|
|
\def\doifundefinedelse#1#2#3%
|
|
{\expandafter\ifx\csname#1\endcsname\relax#2\else#3\fi}
|
|
|
|
\def\doifdefined#1#2%
|
|
{\expandafter\ifx\csname#1\endcsname\relax\else#2\fi}
|
|
|
|
\def\doifundefined#1#2%
|
|
{\expandafter\ifx\csname#1\endcsname\relax#2\fi}
|
|
|
|
\fi
|
|
|
|
%D \macros
|
|
%D {doifinstringelse}
|
|
%D
|
|
%D It seems like we end up with more and more macros here.
|
|
%D Sigh.
|
|
|
|
\ifnocontextobject \doifinstringelse \do
|
|
|
|
\def\p!doifinstringelse#1#2%
|
|
{\def\pp!doifinstringelse##1#1##2##3\war%
|
|
{\csname if\if##2@fals\else tru\fi e\endcsname}%
|
|
\expanded{\pp!doifinstringelse#2#1@@\noexpand\war}}
|
|
|
|
\long\def\doifinstringelse#1#2#3#4%
|
|
{\edef\@@@instring{#1}%
|
|
\@EA\p!doifinstringelse\@EA{\@@@instring}{#2}#3\else#4\fi}
|
|
|
|
\fi
|
|
|
|
%D \macros
|
|
%D {twodigitrounding}
|
|
%D
|
|
%D We don't support rounding outside \CONTEXT. Sorry.
|
|
|
|
\def\twodigitrounding#1{#1}
|
|
|
|
%D \macros
|
|
%D {lineheight}
|
|
%D
|
|
%D In \CONTEXT\ we have \type{\lineheight}, which in many
|
|
%D cases matches \type {\baselineskip}.
|
|
|
|
\ifnocontextobject \lineheight \do
|
|
|
|
\def\lineheight{\baselineskip}
|
|
|
|
\fi
|
|
|
|
%D \macros
|
|
%D {dohandletokens}
|
|
%D
|
|
%D The following macro is the simplified version, but good
|
|
%D enough for day to day hacks.
|
|
%D
|
|
%D \starttyping
|
|
%D \dohandletokens some text\with\somemacro
|
|
%D \stoptyping
|
|
|
|
\ifnocontextobject \dohandletokens \do
|
|
|
|
\def\dodohandletokens
|
|
{\ifx\next\end \else
|
|
\docommand{\next}%
|
|
\expandafter\dohandletokens
|
|
\fi}
|
|
|
|
\def\dohandletokens
|
|
{\afterassignment\dodohandletokens\let\next= }
|
|
|
|
\long\def\handletokens#1\with#2%
|
|
{\let\docommand=#2%
|
|
\dohandletokens#1\end}
|
|
|
|
\fi
|
|
|
|
%D Very reduced:
|
|
|
|
\long\def\appendtoks#1\to#2%
|
|
{\scratchtoks{#1}\expanded{#2{\the#2\the\scratchtoks}}}
|
|
|
|
%D Well, also handy.
|
|
|
|
\def\doiffileelse#1#2#3%
|
|
{\immediate\openin\scratchread=#1\relax
|
|
\ifeof\scratchread
|
|
\def\next{#3}%
|
|
\else
|
|
\def\next{#2}%
|
|
\fi
|
|
\immediate\closein\scratchread
|
|
\next}
|
|
|
|
%D New.
|
|
|
|
\let\donothing\empty
|
|
|
|
%D Also new:
|
|
|
|
\def\letempty #1{\let#1\empty}
|
|
\def\globalletempty#1{\global\let#1\empty}
|
|
|
|
\def\letvalueempty #1{\expandafter\let\csname#1\endcsname\empty}
|
|
\def\letgvalueempty#1{\global\expandafter\let\csname#1\endcsname\empty}
|
|
|
|
%D Sigh
|
|
|
|
\def\settrue #1{\chardef#1\zerocount}
|
|
\def\setfalse#1{\chardef#1\plusone}
|
|
|
|
\let\newconditional = \setfalse
|
|
\let\ifconditional = \ifcase
|
|
|
|
%D We could load \type {norm-tex} but this takes less hash space:
|
|
|
|
\let \normalif = \if
|
|
\let \normalifcase = \ifcase
|
|
\let \normalifcat = \ifcat
|
|
\let \normalifdim = \ifdim
|
|
\let \normalifeof = \ifeof
|
|
\let \normaliffalse = \iffalse
|
|
\let \normalifhbox = \ifhbox
|
|
\let \normalifhmode = \ifhmode
|
|
\let \normalifinner = \ifinner
|
|
\let \normalifmmode = \ifmmode
|
|
\let \normalifnum = \ifnum
|
|
\let \normalifodd = \ifodd
|
|
\let \normaliftrue = \iftrue
|
|
\let \normalifvbox = \ifvbox
|
|
\let \normalifvmode = \ifvmode
|
|
\let \normalifvoid = \ifvoid
|
|
\let \normalifx = \ifx
|
|
\let \normalfi = \fi
|
|
\let \normalelse = \else
|
|
|
|
\let \normalunexpanded = \unexpanded % beware the primitive, not the context one
|
|
|
|
%D That's it. Please forget this junk and take a look at how
|
|
%D it should be done.
|
|
|
|
\StopLatexHack \protect \endinput
|
|
|