%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 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 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. % We should use token registers, but alas, we run out of them and % \ETEX\ has a bug. Well, let's use a token register now (2006). \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 \processcommalist[#1]{\dosetlanguagespecifics{#3}}} % \long\def\dosetlanguagespecifics#1#2% % {\ifundefined{\??la\languageencoding#2\??la}\forgetlanguagespecifics[#2]\fi % % the next line catches the case that specifics are enabled *before* they are defined % \expandafter\ifx\csname\??la\languageencoding#2\??la\endcsname\relax\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\languagespectag#1{\??la\languageencoding#1\??la} \long\def\dosetlanguagespecifics#1#2% {\edef\askedlanguagespecificstag{\languagespectag{#2}}% \ifcsname\askedlanguagespecificstag\endcsname \else \expandafter\newtoks\csname\askedlanguagespecificstag\endcsname \fi \csname\askedlanguagespecificstag\endcsname\@EA{\the\csname\askedlanguagespecificstag\endcsname#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]% {\csname\languagespectag{#1}\endcsname\emptytoks} %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]% % {\the\executeifdefined{\??la % \@EA\ifx\csname\??la#1\c!default\endcsname\relax % \languageencoding % \else % \csname\??la#1\c!default\endcsname % \fi % \??la}\emptytoks % \the\executeifdefined{\??la#1\??la}\emptytoks % \the\executeifdefined{\??la\languageencoding#1\??la}\emptytoks} % dup ? \def\enablelanguagespecifics[#1]% {\edef\askedlanguagespecificslanguage{\defaultlanguage{#1}}% \ifcsname\??la\askedlanguagespecificslanguage\??la\endcsname \the\csname\??la\askedlanguagespecificslanguage\??la\endcsname \fi \ifx\languageencoding\empty\else \ifcsname\??la\languageencoding\askedlanguagespecificslanguage\??la\endcsname \the\csname\??la\languageencoding\askedlanguagespecificslanguage\??la\endcsname \fi \fi} %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% 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,cs,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. \ifx\high \undefined \let\high \firstofoneargument \fi % todo \ifx\notsmallcapped\undefined \let\notsmallcapped\firstofoneargument \fi % todo \def\highordinalstr#1{\high{\notsmallcapped{#1}}} \def\ordinalstr #1{\notsmallcapped{#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