diff options
Diffstat (limited to 'macros/latex/contrib/l3kernel/l3candidates.dtx')
-rw-r--r-- | macros/latex/contrib/l3kernel/l3candidates.dtx | 1927 |
1 files changed, 103 insertions, 1824 deletions
diff --git a/macros/latex/contrib/l3kernel/l3candidates.dtx b/macros/latex/contrib/l3kernel/l3candidates.dtx index 4e859699e0..adb399f9da 100644 --- a/macros/latex/contrib/l3kernel/l3candidates.dtx +++ b/macros/latex/contrib/l3kernel/l3candidates.dtx @@ -2,7 +2,7 @@ % %% File: l3candidates.dtx % -% Copyright (C) 2012-2019 The LaTeX3 Project +% Copyright (C) 2012-2020 The LaTeX3 Project % % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2019-11-07} +% \date{Released 2020-01-12} % % \maketitle % @@ -369,6 +369,47 @@ % conversely: sets it to the inverse of its current value. % \end{function} % +% \begin{function}[added = 2019-02-10, EXP, noTF] +% {\bool_case_true:n, \bool_case_false:n} +% \begin{syntax} +% \cs{bool_case_true:nTF} \\ +% ~~|{| \\ +% ~~~~\Arg{boolexpr case_1} \Arg{code case_1} \\ +% ~~~~\Arg{boolexpr case_2} \Arg{code case_2} \\ +% ~~~~\ldots \\ +% ~~~~\Arg{boolexpr case_n} \Arg{code case_n} \\ +% ~~|}| \\ +% ~~\Arg{true code} +% ~~\Arg{false code} +% \end{syntax} +% Evaluates in turn each of the \meta{boolean expression cases} until +% the first one that evaluates to \texttt{true} or to \texttt{false}, +% for \cs{bool_case_true:n} and \cs{bool_case_false:n}, respectively. +% The \meta{code} associated to this first case is left in the input +% stream, followed by the \meta{true code}, and other cases are +% discarded. If none of the cases match then only the \meta{false +% code} is inserted. The functions \cs{bool_case_true:n} and +% \cs{bool_case_false:n}, which do nothing if there is no match, are +% also available. For example +% \begin{verbatim} +% \bool_case_true:nF +% { +% { \dim_compare_p:n { \l__mypkg_wd_dim <= 10pt } } +% { Fits } +% { \int_compare_p:n { \l__mypkg_total_int >= 10 } } +% { Many } +% { \l__mypkg_special_bool } +% { Special } +% } +% { No idea! } +% \end{verbatim} +% leaves \enquote{\texttt{Fits}} or \enquote{\texttt{Many}} or +% \enquote{\texttt{Special}} or \enquote{\texttt{No idea!}} in the +% input stream, in a way similar to some other language's +% \enquote{\texttt{if} \ldots\ \texttt{elseif} \ldots\ \texttt{elseif} \ldots\ +% \texttt{else} \ldots}. +% \end{function} +% % \section{Additions to \pkg{l3prop}} % % \begin{function}[EXP, added = 2016-12-06] @@ -534,200 +575,6 @@ % % \section{Additions to \pkg{l3tl}} % -% \begin{function}[EXP, added = 2014-06-30, updated = 2016-01-12] -% { -% \tl_lower_case:n, \tl_upper_case:n, \tl_mixed_case:n, -% \tl_lower_case:nn, \tl_upper_case:nn, \tl_mixed_case:nn -% } -% \begin{syntax} -% \cs{tl_upper_case:n} \Arg{tokens} -% \cs{tl_upper_case:nn} \Arg{language} \Arg{tokens} -% \end{syntax} -% These functions are intended to be applied to input which may be -% regarded broadly as \enquote{text}. They traverse the \meta{tokens} and -% change the case of characters as discussed below. The character code of -% the characters replaced may be arbitrary: the replacement characters -% have standard document-level category codes ($11$ for letters, $12$ for -% letter-like characters which can also be case-changed). Begin-group and -% end-group characters in the \meta{tokens} are normalized and become |{| -% and |}|, respectively. -% -% Importantly, notice that these functions are intended for working with -% user text for typesetting. For case changing programmatic data see the -% \pkg{l3str} module and discussion there of \cs{str_lower_case:n}, -% \cs{str_upper_case:n} and \cs{str_fold_case:n}. -% \end{function} -% -% The functions perform expansion on the input in most cases. In particular, -% input in the form of token lists or expandable functions is expanded -% \emph{unless} it falls within one of the special handling classes described -% below. This expansion approach means that in general the result of case -% changing matches the \enquote{natural} outcome expected from a -% \enquote{functional} approach to case modification. For example -% \begin{verbatim} -% \tl_set:Nn \l_tmpa_tl { hello } -% \tl_upper_case:n { \l_tmpa_tl \c_space_tl world } -% \end{verbatim} -% produces -% \begin{verbatim} -% HELLO WORLD -% \end{verbatim} -% The expansion approach taken means that in package mode any \LaTeXe{} -% \enquote{robust} commands which may appear in the input should be converted -% to engine-protected versions using for example the \tn{robustify} command -% from the \pkg{etoolbox} package. -% -% \begin{variable}{\l_tl_case_change_math_tl} -% Case changing does not take place within math mode material so for example -% \begin{verbatim} -% \tl_upper_case:n { Some~text~$y = mx + c$~with~{Braces} } -% \end{verbatim} -% becomes -% \begin{verbatim} -% SOME TEXT $y = mx + c$ WITH {BRACES} -% \end{verbatim} -% Material inside math mode is left entirely unchanged: in particular, no -% expansion is undertaken. -% -% Detection of math mode is controlled by the list of tokens in -% \cs{l_tl_case_change_math_tl}, which should be in open--close pairs. In -% package mode the standard settings is -% \begin{verbatim} -% $ $ \( \) -% \end{verbatim} -% -% Note that while expansion occurs when searching the text it does not -% apply to math mode material (which should be unaffected by case changing). -% As such, whilst the opening token for math mode may be \enquote{hidden} -% inside a command/macro, the closing one cannot be as this is being -% searched for in math mode. Typically, in the types of \enquote{text} -% the case changing functions are intended to apply to this should not be -% an issue. -% \end{variable} -% -% \begin{variable}{\l_tl_case_change_exclude_tl} -% Case changing can be prevented by using any command on the list -% \cs{l_tl_case_change_exclude_tl}. Each entry should be a function -% to be followed by one argument: the latter will be preserved as-is -% with no expansion. Thus for example following -% \begin{verbatim} -% \tl_put_right:Nn \l_tl_case_change_exclude_tl { \NoChangeCase } -% \end{verbatim} -% the input -% \begin{verbatim} -% \tl_upper_case:n -% { Some~text~$y = mx + c$~with~\NoChangeCase {Protection} } -% \end{verbatim} -% will result in -% \begin{verbatim} -% SOME TEXT $y = mx + c$ WITH \NoChangeCase {Protection} -% \end{verbatim} -% Notice that the case changing mapping preserves the inclusion of -% the escape functions: it is left to other code to provide suitable -% definitions (typically equivalent to \cs{use:n}). In particular, the -% result of case changing is returned protected by \cs{exp_not:n}. -% -% When used with \LaTeXe{} the commands |\cite|, |\ensuremath|, |\label| -% and |\ref| are automatically included in the list for exclusion from -% case changing. -% \end{variable} -% -% \begin{variable}{\l_tl_case_change_accents_tl} -% This list specifies accent commands which should be left unexpanded -% in the output. This allows for example -% \begin{verbatim} -% \tl_upper_case:n { \" { a } } -% \end{verbatim} -% to yield -% \begin{verbatim} -% \" { A } -% \end{verbatim} -% irrespective of the expandability of |\"|. -% -% The standard contents of this variable is |\"|, |\'|, |\.|, |\^|, |\`|, -% |\~|, |\c|, |\H|, |\k|, |\r|, |\t|, |\u| and |\v|. -% \end{variable} -% -% \enquote{Mixed} case conversion may be regarded informally as converting the -% first character of the \meta{tokens} to upper case and the rest to lower -% case. However, the process is more complex than this as there are some -% situations where a single lower case character maps to a special form, for -% example \texttt{ij} in Dutch which becomes \texttt{IJ}. As such, -% \cs[index=tl_mixed_case:n]{tl_mixed_case:n(n)} -% implement a more sophisticated mapping which accounts -% for this and for modifying accents on the first letter. Spaces at the start -% of the \meta{tokens} are ignored when finding the first \enquote{letter} for -% conversion. -% \begin{verbatim} -% \tl_mixed_case:n { hello~WORLD } % => "Hello world" -% \tl_mixed_case:n { ~hello~WORLD } % => " Hello world" -% \tl_mixed_case:n { {hello}~WORLD } % => "{Hello} world" -% \end{verbatim} -% When finding the first \enquote{letter} for this process, any content in -% math mode or covered by \cs{l_tl_case_change_exclude_tl} is ignored. -% -% (Note that the Unicode Consortium describe this as \enquote{title case}, but -% that in English title case applies on a word-by-word basis. The -% \enquote{mixed} case implemented here is a lower level concept needed for -% both \enquote{title} and \enquote{sentence} casing of text.) -% -% \begin{variable}{\l_tl_mixed_case_ignore_tl} -% The list of characters to ignore when searching for the first -% \enquote{letter} in mixed-casing is determined by -% \cs{l_tl_mixed_change_ignore_tl}. This has the standard setting -% \begin{verbatim} -% ( [ { ` - -% \end{verbatim} -% where comparisons are made on a character basis. -% \end{variable} -% -% As is generally true for \pkg{expl3}, these functions are designed to -% work with Unicode input only. As such, UTF-8 input is assumed for -% \emph{all} engines. When used with \XeTeX{} or \LuaTeX{} a full range of -% Unicode transformations are enabled. Specifically, the standard mappings -% here follow those defined by the \href{http://www.unicode.org}^^A -% {Unicode Consortium} in \texttt{UnicodeData.txt} and -% \texttt{SpecialCasing.txt}. In the case of $8$-bit engines, mappings -% are provided for characters which can be represented in output typeset -% using the |T1| font encoding. Thus for example |รค| can be case-changed -% using \pdfTeX{}. For \pTeX{} only the ASCII range is covered as the -% engine treats input outside of this range as east Asian. -% -% Context-sensitive mappings are enabled: language-dependent cases are -% discussed below. Context detection expands input but treats any -% unexpandable control sequences as \enquote{failures} to match a context. -% -% Language-sensitive conversions are enabled using the \meta{language} -% argument, and follow Unicode Consortium guidelines. Currently, the -% languages recognised for special handling are as follows. -% \begin{itemize} -% \item Azeri and Turkish (\texttt{az} and \texttt{tr}). -% The case pairs I/i-dotless and I-dot/i are activated for these -% languages. The combining dot mark is removed when lower -% casing I-dot and introduced when upper casing i-dotless. -% \item German (\texttt{de-alt}). -% An alternative mapping for German in which the lower case -% \emph{Eszett} maps to a \emph{gro\ss{}es Eszett}. -% \item Lithuanian (\texttt{lt}). -% The lower case letters i and j should retain a dot above when the -% accents grave, acute or tilde are present. This is implemented for -% lower casing of the relevant upper case letters both when input as -% single Unicode codepoints and when using combining accents. The -% combining dot is removed when upper casing in these cases. Note that -% \emph{only} the accents used in Lithuanian are covered: the behaviour -% of other accents are not modified. -% \item Dutch (\texttt{nl}). -% Capitalisation of \texttt{ij} at the beginning of mixed cased -% input produces \texttt{IJ} rather than \texttt{Ij}. The output -% retains two separate letters, thus this transformation \emph{is} -% available using \pdfTeX{}. -% \end{itemize} -% -% Creating additional context-sensitive mappings requires knowledge -% of the underlying mapping implementation used here. The team are happy -% to add these to the kernel where they are well-documented -% (\emph{e.g.}~in Unicode Consortium or relevant government publications). -% % \begin{function}[EXP, added = 2017-07-15] % { % \tl_range_braced:Nnn, \tl_range_braced:cnn, \tl_range_braced:nnn, @@ -848,38 +695,28 @@ % (\enquote{active}), and character code $32$ (space). % \end{variable} % -% \begin{function}[added = 2018-04-06, updated = 2019-05-03, EXP] -% { -% \char_lower_case:N, \char_upper_case:N, -% \char_mixed_case:N, \char_fold_case:N, -% \char_str_lower_case:N, \char_str_upper_case:N, -% \char_str_mixed_case:N, \char_str_fold_case:N, -% } +% \begin{function}[added = 2020-01-09, EXP]{\char_to_utfviii_bytes:n} % \begin{syntax} -% \cs{char_lower_case:N} \meta{char} -% \end{syntax} -% Converts the \meta{char} to the equivalent case-changed character -% as detailed by the function name (see \cs{str_fold_case:n} -% and \cs{tl_mixed_case:n} for details of these terms). The case mapping -% is carried out with no context-dependence (\emph{cf.}~\cs{tl_upper_case:n}, -% \emph{etc.}) The \texttt{str} versions always generate \enquote{other} -% (category code $12$) characters, whilst the standard versions generate -% characters with the currently-active category code (\emph{i.e.}~as if -% the character had been read directly here). -% \end{function} -% -% \begin{function}[added = 2018-06-01, EXP]{\char_codepoint_to_bytes:n} -% \begin{syntax} -% \cs{char_codepoint_to_bytes:n} \Arg{codepoint} +% \cs{char_to_utfviii_bytes:n} \Arg{codepoint} % \end{syntax} % Converts the (Unicode) \meta{codepoint} to UTF-8 bytes. The expansion % of this function comprises four brace groups, each of which will contain % a hexadecimal value: the appropriate byte. As UTF-8 is a variable-length, -% one or more of the grouos may be empty: the bytes read in the logical order, +% one or more of the groups may be empty: the bytes read in the logical order, % such that a two-byte codepoint will have groups |#1| and |#2| filled % and |#3| and |#4| empty. % \end{function} % +% \begin{function}[added = 2020-01-02, rEXP]{\char_to_nfd:N} +% \begin{syntax} +% \cs{char_to_nfd:N} \meta{char} +% \end{syntax} +% Converts the \meta{char} to the Unicode Normalization Form Canonical +% Decomposition. The category code of the generated character is the +% same as the \meta{char}. With $8$-bit engines, no change is made to the +% character. +% \end{function} +% % \begin{function}[added = 2018-09-23] % { % \peek_catcode_collect_inline:Nn, @@ -1238,6 +1075,52 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}[EXP, noTF]{\bool_case_true:n, \bool_case_false:n} +% \begin{macro}{\@@_case:NnTF} +% \begin{macro}{\@@_case_true:w, \@@_case_false:w, \@@_case_end:nw} +% For boolean cases the overall idea is the same as for +% \cs{tl_case:nn(TF)} as described in \pkg{l3tl}. +% \begin{macrocode} +\cs_new:Npn \bool_case_true:nTF + { \exp:w \@@_case:NnTF \c_true_bool } +\cs_new:Npn \bool_case_true:nT #1#2 + { \exp:w \@@_case:NnTF \c_true_bool {#1} {#2} { } } +\cs_new:Npn \bool_case_true:nF #1 + { \exp:w \@@_case:NnTF \c_true_bool {#1} { } } +\cs_new:Npn \bool_case_true:n #1 + { \exp:w \@@_case:NnTF \c_true_bool {#1} { } { } } +\cs_new:Npn \bool_case_false:nTF + { \exp:w \@@_case:NnTF \c_false_bool } +\cs_new:Npn \bool_case_false:nT #1#2 + { \exp:w \@@_case:NnTF \c_false_bool {#1} {#2} { } } +\cs_new:Npn \bool_case_false:nF #1 + { \exp:w \@@_case:NnTF \c_false_bool {#1} { } } +\cs_new:Npn \bool_case_false:n #1 + { \exp:w \@@_case:NnTF \c_false_bool {#1} { } { } } +\cs_new:Npn \@@_case:NnTF #1#2#3#4 + { + \bool_if:NTF #1 \@@_case_true:w \@@_case_false:w + #2 #1 { } \q_mark {#3} \q_mark {#4} \q_stop + } +\cs_new:Npn \@@_case_true:w #1#2 + { + \bool_if:nTF {#1} + { \@@_case_end:nw {#2} } + { \@@_case_true:w } + } +\cs_new:Npn \@@_case_false:w #1#2 + { + \bool_if:nTF {#1} + { \@@_case_false:w } + { \@@_case_end:nw {#2} } + } +\cs_new:Npn \@@_case_end:nw #1#2#3 \q_mark #4#5 \q_stop + { \exp_end: #1 #4 } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% % \subsection{Additions to \pkg{l3prop}} % % \begin{macrocode} @@ -1544,1616 +1427,12 @@ % \end{macro} % \end{macro} % -% \subsection{Additions to \pkg{l3tl}} -% -% \subsubsection{Unicode case changing} -% -% The mechanisms needed for case changing are somewhat involved, particularly -% to allow for all of the special cases. These functions also require the -% appropriate data extracted from the Unicode documentation (either manually -% or automatically). -% -% First, some code which \enquote{belongs} in \pkg{l3tokens} but has to come -% here. -% \begin{macrocode} -%<@@=char> -% \end{macrocode} -% -% \begin{macro}[EXP] -% { -% \char_lower_case:N, \char_upper_case:N, -% \char_mixed_case:N, \char_fold_case:N -% } -% \begin{macro}[EXP]{\@@_change_case:nNN} -% \begin{macro}[EXP]{\@@_change_case:nN} -% \begin{macro}[EXP]{\@@_change_case_multi:nN, \@@_change_case_multi:vN} -% \begin{macro}[EXP]{\@@_change_case_multi:NNNNw} -% \begin{macro}[EXP]{\@@_change_case:NNN} -% \begin{macro}[EXP]{\@@_change_case:NNNN} -% \begin{macro}[EXP]{\@@_change_case:NN} -% \begin{macro}[EXP]{\@@_change_case_catcode:N} -% \begin{macro}[EXP] -% { -% \char_str_lower_case:N, \char_str_upper_case:N, -% \char_str_mixed_case:N, \char_str_fold_case:N -% } -% \begin{macro}[EXP]{\@@_str_change_case:nNN} -% \begin{macro}[EXP]{\@@_str_change_case:nN} -% Expandable character generation is done using a two-part approach. -% First, see if the current character has a special mapping for the current -% transformation. If it does, insert that. Otherwise, use the \TeX{} data -% to look up the one-to-one mapping, and generate the appropriate character -% with the appropriate category code. Mixed case needs an extra step as it -% may be special-cased or might be a special upper case outcome. The internal -% when using non-Unicode engines has to be set up to only do anything -% with ASCII characters. -% -% To ensure that the category codes produced are predictable, every character -% is re-generated even if it is otherwise unchanged. This makes life a little -% interesting when we might have multiple output characters: we have to -% grab each of them and case change them in reverse order to maintain -% \texttt{f}-type expandability. -% \begin{macrocode} -\cs_new:Npn \char_lower_case:N #1 - { \@@_change_case:nNN { lower } \char_value_lccode:n #1 } -\cs_new:Npn \char_upper_case:N #1 - { \@@_change_case:nNN { upper } \char_value_uccode:n #1 } -\cs_new:Npn \char_mixed_case:N #1 - { - \tl_if_exist:cTF { c_@@_mixed_case_ \token_to_str:N #1 _tl } - { - \@@_change_case_multi:vN - { c_@@_mixed_case_ \token_to_str:N #1 _tl } #1 - } - { \char_upper_case:N #1 } - } -\cs_new:Npn \char_fold_case:N #1 - { \@@_change_case:nNN { fold } \char_value_lccode:n #1 } -\cs_new:Npn \@@_change_case:nNN #1#2#3 - { - \tl_if_exist:cTF { c_@@_ #1 _case_ \token_to_str:N #3 _tl } - { - \@@_change_case_multi:vN - { c_@@_ #1 _case_ \token_to_str:N #3 _tl } #3 - } - { \exp_args:Nf \@@_change_case:nN { #2 { `#3 } } #3 } - } -\cs_new:Npn \@@_change_case:nN #1#2 - { - \int_compare:nNnTF {#1} = 0 - { #2 } - { \char_generate:nn {#1} { \@@_change_case_catcode:N #2 } } - } -\cs_new:Npn \@@_change_case_multi:nN #1#2 - { \@@_change_case_multi:NNNNw #2 #1 \q_no_value \q_no_value \q_stop } -\cs_generate_variant:Nn \@@_change_case_multi:nN { v } -\cs_new:Npn \@@_change_case_multi:NNNNw #1#2#3#4#5 \q_stop - { - \quark_if_no_value:NTF #4 - { - \quark_if_no_value:NTF #3 - { \@@_change_case:NN #1 #2 } - { \@@_change_case:NNN #1 #2#3 } - } - { \@@_change_case:NNNN #1 #2#3#4 } - } -\cs_new:Npn \@@_change_case:NNN #1#2#3 - { - \exp_args:Nnf \use:nn - { \@@_change_case:NN #1 #2 } - { \@@_change_case:NN #1 #3 } - } -\cs_new:Npn \@@_change_case:NNNN #1#2#3#4 - { - \exp_args:Nnff \use:nnn - { \@@_change_case:NN #1 #2 } - { \@@_change_case:NN #1 #3 } - { \@@_change_case:NN #1 #4 } - } -\cs_new:Npn \@@_change_case:NN #1#2 - { \char_generate:nn { `#2 } { \@@_change_case_catcode:N #1 } } -\cs_new:Npn \@@_change_case_catcode:N #1 - { - \if_catcode:w \exp_not:N #1 \c_math_toggle_token - 3 - \else: - \if_catcode:w \exp_not:N #1 \c_alignment_token - 4 - \else: - \if_catcode:w \exp_not:N #1 \c_math_superscript_token - 7 - \else: - \if_catcode:w \exp_not:N #1 \c_math_subscript_token - 8 - \else: - \if_catcode:w \exp_not:N #1 \c_space_token - 10 - \else: - \if_catcode:w \exp_not:N #1 \c_catcode_letter_token - 11 - \else: - \if_catcode:w \exp_not:N #1 \c_catcode_other_token - 12 - \else: - 13 - \fi: - \fi: - \fi: - \fi: - \fi: - \fi: - \fi: - } -% \end{macrocode} -% Same story for the string version, except category code is easier -% to follow. This of course makes this version significantly faster. -% \begin{macrocode} -\cs_new:Npn \char_str_lower_case:N #1 - { \@@_str_change_case:nNN { lower } \char_value_lccode:n #1 } -\cs_new:Npn \char_str_upper_case:N #1 - { \@@_str_change_case:nNN { upper } \char_value_uccode:n #1 } -\cs_new:Npn \char_str_mixed_case:N #1 - { - \tl_if_exist:cTF { c_@@_mixed_case_ \token_to_str:N #1 _tl } - { \tl_to_str:c { c_@@_mixed_case_ \token_to_str:N #1 _tl } } - { \char_str_upper_case:N #1 } - } -\cs_new:Npn \char_str_fold_case:N #1 - { \@@_str_change_case:nNN { fold } \char_value_lccode:n #1 } -\cs_new:Npn \@@_str_change_case:nNN #1#2#3 - { - \tl_if_exist:cTF { c_@@_ #1 _case_ \token_to_str:N #3 _tl } - { \tl_to_str:c { c_@@_ #1 _case_ \token_to_str:N #3 _tl } } - { \exp_args:Nf \@@_str_change_case:nN { #2 { `#3 } } #3 } - } -\cs_new:Npn \@@_str_change_case:nN #1#2 - { - \int_compare:nNnTF {#1} = 0 - { \tl_to_str:n {#2} } - { \char_generate:nn {#1} { 12 } } - } -\cs_if_exist:NF \tex_Uchar:D - { - \cs_set:Npn \@@_str_change_case:nN #1#2 - { \tl_to_str:n {#2} } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}[EXP]{\char_codepoint_to_bytes:n} -% \begin{macro}[EXP]{\@@_codepoint_to_bytes_auxi:n} -% \begin{macro}[EXP]{\@@_codepoint_to_bytes_auxii:Nnn} -% \begin{macro}[EXP]{\@@_codepoint_to_bytes_auxiii:n} -% \begin{macro}[EXP] -% { -% \@@_codepoint_to_bytes_outputi:nw , -% \@@_codepoint_to_bytes_outputii:nw , -% \@@_codepoint_to_bytes_outputiii:nw , -% \@@_codepoint_to_bytes_outputiv:nw -% } -% \begin{macro}[EXP] -% {\@@_codepoint_to_bytes_output:nnn, \@@_codepoint_to_bytes_output:fnn} -% \begin{macro}[EXP]{\@@_codepoint_to_bytes_end:} -% This code converts a codepoint into the correct UTF-8 representation. -% In terms of the algorithm itself, see -% \url{https://en.wikipedia.org/wiki/UTF-8} for the octet pattern. -% \begin{macrocode} -\cs_new:Npn \char_codepoint_to_bytes:n #1 - { - \exp_args:Nf \@@_codepoint_to_bytes_auxi:n - { \int_eval:n {#1} } - } -\cs_new:Npn \@@_codepoint_to_bytes_auxi:n #1 - { - \if_int_compare:w #1 > "80 \exp_stop_f: - \if_int_compare:w #1 < "800 \exp_stop_f: - \@@_codepoint_to_bytes_outputi:nw - { \@@_codepoint_to_bytes_auxii:Nnn C {#1} { 64 } } - \@@_codepoint_to_bytes_outputii:nw - { \@@_codepoint_to_bytes_auxiii:n {#1} } - \else: - \if_int_compare:w #1 < "10000 \exp_stop_f: - \@@_codepoint_to_bytes_outputi:nw - { \@@_codepoint_to_bytes_auxii:Nnn E {#1} { 64 * 64 } } - \@@_codepoint_to_bytes_outputii:nw - { - \@@_codepoint_to_bytes_auxiii:n - { \int_div_truncate:nn {#1} { 64 } } - } - \@@_codepoint_to_bytes_outputiii:nw - { \@@_codepoint_to_bytes_auxiii:n {#1} } - \else: - \@@_codepoint_to_bytes_outputi:nw - { - \@@_codepoint_to_bytes_auxii:Nnn F - {#1} { 64 * 64 * 64 } - } - \@@_codepoint_to_bytes_outputii:nw - { - \@@_codepoint_to_bytes_auxiii:n - { \int_div_truncate:nn {#1} { 64 * 64 } } - } - \@@_codepoint_to_bytes_outputiii:nw - { - \@@_codepoint_to_bytes_auxiii:n - { \int_div_truncate:nn {#1} { 64 } } - } - \@@_codepoint_to_bytes_outputiv:nw - { \@@_codepoint_to_bytes_auxiii:n {#1} } - \fi: - \fi: - \else: - \@@_codepoint_to_bytes_outputi:nw {#1} - \fi: - \@@_codepoint_to_bytes_end: { } { } { } { } - } -\cs_new:Npn \@@_codepoint_to_bytes_auxii:Nnn #1#2#3 - { "#10 + \int_div_truncate:nn {#2} {#3} } -\cs_new:Npn \@@_codepoint_to_bytes_auxiii:n #1 - { \int_mod:nn {#1} { 64 } + 128 } -\cs_new:Npn \@@_codepoint_to_bytes_outputi:nw - #1 #2 \@@_codepoint_to_bytes_end: #3 - { \@@_codepoint_to_bytes_output:fnn { \int_eval:n {#1} } { } {#2} } -\cs_new:Npn \@@_codepoint_to_bytes_outputii:nw - #1 #2 \@@_codepoint_to_bytes_end: #3#4 - { \@@_codepoint_to_bytes_output:fnn { \int_eval:n {#1} } { {#3} } {#2} } -\cs_new:Npn \@@_codepoint_to_bytes_outputiii:nw - #1 #2 \@@_codepoint_to_bytes_end: #3#4#5 - { - \@@_codepoint_to_bytes_output:fnn - { \int_eval:n {#1} } { {#3} {#4} } {#2} - } -\cs_new:Npn \@@_codepoint_to_bytes_outputiv:nw - #1 #2 \@@_codepoint_to_bytes_end: #3#4#5#6 - { - \@@_codepoint_to_bytes_output:fnn - { \int_eval:n {#1} } { {#3} {#4} {#5} } {#2} - } -\cs_new:Npn \@@_codepoint_to_bytes_output:nnn #1#2#3 - { - #3 - \@@_codepoint_to_bytes_end: #2 {#1} - } -\cs_generate_variant:Nn \@@_codepoint_to_bytes_output:nnn { f } -\cs_new:Npn \@@_codepoint_to_bytes_end: { } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} +% \subsubsection{Building a token list} % % \begin{macrocode} %<@@=tl> % \end{macrocode} % -% \begin{macro}[EXP]{\tl_lower_case:n, \tl_upper_case:n, \tl_mixed_case:n} -% \begin{macro}[EXP]{\tl_lower_case:nn, \tl_upper_case:nn, \tl_mixed_case:nn} -% The user level functions here are all wrappers around the internal -% functions for case changing. -% \begin{macrocode} -\cs_new:Npn \tl_lower_case:n { \@@_change_case:nnn { lower } { } } -\cs_new:Npn \tl_upper_case:n { \@@_change_case:nnn { upper } { } } -\cs_new:Npn \tl_mixed_case:n { \@@_change_case:nnn { mixed } { } } -\cs_new:Npn \tl_lower_case:nn { \@@_change_case:nnn { lower } } -\cs_new:Npn \tl_upper_case:nn { \@@_change_case:nnn { upper } } -\cs_new:Npn \tl_mixed_case:nn { \@@_change_case:nnn { mixed } } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[EXP]{\@@_change_case:nnn} -% \begin{macro}[EXP]{\@@_change_case_aux:nnn} -% \begin{macro}[EXP]{\@@_change_case_loop:wnn} -% \begin{macro}[EXP] -% { -% \@@_change_case_output:nwn , -% \@@_change_case_output:Vwn , -% \@@_change_case_output:own , -% \@@_change_case_output:vwn , -% \@@_change_case_output:fwn , -% } -% \begin{macro}[EXP]{\@@_change_case_end:wn} -% \begin{macro}[EXP]{\@@_change_case_group:nwnn} -% \begin{macro}[EXP] -% { -% \@@_change_case_group_lower:nnnn , -% \@@_change_case_group_upper:nnnn , -% \@@_change_case_group_mixed:nnnn -% } -% \begin{macro}[EXP]{\@@_change_case_space:wnn} -% \begin{macro}[EXP]{\@@_change_case_N_type:Nwnn} -% \begin{macro}[EXP]{\@@_change_case_N_type:NNNnnn} -% \begin{macro}[EXP]{\@@_change_case_math:NNNnnn} -% \begin{macro}[EXP]{\@@_change_case_math_loop:wNNnn} -% \begin{macro}[EXP]{\@@_change_case_math:NwNNnn} -% \begin{macro}[EXP]{\@@_change_case_math_group:nwNNnn} -% \begin{macro}[EXP]{\@@_change_case_math_space:wNNnn} -% \begin{macro}[EXP]{\@@_change_case_N_type:Nnnn} -% \begin{macro}[EXP] -% { -% \@@_change_case_char_lower:Nnn , -% \@@_change_case_char_upper:Nnn , -% \@@_change_case_char_mixed:Nnn -% } -% \begin{macro}[EXP]{\@@_change_case_char:nN} -% \begin{macro}[EXP]{\@@_change_case_char_UTFviii:nNN} -% \begin{macro}[EXP]{\@@_change_case_char_UTFviii:nNNN} -% \begin{macro}[EXP]{\@@_change_case_char_UTFviii:nNNNN} -% \begin{macro}[EXP]{\@@_change_case_char_UTFviii:nn} -% \begin{macro}[EXP]{\@@_change_case_cs_letterlike:Nn} -% \begin{macro}[EXP]{\@@_change_case_cs_letterlike:NnN} -% \begin{macro}[EXP]{\@@_change_case_cs_accents:NN} -% \begin{macro}[EXP]{\@@_change_case_cs:N} -% \begin{macro}[EXP]{\@@_change_case_cs:NN} -% \begin{macro}[EXP]{\@@_change_case_cs:NNn} -% \begin{macro}[EXP]{\@@_change_case_protect:wNN} -% \begin{macro}[EXP]{\@@_change_case_if_expandable:NTF} -% \begin{macro}[EXP]{\@@_change_case_cs_expand:Nnw} -% \begin{macro}[EXP]{\@@_change_case_cs_expand:NN} -% \begin{macro}[EXP]{\@@_change_case_mixed_skip:N} -% \begin{macro}[EXP]{\@@_change_case_mixed_skip:NN} -% \begin{macro}[EXP]{\@@_change_case_mixed_skip_tidy:Nwn} -% \begin{macro}[EXP]{\@@_change_case_mixed_switch:w} -% The mechanism for the core conversion of case is based on the idea that -% we can use a loop to grab the entire token list plus a quark: the latter is -% used as an end marker and to avoid any brace stripping. Depending on the -% nature of the first item in the grabbed argument, it can either processed -% as a single token, treated as a group or treated as a space. These -% different cases all work by re-reading |#1| in the appropriate way, hence -% the repetition of |#1 \q_recursion_stop|. -% \begin{macrocode} -\cs_new:Npn \@@_change_case:nnn #1#2#3 - { - \__kernel_exp_not:w \exp_after:wN - { - \exp:w - \@@_change_case_aux:nnn {#1} {#2} {#3} - } - } -\cs_new:Npn \@@_change_case_aux:nnn #1#2#3 - { - \group_align_safe_begin: - \@@_change_case_loop:wnn - #3 \q_recursion_tail \q_recursion_stop {#1} {#2} - \@@_change_case_result:n { } - } -\cs_new:Npn \@@_change_case_loop:wnn #1 \q_recursion_stop - { - \tl_if_head_is_N_type:nTF {#1} - { \@@_change_case_N_type:Nwnn } - { - \tl_if_head_is_group:nTF {#1} - { \@@_change_case_group:nwnn } - { \@@_change_case_space:wnn } - } - #1 \q_recursion_stop - } -% \end{macrocode} -% Earlier versions of the code where only \texttt{x}-type expandable rather -% than \texttt{f}-type: this causes issues with nesting and so the slight -% performance hit is taken for a better outcome in usability terms. Setting -% up for \texttt{f}-type expandability has two requirements: a marker -% token after the main loop (see above) and a mechanism to \enquote{load} -% and finalise the result. That is handled in the code below, which includes -% the necessary material to end the \cs{exp:w} expansion. -% \begin{macrocode} -\cs_new:Npn \@@_change_case_output:nwn #1#2 \@@_change_case_result:n #3 - { #2 \@@_change_case_result:n { #3 #1 } } -\cs_generate_variant:Nn \@@_change_case_output:nwn { V , o , v , f } -\cs_new:Npn \@@_change_case_end:wn #1 \@@_change_case_result:n #2 - { - \group_align_safe_end: - \exp_end: - #2 - } -% \end{macrocode} -% Handling for the cases where the current argument is a brace group or -% a space is relatively easy. For the brace case, the routine works -% recursively, using the expandability of the mechanism to ensure that the -% result is finalised before storage. For the space case it is simply a -% question of removing the space in the input and storing it in the output. -% In both cases, and indeed for the \texttt{N}-type grabber, after removing -% the current item from the input \cs{@@_change_case_loop:wnn} is inserted -% in front of the remaining tokens. -% \begin{macrocode} -\cs_new:Npn \@@_change_case_group:nwnn #1#2 \q_recursion_stop #3#4 - { - \use:c { @@_change_case_group_ #3 : nnnn } {#1} {#2} {#3} {#4} - } -\cs_new:Npn \@@_change_case_group_lower:nnnn #1#2#3#4 - { - \@@_change_case_output:own - { - \exp_after:wN - { - \exp:w - \@@_change_case_aux:nnn {#3} {#4} {#1} - } - } - \@@_change_case_loop:wnn #2 \q_recursion_stop {#3} {#4} - } -\cs_new_eq:NN \@@_change_case_group_upper:nnnn - \@@_change_case_group_lower:nnnn -% \end{macrocode} -% For the \enquote{mixed} case, a group is taken as forcing a switch to lower -% casing. That means we need a separate auxiliary. (Tracking whether we have -% found a first character inside a group and transferring the information out -% looks pretty horrible.) -% \begin{macrocode} -\cs_new:Npn \@@_change_case_group_mixed:nnnn #1#2#3#4 - { - \@@_change_case_output:own - { - \exp_after:wN - { - \exp:w - \@@_change_case_aux:nnn {#3} {#4} {#1} - } - } - \@@_change_case_loop:wnn #2 \q_recursion_stop { lower } {#4} - } -\exp_last_unbraced:NNo \cs_new:Npn \@@_change_case_space:wnn \c_space_tl - { - \@@_change_case_output:nwn { ~ } - \@@_change_case_loop:wnn - } -% \end{macrocode} -% For \texttt{N}-type arguments there are several stages to the approach. -% First, a simply check for the end-of-input marker, which if found triggers -% the final clean up and output step. Assuming that is not the case, the -% first check is for math-mode escaping: this test can encompass control -% sequences or other \texttt{N}-type tokens so is handled up front. -% \begin{macrocode} -\cs_new:Npn \@@_change_case_N_type:Nwnn #1#2 \q_recursion_stop - { - \quark_if_recursion_tail_stop_do:Nn #1 - { \@@_change_case_end:wn } - \exp_after:wN \@@_change_case_N_type:NNNnnn - \exp_after:wN #1 \l_tl_case_change_math_tl - \q_recursion_tail ? \q_recursion_stop {#2} - } -% \end{macrocode} -% Looking for math mode escape first requires a loop over the possible -% token pairs to see if the current input (|#1|) matches an open-math case -% (|#2|). If if does then this test loop is ended and a new input-gathering -% one is begun. The latter simply transfers material from the input to the -% output without any expansion, testing each \texttt{N}-type token to see -% if it matches the close-math case required. If that is the situation then -% the \enquote{math loop} stops and resumes the main loop: as that might -% be either the standard case-changing one or the mixed-case alternative, -% it is not hard-coded into the math loop but is rather passed as argument -% |#3| to \cs{@@_change_case_math:NNNnnn}. If no close-math token is found -% then the final clean-up is forced (\emph{i.e.}~there is no assumption -% of \enquote{well-behaved} input in terms of math mode). -% \begin{macrocode} -\cs_new:Npn \@@_change_case_N_type:NNNnnn #1#2#3 - { - \quark_if_recursion_tail_stop_do:Nn #2 - { \@@_change_case_N_type:Nnnn #1 } - \token_if_eq_meaning:NNTF #1 #2 - { - \use_i_delimit_by_q_recursion_stop:nw - { - \@@_change_case_math:NNNnnn - #1 #3 \@@_change_case_loop:wnn - } - } - { \@@_change_case_N_type:NNNnnn #1 } - } -\cs_new:Npn \@@_change_case_math:NNNnnn #1#2#3#4 - { - \@@_change_case_output:nwn {#1} - \@@_change_case_math_loop:wNNnn #4 \q_recursion_stop #2 #3 - } -\cs_new:Npn \@@_change_case_math_loop:wNNnn #1 \q_recursion_stop - { - \tl_if_head_is_N_type:nTF {#1} - { \@@_change_case_math:NwNNnn } - { - \tl_if_head_is_group:nTF {#1} - { \@@_change_case_math_group:nwNNnn } - { \@@_change_case_math_space:wNNnn } - } - #1 \q_recursion_stop - } -\cs_new:Npn \@@_change_case_math:NwNNnn #1#2 \q_recursion_stop #3#4 - { - \token_if_eq_meaning:NNTF \q_recursion_tail #1 - { \@@_change_case_end:wn } - { - \@@_change_case_output:nwn {#1} - \token_if_eq_meaning:NNTF #1 #3 - { #4 #2 \q_recursion_stop } - { \@@_change_case_math_loop:wNNnn #2 \q_recursion_stop #3#4 } - } - } -\cs_new:Npn \@@_change_case_math_group:nwNNnn #1#2 \q_recursion_stop - { - \@@_change_case_output:nwn { {#1} } - \@@_change_case_math_loop:wNNnn #2 \q_recursion_stop - } -\exp_last_unbraced:NNo - \cs_new:Npn \@@_change_case_math_space:wNNnn \c_space_tl - { - \@@_change_case_output:nwn { ~ } - \@@_change_case_math_loop:wNNnn - } -% \end{macrocode} -% Once potential math-mode cases are filtered out the next stage is to -% test if the token grabbed is a control sequence: they cannot be used in -% the lookup table and also may require expansion. At this stage the loop -% code starting \cs{@@_change_case_loop:wnn} is inserted: all subsequent -% steps in the code which need a look-ahead are coded to rely on this and -% thus have \texttt{w}-type arguments if they may do a look-ahead. -% \begin{macrocode} -\cs_new:Npn \@@_change_case_N_type:Nnnn #1#2#3#4 - { - \token_if_cs:NTF #1 - { \@@_change_case_cs_letterlike:Nn #1 {#3} } - { \use:c { @@_change_case_char_ #3 :Nnn } #1 {#3} {#4} } - \@@_change_case_loop:wnn #2 \q_recursion_stop {#3} {#4} - } -% \end{macrocode} -% For character tokens there are some special cases to deal with then -% the majority of changes are covered by using the \TeX{} data as a lookup -% along with expandable character generation. This avoids needing a very -% large number of macros or (as seen in earlier versions) a somewhat tricky -% split of the characters into various blocks. Notice that the special case -% code may do a look-ahead so requires a final \texttt{w}-type argument -% whereas the core lookup table does not and also guarantees an output so -% \texttt{f}-type expansion may be used to obtain the case-changed result. -% \begin{macrocode} -\cs_new:Npn \@@_change_case_char_lower:Nnn #1#2#3 - { - \cs_if_exist_use:cF { @@_change_case_ #2 _ #3 :Nnw } - { \use_ii:nn } - #1 - { - \use:c { @@_change_case_ #2 _ sigma:Nnw } #1 - { \@@_change_case_char:nN {#2} #1 } - } - } -\cs_new_eq:NN \@@_change_case_char_upper:Nnn - \@@_change_case_char_lower:Nnn -% \end{macrocode} -% For mixed case, the code is somewhat different: there is a need to -% look up both mixed and upper case chars and we have to cover the -% situation where there is a character to skip over. -% \begin{macrocode} -\cs_new:Npn \@@_change_case_char_mixed:Nnn #1#2#3 - { - \@@_change_case_mixed_switch:w - \cs_if_exist_use:cF { @@_change_case_mixed_ #3 :Nnw } - { - \cs_if_exist_use:cF { @@_change_case_upper_ #3 :Nnw } - { \use_ii:nn } - } - #1 - { \@@_change_case_mixed_skip:N #1 } - } -% \end{macrocode} -% For Unicode engines we can handle all characters directly. However, for -% the $8$-bit engines the aim is to deal with (a subset of) Unicode (UTF-8) -% input. They deal with that by making the upper half of the range active, -% so we look for that and if found work out how many UTF-8 octets there -% are to deal with. Those can then be grabbed to reconstruct the full -% Unicode character, which is then used in a lookup. (As will become -% obvious below, there is no intention here of covering all of Unicode.) -% \begin{macrocode} -\bool_lazy_or:nnTF - { \sys_if_engine_luatex_p: } - { \sys_if_engine_xetex_p: } - { - \cs_new:Npn \@@_change_case_char:nN #1#2 - { - \@@_change_case_output:fwn - { \use:c { char_ #1 _case:N } #2 } - } - } - { - \cs_new:Npn \@@_change_case_char:nN #1#2 - { - \int_compare:nNnTF { `#2 } > { "80 } - { - \int_compare:nNnTF { `#2 } < { "E0 } - { \@@_change_case_char_UTFviii:nNNN {#1} #2 } - { - \int_compare:nNnTF { `#2 } < { "F0 } - { \@@_change_case_char_UTFviii:nNNNN {#1} #2 } - { \@@_change_case_char_UTFviii:nNNNNN {#1} #2 } - } - } - { - \@@_change_case_output:fwn - { \use:c { char_ #1 _case:N } #2 } - } - } - } -% \end{macrocode} -% To allow for the special case of mixed case, we insert here a -% action-dependent auxiliary. -% \begin{macrocode} -\bool_lazy_or:nnF - { \sys_if_engine_luatex_p: } - { \sys_if_engine_xetex_p: } - { - \cs_new:Npn \@@_change_case_char_UTFviii:nNNN #1#2#3#4 - { \@@_change_case_char_UTFviii:nnN {#1} {#2#4} #3 } - \cs_new:Npn \@@_change_case_char_UTFviii:nNNNN #1#2#3#4#5 - { \@@_change_case_char_UTFviii:nnN {#1} {#2#4#5} #3 } - \cs_new:Npn \@@_change_case_char_UTFviii:nNNNNN #1#2#3#4#5#6 - { \@@_change_case_char_UTFviii:nnN {#1} {#2#4#5#6} #3 } - \cs_new:Npn \@@_change_case_char_UTFviii:nnN #1#2#3 - { - \cs_if_exist:cTF { c_@@_ #1 _case_ \tl_to_str:n {#2} _tl } - { - \@@_change_case_output:vwn - { c_@@_ #1 _case_ \tl_to_str:n {#2} _tl } - } - { \@@_change_case_output:nwn {#2} } - #3 - } - } -% \end{macrocode} -% Before dealing with general control sequences there are the special -% ones to deal with. Letter-like control sequences are a simple look-up, -% while for accents the loop is much as done elsewhere. Notice that -% we have a no-op test to make sure there is no unexpected expansion of -% letter-like input. The split into two parts here allows us to insert -% the \enquote{switch} code for mixed casing. -% \begin{macrocode} -\cs_new:Npn \@@_change_case_cs_letterlike:Nn #1#2 - { - \str_if_eq:nnTF {#2} { mixed } - { - \@@_change_case_cs_letterlike:NnN #1 { upper } - \@@_change_case_mixed_switch:w - } - { \@@_change_case_cs_letterlike:NnN #1 {#2} \prg_do_nothing: } - } -\cs_new:Npn \@@_change_case_cs_letterlike:NnN #1#2#3 - { - \cs_if_exist:cTF { c_@@_change_case_ #2 _ \token_to_str:N #1 _tl } - { - \@@_change_case_output:vwn - { c_@@_change_case_ #2 _ \token_to_str:N #1 _tl } - #3 - } - { - \cs_if_exist:cTF - { - c_@@_change_case_ - \str_if_eq:nnTF {#2} { lower } { upper } { lower } - _ \token_to_str:N #1 _tl - } - { - \@@_change_case_output:nwn {#1} - #3 - } - { - \exp_after:wN \@@_change_case_cs_accents:NN - \exp_after:wN #1 \l_tl_case_change_accents_tl - \q_recursion_tail \q_recursion_stop - } - } - } -\cs_new:Npn \@@_change_case_cs_accents:NN #1#2 - { - \quark_if_recursion_tail_stop_do:Nn #2 - { \@@_change_case_cs:N #1 } - \str_if_eq:nnTF {#1} {#2} - { - \use_i_delimit_by_q_recursion_stop:nw - { \@@_change_case_output:nwn {#1} } - } - { \@@_change_case_cs_accents:NN #1 } - } -% \end{macrocode} -% To deal with a control sequence there is first a need to test if it is -% on the list which indicate that case changing should be skipped. That's -% done using a loop as for the other special cases. If a hit is found then -% the argument is grabbed: that comes \emph{after} the loop function which -% is therefore rearranged. In a \LaTeXe{} context, \tn{protect} needs -% to be treated specially, to prevent expansion of the next token but -% output it without braces. -% \begin{macrocode} -\cs_new:Npn \@@_change_case_cs:N #1 - { -%<*package> - \str_if_eq:nnTF {#1} { \protect } { \@@_change_case_protect:wNN } -%</package> - \exp_after:wN \@@_change_case_cs:NN - \exp_after:wN #1 \l_tl_case_change_exclude_tl - \q_recursion_tail \q_recursion_stop - } -\cs_new:Npn \@@_change_case_cs:NN #1#2 - { - \quark_if_recursion_tail_stop_do:Nn #2 - { - \@@_change_case_cs_expand:Nnw #1 - { \@@_change_case_output:nwn {#1} } - } - \str_if_eq:nnTF {#1} {#2} - { - \use_i_delimit_by_q_recursion_stop:nw - { \@@_change_case_cs:NNn #1 } - } - { \@@_change_case_cs:NN #1 } - } -\cs_new:Npn \@@_change_case_cs:NNn #1#2#3 - { - \@@_change_case_output:nwn { #1 {#3} } - #2 - } -%<*package> -\cs_new:Npn \@@_change_case_protect:wNN #1 \q_recursion_stop #2 #3 - { \@@_change_case_output:nwn { \protect #3 } #2 } -%</package> -% \end{macrocode} -% When a control sequence is not on the exclude list the other test if -% to see if it is expandable. Once again, if there is a hit then the loop -% function is grabbed as part of the clean-up and reinserted before the -% now expanded material. The test for expandability has to check for -% end-of-recursion as it is needed by the look-ahead code which might hit -% the end of the input. The test is done in two parts as \cs{bool_if:nTF} -% would choke if |#1| was |(|! -% \begin{macrocode} -\cs_new:Npn \@@_change_case_if_expandable:NTF #1 - { - \token_if_expandable:NTF #1 - { - \bool_lazy_any:nTF - { - { \token_if_eq_meaning_p:NN \q_recursion_tail #1 } - { \token_if_protected_macro_p:N #1 } - { \token_if_protected_long_macro_p:N #1 } - } - { \use_ii:nn } - { \use_i:nn } - } - { \use_ii:nn } - } -\cs_new:Npn \@@_change_case_cs_expand:Nnw #1#2 - { - \@@_change_case_if_expandable:NTF #1 - { \@@_change_case_cs_expand:NN #1 } - { #2 } - } -\cs_new:Npn \@@_change_case_cs_expand:NN #1#2 - { \exp_after:wN #2 #1 } -% \end{macrocode} -% For mixed case, there is an additional list of exceptions to deal with: -% once that is sorted, we can move on back to the main loop. -% \begin{macrocode} -\cs_new:Npn \@@_change_case_mixed_skip:N #1 - { - \exp_after:wN \@@_change_case_mixed_skip:NN - \exp_after:wN #1 \l_tl_mixed_case_ignore_tl - \q_recursion_tail \q_recursion_stop - } -\cs_new:Npn \@@_change_case_mixed_skip:NN #1#2 - { - \quark_if_recursion_tail_stop_do:nn {#2} - { \@@_change_case_char:nN { mixed } #1 } - \int_compare:nNnT { `#1 } = { `#2 } - { - \use_i_delimit_by_q_recursion_stop:nw - { - \@@_change_case_output:nwn {#1} - \@@_change_case_mixed_skip_tidy:Nwn - } - } - \@@_change_case_mixed_skip:NN #1 - } -\cs_new:Npn \@@_change_case_mixed_skip_tidy:Nwn #1#2 \q_recursion_stop #3 - { - \@@_change_case_loop:wnn #2 \q_recursion_stop { mixed } - } -% \end{macrocode} -% Needed to switch from mixed to lower casing when we have found a -% first character in the former mode. -% \begin{macrocode} -\cs_new:Npn \@@_change_case_mixed_switch:w - #1 \@@_change_case_loop:wnn #2 \q_recursion_stop #3 - { - #1 - \@@_change_case_loop:wnn #2 \q_recursion_stop { lower } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}[EXP]{\@@_change_case_lower_sigma:Nnw} -% \begin{macro}[EXP]{\@@_change_case_lower_sigma:w} -% \begin{macro}[EXP]{\@@_change_case_lower_sigma:Nw} -% \begin{macro}[EXP]{\@@_change_case_upper_sigma:Nnw} -% If the current char is an upper case sigma, the a check is made on the next -% item in the input. If it is \texttt{N}-type and not a control sequence -% then there is a look-ahead phase. -% \begin{macrocode} -\cs_new:Npn \@@_change_case_lower_sigma:Nnw #1#2#3#4 \q_recursion_stop - { - \int_compare:nNnTF { `#1 } = { "03A3 } - { - \@@_change_case_output:fwn - { \@@_change_case_lower_sigma:w #4 \q_recursion_stop } - } - {#2} - #3 #4 \q_recursion_stop - } -\cs_new:Npn \@@_change_case_lower_sigma:w #1 \q_recursion_stop - { - \tl_if_head_is_N_type:nTF {#1} - { \@@_change_case_lower_sigma:Nw #1 \q_recursion_stop } - { \c_@@_final_sigma_tl } - } -\cs_new:Npn \@@_change_case_lower_sigma:Nw #1#2 \q_recursion_stop - { - \@@_change_case_if_expandable:NTF #1 - { - \exp_after:wN \@@_change_case_lower_sigma:w #1 - #2 \q_recursion_stop - } - { - \token_if_letter:NTF #1 - { \c_@@_std_sigma_tl } - { \c_@@_final_sigma_tl } - } - } -% \end{macrocode} -% Simply skip to the final step for upper casing. -% \begin{macrocode} -\cs_new_eq:NN \@@_change_case_upper_sigma:Nnw \use_ii:nn -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}[EXP]{\@@_change_case_lower_tr:Nnw} -% \begin{macro}[EXP]{\@@_change_case_lower_tr_auxi:Nw} -% \begin{macro}[EXP]{\@@_change_case_lower_tr_auxii:Nw} -% \begin{macro}[EXP]{\@@_change_case_upper_tr:Nnw} -% \begin{macro}[EXP]{\@@_change_case_lower_az:Nnw} -% \begin{macro}[EXP]{\@@_change_case_upper_az:Nnw} -% The Turkic languages need special treatment for dotted-i and dotless-i. -% The lower casing rule can be expressed in terms of searching first for -% either a dotless-I or a dotted-I. In the latter case the mapping is -% easy, but in the former there is a second stage search. -% \begin{macrocode} -\bool_lazy_or:nnTF - { \sys_if_engine_luatex_p: } - { \sys_if_engine_xetex_p: } - { - \cs_new:Npn \@@_change_case_lower_tr:Nnw #1#2 - { - \int_compare:nNnTF { `#1 } = { "0049 } - { \@@_change_case_lower_tr_auxi:Nw } - { - \int_compare:nNnTF { `#1 } = { "0130 } - { \@@_change_case_output:nwn { i } } - {#2} - } - } -% \end{macrocode} -% After a dotless-I there may be a dot-above character. If there is then -% a dotted-i should be produced, otherwise output a dotless-i. When the -% combination is found both the dotless-I and the dot-above char have to -% be removed from the input, which is done by the \cs{use_i:nn} -% (it grabs \cs{@@_change_case_loop:wn} and the dot-above char and -% discards the latter). -% \begin{macrocode} - \cs_new:Npn \@@_change_case_lower_tr_auxi:Nw #1#2 \q_recursion_stop - { - \tl_if_head_is_N_type:nTF {#2} - { \@@_change_case_lower_tr_auxii:Nw #2 \q_recursion_stop } - { \@@_change_case_output:Vwn \c_@@_dotless_i_tl } - #1 #2 \q_recursion_stop - } - \cs_new:Npn \@@_change_case_lower_tr_auxii:Nw #1#2 \q_recursion_stop - { - \@@_change_case_if_expandable:NTF #1 - { - \exp_after:wN \@@_change_case_lower_tr_auxi:Nw #1 - #2 \q_recursion_stop - } - { - \bool_lazy_or:nnTF - { \token_if_cs_p:N #1 } - { ! \int_compare_p:nNn { `#1 } = { "0307 } } - { \@@_change_case_output:Vwn \c_@@_dotless_i_tl } - { - \@@_change_case_output:nwn { i } - \use_i:nn - } - } - } - } -% \end{macrocode} -% For $8$-bit engines, dot-above is not available so there is a simple -% test for an upper-case I. Then we can look for the UTF-8 representation of -% an upper case dotted-I without the combining char. If it's not there, -% preserve the UTF-8 sequence as-is. -% \begin{macrocode} - { - \cs_new:Npn \@@_change_case_lower_tr:Nnw #1#2 - { - \int_compare:nNnTF { `#1 } = { "0049 } - { \@@_change_case_output:Vwn \c_@@_dotless_i_tl } - { - \int_compare:nNnTF { `#1 } = { 196 } - { \@@_change_case_lower_tr_auxi:Nw #1 {#2} } - {#2} - } - } - \cs_new:Npn \@@_change_case_lower_tr_auxi:Nw #1#2#3#4 - { - \int_compare:nNnTF { `#4 } = { 176 } - { - \@@_change_case_output:nwn { i } - #3 - } - { - #2 - #3 #4 - } - } - } -% \end{macrocode} -% Upper casing is easier: just one exception with no context. -% \begin{macrocode} -\cs_new:Npn \@@_change_case_upper_tr:Nnw #1#2 - { - \int_compare:nNnTF { `#1 } = { "0069 } - { \@@_change_case_output:Vwn \c_@@_dotted_I_tl } - {#2} - } -% \end{macrocode} -% Straight copies. -% \begin{macrocode} -\cs_new_eq:NN \@@_change_case_lower_az:Nnw \@@_change_case_lower_tr:Nnw -\cs_new_eq:NN \@@_change_case_upper_az:Nnw \@@_change_case_upper_tr:Nnw -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}[EXP]{\@@_change_case_lower_lt:Nnw} -% \begin{macro}[EXP]{\@@_change_case_lower_lt:nNnw} -% \begin{macro}[EXP]{\@@_change_case_lower_lt:nnw} -% \begin{macro}[EXP]{\@@_change_case_lower_lt:Nw} -% \begin{macro}[EXP]{\@@_change_case_lower_lt:NNw} -% \begin{macro}[EXP]{\@@_change_case_upper_lt:Nnw} -% \begin{macro}[EXP]{\@@_change_case_upper_lt:nnw} -% \begin{macro}[EXP]{\@@_change_case_upper_lt:Nw} -% \begin{macro}[EXP]{\@@_change_case_upper_lt:NNw} -% For Lithuanian, the issue to be dealt with is dots over lower case -% letters: these should be present if there is another accent. That means -% that there is some work to do when lower casing I and J. The first step -% is a simple match attempt: \cs{c_@@_accents_lt_tl} contains -% accented upper case letters which should gain a dot-above char in their -% lower case form. This is done using \texttt{f}-type expansion so only one -% pass is needed to find if it works or not. If there was no hit, the second -% stage is to check for I, J and I-ogonek, and if the current char is a -% match to look for a following accent. -% \begin{macrocode} -\cs_new:Npn \@@_change_case_lower_lt:Nnw #1 - { - \exp_args:Nf \@@_change_case_lower_lt:nNnw - { \str_case:nVF #1 \c_@@_accents_lt_tl \exp_stop_f: } - #1 - } -\cs_new:Npn \@@_change_case_lower_lt:nNnw #1#2 - { - \tl_if_blank:nTF {#1} - { - \exp_args:Nf \@@_change_case_lower_lt:nnw - { - \int_case:nnF {`#2} - { - { "0049 } i - { "004A } j - { "012E } \c_@@_i_ogonek_tl - } - \exp_stop_f: - } - } - { - \@@_change_case_output:nwn {#1} - \use_none:n - } - } -\cs_new:Npn \@@_change_case_lower_lt:nnw #1#2 - { - \tl_if_blank:nTF {#1} - {#2} - { - \@@_change_case_output:nwn {#1} - \@@_change_case_lower_lt:Nw - } - } -% \end{macrocode} -% Grab the next char and see if it is one of the accents used in Lithuanian: -% if it is, add the dot-above char into the output. -% \begin{macrocode} -\cs_new:Npn \@@_change_case_lower_lt:Nw #1#2 \q_recursion_stop - { - \tl_if_head_is_N_type:nT {#2} - { \@@_change_case_lower_lt:NNw } - #1 #2 \q_recursion_stop - } -\cs_new:Npn \@@_change_case_lower_lt:NNw #1#2#3 \q_recursion_stop - { - \@@_change_case_if_expandable:NTF #2 - { - \exp_after:wN \@@_change_case_lower_lt:Nw \exp_after:wN #1 #2 - #3 \q_recursion_stop - } - { - \bool_lazy_and:nnT - { ! \token_if_cs_p:N #2 } - { - \bool_lazy_any_p:n - { - { \int_compare_p:nNn { `#2 } = { "0300 } } - { \int_compare_p:nNn { `#2 } = { "0301 } } - { \int_compare_p:nNn { `#2 } = { "0303 } } - } - } - { \@@_change_case_output:Vwn \c_@@_dot_above_tl } - #1 #2#3 \q_recursion_stop - } - } -% \end{macrocode} -% For upper casing, the test required is for a dot-above char after an I, -% J or I-ogonek. First a test for the appropriate letter, and if found a -% look-ahead and potentially one token dropped. -% \begin{macrocode} -\cs_new:Npn \@@_change_case_upper_lt:Nnw #1 - { - \exp_args:Nf \@@_change_case_upper_lt:nnw - { - \int_case:nnF {`#1} - { - { "0069 } I - { "006A } J - { "012F } \c_@@_I_ogonek_tl - } - \exp_stop_f: - } - } -\cs_new:Npn \@@_change_case_upper_lt:nnw #1#2 - { - \tl_if_blank:nTF {#1} - {#2} - { - \@@_change_case_output:nwn {#1} - \@@_change_case_upper_lt:Nw - } - } -\cs_new:Npn \@@_change_case_upper_lt:Nw #1#2 \q_recursion_stop - { - \tl_if_head_is_N_type:nT {#2} - { \@@_change_case_upper_lt:NNw } - #1 #2 \q_recursion_stop - } -\cs_new:Npn \@@_change_case_upper_lt:NNw #1#2#3 \q_recursion_stop - { - \@@_change_case_if_expandable:NTF #2 - { - \exp_after:wN \@@_change_case_upper_lt:Nw \exp_after:wN #1 #2 - #3 \q_recursion_stop - } - { - \bool_lazy_and:nnTF - { ! \token_if_cs_p:N #2 } - { \int_compare_p:nNn { `#2 } = { "0307 } } - { #1 } - { #1 #2 } - #3 \q_recursion_stop - } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\@@_change_case_upper_de-alt:Nnw} -% A simple alternative version for German. -% \begin{macrocode} -\cs_new:cpn { @@_change_case_upper_de-alt:Nnw } #1#2 - { - \int_compare:nNnTF { `#1 } = { 223 } - { \@@_change_case_output:Vwn \c_@@_upper_Eszett_tl } - {#2} - } -% \end{macrocode} -% \end{macro} -% -% \begin{variable} -% { -% \c_@@_std_sigma_tl , -% \c_@@_final_sigma_tl , -% \c_@@_accents_lt_tl , -% \c_@@_dot_above_tl , -% \c_@@_upper_Eszett_tl -% } -% The above needs various special token lists containing pre-formed characters. -% This set are only available in Unicode engines, with no-op definitions -% for $8$-bit use. -% \begin{macrocode} -\bool_lazy_or:nnTF - { \sys_if_engine_luatex_p: } - { \sys_if_engine_xetex_p: } - { - \group_begin: - \cs_set:Npn \@@_tmp:n #1 - { - \exp_after:wN \exp_after:wN \exp_after:wN \exp_not:N - \char_generate:nn {#1} { \char_value_catcode:n {#1} } - } - \tl_const:Nx \c_@@_std_sigma_tl { \@@_tmp:n { "03C3 } } - \tl_const:Nx \c_@@_final_sigma_tl { \@@_tmp:n { "03C2 } } - \tl_const:Nx \c_@@_accents_lt_tl - { - \@@_tmp:n { "00CC } - { - \@@_tmp:n { "0069 } - \@@_tmp:n { "0307 } - \@@_tmp:n { "0300 } - } - \@@_tmp:n { "00CD } - { - \@@_tmp:n { "0069 } - \@@_tmp:n { "0307 } - \@@_tmp:n { "0301 } - } - \@@_tmp:n { "0128 } - { - \@@_tmp:n { "0069 } - \@@_tmp:n { "0307 } - \@@_tmp:n { "0303 } - } - } - \tl_const:Nx \c_@@_dot_above_tl { \@@_tmp:n { "0307 } } - \tl_const:Nx \c_@@_upper_Eszett_tl { \@@_tmp:n { "1E9E } } - \group_end: - } - { - \tl_const:Nn \c_@@_std_sigma_tl { } - \tl_const:Nn \c_@@_final_sigma_tl { } - \tl_const:Nn \c_@@_accents_lt_tl { } - \tl_const:Nn \c_@@_dot_above_tl { } - \tl_const:Nn \c_@@_upper_Eszett_tl { } - } -% \end{macrocode} -% \end{variable} -% \begin{variable} -% { -% \c_@@_dotless_i_tl , -% \c_@@_dotted_I_tl , -% \c_@@_i_ogonek_tl , -% \c_@@_I_ogonek_tl , -% } -% For cases where there is an $8$-bit option in the |T1| font set up, -% a variant is provided in both cases. -% \begin{macrocode} -\group_begin: - \bool_lazy_or:nnTF - { \sys_if_engine_luatex_p: } - { \sys_if_engine_xetex_p: } - { - \cs_set_protected:Npn \@@_tmp:w #1#2 - { - \tl_const:Nx #1 - { - \exp_after:wN \exp_after:wN \exp_after:wN - \exp_not:N \char_generate:nn - {"#2} { \char_value_catcode:n {"#2} } - } - } - } - { - \cs_set_protected:Npn \@@_tmp:w #1#2 - { - \group_begin: - \cs_set_protected:Npn \@@_tmp:w ##1##2##3##4 - { - \tl_const:Nx #1 - { - \exp_after:wN \exp_after:wN \exp_after:wN - \exp_not:N \char_generate:nn {##1} { 13 } - \exp_after:wN \exp_after:wN \exp_after:wN - \exp_not:N \char_generate:nn {##2} { 13 } - } - } - \tl_set:Nx \l_@@_internal_a_tl - { \char_codepoint_to_bytes:n {"#2} } - \exp_after:wN \@@_tmp:w \l_@@_internal_a_tl - \group_end: - } - } - \@@_tmp:w \c_@@_dotless_i_tl { 0131 } - \@@_tmp:w \c_@@_dotted_I_tl { 0130 } - \@@_tmp:w \c_@@_i_ogonek_tl { 012F } - \@@_tmp:w \c_@@_I_ogonek_tl { 012E } -\group_end: -% \end{macrocode} -% \end{variable} -% -% For $8$-bit engines we now need to define the case-change data for -% the multi-octet mappings. These need a list of what code points are -% doable in |T1| so the list is hard coded (there's no saving in loading -% the mappings dynamically). All of the straight-forward ones have two -% octets, so that is taken as read. -% \begin{macrocode} -\group_begin: - \bool_lazy_or:nnF - { \sys_if_engine_luatex_p: } - { \sys_if_engine_xetex_p: } - { - \cs_set_protected:Npn \@@_loop:nn #1#2 - { - \quark_if_recursion_tail_stop:n {#1} - \tl_set:Nx \l_@@_internal_a_tl - { - \char_codepoint_to_bytes:n {"#1} - \char_codepoint_to_bytes:n {"#2} - } - \exp_after:wN \@@_tmp:w \l_@@_internal_a_tl - \@@_loop:nn - } - \cs_set_protected:Npn \@@_tmp:nnnn #1#2#3#4#5 - { - \tl_const:cx - { - c_@@_ #1 _case_ - \char_generate:nn {#2} { 12 } - \char_generate:nn {#3} { 12 } - _tl - } - { - \exp_after:wN \exp_after:wN \exp_after:wN - \exp_not:N \char_generate:nn {#4} { 13 } - \exp_after:wN \exp_after:wN \exp_after:wN - \exp_not:N \char_generate:nn {#5} { 13 } - } - } - \cs_set_protected:Npn \@@_tmp:w #1#2#3#4#5#6#7#8 - { - \tl_const:cx - { - c_@@_lower_case_ - \char_generate:nn {#1} { 12 } - \char_generate:nn {#2} { 12 } - _tl - } - { - \exp_after:wN \exp_after:wN \exp_after:wN - \exp_not:N \char_generate:nn {#5} { 13 } - \exp_after:wN \exp_after:wN \exp_after:wN - \exp_not:N \char_generate:nn {#6} { 13 } - } - \@@_tmp:nnnn { upper } {#5} {#6} {#1} {#2} - \@@_tmp:nnnn { mixed } {#5} {#6} {#1} {#2} - } - \@@_loop:nn - { 00C0 } { 00E0 } - { 00C2 } { 00E2 } - { 00C3 } { 00E3 } - { 00C4 } { 00E4 } - { 00C5 } { 00E5 } - { 00C6 } { 00E6 } - { 00C7 } { 00E7 } - { 00C8 } { 00E8 } - { 00C9 } { 00E9 } - { 00CA } { 00EA } - { 00CB } { 00EB } - { 00CC } { 00EC } - { 00CD } { 00ED } - { 00CE } { 00EE } - { 00CF } { 00EF } - { 00D0 } { 00F0 } - { 00D1 } { 00F1 } - { 00D2 } { 00F2 } - { 00D3 } { 00F3 } - { 00D4 } { 00F4 } - { 00D5 } { 00F5 } - { 00D6 } { 00F6 } - { 00D8 } { 00F8 } - { 00D9 } { 00F9 } - { 00DA } { 00FA } - { 00DB } { 00FB } - { 00DC } { 00FC } - { 00DD } { 00FD } - { 00DE } { 00FE } - { 0100 } { 0101 } - { 0102 } { 0103 } - { 0104 } { 0105 } - { 0106 } { 0107 } - { 0108 } { 0109 } - { 010A } { 010B } - { 010C } { 010D } - { 010E } { 010F } - { 0110 } { 0111 } - { 0112 } { 0113 } - { 0114 } { 0115 } - { 0116 } { 0117 } - { 0118 } { 0119 } - { 011A } { 011B } - { 011C } { 011D } - { 011E } { 011F } - { 0120 } { 0121 } - { 0122 } { 0123 } - { 0124 } { 0125 } - { 0128 } { 0129 } - { 012A } { 012B } - { 012C } { 012D } - { 012E } { 012F } - { 0132 } { 0133 } - { 0134 } { 0135 } - { 0136 } { 0137 } - { 0139 } { 013A } - { 013B } { 013C } - { 013E } { 013F } - { 0141 } { 0142 } - { 0143 } { 0144 } - { 0145 } { 0146 } - { 0147 } { 0148 } - { 014A } { 014B } - { 014C } { 014D } - { 014E } { 014F } - { 0150 } { 0151 } - { 0152 } { 0153 } - { 0154 } { 0155 } - { 0156 } { 0157 } - { 0158 } { 0159 } - { 015A } { 015B } - { 015C } { 015D } - { 015E } { 015F } - { 0160 } { 0161 } - { 0162 } { 0163 } - { 0164 } { 0165 } - { 0168 } { 0169 } - { 016A } { 016B } - { 016C } { 016D } - { 016E } { 016F } - { 0170 } { 0171 } - { 0172 } { 0173 } - { 0174 } { 0175 } - { 0176 } { 0177 } - { 0178 } { 00FF } - { 0179 } { 017A } - { 017B } { 017C } - { 017D } { 017E } - { 01CD } { 01CE } - { 01CF } { 01D0 } - { 01D1 } { 01D2 } - { 01D3 } { 01D4 } - { 01E2 } { 01E3 } - { 01E6 } { 01E7 } - { 01E8 } { 01E9 } - { 01EA } { 01EB } - { 01F4 } { 01F5 } - { 0218 } { 0219 } - { 021A } { 021B } - \q_recursion_tail ? - \q_recursion_stop - \cs_set_protected:Npn \@@_tmp:w #1#2#3 - { - \group_begin: - \cs_set_protected:Npn \@@_tmp:w ##1##2##3##4 - { - \tl_const:cx - { - c_@@_ #3 _case_ - \char_generate:nn {##1} { 12 } - \char_generate:nn {##2} { 12 } - _tl - } - {#2} - } - \tl_set:Nx \l_@@_internal_a_tl - { \char_codepoint_to_bytes:n { "#1 } } - \exp_after:wN \@@_tmp:w \l_@@_internal_a_tl - \group_end: - } - \@@_tmp:w { 00DF } { SS } { upper } - \@@_tmp:w { 00DF } { Ss } { mixed } - \@@_tmp:w { 0131 } { I } { upper } - } - \group_end: -% \end{macrocode} -% -% The (fixed) look-up mappings for letter-like control sequences. -% \begin{macrocode} -\group_begin: - \cs_set_protected:Npn \@@_change_case_setup:NN #1#2 - { - \quark_if_recursion_tail_stop:N #1 - \tl_const:cn { c_@@_change_case_lower_ \token_to_str:N #1 _tl } - { #2 } - \tl_const:cn { c_@@_change_case_upper_ \token_to_str:N #2 _tl } - { #1 } - \@@_change_case_setup:NN - } - \@@_change_case_setup:NN - \AA \aa - \AE \ae - \DH \dh - \DJ \dj - \IJ \ij - \L \l - \NG \ng - \O \o - \OE \oe - \SS \ss - \TH \th - \q_recursion_tail ? - \q_recursion_stop - \tl_const:cn { c_@@_change_case_upper_ \token_to_str:N \i _tl } { I } - \tl_const:cn { c_@@_change_case_upper_ \token_to_str:N \j _tl } { J } -\group_end: -% \end{macrocode} -% -% \begin{variable}{\l_tl_case_change_accents_tl} -% A list of accents to leave alone. -% \begin{macrocode} -\tl_new:N \l_tl_case_change_accents_tl -\tl_set:Nn \l_tl_case_change_accents_tl - { \" \' \. \^ \` \~ \c \H \k \r \t \u \v } -% \end{macrocode} -% \end{variable} -% -% \begin{macro}[EXP]{\@@_change_case_mixed_nl:Nnw} -% \begin{macro}[EXP]{\@@_change_case_mixed_nl:Nw} -% \begin{macro}[EXP]{\@@_change_case_mixed_nl:NNw} -% For Dutch, there is a single look-ahead test for \texttt{ij} when -% title casing. If the appropriate letters are found, produce \texttt{IJ} -% and gobble the \texttt{j}/\texttt{J}. -% \begin{macrocode} -\cs_new:Npn \@@_change_case_mixed_nl:Nnw #1 - { - \bool_lazy_or:nnTF - { \int_compare_p:nNn { `#1 } = { `i } } - { \int_compare_p:nNn { `#1 } = { `I } } - { - \@@_change_case_output:nwn { I } - \@@_change_case_mixed_nl:Nw - } - } -\cs_new:Npn \@@_change_case_mixed_nl:Nw #1#2 \q_recursion_stop - { - \tl_if_head_is_N_type:nT {#2} - { \@@_change_case_mixed_nl:NNw } - #1 #2 \q_recursion_stop - } -\cs_new:Npn \@@_change_case_mixed_nl:NNw #1#2#3 \q_recursion_stop - { - \@@_change_case_if_expandable:NTF #2 - { - \exp_after:wN \@@_change_case_mixed_nl:Nw \exp_after:wN #1 #2 - #3 \q_recursion_stop - } - { - \bool_lazy_and:nnTF - { ! ( \token_if_cs_p:N #2 ) } - { - \bool_lazy_or_p:nn - { \int_compare_p:nNn { `#2 } = { `j } } - { \int_compare_p:nNn { `#2 } = { `J } } - } - { - \@@_change_case_output:nwn { J } - #1 - } - { #1 #2 } - #3 \q_recursion_stop - } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{variable}{\l_tl_case_change_math_tl} -% The list of token pairs which are treated as math mode and so -% not case changed. -% \begin{macrocode} -\tl_new:N \l_tl_case_change_math_tl -%<*package> -\tl_set:Nn \l_tl_case_change_math_tl - { $ $ \( \) } -%</package> -% \end{macrocode} -% \end{variable} -% -% \begin{variable}{\l_tl_case_change_exclude_tl} -% The list of commands for which an argument is not case changed. -% \begin{macrocode} -\tl_new:N \l_tl_case_change_exclude_tl -%<*package> -\tl_set:Nn \l_tl_case_change_exclude_tl - { \cite \ensuremath \label \ref } -%</package> -% \end{macrocode} -% \end{variable} -% -% \begin{variable}{\l_tl_mixed_case_ignore_tl} -% Characters to skip over when finding the first letter in a word to be -% mixed cased. -% \begin{macrocode} -\tl_new:N \l_tl_mixed_case_ignore_tl -\tl_set:Nx \l_tl_mixed_case_ignore_tl - { - ( % ) - [ % ] - \cs_to_str:N \{ % \} - ` - - - } -% \end{macrocode} -% \end{variable} -% -% \subsubsection{Building a token list} -% % Between \cs{tl_build_begin:N} \meta{tl~var} and \cs{tl_build_end:N} % \meta{tl~var}, the \meta{tl~var} has the structure % \begin{quote} |