summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/l3kernel/l3candidates.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/l3kernel/l3candidates.dtx')
-rw-r--r--macros/latex/contrib/l3kernel/l3candidates.dtx1927
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}