summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/l3kernel/l3str.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/l3kernel/l3str.dtx')
-rw-r--r--macros/latex/contrib/l3kernel/l3str.dtx148
1 files changed, 118 insertions, 30 deletions
diff --git a/macros/latex/contrib/l3kernel/l3str.dtx b/macros/latex/contrib/l3kernel/l3str.dtx
index 897f4b962b..ddfdd10279 100644
--- a/macros/latex/contrib/l3kernel/l3str.dtx
+++ b/macros/latex/contrib/l3kernel/l3str.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2022-02-24}
+% \date{Released 2022-04-10}
%
% \maketitle
%
@@ -222,8 +222,8 @@
%
% \section{String conditionals}
%
-% \begin{function}[EXP,pTF, added = 2015-09-18]
-% {\str_if_empty:N, \str_if_empty:c}
+% \begin{function}[EXP,pTF, added = 2015-09-18, updated = 2022-03-21]
+% {\str_if_empty:N, \str_if_empty:c, \str_if_empty:n}
% \begin{syntax}
% \cs{str_if_empty_p:N} \meta{str~var}
% \cs{str_if_empty:NTF} \meta{str~var} \Arg{true code} \Arg{false code}
@@ -282,8 +282,8 @@
% tests whether \meta{string_2} is found inside \meta{string_1}.
% \end{function}
%
-% \begin{function}[added = 2013-07-24, updated = 2015-02-28, EXP, noTF]
-% {\str_case:nn, \str_case:Vn, \str_case:on, \str_case:nV, \str_case:nv}
+% \begin{function}[added = 2013-07-24, updated = 2022-03-21, EXP, noTF]
+% {\str_case:nn, \str_case:Vn, \str_case:Nn, \str_case:on, \str_case:nV, \str_case:nv}
% \begin{syntax}
% \cs{str_case:nnTF} \Arg{test string} \\
% ~~|{| \\
@@ -747,16 +747,6 @@
% correctly deal with context-dependence and other factors appropriate
% to text case changing.
% \end{itemize}
-%
-% \begin{texnote}
-% As with all \pkg{expl3} functions, the input supported by
-% \cs{str_foldcase:n} is \emph{engine-native} characters which are or
-% interoperate with \textsc{utf-8}. As such, when used with \pdfTeX{}
-% \emph{only} the Latin alphabet characters A--Z are case-folded
-% (\emph{i.e.}~the \textsc{ascii} range which coincides with
-% \textsc{utf-8}). Full \textsc{utf-8} support is available with both
-% \XeTeX{} and \LuaTeX{}.
-% \end{texnote}
% \end{function}
%
% \begin{function}[EXP, added = 2019-11-26]
@@ -789,18 +779,6 @@
% a language-insensitive process, there is no special treatment of
% Turkic input (\emph{i.e.}~\texttt{I} always folds to \texttt{i} and
% not to \texttt{\i}).
-%
-% \begin{texnote}
-% As with all \pkg{expl3} functions, the input supported by
-% \cs{str_foldcase:n} is \emph{engine-native} characters which are or
-% interoperate with \textsc{utf-8}. As such, when used with \pdfTeX{}
-% \emph{only} the Latin alphabet characters A--Z are case-folded
-% (\emph{i.e.}~the \textsc{ascii} range which coincides with
-% \textsc{utf-8}). Full \textsc{utf-8} support is available with both
-% \XeTeX{} and \LuaTeX{}, subject only to the fact that \XeTeX{} in
-% particular has issues with characters of code above hexadecimal
-% $0\mathrm{xFFFF}$ when interacting with \cs{tl_to_str:n}.
-% \end{texnote}
% \end{function}
%
% \section{Viewing strings}
@@ -1113,7 +1091,7 @@
%
% \begin{macro}[pTF, EXP]
% {
-% \str_if_empty:N, \str_if_empty:c,
+% \str_if_empty:N, \str_if_empty:c, \str_if_empty:n,
% \str_if_exist:N, \str_if_exist:c
% }
% More copy-paste!
@@ -1126,6 +1104,8 @@
{ p , T , F , TF }
\prg_new_eq_conditional:NNn \str_if_empty:c \tl_if_empty:c
{ p , T , F , TF }
+\prg_new_eq_conditional:NNn \str_if_empty:n \tl_if_empty:n
+ { p , T , F , TF }
% \end{macrocode}
% \end{macro}
%
@@ -1224,7 +1204,7 @@
% \end{macro}
%
% \begin{macro}[EXP, noTF]
-% {\str_case:nn, \str_case:Vn, \str_case:on, \str_case:nV, \str_case:nv, \str_case_e:nn}
+% {\str_case:nn, \str_case:Vn, \str_case:Nn, \str_case:on, \str_case:nV, \str_case:nv, \str_case_e:nn}
% \begin{macro}[EXP]{\@@_case:nnTF, \@@_case_e:nnTF}
% \begin{macro}[EXP]
% {\@@_case:nw, \@@_case_e:nw, \@@_case_end:nw}
@@ -1254,6 +1234,10 @@
\cs_new:Npn \@@_case:nnTF #1#2#3#4
{ \@@_case:nw {#1} #2 {#1} { } \s_@@_mark {#3} \s_@@_mark {#4} \s_@@_stop }
\cs_generate_variant:Nn \str_case:nn { V , o , nV , nv }
+\cs_new_eq:NN \str_case:Nn \str_case:Vn
+\cs_new_eq:NN \str_case:NnT \str_case:VnT
+\cs_new_eq:NN \str_case:NnF \str_case:VnF
+\cs_new_eq:NN \str_case:NnTF \str_case:VnTF
\prg_generate_conditional_variant:Nnn \str_case:nn
{ V , o , nV , nv } { T , F , TF }
\cs_new:Npn \@@_case:nw #1#2#3
@@ -1918,10 +1902,21 @@
% \begin{macro}[EXP]{\@@_change_case_loop:nw}
% \begin{macro}[EXP]{\@@_change_case_space:n}
% \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 ,
+% \@@_change_case_char_UTFviii_lower:nn ,
+% \@@_change_case_char_UTFviii_upper:nn ,
+% \@@_change_case_char_UTFviii_fold:nn
+% }
% Case changing for programmatic reasons is done by first detokenizing
% input then doing a simple loop that only has to worry about spaces
% and everything else. The output is detokenized to allow data sharing
-% with text-based case changing.
+% with text-based case changing. Similarly, for $8$-bit engines the
+% multi-byte information is shared.
% \begin{macrocode}
\cs_new:Npn \str_foldcase:n #1 { \@@_change_case:nn {#1} { fold } }
\cs_new:Npn \str_lowercase:n #1 { \@@_change_case:nn {#1} { lower } }
@@ -1965,7 +1960,100 @@
{ \use:c { char_str_ #1 case:N } #2 }
\@@_change_case_loop:nw {#1}
}
+\if_int_compare:w 0
+ \cs_if_exist:NT \tex_XeTeXversion:D { 1 }
+ \cs_if_exist:NT \tex_luatexversion:D { 1 }
+ > 0 \exp_stop_f:
+\else:
+ \cs_gset:Npn \@@_change_case_char:nN #1#2
+ {
+ \@@_if_recursion_tail_stop_do:Nn #2
+ { \@@_change_case_end:wn }
+ \int_compare:nNnTF { `#2 } > { "80 }
+ {
+ \int_compare:nNnTF { `#2 } < { "E0 }
+ { \@@_change_case_char_UTFviii:nNN }
+ {
+ \int_compare:nNnTF { `#2 } < { "F0 }
+ { \@@_change_case_char_UTFviii:nNNN }
+ { \@@_change_case_char_UTFviii:nNNNN }
+ }
+ {#1} #2
+ }
+ {
+ \@@_change_case_output:fw
+ { \use:c { char_str_ #1 case:N } #2 }
+ \@@_change_case_loop:nw {#1}
+ }
+ }
+ \cs_new:Npn \@@_change_case_char_UTFviii:nNN #1#2#3
+ { \@@_change_case_char_UTFviii:nn {#1} {#2#3} }
+ \cs_new:Npn \@@_change_case_char_UTFviii:nNNN #1#2#3#4
+ { \@@_change_case_char_UTFviii:nn {#1} {#2#3#4} }
+ \cs_new:Npn \@@_change_case_char_UTFviii:nNNNN #1#2#3#4#5
+ { \@@_change_case_char_UTFviii:nn {#1} {#2#3#4#5} }
% \end{macrocode}
+% Skip high chars for the Japanese engines.
+% \begin{macrocode}
+ \cs_if_exist:NF \tex_pdftexversion:D
+ {
+ \cs_gset:Npn \@@_change_case_char_UTFviii:nNNN #1#2#3#4
+ {
+ \@@_change_case_output:nw {#2#3#4}
+ \@@_change_case_loop:nw {#1}
+ }
+ \cs_gset:Npn \@@_change_case_char_UTFviii:nNNNN #1#2#3#4#5
+ {
+ \@@_change_case_output:nw {#2#3#4#5}
+ \@@_change_case_loop:nw {#1}
+ }
+ }
+ \cs_new:Npn \@@_change_case_char_UTFviii:nn #1#2
+ {
+ \use:c { @@_change_case_char_UTFviii_ #1 :nn } {#1} {#2}
+ }
+ \cs_new:Npn \@@_change_case_char_UTFviii_upper:nn #1#2
+ {
+ \@@_change_case_output:fw
+ {
+ \cs_if_exist:cTF { c__kernel_ #1 case_ #2 _tl }
+ {
+ \__kernel_tl_to_str:w \exp_after:wN \exp_after:wN \exp_after:wN
+ { \cs:w c__kernel_ #1 case_ #2 _tl \cs_end: }
+ }
+ {#2}
+ }
+ \@@_change_case_loop:nw {#1}
+ }
+ \cs_new_eq:NN \@@_change_case_char_UTFviii_lower:nn
+ \@@_change_case_char_UTFviii_upper:nn
+ \cs_new:Npn \@@_change_case_char_UTFviii_fold:nn #1#2
+ {
+ \@@_change_case_output:fw
+ {
+ \cs_if_exist:cTF { c__kernel_ #1 case_ #2 _tl }
+ {
+ \__kernel_tl_to_str:w \exp_after:wN \exp_after:wN \exp_after:wN
+ { \cs:w c__kernel_ #1 case_ #2 _tl \cs_end: }
+ }
+ {
+ \cs_if_exist:cTF { c__kernel_lowercase_ #2 _tl }
+ {
+ \__kernel_tl_to_str:w
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ { \cs:w c__kernel_lowercase_ #2 _tl \cs_end: }
+ }
+ {#2}
+ }
+ }
+ \@@_change_case_loop:nw {#1}
+ }
+\fi:
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}