regi-ini.mkii / last modification: 2020-01-30 14:15
%D \module
%D   [       file=regi-ini,
%D        version=2000.12.27, % 1998.12.03,
%D          title=\CONTEXT\ Regime Macros,
%D       subtitle=Initialization,
%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.

\unprotect

%D Remark: regimes accumulate, so there is no explicit reset in
%D mkii mode.

%D Variables.

\def\@reg@{@r@eg@} % regime prefix

%D \macros
%D   {currentregime}

\let\currentregime\empty
\let\defaultregime\s!default

%D Some low level inheritance stuff (mkii).

\def\doautosetregime#1#2%
  {\ifnum#2>127
     \expanded{\defineactivetoken #2 \@EA\noexpand\csname#1\endcsname}%
   \fi}

%D \macros
%D   {startregime}
%D
%D Sometimes it makes sense to activate the characters in the
%D upper half of the character table. Such a bundle of
%D characters can be packages in a regime. Later we will see
%D encodings (that links characters slots to glyphs) and
%D mappings (that take care of hyphenation and case changes).
%D
%D When character~231 is of category code letter, it
%D directly maps to glyph~231 (unless of course some virtual
%D font is used). By making character~231 active, we can map
%D it onto for instance the glyph in slot 233. This mapping
%D can in itself be indirect, in the sense that it is for
%D instance handled by an accent command.
%D
%D Regimes are implemented roughly the same as mappings, but
%D enabled under different circumstances. In the future, the
%D low level implementation may change.

\def\startregime[#1]%
  {\pushmacro\currentregime
   \edef\currentregime{#1}%
   \checkregimetoks}

\def\checkregimetoks
  {\doifundefined{\@reg@\currentregime}
     {\@EA\newtoks\csname\@reg@\currentregime\endcsname}}

\def\stopregime
  {\popmacro\currentregime}

\def\setregimetoks
  {\checkregimetoks
   \@EA\let\@EA\regimetoks\csname\@reg@\currentregime\endcsname}

%D \macros
%D   {defineactivedecimal, defineactivedecimals, defineactivetoken}
%D
%D The following commands are rather ugly ones. It makes a
%D character active and assigns it a value. When expanded,
%D the decimal number of the character is passed as first
%D argument.
%D
%D \starttyping
%D \def\decimalcharacter#1{\message{#1 is now active}}
%D
%D \defineactivedecimal 122 {\decimalcharacter}
%D
%D \defineactivedecimals 128 to 255 as {\decimalcharacter}
%D \stoptyping
%D
%D This command is typically used in coding definitions,
%D like the \UNICODE\ one.

\def\dodefineactivedecimal#1#2% \unexpanded ? pdfdoc encoding
  {\catcode#1\active
   \scratchcounter\uccode\activehackcode
   \uccode\activehackcode#1\relax
   \uppercase{\unexpanded\edef~{\noexpand#2{\number#1}}}%
   \uccode\activehackcode\scratchcounter}

\long\def\defineactivedecimal#1 #2 %
  {\setregimetoks
   \regimetoks\expandafter{\the\regimetoks\dodefineactivedecimal{#1}{#2}}}

\long\def\defineactivedecimals#1 to #2 as #3 %
  {\setregimetoks
   \dostepwiserecurse{#1}{#2}\plusone
     {\regimetoks\@EA\@EA\@EA{\@EA\the\@EA\regimetoks\@EA\dodefineactivedecimal\@EA{\recurselevel}{#3}}}}

\def\doexpandactivedecimal#1%
  {\ifnum#1>\scratchcounter
     \expandafter\gobbletwoarguments
   \else
     \noexpand\dodefineactivedecimal{#1}{\the\scratchtoks}%
     \expandafter\expandafter\expandafter\doexpandactivedecimal\expandafter
   \fi\expandafter{\the\numexpr#1+\plusone\relax}}

\long\def\defineactivedecimals#1 to #2 as #3 %
  {\setregimetoks
   \scratchcounter#2\relax
   \scratchtoks{#3}%
   \expanded{\regimetoks{\the\regimetoks\doexpandactivedecimal{#1}}}%
   \ignorespaces}

\long\def\defineactivetoken #1 #2% no {} after #2, else no kern
  {\setregimetoks
   \regimetoks\expandafter{\the\regimetoks\defineactivecharacter#1 {#2}}}

\long\def\defineactiveinspector #1 #2% watch the missing {}
  {\setregimetoks
   \regimetoks\expandafter{\the\regimetoks\defineactivecharacter#1 {#2}}}

%D \macros
%D   {defineregimesynonym,trueregimename}

\def\defineregimesynonym
  {\dodoubleargument\dodefineregimesynonym}

\def\dodefineregimesynonym[#1][#2]%
  {\setevalue{\@reg@:s:#1}{#2}}

\def\trueregimename#1%
  {\executeifdefined{\@reg@:s:#1}{#1}}

%D \macros
%D   {useregime}

\def\useregime[#1]%
  {\processcommalist[#1]\douseregime}

\def\douseregime#1%
  {\doifundefined{\c!file\f!regimeprefix#1}%
     {\letgvalue{\c!file\f!regimeprefix#1}\empty
      \makeshortfilename[\truefilename{\f!regimeprefix#1}]%
      \startreadingfile
        \readsysfile{\shortfilename.mkii}
          {\showmessage\m!regimes2{#1}}
          {\showmessage\m!regimes3{#1}}%
      \stopreadingfile}}

%D \macros
%D   {enableregime,disableregime}

\let\enabledregime\empty

\def\enableregime[#1]%
  {\edef\currentregime{\trueregimename{#1}}%
   \doifelsenothing\currentregime
     {\disableregime}
     {\douseregime\currentregime
      \the\executeifdefined{\@reg@\currentregime}\emptytoks}}

\def\disableregime
  {\let\currentregime\empty}

%D \macros
%D   {protectregime, settoletterunlessactive, settocodeunlessactive}
%D
%D The next boolean is used later on to prevent unwanted
%D catcode changes. Use it with care.

\newif\ifprotectregime \protectregimetrue

\def\settoletterunlessactive#1%
  {\ifprotectregime\ifnum\catcode#1=\active\else
     \catcode#1\@@letter
   \fi\else
     \catcode#1\@@letter
   \fi}

\def\settootherunlessactive#1%
  {\ifprotectregime\ifnum\catcode#1=\active\else
     \catcode#1=\@@other
   \fi\else
     \catcode#1=\@@other
   \fi}

\def\settocodeunlessactive#1#2%
  {\ifprotectregime\ifnum\catcode#1=\active\else
     \catcode#1=#2\relax
   \fi\else
     \catcode#1=#2\relax
   \fi}

%D Goodie:

\def\showregime[#1]%
  {\doifnot{#1}{utf}
     {\bgroup
      \enableregime[#1]%
      \starttabulate[|l|l|l|]
      \dostepwiserecurse{128}{255}{1}
        {\expanded
           {\scantokens
              {\NC \recurselevel
               \NC \rawcharacter\recurselevel
               \NC \noexpand\tttf
                   \noexpand\meaning\rawcharacter\recurselevel \NC \NR}}}%
      \stoptabulate
      \unskip
      \egroup}}

%D Sort related:

\def\dowalkregime#1%
  {\the\executeifdefined{\@reg@#1}\emptytoks}

%D Simplify matters for \XETEX.

\ifnum\texengine=\xetexengine

    \def\enableregime[#1]%
      {\doifelse{#1}{utf}%
         {\writestatus\m!regimes{mapping utf to utf-8}%
          \XeTeXinputencoding{utf-8}}
         {\XeTeXinputencoding{#1}}}

    \def\disableregime
      {\XeTeXinputencoding{utf-8}}

    \def\loadregime[#1]{}
    \let\walkregime      \gobbleoneargument
    \let\doautosetregime \gobbletwoarguments

\else

    \useregime[def,uni,utf] % we load the rest runtime

\fi

\protect \endinput