%D \module
%D   [       file=lang-spe,
%D        version=2002.05.07, % 1996.01.25,
%D          title=\CONTEXT\ Language Macros,
%D       subtitle=Specifics,
%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.

%D This code was originally placed in the language
%D initialization module, but isolating it is clearer. Language
%D specifics evolved out of user demands for special features,
%D like the german active quote. After a while I decided to
%D associate them to languages in a more general way so that we
%D could associate all kind of things with language switching.
%D
%D This is a typical example of functionality that occasionally
%D gets improved based on user input and experience. Much of the
%D code is pretty old and could probabbly be done in better ways.
%D It's probably also the kind of code that has been and will be
%D written over and over again by \TEX\ users around the world,
%D so there are probably better implementations of similar
%D functionality around. Therefore, users are invited to pop in
%D their own handling as long as it does not interfere with
%D existing code. Writing the more obscure macros that deal with
%D this is a good learning experience (catcodes, lccodes, token
%D lists, expansion, \unknown).

\writestatus{loading}{Context Language Macros / Specifics}

\unprotect

%D \macros
%D   {everyresetlanguagespecifics,resetlanguagespecifics}
%D
%D Cleanup macros.

\newevery \everyresetlanguagespecifics \relax

\def\resetlanguagespecifics
  {\ifcase\protectionlevel
     \the\everyresetlanguagespecifics
   \else % to be translated
     % \writestatus\m!systems{don't change language in unprotected mode!}%
   \fi}

\appendtoks
  \resetlanguagespecifics
\to \everycleanupfeatures

%D \macros
%D   {startlanguagespecifics,enablelanguagespecifics}
%D
%D Each language has its own typographic pecularities. Some of
%D those can be influenced by parameters, others are handled by
%D the interface, but as soon as specific commands come into
%D view we need another mechanism. In the macro that activates
%D a language, we call \type{\enablelanguagespecifics}. This
%D macro in return calls for the setup of language specific
%D macros. Such specifics are defined as:
%D
%D \starttyping
%D \startlanguagespecifics[de]
%D   \installcompoundcharacter "a {\"a}
%D   \installcompoundcharacter "e {\"e}
%D   \installcompoundcharacter "s {\SS}
%D \stoplanguagespecifics
%D \stoptyping
%D
%D Instead of \type{[du]} we can pass a comma separated
%D list, like \type{[du,nl]}. Next calls to this macro add the
%D specifics to the current list.
%D
%D Before we actually read the specifics, we first take some
%D precautions that will prevent spurious spaces to creep into
%D the list.

\def\startlanguagespecifics%                % we use double to
  {\bgroup
   \catcode`\^^I=\@@ignore
   \catcode`\^^M=\@@ignore
   \catcode`\^^L=\@@ignore
   \dodoubleempty\dostartlanguagespecifics} % get rid of spaces

%D The main macro looks quite complicated but actually does
%D nothing special. By embedding \type{\do} we can easily
%D append to the lists and also execute them at will. Just to
%D be sure, we check on spurious spaces. The second dummy
%D argument gobbles spaces.

\def\languageencoding
  {\ifx\characterencoding\nocharacterencoding \else
     \characterencoding-%
   \fi}

% \long\def\dostartlanguagespecifics[#1][#2]#3\stoplanguagespecifics%
%   {\egroup
%    \long\def\docommando##1%
%      {\doifdefinedelse{\??la\languageencoding##1\??la}
%         {\long\def\do####1####2####3%
%            {\setvalue{\??la\languageencoding####1\??la}{\do{####1}{####2####3}}}%
%          \getvalue{\??la\languageencoding##1\??la}{#3}}
%         {\setvalue{\??la\languageencoding##1\??la}{\do{##1}{#3}}}%
%       \bgroup
%       \setbox0\hbox{\enablelanguagespecifics[##1]}%
%       \ifdim\wd0>\zeropoint
%         \showmessage\m!linguals7{\currentencoding-##1,\the\wd0\space}\wait
%       \else
%         \showmessage\m!linguals8{\currentencoding-##1}%
%       \fi
%       \egroup
%       \doif{##1}{\currentmainlanguage}
%         {\enablelanguagespecifics[##1]}}%
%    \processcommalist[#1]\docommando}

% This saves 3K in the fmt file.

% This should be a token register, but alas, we run out of them and
% \ETEX\ has a bug.

\long\def\dostartlanguagespecifics[#1][#2]#3\stoplanguagespecifics
  {\egroup
   \processcommalist[#1]{\dosetlanguagespecifics{#3}}}

% \long\def\dosetlanguagespecifics#1#2%
%   {\doifdefinedelse{\??la\languageencoding#2\??la}
%      {\long\def\do##1##2##3{\setvalue{\??la\languageencoding##1\??la}{\do{##1}{##2##3}}}%
%       \getvalue{\??la\languageencoding#2\??la}{#1}}
%      {\setvalue{\??la\languageencoding#2\??la}{\do{#2}{#1}}}%
%    \bgroup
%    \setbox\scratchbox\hbox{\enablelanguagespecifics[#2]}%
%    \ifdim\wd\scratchbox>\zeropoint
%      \showmessage\m!linguals7{\currentencoding-#2,\the\wd\scratchbox\space}\wait
%    \else
%      \showmessage\m!linguals8{\currentencoding-#2}%
%    \fi
%    \egroup
%    \doif{#2}\currentmainlanguage
%      {\enablelanguagespecifics[#2]}}

\long\def\dosetlanguagespecifics#1#2%
  {%ifundefined{\??la\languageencoding#2\??la}\letvalue{\??la\languageencoding#2\??la}\empty\fi
   \ifundefined{\??la\languageencoding#2\??la}\forgetlanguagespecifics[#2]\fi
   \appendvalue{\??la\languageencoding#2\??la}{#1}%
   \bgroup
   \setbox\scratchbox\hbox{\enablelanguagespecifics[#2]}%
   \ifdim\wd\scratchbox>\zeropoint
     \showmessage\m!linguals7{\currentencoding-#2,\the\wd\scratchbox\space}\wait
   \else
     \showmessage\m!linguals8{\currentencoding-#2}%
   \fi
   \egroup
   \doif{#2}\currentmainlanguage{\enablelanguagespecifics[#2]}}

\def\forgetlanguagespecifics[#1]%
  {\letvalue{\??la\languageencoding#1\??la}\empty}

%D Enabling them is rather straightforward. We only have to
%D define \type{\do} in such a way that \type{{ }} is removed
%D and the language key is gobbled.

%\def\enablelanguagespecifics[#1]%
%  {\let\do\secondoftwoarguments
%   \doifvaluesomething{\??la#1\c!default}
%     {\getvalue{\??la\getvalue{\??la#1\c!default}\??la}%
%      \getvalue{\??la\languageencoding\??la}}%
%   \getvalue{\??la#1\??la}%
%   \getvalue{\??la\languageencoding#1\??la}}
%
% sped up since used often:

\def\enablelanguagespecifics[#1]%
  {%\let\do\secondoftwoarguments
   \csname
     \??la
     \@EA\ifx\csname\??la#1\c!default\endcsname\relax
       \languageencoding
     \else
       \csname\??la#1\c!default\endcsname
     \fi
     \??la
   \endcsname
   \csname\??la#1\??la\endcsname
   \csname\??la\languageencoding#1\??la\endcsname} % dup ?

%D \macros
%D   {deactivatelanguagespecific}
%D
%D The next code makes it possible to disable the specifics.

\def\deactivatelanguagespecific#1%
  {\ifundefined{l g s \string#1}%
     \letgvalueempty{l g s \string#1}% signal to prevent dup def
     \bgroup
     \catcode`#1=\@@active
     \uccode`~=`#1
     \uppercase{\doglobal\appendtoks\dodeactivatetoken{~}\to\everyresetlanguagespecifics}%
     \egroup
     \expanded{\doglobal\noexpand\appendtoks{#1}{\the\catcode`#1}}\to\everyresetlanguagespecifics
   \fi}

% \def\dodeactivatetoken#1#2#3%
%   {\def#1{#2}\catcode`#2=#3\relax}

\def\dodeactivatetoken#1#2#3% test needed to avoid clash with \unprotect
  {\def#1{#2}\ifnum\catcode`#2=\@@active\catcode`#2=#3\relax\fi}

%D We cannot hook this into the installer since language
%D specifics can be anything. So far, we have the following
%D potentially active characters.

%D Beware, this should happen under an unprotected regime;
%D thanks to Giuseppe Oblomov Bilotta, who first noticed
%D that something was wrong.

\protect

\deactivatelanguagespecific "
\deactivatelanguagespecific /
\deactivatelanguagespecific :
\deactivatelanguagespecific ;
\deactivatelanguagespecific ?
\deactivatelanguagespecific !

\unprotect

% yes or no (taco wins: no)

% \startlanguagespecifics[nl,cz,sk,fr]
%   \lccode`\'=`\'
% \stoplanguagespecifics

%D \macros
%D   {ordinaldaynumber, highordinalstr, ordinalstr}
%D
%D Efficient general ordinal number converters are sometimes
%D difficult to implement. Fortunately dates never exceed the
%D number~31.

\def\highordinalstr#1{\high{\nocap{#1}}}
\def\ordinalstr    #1{\nocap{#1}}

\def\ordinaldaynumber#1% \strippedcsname\ordinaldaynumber
  {\expanded{\executeifdefined{\currentlanguage ordinaldaynumber}%
     \noexpand\firstofoneargument{\number#1}}}

%D Language specific converters have definitions like:
%D
%D \starttyping
%D \def\enordinaldaynumber#1{...}
%D \stoptyping
%D
%D Examples can be found in the other \type {lang} modules.

% \ifprocessingXML is a nasty dependency

\appendtoks
  \ifprocessingXML \else \resetlanguagespecifics \fi
\to \everylanguage

\protect \endinput
