%D \module
%D   [       file=core-nav,
%D        version=1995.01.01,
%D          title=\CONTEXT\ Core Macros,
%D       subtitle=New ones,
%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 Core Macros / New Ones}

\unprotect

% Some kind of new feature, for the moment a private one.
%
% \enablemode[screen,paper,bound]
%
% \doifmodeelse {paper}        {this} {that}
% \doifmode     {paper,screen} {this}
% \doifnotmode  {paper,bound}  {that}
%
% \startmode [list]
% \stopmode
%
% \startnotmode [list]
% \stopnotmode
%
% system modes have a * as prefix
%
% to be implemented: mode naar texutil/scherm + message
%                  : geen #2 en nesting (\startregels)

%D Sometimes, we want to prevent a mode for being set. Think
%D of situations where a style enables a mode, but an outer
%D level style does not want that. Preventing can be
%D considered a permanent disabling on forehand.

% \def\systemmodeprefix{*}
%
% \let\currentmode   \empty
% \let\preventedmodes\empty
%
% \def\preventmode[#1]%
%   {\expanded{\addtocommalist{#1}\noexpand\preventedmodes}}
%
% \def\enablemode[#1]%
%   {\expanded
%      {\doifnotinset{#1}{\preventedmodes}
%         {\noexpand\addtocommalist{#1}\noexpand\currentmode}}}
%
% \def\disablemode[#1]%
%   {\expanded{\removefromcommalist{#1}\noexpand\currentmode}}
%
% \def\doifmodeelse{\unprotect\dodoifmodeelse}
% \def\doifmode    {\unprotect\dodoifmode    }
% \def\doifnotmode {\unprotect\dodoifnotmode }
% \def\startmode   {\unprotect\dostartmode   }
% \def\startnotmode{\unprotect\dostartnotmode}
%
% \long\def\dodoifmodeelse#1%
%   {\protect\expanded{\doifcommonelse{#1}{\currentmode}}}
%
% \long\def\dodoifmode#1%
%   {\protect\expanded{\doifcommon    {#1}{\currentmode}}}
%
% \long\def\dodoifnotmode#1%
%   {\protect\expanded{\doifnotcommon {#1}{\currentmode}}}
%
% \let\stopmode   \relax
% \let\stopnotmode\relax
%
% \long\def\dostartmode[#1]%
%   {\protect
%    \expanded{\doifnotcommon{#1}{\currentmode}}{\gobbleuntil\stopmode}}
%
% \long\def\dostartnotmode[#1]%
%   {\protect
%    \expanded{\doifcommon   {#1}{\currentmode}}{\gobbleuntil\stopnotmode}}
%
% \def\doifallmodeselse{\unprotect\dodoifallmodeselse}
% \def\doifallmodes    {\unprotect\dodoifallmodes}
% \def\doifnotallmodes {\unprotect\dodoifnotallmodes}
% \def\startallmodes   {\unprotect\dostartallmodes}
% \def\startnotallmodes{\unprotect\dostartnotallmodes}
%
% \long\def\dodoifallmodeselse#1%
%   {\protect\expanded{\doifallcommonelse{#1}{\currentmode}}}
%
% \long\def\dodoifallmodes#1%
%   {\protect\expanded{\doifallcommon    {#1}{\currentmode}}}
%
% \long\def\dodoifnotallmodes#1%
%   {\protect\expanded{\doifnotallcommon {#1}{\currentmode}}}
%
% \let\stopallmodes   \relax
% \let\stopnotallmodes\relax
%
% \long\def\dostartallmodes[#1]%
%   {\protect
%    \expanded{\doifnotallcommon{#1}{\currentmode}}{\gobbleuntil\stopallmodes}}
%
% \long\def\dostartnotallmodes[#1]%
%   {\protect
%    \expanded{\doifallcommon   {#1}{\currentmode}}{\gobbleuntil\stopnotallmodes}}

% faster

\def\@mode@{@md@}

\def\systemmodeprefix{*}

\def\disabledmode    {0}
\def\enabledmode     {1}
\def\preventedmode   {2}

% fast internal ones

\def\setmode  #1{\@EA\let\csname\@mode@#1\endcsname\enabledmode }
\def\resetmode#1{\@EA\let\csname\@mode@#1\endcsname\disabledmode}

\def\setsystemmode  #1{\@EA\let\csname\@mode@\systemmodeprefix#1\endcsname\enabledmode }
\def\resetsystemmode#1{\@EA\let\csname\@mode@\systemmodeprefix#1\endcsname\disabledmode}

% user ones

\def\preventmode{\unprotect\dopreventmode}
\def\enablemode {\unprotect\doenablemode }
\def\disablemode{\unprotect\dodisablemode}

\def\dopreventmode[#1]{\protect\rawprocesscommalist[#1]\dodopreventmode}
\def\doenablemode [#1]{\protect\rawprocesscommalist[#1]\dodoenablemode }
\def\dodisablemode[#1]{\protect\rawprocesscommalist[#1]\dododisablemode}

\def\dodopreventmode#1%
  {\@EA\let\csname\@mode@#1\endcsname\preventedmode}

\def\dodoenablemode#1%
  {\ifcase0\csname\@mode@#1\endcsname\relax
     \@EA\let\csname\@mode@#1\endcsname\enabledmode
   \fi}

\def\dododisablemode#1%
  {\ifcase0\csname\@mode@#1\endcsname\or
     \@EA\let\csname\@mode@#1\endcsname\disabledmode
   \fi}

% check macros

\newif\ifcheckedmode

\def\dodocheckformode#1%
  {\ifcase0\csname\@mode@#1\endcsname\or\checkedmodetrue\fi}

\def\docheckformode#1#2#3% will be sped up with a quit
  {\protect\checkedmodefalse\rawprocesscommalist[#3]\dodocheckformode
   \ifcheckedmode\@EA#1\else\@EA#2\fi}

\def\dodocheckforallmodes#1%
  {\ifcase0\csname\@mode@#1\endcsname\relax
     \checkedmodefalse\or\or\checkedmodefalse\fi}

\def\docheckforallmodes#1#2#3% will be sped up with a quit
  {\protect\checkedmodetrue\rawprocesscommalist[#3]\dodocheckforallmodes
   \ifcheckedmode\@EA#1\else\@EA#2\fi}

% simple ones

\def\doifmodeelse{\unprotect\dodoifmodeelse}
\def\doifmode    {\unprotect\dodoifmode}
\def\doifnotmode {\unprotect\dodoifnotmode}
\def\startmode   {\unprotect\dostartmode}
\def\startnotmode{\unprotect\dostartnotmode}

\def\dodoifmodeelse
  {\docheckformode\firstoftwoarguments\secondoftwoarguments}

\def\dodoifmode
  {\docheckformode\firstofoneargument\gobbleoneargument}

\def\dodoifnotmode
  {\docheckformode\gobbleoneargument\firstofoneargument}

\long\def\dostartmode[#1]%
  {\docheckformode\donothing\dostopmode{#1}}

\long\def\dostartnotmode[#1]%
  {\docheckformode\dostopnotmode\donothing{#1}}

\let\stopmode   \donothing
\let\stopnotmode\donothing

\long\def\dostopmode   #1\stopmode   {}
\long\def\dostopnotmode#1\stopnotmode{}

\def\doifallmodeselse{\unprotect\dodoifallmodeselse}
\def\doifallmodes    {\unprotect\dodoifallmodes}
\def\doifnotallmodes {\unprotect\dodoifnotallmodes}
\def\startallmodes   {\unprotect\dostartallmodes}
\def\startnotallmodes{\unprotect\dostartnotallmodes}

\def\doifallmodeselse
  {\docheckforallmodes\firstoftwoarguments\secondoftwoarguments}

\def\doifallmodes
  {\docheckforallmodes\firstofoneargument\gobbleoneargument}

\def\doifnotallmodes
  {\docheckforallmodes\gobbleoneargument\firstofoneargument}

\long\def\dostartallmodes[#1]%
  {\docheckforallmodes\donothing\dostopallmodes{#1}}

\long\def\dostartnotallmodes[#1]%
  {\docheckforallmodes\dostopallmodes\donothing{#1}}

\let\stopallmodes   \donothing
\let\stopnotallmodes\donothing

\long\def\dostopallmodes   #1\stopallmodes   {}
\long\def\dostopnotallmodes#1\stopnotallmodes{}

% \def\setups
%   {\dosingleargument\dosetups}
%
% \def\dosetups[#1]%
%   {\iffirstargument
%      \def\next{\dodosetups{#1}}%
%    \else
%      \let\next\dodosetups
%    \fi
%    \next}
%
% \def\dodosetups#1%
%   {\processcommalist[#1]\dododosetups}
%
% \def\dododosetups#1%
%   {\getvalue{\??su#1}}
%
% \def\doifsetupselse#1%
%   {\doifdefinedelse{\??su#1}}
%
% \long\@EA\def\csname\e!start\v!instellingen\endcsname#1 %
%   {\bgroup
%    \catcode`\^^M=\@@ignore
%    \xdostartsetups{#1}}
%
% \expanded
%   {\long\noexpand\def\noexpand\xdostartsetups##1##2\csname\e!stop\v!instellingen\endcsname
%      {\egroup
%       \long\noexpand\setvalue{\??su##1}{##2}}}
%
% \def\startsetups % for international purposes
%   {\bgroup\doifnextcharelse[{\startsetupsA\stopsetups}{\startsetupsB\stopsetups}}
%
% \def\startlocalsetups % for nested purposes
%   {\bgroup\doifnextcharelse[{\startsetupsA\stoplocalsetups}{\startsetupsB\stoplocalsetups}}
%
% \def\startsetupsA#1[#2]%
%   {\catcode`\^^M=\@@ignore
%    \dostartsetups#1{#2}}
%
% \def\startsetupsB#1#2 % space delimited
%   {\startsetupsA#1[#2]}%
%
% \long\def\dostartsetups#1#2% watch out: not \grabuntil
%   {\dograbuntil#1{\egroup\long\setvalue{\??su#2}}}

% todo : \startsetups[name][XML] \setups[name][XML]

\expanded
  {\long\def\@EA\noexpand\csname\e!start\v!setups\endcsname
     {\bgroup\noexpand\doifnextcharelse[%
        {\noexpand\startsetupsA\@EA\noexpand\csname\e!stop\v!setups\endcsname}
        {\noexpand\startsetupsB\@EA\noexpand\csname\e!stop\v!setups\endcsname}}}

\letvalue{\e!stop\v!setups}\relax

\unexpanded \def\setups{\doifnextcharelse\bgroup\dosetupsA\dosetupsB} % {..} or [..]
\unexpanded \def\setup {\doifnextcharelse\bgroup\dosetups \dosetupsC} % {..} or [..]

\def\dosetupsA  #1{\processcommacommand[#1]\dosetups} % {..}
\def\dosetupsB[#1]{\processcommacommand[#1]\dosetups} % [..]
\def\dosetupsC[#1]{\dosetups{#1}} % [..]

\def\dosetups#1% the grid option will be extended to other main modes
  {\executeifdefined{\??su\ifgridsnapping\v!grid\fi:#1}{\csname\??su:#1\endcsname}\empty}

\let\directsetup\dosetups

\def\doifsetupselse#1% to be done: grid
  {\doifdefinedelse{\??su:#1}}

\chardef\setupseolmode\plusone

\def\startsetups     {\xxstartsetups\plusone  \stopsetups     } \let\stopsetups     \relax
\def\startlocalsetups{\xxstartsetups\plusone  \stoplocalsetups} \let\stoplocalsetups\relax
\def\startrawsetups  {\xxstartsetups\zerocount\stoprawsetups  } \let\stoprawsetups  \relax

\def\xxstartsetups#1#2%
  {\bgroup\chardef\setupseolmode#1\doifnextcharelse[{\startsetupsA#2}{\startsetupsB#2}}

\def\startsetupsA#1% [ ] delimited
  {\ifcase\setupseolmode\or\catcode`\^^M\@@ignore\fi
   \dotripleempty\dostartsetups[#1]}

\def\startsetupsB#1#2 % space delimited
  {\ifcase\setupseolmode\or\catcode`\^^M\@@ignore\fi
   \dodostartsetups#1\empty{#2}}

\def\startsetupsC[#1][#2][#3]{\dodostartsetups#1{#2}{#3}}   % [..] [..]
\def\startsetupsD[#1][#2][#3]{\dodostartsetups#1\empty{#2}} % [..]

\def\dostartsetups
  {\ifthirdargument\@EA\startsetupsC\else\@EA\startsetupsD\fi}

\long\def\dodostartsetups#1#2#3% watch out: not \grabuntil
  {\dograbuntil#1{\egroup\long\setvalue{\??su#2:#3}}}

\def\systemsetupsprefix{*}

\def\systemsetups#1{\dosetups{\systemsetupsprefix#1}}

\def\resetsetups[#1]% see x-fo for usage
  {\ifundefined{\??su\ifgridsnapping\v!grid\fi:#1}%
     \letbeundefined{\??su:#1}%
   \else
     \letbeundefined{\??su\ifgridsnapping\v!grid\fi:#1}%
   \fi}

% or
%
% \def\resetsetups[#1]%
%   {\letbeundefined
%      {\??su:%
%       \ifundefined{\??su\ifgridsnapping\v!grid\fi:#1}#1\else\ifgridsnapping\v!grid\fi%
%       #1}}

% new
%
% \startnointerference
% all kind of code
% \stopnointerference

\newbox\nointerferencebox

\def\startnointerference
  {\setbox\nointerferencebox\vbox
   \bgroup}

\def\stopnointerference
  {\egroup
   \setbox\nointerferencebox\box\voidb@x}

%D new and beta

% \def\defineshortcut
%   {\dodoubleargument\dodefineshortcut}
%
% \bgroup
%
%   \catcode`\<=\@@active
%
%   \gdef\dodefineshortcut[#1][#2]%
%     {\ifsecondargument
%        \catcode`\<=\@@active
%        \def<{\ifmmode\expandafter\normalless\else\expandafter\doshortcut\fi}%
%        \getparameters[\??te#1][\c!commands=,\c!command=,\c!style=,\c!color=,#2]%
%      \else
%        \defineshortcut[][#1]%
%      \fi}
%
% \egroup
%
% \def\doshortcut
%   {\bgroup
%    \catcode`\>=\@@other
%    \dodoshortcut}
%
% \def\dodoshortcut#1>%
%   {\def\shortcut{#1}%
%    \dododoshortcut#1:\end}
%
% \def\dododoshortcut#1:#2\end
%   {\doifelsenothing{#2}
%      {\doifundefinedelse{\??te\c!commands}
%         {\shortcut}
%         {\@EA\dodododoshortcut\@EA\??te\@EA:\shortcut:\end}}
%      {\doifundefinedelse{\??te#1\c!commands}
%         {\shortcut}
%         {\dodododoshortcut\??te#1:#2\end}}%
%    \egroup}
%
% \def\dodododoshortcut#1:#2:\end
%   {\getvalue{#1\c!commands}%
%    \doattributes{#1}\c!style\c!color{\getvalue{#1\c!command}{#2}}}

\def\defineshortcut
  {\dotripleargument\dodefineshortcut}

\def\dodefineshortcut[#1][#2][#3]%
  {\ifthirdargument
     \ConvertConstantAfter\doifelse{#1}{}
       {\dododefineshortcut[<>][#2][#3]}
       {\dododefineshortcut[#1][#2][#3]}%
   \else\ifsecondargument
     \dododefineshortcut[<>][#1][#2]%
   \else
     \dododefineshortcut[<>][][#1]%
   \fi\fi}

\def\dododefineshortcut[#1#2][#3][#4]% #1 is the trigger, #2 the delimiter/tag
  {\doifundefined{\??te\??te\string#2}{\letvalue{\??te\??te\string#2}=#1}%
   \defineactivecharacter #1 {\@EA\doshortcut\string#2} %
   \getparameters
     [\??te\string#2#3]
     [\c!commands=,\c!command=,\c!style=,\c!color=,#4]}

\def\doshortcut#1%
  {\ifmmode
     \getvalue{\??te\??te#1}%
   \else
     \bgroup
     \catcode`#1=\@@other
     \def\dodoshortcut##1#1%
       {\def\shorttag{\??te#1}%
        \def\shortcut{##1}%
        \dododoshortcut##1:\end}%
     \@EA\dodoshortcut
   \fi}

\def\dododoshortcut#1:#2\end
  {\doifelsenothing{#2}
     {\doifundefinedelse{\shorttag\c!commands}
        {\shortcut}
        {\@EA\dodododoshortcut\@EA\shorttag\@EA:\shortcut:\end}}
     {\doifundefinedelse{\shorttag#1\c!commands}
        {\shortcut}
        {\dodododoshortcut\shorttag#1:#2\end}}%
   \egroup}

\def\dodododoshortcut#1:#2:\end
  {\getvalue{#1\c!commands}%
   \doattributes{#1}\c!style\c!color{\getvalue{#1\c!command}{#2}}}

%D \defineshortcut     [style=type]
%D \defineshortcut [b] [style=bold]
%D \defineshortcut [e] [style=\em]
%D \defineshortcut [t] [style=type]
%D \defineshortcut [c] [style=cap]
%D \defineshortcut [k] [style=cap]
%D \defineshortcut [u] [style=type,command=\hyphenatedurl]
%D
%D \startlines
%D test <ziezo> test
%D test test <t:ziezo>
%D test test <b:ziezo>
%D test test <w:ziezo>
%D zus<>zo zus<:>zo zus<::>zo
%D test test <t:ziezo> dat (ziezo)
%D test test <t::ziezo> dat (:ziezo)
%D test test <t:ziezo:> dat (ziezo:)
%D test test <t:zi:ezo:> dat (zi:ezo:)
%D well, <u:http://www.pragma-ade.nl> looks fuzzy
%D $10<20$
%D \stoplines
%D
%D \defineshortcut [<>] [i] [style=\it]
%D \defineshortcut [()] [b] [style=\bf]
%D \defineshortcut [++] [s] [style=\sl]
%D \defineshortcut [//] [u] [style=\underbars]
%D \defineshortcut [--] [a] [style=\overstrike]
%D
%D \startlines
%D it seems <i:to work> well
%D it seems (b:to work) well
%D it seems +s:to work+ well
%D it seems /u:to work/ well
%D it seems -a:to work- well
%D \stoplines

% \def\setupenv{\dodoubleargument\rawgetparameters[\??en]}
%
% \def\doifenvelse#1{\doifdefinedelse{\??en#1}} % speed up
% \def\doifenv    #1{\doifdefined    {\??en#1}} % speed up
% \def\doifnotenv #1{\doifundefined  {\??en#1}} % speed up
%
% \def\env#1{\csname\??en#1\endcsname}
%
% \beginTEX
%
% \def\envvar#1#2%
%   {\@EA\ifx\csname\??en#1\endcsname\relax
%      #2\else\csname\??en#1\endcsname
%    \fi}
%
% \endTEX
%
% \beginETEX \ifcsname
%
% \def\envvar#1#2%
%   {\ifcsname\??en#1\endcsname
%      \csname\??en#1\endcsname\else#2%
%    \fi}
%
% \endETEX

% low level change, now also accessible as \getvariable{environment}{...}; the
% next macros will become obsolete some day in favor of normal variables

\def\s!environment{environment}

\def\setupenv   {\dotripleargument\dosetvariables[\getrawparameters][\s!environment]}
\def\doifenvelse{\doifelsevariable  \s!environment}
\def\doifenv    {\doifvariable      \s!environment}
\def\doifnotenv {\doifnotvariable   \s!environment}
\def\env        {\getvariable       \s!environment}
\def\envvar     {\getvariabledefault\s!environment}

\bgroup

\gdef\cleanedupcolon{:} \catcode`:=\@@active

\gdef\cleanuplabel#1%
  {\bgroup\let:\cleanedupcolon
   \xdef\cleanlabel{#1}%
   \egroup}

\gdef\cleanupprefixedlabel#1#2%
  {\bgroup\let:\cleanedupcolon
   \xdef\cleanprefix{#1}%
   \xdef\cleanlabel {#2}%
   \egroup}

\gdef\protectlabels
  {\let:\cleanedupcolon}

\global\def\blabelgroup {\bgroup \let:\cleanedupcolon}
\global\let\elabelgroup  \egroup

\gdef\labelcsname
  {\bgroup\let:\cleanedupcolon
   \expandafter\egroup\csname}

\gdef\labelvalue#1%
  {\labelcsname#1\endcsname}

\egroup

\protect \endinput
