diff options
author | Norbert Preining <norbert@preining.info> | 2022-12-18 03:04:42 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2022-12-18 03:04:42 +0000 |
commit | 81dce26929e98696f622283b42f25c643dcfe565 (patch) | |
tree | 7b1172ee9247eab226e5d425bc8d42ddea0be53b /macros/latex/contrib | |
parent | 7b88c25271448cb717bea52abc52e2c8ec033dd9 (diff) |
CTAN sync 202212180304
Diffstat (limited to 'macros/latex/contrib')
99 files changed, 1969 insertions, 2523 deletions
diff --git a/macros/latex/contrib/l3kernel/CHANGELOG.md b/macros/latex/contrib/l3kernel/CHANGELOG.md index 91a9b82c57..7952d03430 100644 --- a/macros/latex/contrib/l3kernel/CHANGELOG.md +++ b/macros/latex/contrib/l3kernel/CHANGELOG.md @@ -7,6 +7,20 @@ this project uses date-based 'snapshot' version identifiers. ## [Unreleased] +## [2022-12-17] + +### Added +- `\codepoint_to_nfd:n` +- `\codepoint_generate:n` and `\codepoint_str_generate:n` +- `\str_casefold:n` + +### Changed +- Protect `babel` shorthands from expansion + +### Fixed +- Appearance of `\DescribeOption` (issue + [\#1111](https://github.com/latex3/latex3/issues/1111)) + ## [2022-11-02] ### Added @@ -30,6 +44,13 @@ this project uses date-based 'snapshot' version identifiers. - Creation of a message with some engines (issue [\#1139](https://github.com/latex3/latex3/issues/1139)) +### Deprecated +- `\char_to_nfd:N`, `\char_to_nfd:n` +- `\char_foldcase:N`, `\char_lowercase:N`, `\char_uppercase:N` + and `str` variants +- `\char_to_utfviii_bytes:n` +- `\str_foldcase:n` + ## [2022-09-28] ### Added @@ -1231,7 +1252,8 @@ this project uses date-based 'snapshot' version identifiers. - Step functions have been added for dim variables, e.g. `\dim_step_inline:nnnn` -[Unreleased]: https://github.com/latex3/latex3/compare/2022-11-02...HEAD +[Unreleased]: https://github.com/latex3/latex3/compare/2022-12-17...HEAD +[2022-12-17]: https://github.com/latex3/latex3/compare/2022-11-02...2022-12-17 [2022-11-02]: https://github.com/latex3/latex3/compare/2022-10-26...2022-11-02 [2022-10-26]: https://github.com/latex3/latex3/compare/2022-09-28...2022-10-26 [2022-09-28]: https://github.com/latex3/latex3/compare/2022-08-30...2022-09-28 diff --git a/macros/latex/contrib/l3kernel/README.md b/macros/latex/contrib/l3kernel/README.md index f93c852fbe..8126173a6b 100644 --- a/macros/latex/contrib/l3kernel/README.md +++ b/macros/latex/contrib/l3kernel/README.md @@ -1,7 +1,7 @@ LaTeX3 Programming Conventions ============================== -Release 2022-11-02 +Release 2022-12-17 Overview -------- diff --git a/macros/latex/contrib/l3kernel/expl3.dtx b/macros/latex/contrib/l3kernel/expl3.dtx index 91240143e5..01e337fb62 100644 --- a/macros/latex/contrib/l3kernel/expl3.dtx +++ b/macros/latex/contrib/l3kernel/expl3.dtx @@ -24,7 +24,7 @@ % %<*driver|generic|package|2ekernel> %</driver|generic|package|2ekernel> -\def\ExplFileDate{2022-11-02}% +\def\ExplFileDate{2022-12-17}% %<*driver> \documentclass[full]{l3doc} \usepackage{graphicx} @@ -51,7 +51,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % @@ -1182,9 +1182,15 @@ % Identify the package or add to the format message. % \begin{macrocode} %<*2ekernel> -\everyjob\expandafter{\the\everyjob - \message{L3 programming layer <\ExplFileDate>}% -} +\ifdefined\LaTeXReleaseInfo + \LaTeXReleaseInfo\expandafter{\the\LaTeXReleaseInfo + \show@release@info{L3 programming layer <\ExplFileDate>}% + }% +\else + \everyjob\expandafter{\the\everyjob + \message{L3 programming layer <\ExplFileDate>}% + }% +\fi %</2ekernel> %<*!2ekernel> \ProvidesPackage{expl3} diff --git a/macros/latex/contrib/l3kernel/expl3.pdf b/macros/latex/contrib/l3kernel/expl3.pdf Binary files differindex 0526c9bffd..ea4493fe77 100644 --- a/macros/latex/contrib/l3kernel/expl3.pdf +++ b/macros/latex/contrib/l3kernel/expl3.pdf diff --git a/macros/latex/contrib/l3kernel/interface3.pdf b/macros/latex/contrib/l3kernel/interface3.pdf Binary files differindex 22204b77d6..870a0c86ed 100644 --- a/macros/latex/contrib/l3kernel/interface3.pdf +++ b/macros/latex/contrib/l3kernel/interface3.pdf diff --git a/macros/latex/contrib/l3kernel/interface3.tex b/macros/latex/contrib/l3kernel/interface3.tex index 6d3d96bf29..00518848ed 100644 --- a/macros/latex/contrib/l3kernel/interface3.tex +++ b/macros/latex/contrib/l3kernel/interface3.tex @@ -54,7 +54,7 @@ for those people who are interested. {latex-team@latex-project.org}% }% } -\date{Released 2022-11-02} +\date{Released 2022-12-17} \pagenumbering{roman} \maketitle diff --git a/macros/latex/contrib/l3kernel/l3basics.dtx b/macros/latex/contrib/l3kernel/l3basics.dtx index 45fd5cd492..014b134cba 100644 --- a/macros/latex/contrib/l3kernel/l3basics.dtx +++ b/macros/latex/contrib/l3kernel/l3basics.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3bootstrap.dtx b/macros/latex/contrib/l3kernel/l3bootstrap.dtx index 2b840ae68e..3ee7509804 100644 --- a/macros/latex/contrib/l3kernel/l3bootstrap.dtx +++ b/macros/latex/contrib/l3kernel/l3bootstrap.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3box.dtx b/macros/latex/contrib/l3kernel/l3box.dtx index c80f06ec95..47d18e3e87 100644 --- a/macros/latex/contrib/l3kernel/l3box.dtx +++ b/macros/latex/contrib/l3kernel/l3box.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3candidates.dtx b/macros/latex/contrib/l3kernel/l3candidates.dtx index d422a4dc62..5be78d56d7 100644 --- a/macros/latex/contrib/l3kernel/l3candidates.dtx +++ b/macros/latex/contrib/l3kernel/l3candidates.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % @@ -347,7 +347,7 @@ % \begin{function}[EXP, added = 2016-12-06] % {\prop_rand_key_value:N, \prop_rand_key_value:c} % \begin{syntax} -% \cs{prop_rand_key_value:N} \meta{prop~var} +% \cs{prop_rand_key_value:N} \meta{property list} % \end{syntax} % Selects a pseudo-random key--value pair from the \meta{property list} % and returns \Arg{key} and \Arg{value}. If the \meta{property list} is @@ -626,40 +626,6 @@ % (\enquote{active}), and character code $32$ (space). % \end{variable} % -% \begin{function}[added = 2020-01-09, EXP]{\char_to_utfviii_bytes:n} -% \begin{syntax} -% \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 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 \emph{first} generated character is -% the same as the \meta{char}; second and subsequent chars will have the -% current category code, as they would if typed in directly. For $8$-bit -% engines, no change will take place. -% \end{function} -% -% \begin{function}[added = 2022-08-29, rEXP]{\char_to_nfd:n} -% \begin{syntax} -% \cs{char_to_nfd:n} \Arg{codepoint} -% \end{syntax} -% Converts the (Unicode) \meta{codepoint} to the Unicode Normalization -% Form Canonical Decomposition. The generated character(s) will have -% the current category code as they would if typed in directly. In contrast -% to \cs{char_to_nfd:N}, this function \emph{does} decompose codepoints -% with $8$-bit engines. -% \end{function} -% % \begin{function}[added = 2018-09-23] % { % \peek_catcode_collect_inline:Nn, diff --git a/macros/latex/contrib/l3kernel/l3cctab.dtx b/macros/latex/contrib/l3kernel/l3cctab.dtx index a835763025..41f43dc136 100644 --- a/macros/latex/contrib/l3kernel/l3cctab.dtx +++ b/macros/latex/contrib/l3kernel/l3cctab.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3clist.dtx b/macros/latex/contrib/l3kernel/l3clist.dtx index 35462cf76a..e798879c14 100644 --- a/macros/latex/contrib/l3kernel/l3clist.dtx +++ b/macros/latex/contrib/l3kernel/l3clist.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3coffins.dtx b/macros/latex/contrib/l3kernel/l3coffins.dtx index 263bcadbf1..95a9ab4ee6 100644 --- a/macros/latex/contrib/l3kernel/l3coffins.dtx +++ b/macros/latex/contrib/l3kernel/l3coffins.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3color.dtx b/macros/latex/contrib/l3kernel/l3color.dtx index a904ddeaa1..7535b45bd5 100644 --- a/macros/latex/contrib/l3kernel/l3color.dtx +++ b/macros/latex/contrib/l3kernel/l3color.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % @@ -2146,7 +2146,7 @@ { \exp_args:Nee \@@_model_new:nnn { \tl_to_str:n {#1} } - { \str_foldcase:n {#2} } {#3} + { \str_casefold:n {#2} } {#3} } \cs_new_protected:Npn \@@_model_new:nnn #1#2#3 { diff --git a/macros/latex/contrib/l3kernel/l3debug.dtx b/macros/latex/contrib/l3kernel/l3debug.dtx index aa437dae72..45377dfa27 100644 --- a/macros/latex/contrib/l3kernel/l3debug.dtx +++ b/macros/latex/contrib/l3kernel/l3debug.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3deprecation.dtx b/macros/latex/contrib/l3kernel/l3deprecation.dtx index b7db3e0efb..9d6dc6b09a 100644 --- a/macros/latex/contrib/l3kernel/l3deprecation.dtx +++ b/macros/latex/contrib/l3kernel/l3deprecation.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % @@ -468,10 +468,20 @@ \cs_gset:Npn \str_upper_case:n { \str_uppercase:n } \__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \str_uppercase:f } \cs_gset:Npn \str_upper_case:f { \str_uppercase:f } -\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \str_foldcase:n } -\cs_gset:Npn \str_fold_case:n { \str_foldcase:n } -\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \str_foldcase:V } -\cs_gset:Npn \str_fold_case:V { \str_foldcase:V } +\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \str_casefold:n } +\cs_gset:Npn \str_fold_case:n { \str_casefold:n } +\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \str_casefold:V } +\cs_gset:Npn \str_fold_case:V { \str_casefold:V } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP] +% {\str_foldcase:n, \str_foldcase:V} +% \begin{macrocode} +\__kernel_patch_deprecation:nnNNpn { 2020-10-17 } { \str_casefold:n } +\cs_gset:Npn \str_foldcase:n { \str_casefold:n } +\__kernel_patch_deprecation:nnNNpn { 2022-10-17 } { \str_casefold:V } +\cs_gset:Npn \str_foldcase:V { \str_casefold:V } % \end{macrocode} % \end{macro} % @@ -549,6 +559,22 @@ % % \subsection{Deprecated \pkg{l3token} functions} % +% \begin{macro}[EXP]{\char_to_utfviii_bytes:n} +% \begin{macrocode} +\__kernel_patch_deprecation:nnNNpn { 2022-10-09 } { [ \codepoint_generate:n ] } +\cs_gset:Npn \char_to_utfviii_bytes:n { \__kernel_codepoint_to_bytes:n } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\char_to_nfd:Nm, \char_to_nfd:n} +% \begin{macrocode} +\__kernel_patch_deprecation:nnNNpn { 2022-10-09 } { \codepoint_to_nfd:n } +\cs_gset:Npn \char_to_nfd:N #1 { \codepoint_to_nfd:n {`#1} } +\__kernel_patch_deprecation:nnNNpn { 2022-10-09 } { \codepoint_to_nfd:n } +\cs_gset:Npn \char_to_nfd:n { \codepoint_to_nfd:n } +% \end{macrocode} +% \end{macro} +% % \begin{macro}[EXP] % { % \char_lower_case:N, \char_upper_case:N, @@ -557,22 +583,45 @@ % \char_str_mixed_case:Nn, \char_str_fold_case:N, % } % \begin{macrocode} -\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \char_lowercase:N } -\cs_gset:Npn \char_lower_case:N { \char_lowercase:N } -\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \char_uppercase:N } -\cs_gset:Npn \char_upper_case:N { \char_uppercase:N } -\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \char_titlecase:N } -\cs_gset:Npn \char_mixed_case:N { \char_titlecase:N } -\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \char_foldcase:N } -\cs_gset:Npn \char_fold_case:N { \char_foldcase:N } -\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \char_str_lowercase:N } -\cs_gset:Npn \char_str_lower_case:N { \char_str_lowercase:N } -\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \char_str_uppercase:N } -\cs_gset:Npn \char_str_upper_case:N { \char_str_uppercase:N } -\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \char_str_titlecase:N } -\cs_gset:Npn \char_str_mixed_case:N { \char_str_titlecase:N } -\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \char_str_foldcase:N } -\cs_gset:Npn \char_str_fold_case:N { \char_str_foldcase:N } +\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \text_lowercase:n } +\cs_gset:Npn \char_lower_case:N { \text_lowercase:n } +\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \text_uppercase:n } +\cs_gset:Npn \char_upper_case:N { \text_uppercase:n } +\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \text_titlecase:n } +\cs_gset:Npn \char_mixed_case:N { \text_titlecase:n } +\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \str_casefold:n } +\cs_gset:Npn \char_fold_case:N { \str_casefold:n } +\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \str_lowercase:n } +\cs_gset:Npn \char_str_lower_case:N { \str_lowercase:n } +\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \str_uppercase:n } +\cs_gset:Npn \char_str_upper_case:N { \str_uppercase:n } +\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \str_titlecase:n } +\cs_gset:Npn \char_str_mixed_case:N { \str_titlecase:n } +\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \str_casefold:n } +\cs_gset:Npn \char_str_fold_case:N { \str_casefold:n } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP] +% { +% \char_lowercase:N, \char_uppercase:N, +% \char_foldcase:N, +% \char_str_lowercase:N, \char_str_uppercase:N, +% \char_str_foldcase:N, +% } +% \begin{macrocode} +\__kernel_patch_deprecation:nnNNpn { 2022-10-17 } { \text_lowercase:n } +\cs_gset:Npn \char_lowercase:N { \text_lowercase:n } +\__kernel_patch_deprecation:nnNNpn { 2022-10-17 } { \text_uppercase:n } +\cs_gset:Npn \char_uppercase:N { \text_uppercase:n } +\__kernel_patch_deprecation:nnNNpn { 2022-10-17 } { \str_casefold:n } +\cs_gset:Npn \char_foldcase:N { \str_casefold:n } +\__kernel_patch_deprecation:nnNNpn { 2022-10-17 } { \str_lowercase:n } +\cs_gset:Npn \char_str_lowercase:N { \str_lowercase:n } +\__kernel_patch_deprecation:nnNNpn { 2022-10-17 } { \str_uppercase:n } +\cs_gset:Npn \char_str_uppercase:N { \str_uppercase:n } +\__kernel_patch_deprecation:nnNNpn { 2022-10-17 } { \str_casefold:n } +\cs_gset:Npn \char_str_foldcase:N { \str_casefold:n } % \end{macrocode} % \end{macro} % diff --git a/macros/latex/contrib/l3kernel/l3doc.dtx b/macros/latex/contrib/l3kernel/l3doc.dtx index 78a9412025..224b1aaead 100644 --- a/macros/latex/contrib/l3kernel/l3doc.dtx +++ b/macros/latex/contrib/l3kernel/l3doc.dtx @@ -85,7 +85,7 @@ and all files in that bundle must be distributed together. % require you to do updates, if the class changes.}} % % \author{\Team} -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % \maketitle % \tableofcontents % @@ -3410,52 +3410,10 @@ and all files in that bundle must be distributed together. % \subsubsection{Misc} % % \begin{macro}{\DescribeOption} -% For describing package options. Due to Joseph Wright. Name/usage -% might change soon. +% For describing package options: retained for consistency, but updated for +% \pkg{doc}~v3. % \begin{macrocode} -\newcommand*{\DescribeOption} - { - \leavevmode - \@bsphack - \begingroup - \MakePrivateLetters - \Describe@Option - } -% \end{macrocode} -% -% \begin{macrocode} -\newcommand*{\Describe@Option}[1] - { - \endgroup - \marginpar{ - \raggedleft - \PrintDescribeEnv{#1} - } - \SpecialOptionIndex{#1} - \@esphack - \ignorespaces - } -% \end{macrocode} -% -% \begin{macrocode} -\newcommand*{\SpecialOptionIndex}[1] - { - \@bsphack - \begingroup - \@@_target: - \index - { - #1\actualchar{\protect\ttfamily#1}~(option) - \encapchar hdclindex{\the\c@HD@hypercount}{usage} - } - \index - { - options:\levelchar#1\actualchar{\protect\ttfamily#1} - \encapchar hdclindex{\the\c@HD@hypercount}{usage} - } - \endgroup - \@esphack - } +\NewDocElement[idxtype = option, idxgroup = options]{Option}{optionenv} % \end{macrocode} % \end{macro} % diff --git a/macros/latex/contrib/l3kernel/l3doc.pdf b/macros/latex/contrib/l3kernel/l3doc.pdf Binary files differindex 9b8c5d1ab9..dd28a7c8ec 100644 --- a/macros/latex/contrib/l3kernel/l3doc.pdf +++ b/macros/latex/contrib/l3kernel/l3doc.pdf diff --git a/macros/latex/contrib/l3kernel/l3docstrip.dtx b/macros/latex/contrib/l3kernel/l3docstrip.dtx index 7708f045e4..55498a07d7 100644 --- a/macros/latex/contrib/l3kernel/l3docstrip.dtx +++ b/macros/latex/contrib/l3kernel/l3docstrip.dtx @@ -63,7 +63,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3docstrip.pdf b/macros/latex/contrib/l3kernel/l3docstrip.pdf Binary files differindex 1b744af08b..d63049b0ad 100644 --- a/macros/latex/contrib/l3kernel/l3docstrip.pdf +++ b/macros/latex/contrib/l3kernel/l3docstrip.pdf diff --git a/macros/latex/contrib/l3kernel/l3expan.dtx b/macros/latex/contrib/l3kernel/l3expan.dtx index 788143f549..218e673d5c 100644 --- a/macros/latex/contrib/l3kernel/l3expan.dtx +++ b/macros/latex/contrib/l3kernel/l3expan.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3file.dtx b/macros/latex/contrib/l3kernel/l3file.dtx index 55a83f486e..d541aa574e 100644 --- a/macros/latex/contrib/l3kernel/l3file.dtx +++ b/macros/latex/contrib/l3kernel/l3file.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3flag.dtx b/macros/latex/contrib/l3kernel/l3flag.dtx index 517ebfb46a..afcaffd7ad 100644 --- a/macros/latex/contrib/l3kernel/l3flag.dtx +++ b/macros/latex/contrib/l3kernel/l3flag.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3fp-assign.dtx b/macros/latex/contrib/l3kernel/l3fp-assign.dtx index 0a6ea7325d..fccec11696 100644 --- a/macros/latex/contrib/l3kernel/l3fp-assign.dtx +++ b/macros/latex/contrib/l3kernel/l3fp-assign.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % \maketitle % % \begin{documentation} diff --git a/macros/latex/contrib/l3kernel/l3fp-aux.dtx b/macros/latex/contrib/l3kernel/l3fp-aux.dtx index 48696082c6..4a1af5bfe5 100644 --- a/macros/latex/contrib/l3kernel/l3fp-aux.dtx +++ b/macros/latex/contrib/l3kernel/l3fp-aux.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3fp-basics.dtx b/macros/latex/contrib/l3kernel/l3fp-basics.dtx index 71f166ceca..67cf7d43c7 100644 --- a/macros/latex/contrib/l3kernel/l3fp-basics.dtx +++ b/macros/latex/contrib/l3kernel/l3fp-basics.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3fp-convert.dtx b/macros/latex/contrib/l3kernel/l3fp-convert.dtx index 515c1b3ab9..dc98c5fdf0 100644 --- a/macros/latex/contrib/l3kernel/l3fp-convert.dtx +++ b/macros/latex/contrib/l3kernel/l3fp-convert.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3fp-expo.dtx b/macros/latex/contrib/l3kernel/l3fp-expo.dtx index 8b816a222f..93d79258f1 100644 --- a/macros/latex/contrib/l3kernel/l3fp-expo.dtx +++ b/macros/latex/contrib/l3kernel/l3fp-expo.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3fp-extended.dtx b/macros/latex/contrib/l3kernel/l3fp-extended.dtx index 8b592233dd..3528e7bb44 100644 --- a/macros/latex/contrib/l3kernel/l3fp-extended.dtx +++ b/macros/latex/contrib/l3kernel/l3fp-extended.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3fp-logic.dtx b/macros/latex/contrib/l3kernel/l3fp-logic.dtx index 52f1e9b8bc..d4571626de 100644 --- a/macros/latex/contrib/l3kernel/l3fp-logic.dtx +++ b/macros/latex/contrib/l3kernel/l3fp-logic.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3fp-parse.dtx b/macros/latex/contrib/l3kernel/l3fp-parse.dtx index 2f0fccdc23..6ece846860 100644 --- a/macros/latex/contrib/l3kernel/l3fp-parse.dtx +++ b/macros/latex/contrib/l3kernel/l3fp-parse.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % @@ -1023,7 +1023,7 @@ \cs_if_exist_use:cF { @@_parse_word_#2:N } { \cs_if_exist_use:cF - { @@_parse_caseless_ \str_foldcase:n {#2} :N } + { @@_parse_caseless_ \str_casefold:n {#2} :N } { \msg_expandable_error:nnn { fp } { unknown-fp-word } {#2} diff --git a/macros/latex/contrib/l3kernel/l3fp-random.dtx b/macros/latex/contrib/l3kernel/l3fp-random.dtx index 04bd5285b0..732bcc657c 100644 --- a/macros/latex/contrib/l3kernel/l3fp-random.dtx +++ b/macros/latex/contrib/l3kernel/l3fp-random.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3fp-round.dtx b/macros/latex/contrib/l3kernel/l3fp-round.dtx index 65db824b79..45514ebdef 100644 --- a/macros/latex/contrib/l3kernel/l3fp-round.dtx +++ b/macros/latex/contrib/l3kernel/l3fp-round.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3fp-traps.dtx b/macros/latex/contrib/l3kernel/l3fp-traps.dtx index 6863f69abc..df2ba96aee 100644 --- a/macros/latex/contrib/l3kernel/l3fp-traps.dtx +++ b/macros/latex/contrib/l3kernel/l3fp-traps.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % \maketitle % % \begin{documentation} diff --git a/macros/latex/contrib/l3kernel/l3fp-trig.dtx b/macros/latex/contrib/l3kernel/l3fp-trig.dtx index 7b7129d7f4..f7d669a2a2 100644 --- a/macros/latex/contrib/l3kernel/l3fp-trig.dtx +++ b/macros/latex/contrib/l3kernel/l3fp-trig.dtx @@ -40,7 +40,7 @@ % {latex-team@latex-project.org}^^A % }^^A % } -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3fp.dtx b/macros/latex/contrib/l3kernel/l3fp.dtx index 59e97b0648..efb246efe7 100644 --- a/macros/latex/contrib/l3kernel/l3fp.dtx +++ b/macros/latex/contrib/l3kernel/l3fp.dtx @@ -49,7 +49,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3fparray.dtx b/macros/latex/contrib/l3kernel/l3fparray.dtx index 2b21ad7ff4..7d5a54e4a0 100644 --- a/macros/latex/contrib/l3kernel/l3fparray.dtx +++ b/macros/latex/contrib/l3kernel/l3fparray.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3int.dtx b/macros/latex/contrib/l3kernel/l3int.dtx index 0d45445773..c8342428f1 100644 --- a/macros/latex/contrib/l3kernel/l3int.dtx +++ b/macros/latex/contrib/l3kernel/l3int.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3intarray.dtx b/macros/latex/contrib/l3kernel/l3intarray.dtx index 9d71901191..78701c1dc9 100644 --- a/macros/latex/contrib/l3kernel/l3intarray.dtx +++ b/macros/latex/contrib/l3kernel/l3intarray.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3kernel-functions.dtx b/macros/latex/contrib/l3kernel/l3kernel-functions.dtx index 6a5a81e6ef..143231de87 100644 --- a/macros/latex/contrib/l3kernel/l3kernel-functions.dtx +++ b/macros/latex/contrib/l3kernel/l3kernel-functions.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % @@ -105,6 +105,18 @@ % all of these tests succeed then the \meta{true code} is run. % \end{function} % +% \begin{function}[EXP]{\__kernel_codepoint_to_bytes:n} +% \begin{syntax} +% \cs{__kernel_codepoint_to_bytes:n} \Arg{codepoint} +% \end{syntax} +% Converts the \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 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}{\__kernel_cs_parm_from_arg_count:nnF} % \begin{syntax} % \cs{__kernel_cs_parm_from_arg_count:nnF} \Arg{follow-on} \Arg{args} \Arg{false code} @@ -477,6 +489,41 @@ % \meta{tl~var} and \meta{tokens}. % \end{function} % +% \begin{function}[EXP]{\__kernel_codepoint_data:nn} +% \begin{syntax} +% \cs{__kernel_codepoint_data:nn} \Arg{type} \Arg{codepoint} +% \end{syntax} +% Expands to the appropriate value for the \meta{type} of data +% requested for a \meta{codepoint}. The current list of \meta{types} and +% results are +% \begin{description} +% \item[\texttt{lowercase}] The \emph{single} codepoint specified by +% \texttt{UnicodeData.txt} for lowercase mapping of the codepoint: +% will be equal to the input \meta{codepoint} if there is no mapping +% specified in \texttt{UnicodeData.txt} +% \item[\texttt{uppercase}] The \emph{single} codepoint specified by +% \texttt{UnicodeData.txt} for uppercase mapping of the codepoint: +% will be equal to the input \meta{codepoint} if there is no mapping +% specified in \texttt{UnicodeData.txt} +% \end{description} +% \end{function} +% +% \begin{function}[EXP]{\__kernel_codepoint_case:nn} +% \begin{syntax} +% \cs{__kernel_codepoint_case:nn} \Arg{mapping} \Arg{codepoint} +% \end{syntax} +% Expands to a list of three balanced text, of which at least the first +% will contain a codepoint. This list of up to three codepoints specifies +% the full case mapping for the input \meta{codepoint}. The \meta{mapping} +% should be one of +% \begin{itemize} +% \item \texttt{casefold} +% \item \texttt{lowercase} +% \item \texttt{titlecase} +% \item \texttt{uppercase} +% \end{itemize} +% \end{function} +% % \subsection{Kernel backend functions} % % These functions are required to pass information to the backend. The nature diff --git a/macros/latex/contrib/l3kernel/l3keys.dtx b/macros/latex/contrib/l3kernel/l3keys.dtx index 9852a753d8..71667e2d7b 100644 --- a/macros/latex/contrib/l3kernel/l3keys.dtx +++ b/macros/latex/contrib/l3kernel/l3keys.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3legacy.dtx b/macros/latex/contrib/l3kernel/l3legacy.dtx index 089e86c018..df626bb4be 100644 --- a/macros/latex/contrib/l3kernel/l3legacy.dtx +++ b/macros/latex/contrib/l3kernel/l3legacy.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3luatex.dtx b/macros/latex/contrib/l3kernel/l3luatex.dtx index 2b061e4f0e..78a8e07339 100644 --- a/macros/latex/contrib/l3kernel/l3luatex.dtx +++ b/macros/latex/contrib/l3kernel/l3luatex.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3msg.dtx b/macros/latex/contrib/l3kernel/l3msg.dtx index 6a0bf9ff19..d4fc2f55c7 100644 --- a/macros/latex/contrib/l3kernel/l3msg.dtx +++ b/macros/latex/contrib/l3kernel/l3msg.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3names.dtx b/macros/latex/contrib/l3kernel/l3names.dtx index 1a98cb6bcf..96373ef311 100644 --- a/macros/latex/contrib/l3kernel/l3names.dtx +++ b/macros/latex/contrib/l3kernel/l3names.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3news.pdf b/macros/latex/contrib/l3kernel/l3news.pdf Binary files differindex 8a77fbdc78..160f2697c6 100644 --- a/macros/latex/contrib/l3kernel/l3news.pdf +++ b/macros/latex/contrib/l3kernel/l3news.pdf diff --git a/macros/latex/contrib/l3kernel/l3news01.pdf b/macros/latex/contrib/l3kernel/l3news01.pdf Binary files differindex 1c7968aa22..c6b2d9848b 100644 --- a/macros/latex/contrib/l3kernel/l3news01.pdf +++ b/macros/latex/contrib/l3kernel/l3news01.pdf diff --git a/macros/latex/contrib/l3kernel/l3news02.pdf b/macros/latex/contrib/l3kernel/l3news02.pdf Binary files differindex b246291c8b..9467dde377 100644 --- a/macros/latex/contrib/l3kernel/l3news02.pdf +++ b/macros/latex/contrib/l3kernel/l3news02.pdf diff --git a/macros/latex/contrib/l3kernel/l3news03.pdf b/macros/latex/contrib/l3kernel/l3news03.pdf Binary files differindex 0d916b022d..18d37d2382 100644 --- a/macros/latex/contrib/l3kernel/l3news03.pdf +++ b/macros/latex/contrib/l3kernel/l3news03.pdf diff --git a/macros/latex/contrib/l3kernel/l3news04.pdf b/macros/latex/contrib/l3kernel/l3news04.pdf Binary files differindex b8c5573d59..757e848070 100644 --- a/macros/latex/contrib/l3kernel/l3news04.pdf +++ b/macros/latex/contrib/l3kernel/l3news04.pdf diff --git a/macros/latex/contrib/l3kernel/l3news05.pdf b/macros/latex/contrib/l3kernel/l3news05.pdf Binary files differindex d4c99c59af..ccd814f681 100644 --- a/macros/latex/contrib/l3kernel/l3news05.pdf +++ b/macros/latex/contrib/l3kernel/l3news05.pdf diff --git a/macros/latex/contrib/l3kernel/l3news06.pdf b/macros/latex/contrib/l3kernel/l3news06.pdf Binary files differindex 99efa5b462..e10d0b9c9d 100644 --- a/macros/latex/contrib/l3kernel/l3news06.pdf +++ b/macros/latex/contrib/l3kernel/l3news06.pdf diff --git a/macros/latex/contrib/l3kernel/l3news07.pdf b/macros/latex/contrib/l3kernel/l3news07.pdf Binary files differindex 70f5efb753..5f970f1755 100644 --- a/macros/latex/contrib/l3kernel/l3news07.pdf +++ b/macros/latex/contrib/l3kernel/l3news07.pdf diff --git a/macros/latex/contrib/l3kernel/l3news08.pdf b/macros/latex/contrib/l3kernel/l3news08.pdf Binary files differindex f2305506a0..1b931f862a 100644 --- a/macros/latex/contrib/l3kernel/l3news08.pdf +++ b/macros/latex/contrib/l3kernel/l3news08.pdf diff --git a/macros/latex/contrib/l3kernel/l3news09.pdf b/macros/latex/contrib/l3kernel/l3news09.pdf Binary files differindex d426dba685..41f5542562 100644 --- a/macros/latex/contrib/l3kernel/l3news09.pdf +++ b/macros/latex/contrib/l3kernel/l3news09.pdf diff --git a/macros/latex/contrib/l3kernel/l3news10.pdf b/macros/latex/contrib/l3kernel/l3news10.pdf Binary files differindex 87c6b75bb0..370eb06cf4 100644 --- a/macros/latex/contrib/l3kernel/l3news10.pdf +++ b/macros/latex/contrib/l3kernel/l3news10.pdf diff --git a/macros/latex/contrib/l3kernel/l3news11.pdf b/macros/latex/contrib/l3kernel/l3news11.pdf Binary files differindex 113a3a3cef..e8162c9a05 100644 --- a/macros/latex/contrib/l3kernel/l3news11.pdf +++ b/macros/latex/contrib/l3kernel/l3news11.pdf diff --git a/macros/latex/contrib/l3kernel/l3news12.pdf b/macros/latex/contrib/l3kernel/l3news12.pdf Binary files differindex 1207717863..37bda3fe3a 100644 --- a/macros/latex/contrib/l3kernel/l3news12.pdf +++ b/macros/latex/contrib/l3kernel/l3news12.pdf diff --git a/macros/latex/contrib/l3kernel/l3pdf.dtx b/macros/latex/contrib/l3kernel/l3pdf.dtx index 8a359528d9..c29dbe4141 100644 --- a/macros/latex/contrib/l3kernel/l3pdf.dtx +++ b/macros/latex/contrib/l3kernel/l3pdf.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3prefixes.csv b/macros/latex/contrib/l3kernel/l3prefixes.csv index 31d77835d4..c69216e094 100644 --- a/macros/latex/contrib/l3kernel/l3prefixes.csv +++ b/macros/latex/contrib/l3kernel/l3prefixes.csv @@ -41,6 +41,7 @@ cmd,latex2e,The LaTeX Project,https://www.latex-project.org/latex3.html,https:// code,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2021-04-23,2021-04-23, codedoc,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,Somewhat experimental: may change codehigh,codehigh,Jianrui Lyu,https://github.com/lvjr/codehigh,https://github.com/lvjr/codehigh.git,https://github.com/lvjr/codehigh/issues,2022-04-02,2022-04-02, +codepoint,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27, coffin,"l3kernel,xcoffins",The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27, colon,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2018-05-12,2018-05-12, color,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27, diff --git a/macros/latex/contrib/l3kernel/l3prefixes.pdf b/macros/latex/contrib/l3kernel/l3prefixes.pdf Binary files differindex 0290386f55..a965d3d543 100644 --- a/macros/latex/contrib/l3kernel/l3prefixes.pdf +++ b/macros/latex/contrib/l3kernel/l3prefixes.pdf diff --git a/macros/latex/contrib/l3kernel/l3prg.dtx b/macros/latex/contrib/l3kernel/l3prg.dtx index 3b50dee107..65e89f9b4b 100644 --- a/macros/latex/contrib/l3kernel/l3prg.dtx +++ b/macros/latex/contrib/l3kernel/l3prg.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3prop.dtx b/macros/latex/contrib/l3kernel/l3prop.dtx index c124459362..0cc1c3730b 100644 --- a/macros/latex/contrib/l3kernel/l3prop.dtx +++ b/macros/latex/contrib/l3kernel/l3prop.dtx @@ -43,13 +43,13 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % % \begin{documentation} % -% \LaTeX3 implements a \enquote{property list} data type, which contain +% \pkg{expl3} implements a \meta{property list} data type, which contain % an unordered list of entries each of which consists of a \meta{key} and % an associated \meta{value}. The \meta{key} and \meta{value} may both % be any \meta{balanced text}, the \meta{key} is processed using @@ -117,13 +117,13 @@ % \prop_gset_from_keyval:Nn, \prop_gset_from_keyval:cn, % } % \begin{syntax} -% \cs{prop_set_from_keyval:Nn} \meta{prop~var} +% \cs{prop_set_from_keyval:Nn} \meta{property list} % \{ % \meta{key1} |=| \meta{value1} |,| % \meta{key2} |=| \meta{value2} |,| \ldots{} % \} % \end{syntax} -% Sets \meta{prop~var} to contain key--value pairs given in the second +% Sets \meta{property list} to contain key--value pairs given in the second % argument. If duplicate keys appear only the last of the values is kept. % % Spaces are trimmed around every \meta{key} and every \meta{value}, @@ -142,14 +142,14 @@ % \begin{function}[added = 2017-11-28, updated = 2021-11-07] % {\prop_const_from_keyval:Nn, \prop_const_from_keyval:cn} % \begin{syntax} -% \cs{prop_const_from_keyval:Nn} \meta{prop~var} +% \cs{prop_const_from_keyval:Nn} \meta{property list} % \{ % \meta{key1} |=| \meta{value1} |,| % \meta{key2} |=| \meta{value2} |,| \ldots{} % \} % \end{syntax} -% Creates a new constant \meta{prop~var} or raises an error if the -% name is already taken. The \meta{prop~var} is set globally to +% Creates a new constant \meta{property list} or raises an error if the +% name is already taken. The \meta{property list} is set globally to % contain key--value pairs given in the second argument, processed in % the way described for \cs{prop_set_from_keyval:Nn}. If duplicate % keys appear only the last of the values is kept. @@ -209,12 +209,12 @@ % \prop_gconcat:NNN, \prop_gconcat:ccc % } % \begin{syntax} -% \cs{prop_concat:NNN} \meta{prop~var_1} \meta{prop~var_2} \meta{prop~var_3} +% \cs{prop_concat:NNN} \meta{property list_1} \meta{property list_2} \meta{property list3} % \end{syntax} -% Combines the key--value pairs of \meta{prop~var_2} and -% \meta{prop~var_3}, and saves the result in \meta{prop~var_1}. If a -% key appears in both \meta{prop~var_2} and \meta{prop~var_3} then the -% last value, namely the value in \meta{prop~var_3} is kept. +% Combines the key--value pairs of \meta{property list_2} and +% \meta{property list_3}, and saves the result in \meta{pproperty list_1}. If a +% key appears in both \meta{property list_2} and \meta{property list_3} then the +% last value, namely the value in \meta{property list_3} is kept. % \end{function} % % \begin{function}[added = 2021-05-16, updated = 2021-11-07] @@ -223,22 +223,22 @@ % \prop_gput_from_keyval:Nn, \prop_gput_from_keyval:cn, % } % \begin{syntax} -% \cs{prop_put_from_keyval:Nn} \meta{prop~var} +% \cs{prop_put_from_keyval:Nn} \meta{property list} % \{ % \meta{key1} |=| \meta{value1} |,| % \meta{key2} |=| \meta{value2} |,| \ldots{} % \} % \end{syntax} -% Updates the \meta{prop~var} by adding entries for each key--value +% Updates the \meta{property list} by adding entries for each key--value % pair given in the second argument. The addition is done through -% \cs{prop_put:Nnn}, hence if the \meta{prop~var} already contains +% \cs{prop_put:Nnn}, hence if the \meta{property list} already contains % some of the keys, the corresponding values are discarded and % replaced by those given in the key--value list. If duplicate keys % appear in the key--value list then only the last of the values is kept. % % The function is equivalent to storing the key--value pairs in a -% temporary property variable using \cs{prop_set_from_keyval:Nn}, then -% combining \meta{prop~var} with the temporary variable using +% temporary property list using \cs{prop_set_from_keyval:Nn}, then +% combining \meta{property list} with the temporary variable using % \cs{prop_concat:NNN}. In particular, the \meta{keys} and % \meta{values} are space-trimmed and unbraced as described in % \cs{prop_set_from_keyval:Nn}. diff --git a/macros/latex/contrib/l3kernel/l3quark.dtx b/macros/latex/contrib/l3kernel/l3quark.dtx index 05291a288f..9d3cd27c41 100644 --- a/macros/latex/contrib/l3kernel/l3quark.dtx +++ b/macros/latex/contrib/l3kernel/l3quark.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % @@ -942,15 +942,6 @@ %<@@=scan> % \end{macrocode} % -% \begin{variable}{\g_@@_marks_tl} -% \UnitTested -% The list of all scan marks currently declared. -% No \pkg{l3tl} yet, so define this by hand. -% \begin{macrocode} -\cs_gset:Npn \g_@@_marks_tl { } -% \end{macrocode} -% \end{variable} -% % \begin{macro}{\scan_new:N} % \UnitTested % Check whether the variable is already a scan mark, @@ -972,26 +963,30 @@ % \end{macro} % % \begin{variable}{\s_stop} +% \begin{variable}{\g_@@_marks_tl} % \UnitTested % We only declare one scan mark here, more can be defined % by specific modules. % Can't use \cs{scan_new:N} yet because \pkg{l3tl} isn't loaded, % so define \cs{s_stop} by hand and add it to \cs{g_@@_marks_tl}. -% We also add \cs{s__quark} (declared earlier) to the pool here. -% Since it lives in a different namespace, a little \pkg{l3docstrip} +% We also add the scan marks declared earlier to the pool here. +% Since they lives in a different namespace, a little \pkg{l3docstrip} % cheating is necessary. % \begin{macrocode} \cs_new_eq:NN \s_stop \scan_stop: -\cs_gset_nopar:Npx \g_@@_marks_tl +\cs_gset_nopar:Npn \g_@@_marks_tl { - \exp_not:o \g_@@_marks_tl \s_stop %<@@=quark> \s_@@ +%<@@=cs> + \s_@@_mark + \s_@@_stop %<@@=scan> } % \end{macrocode} % \end{variable} +% \end{variable} % % \begin{macro}[EXP]{\use_none_delimit_by_s_stop:w} % \UnitTested diff --git a/macros/latex/contrib/l3kernel/l3regex.dtx b/macros/latex/contrib/l3kernel/l3regex.dtx index 9a42b6badc..720efab1e2 100644 --- a/macros/latex/contrib/l3kernel/l3regex.dtx +++ b/macros/latex/contrib/l3kernel/l3regex.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3seq.dtx b/macros/latex/contrib/l3kernel/l3seq.dtx index 4251d71330..36cfb7e9b0 100644 --- a/macros/latex/contrib/l3kernel/l3seq.dtx +++ b/macros/latex/contrib/l3kernel/l3seq.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3skip.dtx b/macros/latex/contrib/l3kernel/l3skip.dtx index aa2066c487..d111a3ae5d 100644 --- a/macros/latex/contrib/l3kernel/l3skip.dtx +++ b/macros/latex/contrib/l3kernel/l3skip.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3sort.dtx b/macros/latex/contrib/l3kernel/l3sort.dtx index cc6dd07f8f..4fb92cda08 100644 --- a/macros/latex/contrib/l3kernel/l3sort.dtx +++ b/macros/latex/contrib/l3kernel/l3sort.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3str-convert.dtx b/macros/latex/contrib/l3kernel/l3str-convert.dtx index 3e3a2a6080..1b3800d9e0 100644 --- a/macros/latex/contrib/l3kernel/l3str-convert.dtx +++ b/macros/latex/contrib/l3kernel/l3str-convert.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % @@ -2635,7 +2635,7 @@ \cs_new:Npn \@@_convert_pdfname_bytes:n #1 { \exp_args:Ne \@@_convert_pdfname_bytes_aux:n - { \char_to_utfviii_bytes:n {`#1} } + { \__kernel_codepoint_to_bytes:n {`#1} } } \cs_new:Npn \@@_convert_pdfname_bytes_aux:n #1 { \@@_convert_pdfname_bytes_aux:nnnn #1 } diff --git a/macros/latex/contrib/l3kernel/l3str.dtx b/macros/latex/contrib/l3kernel/l3str.dtx index 4b240c2aa3..3e8882fb3c 100644 --- a/macros/latex/contrib/l3kernel/l3str.dtx +++ b/macros/latex/contrib/l3kernel/l3str.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % @@ -744,7 +744,7 @@ % % These functions should \emph{not} be used for % \begin{itemize} -% \item Caseless comparisons: use \cs{str_foldcase:n} for this +% \item Caseless comparisons: use \cs{str_casefold:n} for this % situation (case folding is distinct from lower casing). % \item Case changing text for typesetting: see the % \cs[index=text_lowercase:n]{text_lowercase:n(n)}, @@ -755,10 +755,10 @@ % \end{itemize} % \end{function} % -% \begin{function}[EXP, added = 2019-11-26] -% {\str_foldcase:n, \str_foldcase:V} +% \begin{function}[EXP, added = 2022-10-16] +% {\str_casefold:n, \str_casefold:V} % \begin{syntax} -% \cs{str_foldcase:n} \Arg{tokens} +% \cs{str_casefold:n} \Arg{tokens} % \end{syntax} % Converts the input \meta{tokens} to their string representation, as % described for \cs{tl_to_str:n}, and then folds the case of the resulting @@ -766,7 +766,7 @@ % left in the input stream. % % String folding is a process used for material such as identifiers rather -% than for \enquote{text}. The folding provided by \cs{str_foldcase:n} +% than for \enquote{text}. The folding provided by \cs{str_casefold:n} % follows the mappings provided by the \href{http://www.unicode.org}^^A % {Unicode Consortium}, who % \href{http://www.unicode.org/faq/casemap_charprop.html#2}{state}: @@ -779,7 +779,7 @@ % should be used solely for internal processing and generally should not be % stored or displayed to the end user. % \end{quote} -% The folding approach implemented by \cs{str_foldcase:n} follows the +% The folding approach implemented by \cs{str_casefold:n} follows the % \enquote{full} scheme defined by the Unicode Consortium % (\emph{e.g.}~\SS folds to \texttt{SS}). As case-folding is % a language-insensitive process, there is no special treatment of @@ -843,6 +843,16 @@ % code and so should only be used for short-term storage. % \end{variable} % +% \section{Deprecated functions} +% +% \begin{function}[EXP, added = 2019-11-26] +% {\str_foldcase:n, \str_foldcase:V} +% \begin{syntax} +% \cs{str_foldcase:n} \Arg{tokens} +% \end{syntax} +% A previous name for the functionally-identical \cs{str_casefold:n}. +% \end{function} +% % \end{documentation} % % \begin{implementation} @@ -1896,7 +1906,7 @@ % % \begin{macro}[EXP] % { -% \str_foldcase:n, \str_foldcase:V, +% \str_casefold:n, \str_casefold:V, % \str_lowercase:n, \str_lowercase:f, % \str_uppercase:n, \str_uppercase:f % } @@ -1907,27 +1917,23 @@ % \begin{macro}[EXP]{\@@_change_case_end:nw} % \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 -% } +% \begin{macro}[EXP]{\@@_change_case_char:nN, \@@_change_case_char_aux:nN} +% \begin{macro}[EXP]{\@@_change_case_codepoint:nN} +% \begin{macro}[EXP]{\@@_change_case_codepoint:nNN} +% \begin{macro}[EXP]{\@@_change_case_codepoint:nNNN} +% \begin{macro}[EXP]{\@@_change_case_codepoint:nNNNN} +% \begin{macro}[EXP]{\@@_change_case_char:nnn, \@@_change_case_char_aux:nnn} +% \begin{macro}[EXP]{\@@_change_case_char:nnnnn} % 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. 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 } } -\cs_new:Npn \str_uppercase:n #1 { \@@_change_case:nn {#1} { upper } } -\cs_generate_variant:Nn \str_foldcase:n { V } +\cs_new:Npn \str_casefold:n #1 { \@@_change_case:nn {#1} { casefold } } +\cs_new:Npn \str_lowercase:n #1 { \@@_change_case:nn {#1} { lowercase } } +\cs_new:Npn \str_uppercase:n #1 { \@@_change_case:nn {#1} { uppercase } } +\cs_generate_variant:Nn \str_casefold:n { V } \cs_generate_variant:Nn \str_lowercase:n { f } \cs_generate_variant:Nn \str_uppercase:n { f } \cs_new:Npn \@@_change_case:nn #1 @@ -1962,99 +1968,90 @@ { \@@_if_recursion_tail_stop_do:Nn #2 { \@@_change_case_end:wn } - \@@_change_case_output:fw - { \use:c { char_str_ #1 case:N } #2 } - \@@_change_case_loop:nw {#1} + \@@_change_case_codepoint:nN {#1} #2 } \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: + \cs_new:Npn \@@_change_case_codepoint:nN #1#2 + { \@@_change_case_char:fnn { \int_eval:n {`#2} } {#1} {#2} } \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} - } + \cs_new:Npn \@@_change_case_codepoint:nN #1#2 + { + \int_compare:nNnTF {`#2} > { "80 } + { + \int_compare:nNnTF {`#2} < { "E0 } + { \@@_change_case_codepoint:nNN } + { + \int_compare:nNnTF {`#2} < { "F0 } + { \@@_change_case_codepoint:nNNN } + { \@@_change_case_codepoint:nNNNNN } + } + } + { \@@_change_case_char_aux:nN } + {#1} #2 + } + \cs_new:Npn \@@_change_case_char_aux:nN #1#2 + { \@@_change_case_char:fnn { \int_eval:n {`#2} } {#1} {#2} } + \cs_new:Npn \@@_change_case_codepoint:nNN #1#2#3 + { + \@@_change_case_char:fnn + { \int_eval:n { (`#2 - "C0) * "40 + `#3 - "80 } } + {#1} {#2#3} + } + \cs_new:Npn \@@_change_case_codepoint:nNNN #1#2#3#4 + { + \@@_change_case_char:fnn + { + \int_eval:n + { (`#2 - "E0) * "1000 + (`#3 - "80) * "40 + `#4 - "80 } + } + {#1} {#2#3#4} + } + \cs_new:Npn \@@_change_case_codepoint:nNNNN #1#2#3#4#5 + { + \@@_change_case_char:fnn + { + \int_eval:n + { + (`#2 - "F0) * "40000 + + (`#3 - "80) * "1000 + + (`#4 - "80) * "40 + + `#5 - "80 + } + } + {#1} {#2#3#4#5} + } \fi: +\cs_new:Npn \@@_change_case_char:nnn #1#2#3 + { + \@@_change_case_output:fw + { + \exp_args:Ne \@@_change_case_char_aux:nnn + { \__kernel_codepoint_case:nn {#2} {#1} } {#1} {#3} + } + \@@_change_case_loop:nw {#2} + } +\cs_generate_variant:Nn \@@_change_case_char:nnn { f } +\cs_new:Npn \@@_change_case_char_aux:nnn #1#2#3 + { + \use:e { \@@_change_case_char:nnnnn #1 {#2} {#3} } + } +\cs_new:Npn \@@_change_case_char:nnnnn #1#2#3#4#5 + { + \int_compare:nNnTF {#1} = {#4} + { \tl_to_str:n {#5} } + { + \codepoint_str_generate:n {#1} + \tl_if_blank:nF {#2} + { + \codepoint_str_generate:n {#2} + \tl_if_blank:nF {#3} + { \codepoint_str_generate:n {#3} } + } + } + } % \end{macrocode} % \end{macro} % \end{macro} @@ -2069,6 +2066,8 @@ % \end{macro} % \end{macro} % \end{macro} +% \end{macro} +% \end{macro} % % \begin{variable} % { diff --git a/macros/latex/contrib/l3kernel/l3styleguide.pdf b/macros/latex/contrib/l3kernel/l3styleguide.pdf Binary files differindex 4532b1ebeb..75ccd79ad8 100644 --- a/macros/latex/contrib/l3kernel/l3styleguide.pdf +++ b/macros/latex/contrib/l3kernel/l3styleguide.pdf diff --git a/macros/latex/contrib/l3kernel/l3styleguide.tex b/macros/latex/contrib/l3kernel/l3styleguide.tex index 20520ef462..b3578e3832 100644 --- a/macros/latex/contrib/l3kernel/l3styleguide.tex +++ b/macros/latex/contrib/l3kernel/l3styleguide.tex @@ -32,7 +32,7 @@ The released version of this bundle is available from CTAN. {latex-team@latex-project.org}% }% } -\date{Released 2022-11-02} +\date{Released 2022-12-17} \begin{document} diff --git a/macros/latex/contrib/l3kernel/l3syntax-changes.pdf b/macros/latex/contrib/l3kernel/l3syntax-changes.pdf Binary files differindex b7de97fd79..138dbc30cf 100644 --- a/macros/latex/contrib/l3kernel/l3syntax-changes.pdf +++ b/macros/latex/contrib/l3kernel/l3syntax-changes.pdf diff --git a/macros/latex/contrib/l3kernel/l3syntax-changes.tex b/macros/latex/contrib/l3kernel/l3syntax-changes.tex index a5f009088b..1768810b84 100644 --- a/macros/latex/contrib/l3kernel/l3syntax-changes.tex +++ b/macros/latex/contrib/l3kernel/l3syntax-changes.tex @@ -32,7 +32,7 @@ The released version of this bundle is available from CTAN. {latex-team@latex-project.org}% }% } -\date{Released 2022-11-02} +\date{Released 2022-12-17} \newcommand{\TF}{\textit{(TF)}} diff --git a/macros/latex/contrib/l3kernel/l3sys.dtx b/macros/latex/contrib/l3kernel/l3sys.dtx index 6fa144c8a7..fa0bd971f7 100644 --- a/macros/latex/contrib/l3kernel/l3sys.dtx +++ b/macros/latex/contrib/l3kernel/l3sys.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3term-glossary.pdf b/macros/latex/contrib/l3kernel/l3term-glossary.pdf Binary files differindex daa7d1730c..d4c669ba6e 100644 --- a/macros/latex/contrib/l3kernel/l3term-glossary.pdf +++ b/macros/latex/contrib/l3kernel/l3term-glossary.pdf diff --git a/macros/latex/contrib/l3kernel/l3term-glossary.tex b/macros/latex/contrib/l3kernel/l3term-glossary.tex index 930982500d..25f41a2c18 100644 --- a/macros/latex/contrib/l3kernel/l3term-glossary.tex +++ b/macros/latex/contrib/l3kernel/l3term-glossary.tex @@ -32,7 +32,7 @@ The released version of this bundle is available from CTAN. {latex-team@latex-project.org}% }% } -\date{Released 2022-11-02} +\date{Released 2022-12-17} \newcommand{\TF}{\textit{(TF)}} @@ -41,7 +41,7 @@ The released version of this bundle is available from CTAN. \maketitle This file describes aspects of \TeX{} programming that are relevant in a -\LaTeX3 context. +\pkg{expl3} context. \section{Reading a file} @@ -79,7 +79,7 @@ The meaning of a (non-active) character token is fixed by its category code (and character code) and cannot be changed. We call these tokens \emph{explicit} character tokens. Category codes that a character token can have are listed below by giving a sample output of the \TeX{} -primitive \tn{meaning}, together with their \LaTeX3 names and most +primitive \tn{meaning}, together with their \pkg{expl3} names and most common example: \begin{itemize} \item[1] begin-group character (|group_begin|, often |{|), @@ -103,11 +103,11 @@ to that of any character token listed above (with any character code), and we call such tokens \emph{implicit} character tokens. The meaning is otherwise in the following list: \begin{itemize} - \item a macro, used in \LaTeX3 for most functions and some variables + \item a macro, used in \pkg{expl3} for most functions and some variables (|tl|, |fp|, |seq|, \ldots{}), - \item a primitive such as \tn{def} or \tn{topmark}, used in \LaTeX3 + \item a primitive such as \tn{def} or \tn{topmark}, used in \pkg{expl3} for some functions, - \item a register such as \tn{count}|123|, used in \LaTeX3{} for the + \item a register such as \tn{count}|123|, used in \pkg{expl3} for the implementation of some variables (|int|, |dim|, \ldots{}), \item a constant integer such as \tn{char}|"56| or \tn{mathchar}|"121|, used when defining a constant using @@ -116,7 +116,7 @@ is otherwise in the following list: \item undefined. \end{itemize} Macros can be \tn{protected} or not, \tn{long} or not (the opposite of -what \LaTeX3 calls |nopar|), and \tn{outer} or not (unused in \LaTeX3). +what \pkg{expl3} calls |nopar|), and \tn{outer} or not (unused in \pkg{expl3}). Their \tn{meaning} takes the form \begin{quote} \meta{prefix} |macro:|\meta{argument}|->|\meta{replacement} @@ -146,14 +146,4 @@ removed) becomes the argument. Note that explicit space characters at the start of the argument are \emph{not} ignored in this case (and they prevent brace-stripping). -\section{Quantities and expressions} - -Integer denotations, dimensions, glue (including \texttt{fill} and \texttt{true pt} and the like). - -Syntax of integer expressions (including the trap that \verb|-(1+2)| is invalid). - -\section{\LaTeX3 terms} - -Terms like ``intexpr'' or ``seq var'' used in syntax blocks. - \end{document} diff --git a/macros/latex/contrib/l3kernel/l3text-case.dtx b/macros/latex/contrib/l3kernel/l3text-case.dtx index caaf003bcb..1767bc97e1 100644 --- a/macros/latex/contrib/l3kernel/l3text-case.dtx +++ b/macros/latex/contrib/l3kernel/l3text-case.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % @@ -138,7 +138,8 @@ % \@@_change_case_group_titleonly:nnn % } % \begin{macro}[EXP]{\@@_change_case_space:nnw} -% \begin{macro}[EXP]{\@@_change_case_N_type:nnN, \@@_change_case_N_type_aux:nnN} +% \begin{macro}[EXP] +% {\@@_change_case_N_type:nnN, \@@_change_case_N_type_aux:nnN} % \begin{macro}[EXP]{\@@_change_case_N_type:nnnN} % \begin{macro}[EXP]{\@@_change_case_math_search:nnNNN} % \begin{macro}[EXP]{\@@_change_case_math_loop:nnNw} @@ -170,36 +171,38 @@ % } % \begin{macro}[EXP]{\@@_change_case_letterlike:nnnnN} % \begin{macro}[EXP] -% {\@@_change_case_char_lower:nnN, \@@_change_case_char_upper:nnN} +% { +% \@@_change_case_codepoint_lower:nnn , +% \@@_change_case_codepoint_upper:nnn , +% \@@_change_case_codepoint_title:nnn , +% \@@_change_case_codepoint_titleonly:nnn +% } +% \begin{macro}[EXP]{\@@_change_case_lower_sigma:nnnn} +% \begin{macro}[EXP]{\@@_change_case_lower_sigma:nnnw} % \begin{macro}[EXP]{\@@_change_case_lower_sigma:nnnN} -% \begin{macro}[EXP]{\@@_change_case_lower_sigma:nnNw} -% \begin{macro}[EXP]{\@@_change_case_lower_sigma:NnnN} -% \begin{macro}[EXP]{\@@_change_case_lower_sigma:nnnNN} -% \begin{macro}[EXP]{\@@_change_case_lower_sigma:nnw} -% \begin{macro}[EXP]{\@@_change_case_lower_sigma:nnN} % \begin{macro}[EXP] -% {\@@_change_case_char_title:nnN, \@@_change_case_char_titleonly:nnN} +% { +% \@@_change_case_codepoint_title:nn , +% \@@_change_case_codepoint_titleonly:nn +% } +% \begin{macro}[EXP]{\@@_change_case_codepoint_title:nnnn} % \begin{macro}[EXP] -% {\@@_change_case_char_title:nN, \@@_change_case_char_titleonly:nN} -% \begin{macro}[EXP]{\@@_change_case_char_title:nnnN} +% {\@@_change_case_codepoint:nnnn, \@@_change_case_codepoint_aux:nnnn} +% \begin{macro}[EXP]{\@@_change_case_codepoint:nn} % \begin{macro}[EXP] % { -% \@@_change_case_char:nnnN , -% \@@_change_case_char_auxi:nnnN , -% \@@_change_case_char_auxii:nnnN +% \@@_change_case_codepoint:nnn , +% \@@_change_case_codepoint:fnn , +% \@@_change_case_codepoint_aux:nnn % } -% \begin{macro}[EXP]{\@@_change_case_char_UTFviii:nnnNN} -% \begin{macro}[EXP]{\@@_change_case_char_UTFviii:nnnNNN} -% \begin{macro}[EXP]{\@@_change_case_char_UTFviii:nnnNNNN} -% \begin{macro}[EXP]{\@@_change_case_char_UTFviii:nnnn} % \begin{macro}[EXP] % { -% \@@_change_case_char_next_lower:nn , -% \@@_change_case_char_next_upper:nn , -% \@@_change_case_char_next_title:nn , -% \@@_change_case_char_next_titleonly:nn +% \@@_change_case_next_lower:nn , +% \@@_change_case_next_upper:nn , +% \@@_change_case_next_title:nn , +% \@@_change_case_next_titleonly:nn , +% \@@_change_case_next_end:nn % } -% \begin{macro}[EXP]{\@@_change_case_char_next_end:nn} % As for the expansion code, the business end of case changing is the % handling of \texttt{N}-type tokens. First, we expand the input fully % (so the loops here don't need to worry about awkward look-aheads and the @@ -246,7 +249,7 @@ { \@@_change_case_BCP:nnnnw {#1} {#2} {#4} {#3} #3 - - \q_@@_stop } \cs_new:Npn \@@_change_case_BCP:nnnnw #1#2#3#4#5 - #6 - #7 \q_@@_stop { - \cs_if_exist:cTF { @@_change_case_ #2 _ #5 -x- #3 :nnnN } + \cs_if_exist:cTF { @@_change_case_ #2 _ #5 -x- #3 :nnnn } { \@@_change_case_auxii:nnn {#1} {#2} { #5 -x- #3 } } { \@@_change_case_auxii:nnn {#1} {#2} {#4} } } @@ -429,9 +432,12 @@ \cs_new:Npn \@@_change_case_cs_check:nnN #1#2#3 { \token_if_cs:NTF #3 - { \@@_change_case_exclude:nnN } - { \use:c { @@_change_case_char_ #1 :nnN } } - {#1} {#2} #3 + { \@@_change_case_exclude:nnN {#1} {#2} } + { + \@@_codepoint_process:nN + { \use:c { @@_change_case_codepoint_ #1 :nnn } {#1} {#2} } + } + #3 } % \end{macrocode} % To deal with a control sequence there is first a need to test if it is @@ -545,7 +551,7 @@ { \@@_change_case_store:v { c_@@_ #1 case_ \token_to_str:N #5 _tl } - \use:c { @@_change_case_char_next_ #2 :nn } {#2} {#4} + \use:c { @@_change_case_next_ #2 :nn } {#2} {#4} } { \@@_change_case_store:n {#5} @@ -555,7 +561,7 @@ \str_if_eq:nnTF {#1} { lower } { upper } { lower } case_ \token_to_str:N #5 _tl } - { \use:c { @@_change_case_char_next_ #2 :nn } {#2} {#4} } + { \use:c { @@_change_case_next_ #2 :nn } {#2} {#4} } { \@@_change_case_loop:nnw {#3} {#4} } } } @@ -563,222 +569,196 @@ % For upper- and lowercase changes, once we get to this stage there are only % a couple of questions remaining: is there a language-specific mapping and % is there the special case of a terminal sigma. If not, then we pass to -% a simple character mapping. +% a simple codepoint mapping. % \begin{macrocode} -\cs_new:Npn \@@_change_case_char_lower:nnN #1#2#3 +\cs_new:Npn \@@_change_case_codepoint_lower:nnn #1#2#3 { - \cs_if_exist_use:cF { @@_change_case_lower_ #2 :nnnN } - { \@@_change_case_lower_sigma:nnnN } - {#1} {#1} {#2} #3 + \cs_if_exist_use:cF { @@_change_case_lower_ #2 :nnnn } + { \@@_change_case_lower_sigma:nnnn } + {#1} {#1} {#2} {#3} } -\cs_new:Npn \@@_change_case_char_upper:nnN #1#2#3 +\cs_new:Npn \@@_change_case_codepoint_upper:nnn #1#2#3 { - \cs_if_exist_use:cF { @@_change_case_upper_ #2 :nnnN } - { \@@_change_case_char:nnnN } - {#1} {#1} {#2} #3 + \cs_if_exist_use:cF { @@_change_case_upper_ #2 :nnnn } + { \@@_change_case_codepoint:nnnn } + {#1} {#1} {#2} {#3} } % \end{macrocode} % If the current character is an uppercase 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: the logic here is simply based on letters. -% The one exception is Dutch: see below. +% then there is a look-ahead phase: the logic here is simply based on letters +% or actives (to cover $8$-bit engines). % \begin{macrocode} -\bool_lazy_or:nnTF - { \sys_if_engine_luatex_p: } - { \sys_if_engine_xetex_p: } +\cs_new:Npn \@@_change_case_lower_sigma:nnnn #1#2#3#4 { - \cs_new:Npn \@@_change_case_lower_sigma:nnnN #1#2#3#4 - { - \int_compare:nNnTF { `#4 } = { "03A3 } - { \@@_change_case_lower_sigma:nnNw {#2} {#3} #4 } - { \@@_change_case_char:nnnN {#1} {#2} {#3} #4 } - } - \cs_new:Npn \@@_change_case_lower_sigma:nnNw #1#2#3#4 \q_@@_recursion_stop - { - \tl_if_head_is_N_type:nTF {#4} - { \@@_change_case_lower_sigma:NnnN #3 } - { - \@@_change_case_store:e - { \char_generate:nn { "03C2 } { \@@_char_catcode:N #3 } } - \@@_change_case_loop:nnw - } - {#1} {#2} #4 \q_@@_recursion_stop - } - \cs_new:Npn \@@_change_case_lower_sigma:NnnN #1#2#3#4 + \@@_codepoint_compare:nNnTF {#4} = { "03A3 } + { \@@_change_case_lower_sigma:nnnw {#2} } + { \@@_change_case_codepoint:nnnn {#1} {#2} } + {#3} {#4} + } +\cs_new:Npn \@@_change_case_lower_sigma:nnnw #1#2#3#4 \q_@@_recursion_stop + { + \tl_if_head_is_N_type:nTF {#4} + { \@@_change_case_lower_sigma:nnnN {#3} } { \@@_change_case_store:e - { - \token_if_letter:NTF #4 - { \char_generate:nn { "03C3 } { \@@_char_catcode:N #1 } } - { \char_generate:nn { "03C2 } { \@@_char_catcode:N #1 } } - } - \@@_change_case_loop:nnw {#2} {#3} #4 + { \codepoint_generate:nn { "03C2 } { \@@_char_catcode:N #3 } } + \@@_change_case_loop:nnw } + {#1} {#2} #4 \q_@@_recursion_stop } -% \end{macrocode} -% In the $8$-bit engines, we have to look ahead once we find the first byte of the -% possible hit. -% \begin{macrocode} +\cs_new:Npn \@@_change_case_lower_sigma:nnnN #1#2#3#4 { - \cs_new:Npn \@@_change_case_lower_sigma:nnnN #1#2#3#4 - { - \int_compare:nNnTF { `#4 } = { "CE } - { \@@_change_case_lower_sigma:nnnNN } - { \@@_change_case_char:nnnN } - {#1} {#2} {#3} #4 - } - \cs_new:Npn \@@_change_case_lower_sigma:nnnNN #1#2#3#4#5 - { - \int_compare:nNnTF { `#5 } = { "A3 } - { \@@_change_case_lower_sigma:nnw {#2} {#3} } - { \@@_change_case_char:nnnN {#1} {#2} {#3} #4#5 } - } - \cs_new:Npn \@@_change_case_lower_sigma:nnw #1#2#3 \q_@@_recursion_stop - { - \tl_if_head_is_N_type:nTF {#3} - { \@@_change_case_lower_sigma:nnN } - { - \@@_change_case_store:V \c_@@_final_sigma_tl - \@@_change_case_loop:nnw - } - {#1} {#2} #3 \q_@@_recursion_stop - } - \cs_new:Npn \@@_change_case_lower_sigma:nnN #1#2#3 + \@@_change_case_store:e { \bool_lazy_or:nnTF - { \token_if_letter_p:N #3 } + { \token_if_letter_p:N #4 } { \bool_lazy_and_p:nn - { \token_if_active_p:N #3 } - { \int_compare_p:nNn { `#3 } > { "80 } } + { \token_if_active_p:N #4 } + { \int_compare_p:nNn {`#4} > { "80 } } } - { \@@_change_case_store:V \c_@@_sigma_tl } - { \@@_change_case_store:V \c_@@_final_sigma_tl } - \@@_change_case_loop:nnw {#1} {#2} #3 + { \codepoint_generate:nn { "03C3 } { \@@_char_catcode:N #1 } } + { \codepoint_generate:nn { "03C2 } { \@@_char_catcode:N #1 } } } + \@@_change_case_loop:nnw {#2} {#3} #4 } % \end{macrocode} % For titlecasing, we need to fully expand the new character to see if it -% is a letter (or active) But that means looking ahead in the $8$-bit case, so -% we have to grab the required tokens up-front. Life is a lot easier for Unicode -% \TeX{}'s, where we just have one token to worry about. The one wrinkle here -% is that for look-ahead we'd get into trouble: luckily, only Dutch has that -% issue. +% is a letter (or active). % \begin{macrocode} -\cs_new:Npx \@@_change_case_char_title:nnN #1#2#3 +\cs_new:Npn \@@_change_case_codepoint_title:nnn #1#2#3 { - \exp_not:N \bool_if:NTF \l_text_titlecase_check_letter_bool + \bool_if:NTF \l_text_titlecase_check_letter_bool { - \bool_lazy_or:nnTF - { \sys_if_engine_luatex_p: } - { \sys_if_engine_xetex_p: } - { \exp_not:N \token_if_letter:NTF #3 } + \tl_if_single:nTF {#3} { - \exp_not:N \bool_lazy_or:nnTF - { \exp_not:N \token_if_letter_p:N #3 } - { \exp_not:N \token_if_active_p:N #3 } + \bool_lazy_or:nnTF + { \token_if_letter_p:N #3 } + { + \bool_lazy_and_p:nn + { \token_if_active_p:N #3 } + { ! \int_compare_p:nNn {`#3} < { "80 } } + } + { \use:c { @@_change_case_codepoint_ #1 :nn } } + { \@@_change_case_codepoint_title:nnnn { title } {#1} } } - { \exp_not:N \use:c { @@_change_case_char_ #1 :nN } } - { \exp_not:N \@@_change_case_char_title:nnnN { title } {#1} } + { \use:c { @@_change_case_codepoint_ #1 :nn } } } - { \exp_not:N \use:c { @@_change_case_char_ #1 :nN } } - {#2} #3 + { \use:c { @@_change_case_codepoint_ #1 :nn } } + {#2} {#3} } -\cs_new_eq:NN \@@_change_case_char_titleonly:nnN - \@@_change_case_char_title:nnN -\cs_new:Npn \@@_change_case_char_title:nN #1#2 - { \@@_change_case_char_title:nnnN { title } { lower } {#1} #2 } -\cs_new:Npn \@@_change_case_char_titleonly:nN #1#2 - { \@@_change_case_char_title:nnnN { title } { end } {#1} #2 } -\cs_new:Npn \@@_change_case_char_title:nnnN #1#2#3#4 +\cs_new_eq:NN \@@_change_case_codepoint_titleonly:nnn + \@@_change_case_codepoint_title:nnn +\cs_new:Npn \@@_change_case_codepoint_title:nn #1#2 + { \@@_change_case_codepoint_title:nnnn { title } { lower } {#1} {#2} } +\cs_new:Npn \@@_change_case_codepoint_titleonly:nn #1#2 + { \@@_change_case_codepoint_title:nnnn { title } { end } {#1} {#2} } +\cs_new:Npn \@@_change_case_codepoint_title:nnnn #1#2#3#4 { - \cs_if_exist_use:cF { @@_change_case_title_ #3 :nnnN } + \cs_if_exist_use:cF { @@_change_case_title_ #3 :nnnn } { - \cs_if_exist_use:cF { @@_change_case_upper_ #3 :nnnN } - { \@@_change_case_char:nnnN } + \cs_if_exist_use:cF { @@_change_case_upper_ #3 :nnnn } + { \@@_change_case_codepoint:nnnn } } - {#1} {#2} {#3} #4 + {#1} {#2} {#3} {#4} } -% \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.) -% For (u)p-\TeX{} there are a limited number of tokens we can touch. -% \begin{macrocode} -\cs_new:Npn \@@_change_case_char:nnnN #1#2#3#4 +\cs_new:Npn \@@_change_case_codepoint:nnnn #1#2#3#4 { - \token_if_active:NTF #4 + \bool_lazy_and:nnTF + { \tl_if_single_p:n {#4} } + { \token_if_active_p:N #4 } { \@@_change_case_store:n {#4} } { \@@_change_case_store:e - { \use:c { char_ #1 case :N } #4 } + { \@@_change_case_codepoint:nn {#1} {#4} } } - \use:c { @@_change_case_char_next_ #2 :nn } {#2} {#3} + \use:c { @@_change_case_next_ #2 :nn } {#2} {#3} } -\bool_lazy_or:nnF - { \sys_if_engine_luatex_p: } - { \sys_if_engine_xetex_p: } +\cs_new:Npn \@@_change_case_codepoint:nn #1#2 { - \cs_new_eq:NN \@@_change_case_char_auxi:nnnN - \@@_change_case_char:nnnN - \cs_gset:Npn \@@_change_case_char:nnnN #1#2#3#4 - { - \int_compare:nNnTF { `#4 } > { "80 } - { - \int_compare:nNnTF { `#4 } < { "E0 } - { \@@_change_case_char_UTFviii:nnnNN } - { \@@_change_case_char_auxii:nnnN } - } - { \@@_change_case_char_auxi:nnnN } - {#1} {#2} {#3} #4 - } - \sys_if_engine_pdftex:TF + \@@_change_case_codepoint:fnn + { \int_eval:n { \@@_codepoint_from_chars:Nw #2 } } {#1} {#2} + } +\cs_new:Npn \@@_change_case_codepoint:nnn #1#2#3 + { + \exp_args:Ne \@@_change_case_codepoint_aux:nn + { \__kernel_codepoint_case:nn { #2 case } {#1} } {#3} + } +\cs_generate_variant:Nn \@@_change_case_codepoint:nnn { f } +% \end{macrocode} +% Avoid high chars with p\TeX{}. +% \begin{macrocode} +\sys_if_engine_ptex:T + { + \cs_new_eq:NN \@@_change_case_codepoint_aux:nnn + \@@_change_case_codepoint:nnn + \cs_gset:Npn \@@_change_case_codepoint:nnn #1#2#3 { - \cs_new:Npn \@@_change_case_char_auxii:nnnN #1#2#3#4 - { - \int_compare:nNnTF { `#4 } < { "F0 } - { \@@_change_case_char_UTFviii:nnnNNN } - { \@@_change_case_char_UTFviii:nnnNNNN } - {#1} {#2} {#3} #4 - } + \int_compare:nNnTF {#1} = { -1 } + { \exp_not:n {#3} } + { \@@_change_case_codepoint_aux:nnn {#1} {#2} {#3} } } + } +\cs_new:Npn \@@_change_case_codepoint_aux:nn #1#2 + { + \use:e { \@@_change_case_codepoint_aux:nnnn #1 {#2} } + } +\cs_new:Npn \@@_change_case_codepoint_aux:nnnn #1#2#3#4 + { + \@@_codepoint_compare:nNnTF {#4} = {#1} + { \exp_not:n {#4} } { - \cs_new:Npn \@@_change_case_char_auxii:nnnN #1#2#3#4 + \codepoint_generate:nn {#1} + { \@@_change_case_catcode:nn {#4} {#1} } + \tl_if_blank:nF {#2} { - \@@_change_case_store:n {#4} - \use:c { @@_change_case_char_next_ #2 :nn } {#2} {#3} + \codepoint_generate:nn {#2} + { \char_value_catcode:n {#2} } + \tl_if_blank:nF {#3} + { + \codepoint_generate:nn {#3} + { \char_value_catcode:n {#3} } + } } } - \cs_new:Npn \@@_change_case_char_UTFviii:nnnNN #1#2#3#4#5 - { \@@_change_case_char_UTFviii:nnnn {#1} {#2} {#3} {#4#5} } - \cs_new:Npn \@@_change_case_char_UTFviii:nnnNNN #1#2#3#4#5#6 - { \@@_change_case_char_UTFviii:nnnn {#1} {#2} {#3} {#4#5#6} } - \cs_new:Npn \@@_change_case_char_UTFviii:nnnNNNN #1#2#3#4#5#6#7 - { \@@_change_case_char_UTFviii:nnnn {#1} {#2} {#3} {#4#5#6#7} } - \cs_new:Npn \@@_change_case_char_UTFviii:nnnn #1#2#3#4 + } +% \end{macrocode} +% We need to ensure that only valid catcode-extraction is attempted. That's +% fine with Unicode engines but needs a bit of work with 8-bit ones. The +% logic is that if the original codepoint was in the ASCII range, we keep +% the catcode. Otherwise, if the target is in the ASCII range, we use +% the standard catcode. If neither are true, we set as 13 on the grounds that +% this will be what is used anyway! +% \begin{macrocode} +\bool_lazy_or:nnTF + { \sys_if_engine_luatex_p: } + { \sys_if_engine_xetex_p: } + { + \cs_new:Npn \@@_change_case_catcode:nn #1#2 + { \@@_char_catcode:N #1 } + } + { + \cs_new:Npn \@@_change_case_catcode:nn #1#2 { - \cs_if_exist:cTF { c__kernel_ #1 case_ \tl_to_str:n {#4} _tl } + \@@_codepoint_compare:nNnTF {#1} < { "80 } + { \@@_char_catcode:N #1 } { - \@@_change_case_store:v - { c__kernel_ #1 case_ \tl_to_str:n {#4} _tl } + \int_compare:nNnTF {#2} < { "80 } + { \char_value_catcode:n {#2} } + { 13 } } - { \@@_change_case_store:n {#4} } - \use:c { @@_change_case_char_next_ #2 :nn } {#2} {#3} } } -\cs_new:Npn \@@_change_case_char_next_lower:nn #1#2 +\cs_new:Npn \@@_change_case_next_lower:nn #1#2 { \@@_change_case_loop:nnw {#1} {#2} } -\cs_new_eq:NN \@@_change_case_char_next_upper:nn - \@@_change_case_char_next_lower:nn -\cs_new_eq:NN \@@_change_case_char_next_title:nn - \@@_change_case_char_next_lower:nn -\cs_new_eq:NN \@@_change_case_char_next_titleonly:nn - \@@_change_case_char_next_lower:nn -\cs_new:Npn \@@_change_case_char_next_end:nn #1#2 +\cs_new_eq:NN \@@_change_case_next_upper:nn + \@@_change_case_next_lower:nn +\cs_new_eq:NN \@@_change_case_next_title:nn + \@@_change_case_next_lower:nn +\cs_new_eq:NN \@@_change_case_next_titleonly:nn + \@@_change_case_next_lower:nn +\cs_new:Npn \@@_change_case_next_end:nn #1#2 { \@@_change_case_break:w } % \end{macrocode} % \end{macro} @@ -822,13 +802,6 @@ % \end{macro} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % % \begin{macro}{\text_declare_case_equivalent:Nn} % Create equivalents to allow replacement. @@ -855,76 +828,63 @@ % \end{macro} % \end{macro} % -% \begin{macro}[EXP]{\@@_change_case_upper_de-x-eszett:nnnN, \@@_change_case_upper_de-alt:nnnN} -% \begin{macro}[EXP]{\@@_change_case_upper_de-x-eszett:nnnNN} +% \begin{macro}[EXP] +% {\@@_change_case_upper_de-x-eszett:nnnn, \@@_change_case_upper_de-alt:nnnn} % A simple alternative version for German. % \begin{macrocode} -\bool_lazy_or:nnTF - { \sys_if_engine_luatex_p: } - { \sys_if_engine_xetex_p: } - { - \cs_new:cpn { @@_change_case_upper_de-x-eszett:nnnN } #1#2#3#4 - { - \int_compare:nNnTF { `#4 } = { "00DF } - { - \@@_change_case_store:e - { \char_generate:nn { "1E9E } { \@@_char_catcode:N #4 } } - \use:c { @@_change_case_char_next_ #2 :nn } - {#2} {#3} - } - { \@@_change_case_char:nnnN {#1} {#2} {#3} #4 } - } - } +\cs_new:cpn { @@_change_case_upper_de-x-eszett:nnnn } #1#2#3#4 { - \cs_new:cpx { @@_change_case_upper_de-x-eszett:nnnN } #1#2#3#4 + \@@_codepoint_compare:nNnTF {#4} = { "00DF } { - \exp_not:N \int_compare:nNnTF { `#4 } = { "00C3 } - { - \exp_not:c { @@_change_case_upper_de-x-eszett:nnnNN } - {#1} {#2} {#3} #4 - } - { \exp_not:N \@@_change_case_char:nnnN {#1} {#2} {#3} #4 } - } - \cs_new:cpn { @@_change_case_upper_de-x-eszett:nnnNN } #1#2#3#4#5 - { - \int_compare:nNnTF { `#5 } = { "009F } - { - \@@_change_case_store:V \c_@@_grosses_Eszett_tl - \use:c { @@_change_case_char_next_ #2 :nn } {#2} {#3} - } - { \@@_change_case_char:nnnN {#1} {#2} {#3} #4#5 } + \@@_change_case_store:e + { + \codepoint_generate:nn { "1E9E } + { \@@_change_case_catcode:nn {#4} { "1E9E } } + } + \use:c { @@_change_case_next_ #2 :nn } + {#2} {#3} } + { \@@_change_case_codepoint:nnnn {#1} {#2} {#3} {#4} } } -\cs_new_eq:cc { @@_change_case_upper_de-alt:nnnN } - { @@_change_case_upper_de-x-eszett:nnnN } +\cs_new_eq:cc { @@_change_case_upper_de-alt:nnnn } + { @@_change_case_upper_de-x-eszett:nnnn } % \end{macrocode} % \end{macro} -% \end{macro} % % \begin{macro}[EXP] -% {\@@_change_case_upper_el:nnnN, \@@_change_case_upper_el-x-iota:nnnN} +% { +% \@@_change_case_upper_el:nnnn , +% \@@_change_case_upper_el_aux:nnnn , +% \@@_change_case_upper_el-x-iota:nnnn +% } % \begin{macro}[EXP] -% {\@@_change_case_upper_el:N, \@@_change_case_upper_el-x-iota:N} +% {\@@_change_case_upper_el:n, \@@_change_case_upper_el-x-iota:n} % \begin{macro}[EXP]{\@@_change_case_upper_el:nnn} -% \begin{macro}[EXP]{\@@_change_case_upper_el:nnNw} -% \begin{macro}[EXP]{\@@_change_case_upper_el:NnnN} -% \begin{macro}[EXP]{\@@_change_case_upper_el_ypogegrammeni:Nnnnnw} -% \begin{macro}[EXP]{\@@_change_case_upper_el_ypogegrammeni:NnnnnN} -% \begin{macro}[EXP]{\@@_change_case_upper_el_dialytika:nnN} -% \begin{macro}[EXP]{\@@_change_case_upper_el_dialytika:N} -% \begin{macro}[EXP]{\@@_change_case_upper_el_hiatus:nnNw} +% \begin{macro}[EXP]{\@@_change_case_upper_el:nnnw} +% \begin{macro}[EXP] +% {\@@_change_case_upper_el:nnnN, \@@_change_case_upper_el_aux:nnnN} +% \begin{macro}[EXP]{\@@_change_case_upper_el_ypogegrammeni:nnnnnw} +% \begin{macro}[EXP]{\@@_change_case_upper_el_ypogegrammeni:nnnnnN} +% \begin{macro}[EXP]{\@@_change_case_upper_el_ypogegrammeni:nnnnnn} +% \begin{macro}[EXP]{\@@_change_case_upper_el_dialytika:nnn} +% \begin{macro}[EXP]{\@@_change_case_upper_el_dialytika:n} +% \begin{macro}[EXP]{\@@_change_case_upper_el_hiatus:nnnw} % \begin{macro}[EXP]{\@@_change_case_upper_el_hiatus:nnN} +% \begin{macro}[EXP]{\@@_change_case_upper_el_hiatus:nnn} % \begin{macro}[EXP]{\@@_change_case_upper_el_gobble:nnw} % \begin{macro}[EXP]{\@@_change_case_upper_el_gobble:nnN} -% \begin{macro}[EXP]{\@@_change_case_upper_el:nnnNN} -% \begin{macro}[EXP]{\@@_change_case_upper_el:nnnNNN} -% \begin{macro}[EXP]{\@@_change_case_upper_el:nnnn} +% \begin{macro}[EXP]{\@@_change_case_upper_el_gobble:nnn} % \begin{macro}[EXP,TF]{\@@_change_case_if_greek:n} +% \begin{macro}[EXP]{\@@_change_case_if_greek:n} % \begin{macro}[EXP,pTF]{\@@_change_case_if_greek:n} % \begin{macro}[EXP,pTF]{\@@_change_case_if_greek_accent:n} +% \begin{macro}[EXP]{\@@_change_case_if_greek_accent:n} % \begin{macro}[EXP,pTF]{\@@_change_case_if_greek_diacritic:n} +% \begin{macro}[EXP]{\@@_change_case_if_greek_diacritic:n} % \begin{macro}[EXP,TF]{\@@_change_case_if_takes_dialytika:n} +% \begin{macro}[EXP]{\@@_change_case_if_takes_dialytika:n} % \begin{macro}[EXP,TF]{\@@_change_case_if_takes_ypogegrammeni:n} +% \begin{macro}[EXP]{\@@_change_case_if_takes_ypogegrammeni:n} % For Greek uppercasing, we need to know if characters \emph{in the Greek % range} have accents. That means doing a \textsc{nfd} conversion first, then % starting a search. As described by the Unicode \textsc{cldr}, Greek accents @@ -936,55 +896,58 @@ % \emph{ypogegrammeni} is filtered out here as it is not actually in the % Greek range, so gets lost if we leave until later. % \begin{macrocode} -\bool_lazy_or:nnTF - { \sys_if_engine_luatex_p: } - { \sys_if_engine_xetex_p: } +\cs_new:Npn \@@_change_case_upper_el:nnnn #1#2#3#4 { - \cs_new:Npn \@@_change_case_upper_el:nnnN #1#2#3#4 + \@@_change_case_if_greek:nTF {#4} { - \@@_change_case_if_greek:nTF { `#4 } + \exp_args:Ne \@@_change_case_upper_el:nnn { - \exp_args:Ne \@@_change_case_upper_el:nnn - { \char_to_nfd:N #4 } {#2} {#3} + \codepoint_to_nfd:n { \@@_codepoint_from_chars:Nw #4 } } + {#2} {#3} + } + { + \@@_codepoint_compare:nNnTF {#4} = { "0345 } { - \int_compare:nNnTF { `#4 } = { "0345 } + \@@_change_case_store:e { - \@@_change_case_store:e - { - \use:c { @@_change_case_upper_ #3 :N } #4 - } - \@@_change_case_loop:nnw {#2} {#3} + \use:c { @@_change_case_upper_ #3 :n } {#4} } - { \@@_change_case_char:nnnN {#1} {#2} {#3} #4 } + \@@_change_case_loop:nnw {#2} {#3} } + { \@@_change_case_codepoint:nnnn {#1} {#2} {#3} {#4} } } - \cs_new_eq:cN { @@_change_case_upper_el-x-iota:nnnN } - \@@_change_case_upper_el:nnnN - \cs_new:Npn \@@_change_case_upper_el:N #1 - { - \char_generate:nn { "0399 } - { \char_value_catcode:n { "0399 } } - } - \cs_new:cpn { @@_change_case_upper_el-x-iota:N } #1 - { \exp_not:n {#1} } - \cs_new:Npn \@@_change_case_upper_el:nnn #1#2#3 - { \@@_change_case_upper_el:nnNw {#2} {#3} #1 } + } +\cs_new_eq:cN { @@_change_case_upper_el-x-iota:nnnn } + \@@_change_case_upper_el:nnnn +\cs_new:Npn \@@_change_case_upper_el:n #1 + { + \codepoint_generate:nn { "0399 } + { \char_value_catcode:n { "0399 } } + } +\cs_new:cpn { @@_change_case_upper_el-x-iota:n } #1 + { \exp_not:n {#1} } +\cs_new:Npn \@@_change_case_upper_el:nnn #1#2#3 + { + \@@_codepoint_process:nN + { \@@_change_case_upper_el:nnnw {#2} {#3} } #1 + } % \end{macrocode} % At this stage we have the first NFD codepoint as |#3|. What we need to know -% is whether after that we have another character token, either from the NFD or +% is whether after that we have another character, either from the NFD or % directly in the input. If not, we store the changed character at this stage. % \begin{macrocode} - \cs_new:Npn \@@_change_case_upper_el:nnNw #1#2#3#4 \q_@@_recursion_stop +\cs_new:Npn \@@_change_case_upper_el:nnnw #1#2#3#4 \q_@@_recursion_stop + { + \tl_if_head_is_N_type:nTF {#4} + { \@@_change_case_upper_el:nnnN {#3} } { - \tl_if_head_is_N_type:nTF {#4} - { \@@_change_case_upper_el:NnnN #3 } - { - \@@_change_case_store:e { \char_uppercase:N #3 } - \@@_change_case_loop:nnw - } - {#1} {#2} #4 \q_@@_recursion_stop + \@@_change_case_store:e + { \@@_change_case_codepoint:nn { upper } {#3} } + \@@_change_case_loop:nnw } + {#1} {#2} #4 \q_@@_recursion_stop + } % \end{macrocode} % Now, we check the detail of the next codepoint: again we filter out the % not-a-char cases, before checking if it's an dialytika, accent or diacritic. @@ -993,193 +956,200 @@ % to move any ypogegrammeni to after accents (in case the input is not % normalised). The ypogegrammeni itself is handled separately. % \begin{macrocode} - \cs_new:Npn \@@_change_case_upper_el:NnnN #1#2#3#4 +\cs_new:Npn \@@_change_case_upper_el:nnnN #1#2#3#4 + { + \token_if_cs:NTF #4 { - \token_if_cs:NTF #4 - { - \@@_change_case_store:e { \char_uppercase:N #1 } - \@@_change_case_loop:nnw {#2} {#3} #4 - } + \@@_change_case_store:e + { \@@_change_case_codepoint:nn { upper } {#1} } + \@@_change_case_loop:nnw {#2} {#3} #4 + } + { + \@@_change_case_if_takes_ypogegrammeni:nTF {#1} { - \@@_change_case_if_takes_ypogegrammeni:nTF { `#1 } - { - \@@_change_case_upper_el_ypogegrammeni:Nnnnnw - #1 {#2} {#3} { } { } #4 - } - { \@@_change_case_upper_el_aux:NnnN #1 {#2} {#3} #4 } + \@@_change_case_upper_el_ypogegrammeni:nnnnnw + {#1} {#2} {#3} { } { } #4 } + { \@@_change_case_upper_el_aux:nnnN {#1} {#2} {#3} #4 } } - \cs_new:Npn \@@_change_case_upper_el_ypogegrammeni:Nnnnnw - #1#2#3#4#5#6 \q_@@_recursion_stop + } +\cs_new:Npn \@@_change_case_upper_el_ypogegrammeni:nnnnnw + #1#2#3#4#5#6 \q_@@_recursion_stop + { + \tl_if_head_is_N_type:nTF {#6} { - \tl_if_head_is_N_type:nTF {#6} + \@@_change_case_upper_el_ypogegrammeni:nnnnnN + {#1} {#2} {#3} {#4} {#5} + } + { \@@_change_case_upper_el_aux:nnnN {#1} {#2} {#3} #4#5 } + #6 \q_@@_recursion_stop + } +\cs_new:Npn \@@_change_case_upper_el_ypogegrammeni:nnnnnN #1#2#3#4#5#6 + { + \token_if_cs:NTF #6 + { \@@_change_case_upper_el_aux:nnnN {#1} {#2} {#3} #4#5 #6 } + { + \@@_codepoint_process:nN { - \@@_change_case_upper_el_ypogegrammeni:NnnnnN - #1 {#2} {#3} {#4} {#5} + \@@_change_case_upper_el_ypogegrammeni:nnnnnn + {#1} {#2} {#3} {#4} {#5} } - { \@@_change_case_upper_el_aux:NnnN #1 {#2} {#3} #4#5 } - #6 \q_@@_recursion_stop + #6 + } + } +\cs_new:Npn \@@_change_case_upper_el_ypogegrammeni:nnnnnn #1#2#3#4#5#6 + { + \@@_codepoint_compare:nNnTF {#6} = { "0345 } + { + \@@_change_case_upper_el_ypogegrammeni:nnnnnw + {#1} {#2} {#3} {#4} {#6} } - \cs_new:Npn \@@_change_case_upper_el_ypogegrammeni:NnnnnN #1#2#3#4#5#6 { - \token_if_cs:NTF #6 - { \@@_change_case_upper_el_aux:NnnN #1 {#2} {#3} #4#5 #6 } + \bool_lazy_or:nnTF + { \@@_change_case_if_greek_accent_p:n {#6} } + { \@@_change_case_if_greek_diacritic_p:n {#6} } { - \int_compare:nNnTF { `#6 } = { "0345 } - { - \@@_change_case_upper_el_ypogegrammeni:Nnnnnw - #1 {#2} {#3} {#4} {#6} - } - { - \bool_lazy_or:nnTF - { \@@_change_case_if_greek_accent_p:n { `#6 } } - { \@@_change_case_if_greek_diacritic_p:n { `#6 } } - { - \@@_change_case_upper_el_ypogegrammeni:Nnnnnw - #1 {#2} {#3} {#4#6} {#5} - } - { \@@_change_case_upper_el_aux:NnnN #1 {#2} {#3} #4#5 #6 } - } + \@@_change_case_upper_el_ypogegrammeni:nnnnnw + {#1} {#2} {#3} {#4#6} {#5} } + { \@@_change_case_upper_el_aux:nnnN {#1} {#2} {#3} #4#5 #6 } } - \cs_new:Npn \@@_change_case_upper_el_aux:NnnN #1#2#3#4 + } +\cs_new:Npn \@@_change_case_upper_el_aux:nnnN #1#2#3#4 + { + \@@_codepoint_process:nN + { \@@_change_case_upper_el_aux:nnnn {#1} {#2} {#3} } #4 + } +\cs_new:Npn \@@_change_case_upper_el_aux:nnnn #1#2#3#4 + { + \@@_codepoint_compare:nNnTF {#4} = { "0308 } + { \@@_change_case_upper_el_dialytika:nnn {#2} {#3} {#1} } { - \int_compare:nNnTF { `#4 } = { "0308 } - { \@@_change_case_upper_el_dialytika:nnN {#2} {#3} #1 } + \@@_change_case_if_greek_accent:nTF {#4} + { \@@_change_case_upper_el_hiatus:nnnw {#2} {#3} {#1} } { - \@@_change_case_if_greek_accent:nTF { `#4 } - { \@@_change_case_upper_el_hiatus:nnNw {#2} {#3} #1 } + \@@_change_case_if_greek_diacritic:nTF {#4} { - \@@_change_case_if_greek_diacritic:nTF { `#4 } - { - \@@_change_case_store:e { \char_uppercase:N #1 } - \@@_change_case_loop:nnw {#2} {#3} - } + \@@_change_case_store:e + { \@@_change_case_codepoint:nn { upper } {#1} } + \@@_change_case_loop:nnw {#2} {#3} + } + { + \@@_codepoint_compare:nNnTF {#4} = { "0345 } + { \@@_change_case_store:e { [XXX] } } { - \int_compare:nNnTF { `#4 } = { "0345 } - { \@@_change_case_store:e { [XXX] } } - { \@@_change_case_store:e { \char_uppercase:N #1 } } - \@@_change_case_loop:nnw {#2} {#3} #4 + \@@_change_case_store:e + { \@@_change_case_codepoint:nn { upper } {#1} } } + \@@_change_case_loop:nnw {#2} {#3} #4 } } } -% \end{macrocode} + } +% \end{macrocode} % We handle \emph{dialytika} in parts as it's also needed for the hiatus. % We know only two letters take it, so we can shortcut here on the second % part of the tests. % \begin{macrocode} - \cs_new:Npn \@@_change_case_upper_el_dialytika:nnN #1#2#3 +\cs_new:Npn \@@_change_case_upper_el_dialytika:nnn #1#2#3 + { + \@@_change_case_if_takes_dialytika:nTF {#3} + { \@@_change_case_upper_el_dialytika:n {#3} } { - \@@_change_case_if_takes_dialytika:nTF { `#3 } - { \@@_change_case_upper_el_dialytika:N #3 } - { \@@_change_case_store:e { \char_uppercase:N #3 } } - \@@_change_case_upper_el_gobble:nnw {#1} {#2} + \@@_change_case_store:e + { \@@_change_case_codepoint:nn { upper } {#3} } } - \cs_new:Npn \@@_change_case_upper_el_dialytika:N #1 + \@@_change_case_upper_el_gobble:nnw {#1} {#2} + } +\cs_new:Npn \@@_change_case_upper_el_dialytika:n #1 + { + \@@_change_case_store:e { - \@@_change_case_store:e + \bool_lazy_or:nnTF + { \@@_codepoint_compare_p:nNn {#1} = { "0399 } } + { \@@_codepoint_compare_p:nNn {#1} = { "03B9 } } { - \bool_lazy_or:nnTF - { \int_compare_p:nNn { `#1 } = { "0399 } } - { \int_compare_p:nNn { `#1 } = { "03B9 } } - { \char_generate:nn { "03AA } { \@@_char_catcode:N #1 } } - { \char_generate:nn { "03AB } { \@@_char_catcode:N #1 } } + \codepoint_generate:nn { "03AA } + { \@@_change_case_catcode:nn {#1} { "03AA } } + } + { + \codepoint_generate:nn { "03AB } + { \@@_change_case_catcode:nn {#1} { "03AB } } } } + } % \end{macrocode} % Adding a hiatus needs some of the same ideas, but if there is not one we % skip this code point, hence needing a separate function. % \begin{macrocode} - \cs_new:Npn \@@_change_case_upper_el_hiatus:nnNw - #1#2#3#4 \q_@@_recursion_stop +\cs_new:Npn \@@_change_case_upper_el_hiatus:nnnw + #1#2#3#4 \q_@@_recursion_stop + { + \@@_change_case_store:e + { \@@_change_case_codepoint:nn { upper } {#3} } + \tl_if_head_is_N_type:nTF {#4} + { \@@_change_case_upper_el_hiatus:nnN } + { \@@_change_case_loop:nnw } + {#1} {#2} #4 \q_@@_recursion_stop + } +\cs_new:Npn \@@_change_case_upper_el_hiatus:nnN #1#2#3 + { + \token_if_cs:NTF #3 + { \@@_change_case_loop:nnw {#1} {#2} #3 } { - \@@_change_case_store:e { \char_uppercase:N #3 } - \tl_if_head_is_N_type:nTF {#4} - { \@@_change_case_upper_el_hiatus:nnN } - { \@@_change_case_loop:nnw } - {#1} {#2} #4 \q_@@_recursion_stop + \@@_codepoint_process:nN + { \@@_change_case_upper_el_hiatus:nnn {#1} {#2} } #3 } - \cs_new:Npn \@@_change_case_upper_el_hiatus:nnN #1#2#3 + } +\cs_new:Npn \@@_change_case_upper_el_hiatus:nnn #1#2#3 + { + \@@_change_case_if_takes_dialytika:nTF {#3} { - \token_if_cs:NTF #3 - { \@@_change_case_loop:nnw {#1} {#2} #3 } - { - \@@_change_case_if_takes_dialytika:nTF { `#3 } - { - \@@_change_case_upper_el_dialytika:N #3 - \@@_change_case_upper_el_gobble:nnw {#1} {#2} - } - { \@@_change_case_loop:nnw {#1} {#2} #3 } - } + \@@_change_case_upper_el_dialytika:n {#3} + \@@_change_case_upper_el_gobble:nnw {#1} {#2} } + { \@@_change_case_loop:nnw {#1} {#2} #3 } + } % \end{macrocode} % For clearing out trailing combining marks after we have dealt with % the first one. % \begin{macrocode} - \cs_new:Npn \@@_change_case_upper_el_gobble:nnw - #1#2#3 \q_@@_recursion_stop - { - \tl_if_head_is_N_type:nTF {#3} - { \@@_change_case_upper_el_gobble:nnN } - { \@@_change_case_loop:nnw } - {#1} {#2} #3 \q_@@_recursion_stop - } - \cs_new:Npn \@@_change_case_upper_el_gobble:nnN #1#2#3 - { - \bool_lazy_or:nnTF - { \token_if_cs_p:N #3 } - { - ! \bool_lazy_or_p:nn - { \@@_change_case_if_greek_accent_p:n { `#3 } } - { \@@_change_case_if_greek_diacritic_p:n { `#3 } } - } - { \@@_change_case_loop:nnw {#1} {#2} #3 } - { \@@_change_case_upper_el_gobble:nnw {#1} {#2} } - } +\cs_new:Npn \@@_change_case_upper_el_gobble:nnw + #1#2#3 \q_@@_recursion_stop + { + \tl_if_head_is_N_type:nTF {#3} + { \@@_change_case_upper_el_gobble:nnN } + { \@@_change_case_loop:nnw } + {#1} {#2} #3 \q_@@_recursion_stop } -% \end{macrocode} -% For $8$-bit engines we use a simplified approach: covers the common -% requirements. This is basically how \pkg{xgreek} works but done by -% expansion: use fixed mappings from accented to accent-free letters. -% Only the two- and three-byte ranges can be involved. -% \begin{macrocode} +\cs_new:Npn \@@_change_case_upper_el_gobble:nnN #1#2#3 { - \cs_new:Npn \@@_change_case_upper_el:nnnN #1#2#3#4 - { - \int_compare:nNnTF { `#4 } > { "80 } - { - \int_compare:nNnTF { `#4 } < { "E0 } - { \@@_change_case_upper_el:nnnNN } - { - \int_compare:nNnTF { `#4 } < { "F0 } - { \@@_change_case_upper_el:nnnNNN } - { \@@_change_case_char:nnnN } - } - } - { \@@_change_case_char:nnnN } - {#1} {#2} {#3} #4 - } - \cs_new:Npn \@@_change_case_upper_el:nnnNN #1#2#3#4#5 - { \@@_change_case_upper_el:nnnn {#1} {#2} {#3} {#4#5} } - \cs_new:Npn \@@_change_case_upper_el:nnnNNN #1#2#3#4#5#6 - { \@@_change_case_upper_el:nnnn {#1} {#2} {#3} {#4#5#6} } - \cs_new:Npn \@@_change_case_upper_el:nnnn #1#2#3#4 + \token_if_cs:NTF #3 + { \@@_change_case_loop:nnw {#1} {#2} } { - \cs_if_exist:cTF { c_@@_uppercase_el_ \tl_to_str:n {#4} _tl } - { - \@@_change_case_store:v - { c_@@_uppercase_el_ \tl_to_str:n {#4} _tl } - \@@_change_case_loop:nnw {#1} {#3} - } - { \@@_change_case_char:nnnN {#1} {#2} {#3} #4 } + \@@_codepoint_process:nN + { \@@_change_case_upper_el_gobble:nnn {#1} {#2} } } + #3 + } +\cs_new:Npn \@@_change_case_upper_el_gobble:nnn #1#2#3 + { + \bool_lazy_or:nnTF + { \@@_change_case_if_greek_accent_p:n {#3} } + { \@@_change_case_if_greek_diacritic_p:n {#3} } + { \@@_change_case_upper_el_gobble:nnw {#1} {#2} } + { \@@_change_case_loop:nnw {#1} {#2} #3 } } % \end{macrocode} % Luckily the Greek range is limited and clear. % \begin{macrocode} \prg_new_conditional:Npnn \@@_change_case_if_greek:n #1 { TF } { + \exp_args:Nf \@@_change_case_if_greek:n + { \int_eval:n { \@@_codepoint_from_chars:Nw #1 } } + } +\cs_new:Npn \@@_change_case_if_greek:n #1 + { \if_int_compare:w #1 < "0370 \exp_stop_f: \prg_return_false: \else: @@ -1207,6 +1177,11 @@ % \begin{macrocode} \prg_new_conditional:Npnn \@@_change_case_if_greek_accent:n #1 { TF , p } { + \exp_args:Nf \@@_change_case_if_greek_accent:n + { \int_eval:n { \@@_codepoint_from_chars:Nw #1 } } + } +\cs_new:Npn \@@_change_case_if_greek_accent:n #1 + { \if_int_compare:w #1 = "0300 \exp_stop_f: \prg_return_true: \else: @@ -1236,6 +1211,11 @@ \prg_new_conditional:Npnn \@@_change_case_if_greek_diacritic:n #1 { TF , p } { + \exp_args:Nf \@@_change_case_if_greek_diacritic:n + { \int_eval:n { \@@_codepoint_from_chars:Nw #1 } } + } +\cs_new:Npn \@@_change_case_if_greek_diacritic:n #1 + { \if_int_compare:w #1 = "0304 \exp_stop_f: \prg_return_true: \else: @@ -1260,6 +1240,11 @@ } \prg_new_conditional:Npnn \@@_change_case_if_takes_dialytika:n #1 { TF } { + \exp_args:Nf \@@_change_case_if_takes_dialytika:n + { \int_eval:n { \@@_codepoint_from_chars:Nw #1 } } + } +\cs_new:Npn \@@_change_case_if_takes_dialytika:n #1 + { \if_int_compare:w #1 = "0399 \exp_stop_f: \prg_return_true: \else: @@ -1280,6 +1265,11 @@ } \prg_new_conditional:Npnn \@@_change_case_if_takes_ypogegrammeni:n #1 { TF } { + \exp_args:Nf \@@_change_case_if_takes_ypogegrammeni:n + { \int_eval:n { \@@_codepoint_from_chars:Nw #1 } } + } +\cs_new:Npn \@@_change_case_if_takes_ypogegrammeni:n #1 + { \if_int_compare:w #1 = "03B1 \exp_stop_f: \prg_return_true: \else: @@ -1317,60 +1307,79 @@ % \end{macro} % \end{macro} % \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} % \begin{macro}[EXP]{\@@_change_case_boundary_upper_el:Nnnw} % \begin{macro}[EXP]{\@@_change_case_boundary_upper_el:nnN} -% \begin{macro}[EXP]{\@@_change_case_boundary_upper_el:nnNw} -% \begin{macro}[EXP]{\@@_change_case_boundary_upper_el:NnnN} +% \begin{macro}[EXP]{\@@_change_case_boundary_upper_el:nnn} +% \begin{macro}[EXP]{\@@_change_case_boundary_upper_el:nnnw} +% \begin{macro}[EXP]{\@@_change_case_boundary_upper_el:nnnN} % There is one special case in Greek that needs to be picked up based on % being an isolated letter. We do that using a test similar to final sigma, % but it has to fire off from the space grabber. % \begin{macrocode} -\bool_lazy_or:nnT - { \sys_if_engine_luatex_p: } - { \sys_if_engine_xetex_p: } +\cs_new:Npn \@@_change_case_boundary_upper_el:Nnnw + #1#2#3#4 \q_@@_recursion_stop + { + \tl_if_head_is_N_type:nTF {#4} + { \@@_change_case_boundary_upper_el:nnN } + { \@@_change_case_loop:nnw } + {#2} {#3} #4 \q_@@_recursion_stop + } +\cs_new:Npn \@@_change_case_boundary_upper_el:nnN #1#2#3 { - \cs_new:Npn \@@_change_case_boundary_upper_el:Nnnw - #1#2#3#4 \q_@@_recursion_stop + \token_if_cs:NTF #3 + { \@@_change_case_loop:nnw {#1} {#2} } { - \tl_if_head_is_N_type:nTF {#4} - { \@@_change_case_boundary_upper_el:nnN } - { \@@_change_case_loop:nnw } - {#2} {#3} #4 \q_@@_recursion_stop + \@@_codepoint_process:nN + { \@@_change_case_boundary_upper_el:nnn {#1} {#2} } } - \cs_new:Npn \@@_change_case_boundary_upper_el:nnN #1#2#3 + #3 + } +\cs_new:Npn \@@_change_case_boundary_upper_el:nnn #1#2#3 + { + \bool_lazy_or:nnTF + { \@@_codepoint_compare_p:nNn {#3} = { "03AE } } + { \@@_codepoint_compare_p:nNn {#3} = { "1F22 } } + { \@@_change_case_boundary_upper_el:nnnw {#1} {#2} {#3} } + { \@@_change_case_loop:nnw {#1} {#2} #3 } + } +\cs_new:Npn \@@_change_case_boundary_upper_el:nnnw + #1#2#3#4 \q_@@_recursion_stop + { + \tl_if_head_is_N_type:nTF {#4} + { \@@_change_case_boundary_upper_el:nnnN {#3} } { - \bool_lazy_or:nnTF - { \token_if_cs_p:N #3 } + \@@_change_case_store:e { - ! \bool_lazy_or_p:nn - { \int_compare_p:nNn { `#3 } = { "03AE } } - { \int_compare_p:nNn { `#3 } = { "1F22 } } + \codepoint_generate:nn { "0389 } + { \@@_change_case_catcode:nn {#3} { "0389 } } } - { \@@_change_case_loop:nnw } - { \@@_change_case_boundary_upper_el:nnNw } - {#1} {#2} #3 + \@@_change_case_loop:nnw } - \cs_new:Npn \@@_change_case_boundary_upper_el:nnNw - #1#2#3#4 \q_@@_recursion_stop - { - \tl_if_head_is_N_type:nTF {#4} - { \@@_change_case_boundary_upper_el:NnnN #3 } - { - \@@_change_case_store:e - { \char_generate:nn { "0389 } { \@@_char_catcode:N #3 } } - \@@_change_case_loop:nnw - } - {#1} {#2} #4 \q_@@_recursion_stop + {#1} {#2} #4 \q_@@_recursion_stop + } +\cs_new:Npn \@@_change_case_boundary_upper_el:nnnN #1#2#3#4 + { + \MARJ + \bool_lazy_or:nnTF + { \token_if_letter_p:N #4 } + { + \bool_lazy_and_p:nn + { \token_if_active_p:N #4 } + { ! \int_compare_p:nNn {`#4} < { "80 } } } - \cs_new:Npn \@@_change_case_boundary_upper_el:NnnN #1#2#3#4 + { \@@_change_case_loop:nnw {#2} {#3} #1#4 } { - \token_if_letter:NTF #4 - { \@@_change_case_loop:nnw {#2} {#3} #1#4 } + \@@_change_case_store:e { - \@@_change_case_store:e - { \char_generate:nn { "0389 } { \@@_char_catcode:N #1 } } - \@@_change_case_loop:nnw {#2} {#3} #4 + \codepoint_generate:nn { "0389 } + { \@@_change_case_catcode:nn {#1} { "0389 } } } + \@@_change_case_loop:nnw {#2} {#3} #4 } } % \end{macrocode} @@ -1378,98 +1387,89 @@ % \end{macro} % \end{macro} % \end{macro} -% \begin{macro}[EXP]{\@@_change_case_title_el:nnnN} +% \end{macro} +% \begin{macro}[EXP]{\@@_change_case_title_el:nnnn} % Titlecasing retains accents, but to prevent the uppercasing code % from kicking in, there has to be an explicit function here. % \begin{macrocode} -\bool_lazy_or:nnT - { \sys_if_engine_luatex_p: } - { \sys_if_engine_xetex_p: } - { - \cs_new:Npn \@@_change_case_title_el:nnnN #1#2#3#4 - { \@@_change_case_char:nnnN {#1} {#2} {#3} #4 } - } +\cs_new:Npn \@@_change_case_title_el:nnnn #1#2#3#4 + { \@@_change_case_codepoint:nnnn {#1} {#2} {#3} {#4} } % \end{macrocode} % \end{macro} % % \begin{macro}[EXP] % { -% \@@_change_case_upper_hy:nnnN , -% \@@_change_case_title_hy:nnNN , -% \@@_change_case_upper_hy-x-yiwn:nnnN , -% \@@_change_case_title_hy-x-yiwn:nnNN +% \@@_change_case_upper_hy:nnnn , +% \@@_change_case_title_hy:nnnn , +% \@@_change_case_upper_hy-x-yiwn:nnnn , +% \@@_change_case_title_hy-x-yiwn:nnnn % } % See \url{https://www.unicode.org/L2/L2020/20143-armenian-ech-yiwn.pdf}. % \begin{macrocode} -\bool_lazy_or:nnT - { \sys_if_engine_luatex_p: } - { \sys_if_engine_xetex_p: } +\cs_new:Npn \@@_change_case_upper_hy:nnnn #1#2#3#4 { - \cs_new:cpn { @@_change_case_upper_hy:nnnN } #1#2#3#4 + \@@_codepoint_compare:nNnTF {#4} = { "0587 } { - \int_compare:nNnTF { `#4 } = { "0587 } + \@@_change_case_store:e { - \@@_change_case_store:e - { - \char_generate:nn { "0535 } { \@@_char_catcode:N #4 } - \char_generate:nn { "054E } { \@@_char_catcode:N #4 } - } - \use:c { @@_change_case_char_next_ #2 :nn } - {#2} {#3} + \codepoint_generate:nn { "0535 } + { \@@_change_case_catcode:nn {#4} { "0535 } } + \codepoint_generate:nn { "054E } + { \@@_change_case_catcode:nn {#4} { "054E } } } - { \@@_change_case_char:nnnN {#1} {#2} {#3} #4 } + \use:c { @@_change_case_next_ #2 :nn } + {#2} {#3} } - \cs_new:cpn { @@_change_case_title_hy:nnnN } #1#2#3#4 + { \@@_change_case_codepoint:nnnn {#1} {#2} {#3} {#4} } + } +\cs_new:Npn \@@_change_case_title_hy:nnnn #1#2#3#4 + { + \@@_codepoint_compare:nNnTF {#4} = { "0587 } { - \int_compare:nNnTF { `#4 } = { "0587 } + \@@_change_case_store:e { - \@@_change_case_store:e - { - \char_generate:nn { "0535 } { \@@_char_catcode:N #4 } - \char_generate:nn { "057E } { \@@_char_catcode:N #4 } - } - \use:c { @@_change_case_char_next_ #2 :nn } - {#2} {#3} + \codepoint_generate:nn { "0535 } + { \@@_change_case_catcode:nn {#4} { "0535 } } + \codepoint_generate:nn { "057E } + { \@@_change_case_catcode:nn {#4} { "057E } } } - { \@@_change_case_char:nnnN {#1} {#2} {#3} #4 } + \use:c { @@_change_case_next_ #2 :nn } + {#2} {#3} } - \cs_new:cpn { @@_change_case_upper_hy-x-yiwn:nnnN } #1#2#3#4 - { \@@_change_case_char:nnnN {#1} {#2} {#3} #4 } - \cs_new_eq:cc { @@_change_case_title_hy-x-yiwn:nnnN } - { @@_change_case_upper_hy-x-yiwn:nnnN } + { \@@_change_case_codepoint:nnnn {#1} {#2} {#3} {#4} } } +\cs_new:cpn { @@_change_case_upper_hy-x-yiwn:nnnn } #1#2#3#4 + { \@@_change_case_codepoint:nnnn {#1} {#2} {#3} {#4} } +\cs_new_eq:cc { @@_change_case_title_hy-x-yiwn:nnnn } + { @@_change_case_upper_hy-x-yiwn:nnnn } % \end{macrocode} % \end{macro} % -% \begin{macro}[EXP]{\@@_change_case_lower_la-x-medieval:nnnN} -% \begin{macro}[EXP]{\@@_change_case_upper_la-x-medieval:nnnN} +% \begin{macro}[EXP]{\@@_change_case_lower_la-x-medieval:nnnn} +% \begin{macro}[EXP]{\@@_change_case_upper_la-x-medieval:nnnn} % Simply swaps of characters. % \begin{macrocode} -\cs_new:cpn { @@_change_case_lower_la-x-medieval:nnnN } #1#2#3#4 +\cs_new:cpn { @@_change_case_lower_la-x-medieval:nnnn } #1#2#3#4 { - \int_compare:nNnTF { `#4 } = { `V } + \@@_codepoint_compare:nNnTF {#4} = { "0056 } { \@@_change_case_store:e - { - \char_generate:nn { `u } { \@@_char_catcode:N #4 } - } - \use:c { @@_change_case_char_next_ #2 :nn } + { \char_generate:nn { "0075 } { \@@_char_catcode:N #4 } } + \use:c { @@_change_case_next_ #2 :nn } {#2} {#3} } - { \@@_change_case_char:nnnN {#1} {#2} {#3} #4 } + { \@@_change_case_codepoint:nnnn {#1} {#2} {#3} {#4} } } -\cs_new:cpn { @@_change_case_upper_la-x-medieval:nnnN } #1#2#3#4 +\cs_new:cpn { @@_change_case_upper_la-x-medieval:nnnn } #1#2#3#4 { - \int_compare:nNnTF { `#4 } = { `u } + \@@_codepoint_compare:nNnTF {#4} = { "0075 } { \@@_change_case_store:e - { - \char_generate:nn { `V } { \@@_char_catcode:N #4 } - } - \use:c { @@_change_case_char_next_ #2 :nn } + { \char_generate:nn { "0056 } { \@@_char_catcode:N #4 } } + \use:c { @@_change_case_next_ #2 :nn } {#2} {#3} } - { \@@_change_case_char:nnnN {#1} {#2} {#3} #4 } + { \@@_change_case_codepoint:nnnn {#1} {#2} {#3} {#4} } } % \end{macrocode} % \end{macro} @@ -1477,191 +1477,223 @@ % % \begin{macro}[EXP] % { -% \@@_change_cases_lower_lt:nnnN , -% \@@_change_cases_lower_lt_auxi:nnnN , -% \@@_change_cases_lower_lt_auxii:nnnN +% \@@_change_cases_lower_lt:nnnn , +% \@@_change_cases_lower_lt_auxi:nnnn , +% \@@_change_cases_lower_lt_auxii:nnnn % } % \begin{macro}[rEXP]{\@@_change_case_lower_lt:nnw} % \begin{macro}[rEXP]{\@@_change_case_lower_lt:nnN} +% \begin{macro}[rEXP]{\@@_change_case_lower_lt:nnn} % For Lithuanian, the issue to be dealt with is dots over lower case % letters: these should be present if there is another accent. The first step % is a simple match attempt: look for the three uppercase accented letters % which should gain a dot-above char in their lowercase form. % \begin{macrocode} -\bool_lazy_or:nnT - { \sys_if_engine_luatex_p: } - { \sys_if_engine_xetex_p: } +\cs_new:Npn \@@_change_case_lower_lt:nnnn #1#2#3#4 { - \cs_new:Npn \@@_change_case_lower_lt:nnnN #1#2#3#4 - { - \exp_args:Ne \@@_change_case_lower_lt_auxi:nnnN + \exp_args:Ne \@@_change_case_lower_lt_auxi:nnnn + { + \int_case:nn { \@@_codepoint_from_chars:Nw #4 } { - \int_case:nn { `#4 } - { - { "00CC } { "0300 } - { "00CD } { "0301 } - { "0128 } { "0303 } - } - } - {#2} {#3} #4 + { "00CC } { "0300 } + { "00CD } { "0301 } + { "0128 } { "0303 } + } } + {#2} {#3} {#4} + } % \end{macrocode} % If there was a hit, output the result with the dot-above and move on. % Otherwise, look for one of the three letters that can take a combining % accent: I, J and I-ogonek. % \begin{macrocode} - \cs_new:Npn \@@_change_case_lower_lt_auxi:nnnN #1#2#3#4 +\cs_new:Npn \@@_change_case_lower_lt_auxi:nnnn #1#2#3#4 + { + \tl_if_blank:nTF {#1} { - \tl_if_blank:nTF {#1} + \exp_args:Ne \@@_change_case_lower_lt_auxii:nnnn { - \exp_args:Ne \@@_change_case_lower_lt_auxii:nnnN + \int_case:nn { \@@_codepoint_from_chars:Nw #4 } { - \int_case:nn { `#4 } - { - { "0049 } { "0069 } - { "004A } { "006A } - { "012E } { "012F } - } - } - {#2} {#3} #4 + { "0049 } { "0069 } + { "004A } { "006A } + { "012E } { "012F } + } } + {#2} {#3} {#4} + } + { + \@@_change_case_store:e { - \@@_change_case_store:e - { - \char_generate:nn { "0069 } { \@@_char_catcode:N #4 } - \char_generate:nn { "0307 } { \@@_char_catcode:N #4 } - \char_generate:nn {#1} { \@@_char_catcode:N #4 } - } - \@@_change_case_loop:nnw {#2} {#3} + \codepoint_generate:nn { "0069 } + { \@@_change_case_catcode:nn {#4} { "0069 } } + \codepoint_generate:nn { "0307 } + { \@@_change_case_catcode:nn {#4} { "0307 } } + \codepoint_generate:nn {#1} + { \@@_change_case_catcode:nn {#4} {#1} } } + \@@_change_case_loop:nnw {#2} {#3} } + } % \end{macrocode} % Again, branch depending on a hit. If there is one, we output the character % then need to look for a combining accent: as usual, we need to be aware of % the loop situation. % \begin{macrocode} - \cs_new:Npn \@@_change_case_lower_lt_auxii:nnnN #1#2#3#4 +\cs_new:Npn \@@_change_case_lower_lt_auxii:nnnn #1#2#3#4 + { + \tl_if_blank:nTF {#1} + { \@@_change_case_codepoint:nnnn {#2} {#2} {#3} {#4} } { - \tl_if_blank:nTF {#1} - { \@@_change_case_lower_sigma:nnnN {#2} {#2} {#3} #4 } + \@@_change_case_store:e { - \@@_change_case_store:e - { \char_generate:nn {#1} { \@@_char_catcode:N #4 } } - \@@_change_case_lower_lt:nnw {#2} {#3} + \codepoint_generate:nn {#1} + { \@@_change_case_catcode:nn {#4} {#1} } } + \@@_change_case_lower_lt:nnw {#2} {#3} } - \cs_new:Npn \@@_change_case_lower_lt:nnw #1#2#3 \q_@@_recursion_stop + } +\cs_new:Npn \@@_change_case_lower_lt:nnw #1#2#3 \q_@@_recursion_stop + { + \tl_if_head_is_N_type:nTF {#3} + { \@@_change_case_lower_lt:nnN } + { \@@_change_case_loop:nnw } + {#1} {#2} #3 \q_@@_recursion_stop + } +\cs_new:Npn \@@_change_case_lower_lt:nnN #1#2#3 + { + \@@_codepoint_process:nN + { \@@_change_case_lower_lt:nnn {#1} {#2} } #3 + } +\cs_new:Npn \@@_change_case_lower_lt:nnn #1#2#3 + { + \bool_lazy_and:nnT { - \tl_if_head_is_N_type:nTF {#3} - { \@@_change_case_lower_lt:nnN } - { \@@_change_case_loop:nnw } - {#1} {#2} #3 \q_@@_recursion_stop + \bool_lazy_or_p:nn + { ! \tl_if_single_p:n {#3} } + { ! \token_if_cs_p:N #3 } } - \cs_new:Npn \@@_change_case_lower_lt:nnN #1#2#3 { - \bool_lazy_and:nnT - { ! \token_if_cs_p:N #3 } + \bool_lazy_any_p:n { - \bool_lazy_any_p:n - { - { \int_compare_p:nNn { `#3 } = { "0300 } } - { \int_compare_p:nNn { `#3 } = { "0301 } } - { \int_compare_p:nNn { `#3 } = { "0303 } } - } + { \@@_codepoint_compare_p:nNn {#3} = { "0300 } } + { \@@_codepoint_compare_p:nNn {#3} = { "0301 } } + { \@@_codepoint_compare_p:nNn {#3} = { "0303 } } } + } + { + \@@_change_case_store:e { - \@@_change_case_store:e - { \char_generate:nn { "0307 } { \@@_char_catcode:N #3 } } + \codepoint_generate:nn { "0307 } + { \@@_change_case_catcode:nn {#3} { "0307 } } } - \@@_change_case_loop:nnw {#1} {#2} #3 } + \@@_change_case_loop:nnw {#1} {#2} #3 } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} +% \end{macro} % \begin{macro}[EXP] % { -% \@@_change_cases_upper_lt:nnnN , -% \@@_change_cases_upper_lt_aux:nnnN +% \@@_change_cases_upper_lt:nnnn , +% \@@_change_cases_upper_lt_aux:nnnn % } % \begin{macro}[rEXP]{\@@_change_case_upper_lt:nnw} % \begin{macro}[rEXP]{\@@_change_case_upper_lt:nnN} +% \begin{macro}[rEXP]{\@@_change_case_upper_lt:nnn} % The uppercasing version: first find i/j/i-ogonek, then look for the % combining char: drop it if present. % \begin{macrocode} -\bool_lazy_or:nnT - { \sys_if_engine_luatex_p: } - { \sys_if_engine_xetex_p: } - { - \cs_new:Npn \@@_change_case_upper_lt:nnnN #1#2#3#4 - { - \exp_args:Ne \@@_change_case_upper_lt_aux:nnnN +\cs_new:Npn \@@_change_case_upper_lt:nnnn #1#2#3#4 + { + \exp_args:Ne \@@_change_case_upper_lt_aux:nnnn + { + \int_case:nn { \@@_codepoint_from_chars:Nw #4 } { - \int_case:nn { `#4 } - { - { "0069 } { "0049 } - { "006A } { "004A } - { "012F } { "012E } - } - } - {#2} {#3} #4 + { "0069 } { "0049 } + { "006A } { "004A } + { "012F } { "012E } + } } - \cs_new:Npn \@@_change_case_upper_lt_aux:nnnN #1#2#3#4 - { - \tl_if_blank:nTF {#1} - { \@@_change_case_char:nnnN { upper } {#2} {#3} #4 } - { - \@@_change_case_store:e - { \char_generate:nn {#1} { \@@_char_catcode:N #4 } } - \@@_change_case_upper_lt:nnw {#2} {#3} - } - } - \cs_new:Npn \@@_change_case_upper_lt:nnw #1#2#3 \q_@@_recursion_stop + {#2} {#3} {#4} + } +\cs_new:Npn \@@_change_case_upper_lt_aux:nnnn #1#2#3#4 + { + \tl_if_blank:nTF {#1} + { \@@_change_case_codepoint:nnnn { upper } {#2} {#3} {#4} } { - \tl_if_head_is_N_type:nTF {#3} - { \@@_change_case_upper_lt:nnN } - { \use:c { @@_change_case_char_next_ #1 :nn } } - {#1} {#2} #3 \q_@@_recursion_stop + \@@_change_case_store:e + { + \codepoint_generate:nn {#1} + { \@@_change_case_catcode:nn {#4} {#1} } + } + \@@_change_case_upper_lt:nnw {#2} {#3} } - \cs_new:Npn \@@_change_case_upper_lt:nnN #1#2#3 + } +\cs_new:Npn \@@_change_case_upper_lt:nnw #1#2#3 \q_@@_recursion_stop + { + \tl_if_head_is_N_type:nTF {#3} + { \@@_change_case_upper_lt:nnN } + { \use:c { @@_change_case_next_ #1 :nn } } + {#1} {#2} #3 \q_@@_recursion_stop + } +\cs_new:Npn \@@_change_case_upper_lt:nnN #1#2#3 + { + \@@_codepoint_process:nN + { \@@_change_case_upper_lt:nnn {#1} {#2} } #3 + } +\cs_new:Npn \@@_change_case_upper_lt:nnn #1#2#3 + { + \bool_lazy_and:nnTF { - \bool_lazy_and:nnTF + \bool_lazy_or_p:nn + { ! \tl_if_single_p:n {#3} } { ! \token_if_cs_p:N #3 } - { \int_compare_p:nNn { `#3 } = { "0307 } } - { \use:c { @@_change_case_char_next_ #1 :nn } {#1} {#2} } - { \use:c { @@_change_case_char_next_ #1 :nn } {#1} {#2} #3 } } + { \@@_codepoint_compare_p:nNn {#3} = { "0307 } } + { \use:c { @@_change_case_next_ #1 :nn } {#1} {#2} } + { \use:c { @@_change_case_next_ #1 :nn } {#1} {#2} #3 } } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} +% \end{macro} % -% \begin{macro}[EXP]{\@@_change_case_title_nl:nnnN} +% \begin{macro}[EXP] +% {\@@_change_case_title_nl:nnnn, \@@_change_case_title_nl_aux:nnnn} % \begin{macro}[EXP]{\@@_change_case_title_nl:nnw} % \begin{macro}[EXP]{\@@_change_case_title_nl:nnN} % 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_title_nl:nnnN #1#2#3#4 +\cs_new:Npn \@@_change_case_title_nl:nnnn #1#2#3#4 + { + \tl_if_single:nTF {#4} + { \@@_change_case_title_nl_aux:nnnn } + { \@@_change_case_codepoint:nnnn } + {#1} {#2} {#3} {#4} + } +\cs_new:Npn \@@_change_case_title_nl_aux:nnnn #1#2#3#4 { \bool_lazy_or:nnTF - { \int_compare_p:nNn { `#4 } = { "0049 } } - { \int_compare_p:nNn { `#4 } = { "0069 } } + { \int_compare_p:nNn {`#4} = { "0049 } } + { \int_compare_p:nNn {`#4} = { "0069 } } { \@@_change_case_store:e { \char_generate:nn { "0049 } { \@@_char_catcode:N #4 } } \@@_change_case_title_nl:nnw {#2} {#3} } - { \@@_change_case_char:nnnN {#1} {#2} {#3} #4 } + { \@@_change_case_codepoint:nnnn {#1} {#2} {#3} {#4} } } \cs_new:Npn \@@_change_case_title_nl:nnw #1#2#3 \q_@@_recursion_stop { \tl_if_head_is_N_type:nTF {#3} { \@@_change_case_title_nl:nnN } - { \use:c { @@_change_case_char_next_ #1 :nn } } + { \use:c { @@_change_case_next_ #1 :nn } } {#1} {#2} #3 \q_@@_recursion_stop } \cs_new:Npn \@@_change_case_title_nl:nnN #1#2#3 @@ -1670,118 +1702,96 @@ { ! \token_if_cs_p:N #3 } { \bool_lazy_or_p:nn - { \int_compare_p:nNn { `#3 } = { "004A } } - { \int_compare_p:nNn { `#3 } = { "006A } } + { \int_compare_p:nNn {`#3} = { "004A } } + { \int_compare_p:nNn {`#3} = { "006A } } } { \@@_change_case_store:e { \char_generate:nn { "004A } { \@@_char_catcode:N #3 } } - \use:c { @@_change_case_char_next_ #1 :nn } {#1} {#2} + \use:c { @@_change_case_next_ #1 :nn } {#1} {#2} } - { \use:c { @@_change_case_char_next_ #1 :nn } {#1} {#2} #3 } + { \use:c { @@_change_case_next_ #1 :nn } {#1} {#2} #3 } } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % -% \begin{macro}[EXP]{\@@_change_case_lower_tr:nnnN} +% \begin{macro}[EXP]{\@@_change_case_lower_tr:nnnn} % \begin{macro}[EXP]{\@@_change_case_lower_tr:nnNw} % \begin{macro}[EXP]{\@@_change_case_lower_tr:NnnN} -% \begin{macro}[EXP]{\@@_change_case_lower_tr:nnnNN} +% \begin{macro}[EXP]{\@@_change_case_lower_tr:Nnnn} % 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:nnnn #1#2#3#4 { - \cs_new:Npn \@@_change_case_lower_tr:nnnN #1#2#3#4 + \@@_codepoint_compare:nNnTF {#4} = { "0049 } + { \@@_change_case_lower_tr:nnNw {#1} {#3} #4 } { - \int_compare:nNnTF { `#4 } = { "0049 } - { \@@_change_case_lower_tr:nnNw {#1} {#3} #4 } + \@@_codepoint_compare:nNnTF {#4} = { "0130 } { - \int_compare:nNnTF { `#4 } = { "0130 } + \@@_change_case_store:e { - \@@_change_case_store:e - { \char_generate:nn { "0069 } { \@@_char_catcode:N #4 } } - \@@_change_case_loop:nnw {#1} {#3} + \codepoint_generate:nn { "0069 } + { \@@_change_case_catcode:nn {#4} { "0069 } } } - { \@@_change_case_lower_sigma:nnnN {#1} {#2} {#3} #4 } + \@@_change_case_loop:nnw {#1} {#3} } + { \@@_change_case_codepoint:nnnn {#1} {#2} {#3} {#4} } } + } % \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. % \begin{macrocode} - \cs_new:Npn \@@_change_case_lower_tr:nnNw #1#2#3#4 \q_@@_recursion_stop +\cs_new:Npn \@@_change_case_lower_tr:nnNw #1#2#3#4 \q_@@_recursion_stop + { + \tl_if_head_is_N_type:nTF {#4} + { \@@_change_case_lower_tr:NnnN #3 {#1} {#2} } { - \tl_if_head_is_N_type:nTF {#4} - { \@@_change_case_lower_tr:NnnN #3 } + \@@_change_case_store:e { - \@@_change_case_store:e - { \char_generate:nn { "0131 } { \@@_char_catcode:N #3 } } - \@@_change_case_loop:nnw + \codepoint_generate:nn { "0131 } + { \@@_change_case_catcode:nn {#3} { "0131 } } } - {#1} {#2} #4 \q_@@_recursion_stop + \@@_change_case_loop:nnw {#1} {#2} } - \cs_new:Npn \@@_change_case_lower_tr:NnnN #1#2#3#4 + #4 \q_@@_recursion_stop + } +\cs_new:Npn \@@_change_case_lower_tr:NnnN #1#2#3#4 + { + \@@_codepoint_process:nN + { \@@_change_case_lower_tr:Nnnn #1 {#2} {#3} } #4 + } +\cs_new:Npn \@@_change_case_lower_tr:Nnnn #1#2#3#4 + { + \bool_lazy_or:nnTF { - \bool_lazy_or:nnTF + \bool_lazy_and_p:nn + { \tl_if_single_p:n {#4} } { \token_if_cs_p:N #4 } - { ! \int_compare_p:nNn { `#4 } = { "0307 } } - { - \@@_change_case_store:e - { \char_generate:nn { "0131 } { \@@_char_catcode:N #1 } } - \@@_change_case_loop:nnw {#2} {#3} #4 - } - { - \@@_change_case_store:e - { \char_generate:nn { "0069 } { \@@_char_catcode:N #1 } } - \@@_change_case_loop:nnw {#2} {#3} - } } - } -% \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. With $8$bit engines, we cannot -% completely preserve category codes, so we have to make some assumptions: -% output a \enquote{normal} \texttt{i} for the dotted case. As the original -% character here is catcode-$13$, we have to make a choice about handling -% of |i|: generate a \enquote{normal} one. -% \begin{macrocode} - { - \cs_new:Npn \@@_change_case_lower_tr:nnnN #1#2#3#4 + { ! \@@_codepoint_compare_p:nNn {#4} = { "0307 } } { - \int_compare:nNnTF { `#4 } = { "0049 } - { - \@@_change_case_store:V \c_@@_dotless_i_tl - \@@_change_case_loop:nnw {#1} {#3} - } + \@@_change_case_store:e { - \int_compare:nNnTF { `#4 } = { "00C4 } - { \@@_change_case_lower_tr:nnnNN {#1} {#2} {#3} #4 } - { \@@_change_case_char:nnnN {#1} {#2} {#3} #4 } + \codepoint_generate:nn { "0131 } + { \@@_change_case_catcode:nn {#1} { "0131 } } } + \@@_change_case_loop:nnw {#2} {#3} #4 } - \cs_new:Npn \@@_change_case_lower_tr:nnnNN #1#2#3#4#5 { - \int_compare:nNnTF { `#5 } = { "00B0 } + \@@_change_case_store:e { - \@@_change_case_store:e - { - \char_generate:nn { "0069 } - { \char_value_catcode:n { "0069 } } - } - \@@_change_case_loop:nnw {#1} {#3} + \codepoint_generate:nn { "0069 } + { \@@_change_case_catcode:nn {#1} { "0069 } } } - { \@@_change_case_char:nnnN {#1} {#2} {#3} #4#5 } + \@@_change_case_loop:nnw {#2} {#3} } } % \end{macrocode} @@ -1789,1055 +1799,36 @@ % \end{macro} % \end{macro} % \end{macro} -% \begin{macro}[EXP]{\@@_change_case_upper_tr:nnnN} +% \begin{macro}[EXP]{\@@_change_case_upper_tr:nnnn} % Uppercasing is easier: just one exception with no context. % \begin{macrocode} -\cs_new:Npx \@@_change_case_upper_tr:nnnN #1#2#3#4 +\cs_new:Npn \@@_change_case_upper_tr:nnnn #1#2#3#4 { - \exp_not:N \int_compare:nNnTF { `#4 } = { "0069 } + \@@_codepoint_compare:nNnTF {#4} = { "0069 } { - \bool_lazy_or:nnTF - { \sys_if_engine_luatex_p: } - { \sys_if_engine_xetex_p: } - { - \exp_not:N \@@_change_case_store:e - { - \exp_not:N \char_generate:nn { "0130 } - { \exp_not:N \@@_char_catcode:N #4 } - } - } + \@@_change_case_store:e { - \exp_not:N \@@_change_case_store:V - \exp_not:N \c_@@_dotted_I_tl + \codepoint_generate:nn { "0130 } + { \@@_change_case_catcode:nn {#4} { "0130 } } } - \exp_not:N \use:c { @@_change_case_char_next_ #2 :nn } {#2} {#3} + \use:c { @@_change_case_next_ #2 :nn } {#2} {#3} } - { \exp_not:N \@@_change_case_char:nnnN {#1} {#2} {#3} #4 } + { \@@_change_case_codepoint:nnnn {#1} {#2} {#3} {#4} } } % \end{macrocode} % \end{macro} % % \begin{macro}[EXP] -% {\@@_change_case_lower_az:nnnN, \@@_change_case_upper_az:nnnN} +% {\@@_change_case_lower_az:nnnn, \@@_change_case_upper_az:nnnn} % Straight copies. % \begin{macrocode} -\cs_new_eq:NN \@@_change_case_lower_az:nnnN - \@@_change_case_lower_tr:nnnN -\cs_new_eq:NN \@@_change_case_upper_az:nnnN - \@@_change_case_upper_tr:nnnN +\cs_new_eq:NN \@@_change_case_lower_az:nnnn + \@@_change_case_lower_tr:nnnn +\cs_new_eq:NN \@@_change_case_upper_az:nnnn + \@@_change_case_upper_tr:nnnn % \end{macrocode} % \end{macro} % -% \subsection{Case changing data for $8$-bit engines} -% -% \begin{variable} -% { -% \c_@@_dotless_i_tl , -% \c_@@_dotted_I_tl , -% \c_@@_i_ogonek_tl , -% \c_@@_I_ogonek_tl , -% \c_@@_final_sigma_tl , -% \c_@@_sigma_tl , -% \c_@@_grosses_Eszett_tl -% } -% For cases where there is an $8$-bit option in the |T1| font set up, -% a variant is provided in both cases. There are also a few extras for -% |LGR|. -% \begin{macrocode} -\group_begin: - \bool_lazy_or:nnF - { \sys_if_engine_luatex_p: } - { \sys_if_engine_xetex_p: } - { - \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_if_blank:nF {##3} - { - \exp_after:wN \exp_after:wN \exp_after:wN - \exp_not:N \char_generate:nn {##3} { 13 } - } - } - } - \use:x - { \@@_tmp:w \char_to_utfviii_bytes:n { "#2 } } - \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 } - \@@_tmp:w \c_@@_final_sigma_tl { 03C2 } - \@@_tmp:w \c_@@_sigma_tl { 03C3 } - \@@_tmp:w \c_@@_grosses_Eszett_tl { 1E9E } - } -\group_end: -% \end{macrocode} -% \end{variable} -% -% For $8$-bit engines we now need to define the case-change data for -% the multi-octet mappings. This data is here not in the \pkg{char} module -% as the multi-byte nature means they are never |N|-type. As this data is -% needed both for text and string work, it is stored as |kernel|: it remains -% internal as it is not really suitable for wider exposure. -% -% The first set of codepoints are those in |T1|: all of these are two bytes. -% \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} - \use:x - { - \@@_tmp:w - \char_to_utfviii_bytes:n { "#1 } - \char_to_utfviii_bytes:n { "#2 } - } - \@@_loop:nn - } - \cs_set_protected:Npn \@@_tmp:nnnn #1#2#3#4#5 - { - \tl_const:cx - { - c__kernel_ #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__kernel_lowercase_ - \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 { title } {#5} {#6} {#1} {#2} - } - \@@_loop:nn - { 00C0 } { 00E0 } - { 00C1 } { 00E1 } - { 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 } - { 01A0 } { 01A1 } - { 01AF } { 01B0 } - { 01CD } { 01CE } - { 01CF } { 01D0 } - { 01D1 } { 01D2 } - { 01D3 } { 01D4 } - { 01E2 } { 01E3 } - { 01E6 } { 01E7 } - { 01E8 } { 01E9 } - { 01EA } { 01EB } - { 01F4 } { 01F5 } - { 0218 } { 0219 } - { 021A } { 021B } -% \end{macrocode} -% Add |T2| (Cyrillic) : again two bytes. -% \begin{macrocode} - { 0400 } { 0450 } - { 0401 } { 0451 } - { 0402 } { 0452 } - { 0403 } { 0453 } - { 0404 } { 0454 } - { 0405 } { 0455 } - { 0406 } { 0456 } - { 0407 } { 0457 } - { 0408 } { 0458 } - { 0409 } { 0459 } - { 040A } { 045A } - { 040B } { 045B } - { 040C } { 045C } - { 040D } { 045D } - { 040E } { 045E } - { 040F } { 045F } - { 0410 } { 0430 } - { 0411 } { 0431 } - { 0412 } { 0432 } - { 0413 } { 0433 } - { 0414 } { 0434 } - { 0415 } { 0435 } - { 0416 } { 0436 } - { 0417 } { 0437 } - { 0418 } { 0438 } - { 0419 } { 0439 } - { 041A } { 043A } - { 041B } { 043B } - { 041C } { 043C } - { 041D } { 043D } - { 041E } { 043E } - { 041F } { 043F } - { 0420 } { 0440 } - { 0421 } { 0441 } - { 0422 } { 0442 } - { 0423 } { 0443 } - { 0424 } { 0444 } - { 0425 } { 0445 } - { 0426 } { 0446 } - { 0427 } { 0447 } - { 0428 } { 0448 } - { 0429 } { 0449 } - { 042A } { 044A } - { 042B } { 044B } - { 042C } { 044C } - { 042D } { 044D } - { 042E } { 044E } - { 042F } { 044F } -% \end{macrocode} -% Greek support: everything in the two-octet range. -% \begin{macrocode} - { 0370 } { 0371 } - { 0372 } { 0373 } - { 0376 } { 0377 } - { 03FD } { 037B } - { 03FE } { 037C } - { 03FF } { 037D } - { 0386 } { 03AC } - { 0388 } { 03AD } - { 0389 } { 03AE } - { 038A } { 03AF } - { 0391 } { 03B1 } - { 0392 } { 03B2 } - { 0393 } { 03B3 } - { 0394 } { 03B4 } - { 0395 } { 03B5 } - { 0396 } { 03B6 } - { 0397 } { 03B7 } - { 0398 } { 03B8 } - { 0399 } { 03B9 } - { 039A } { 03BA } - { 039B } { 03BB } - { 039C } { 03BC } - { 039D } { 03BD } - { 039E } { 03BE } - { 039F } { 03BF } - { 03A0 } { 03C0 } - { 03A1 } { 03C1 } - { 03A3 } { 03C3 } - { 03A4 } { 03C4 } - { 03A5 } { 03C5 } - { 03A6 } { 03C6 } - { 03A7 } { 03C7 } - { 03A8 } { 03C8 } - { 03A9 } { 03C9 } - { 03AA } { 03CA } - { 03AB } { 03CB } - { 038C } { 03CC } - { 038E } { 03CD } - { 038F } { 03CE } - { 03CF } { 03D7 } - { 03D8 } { 03D9 } - { 03DA } { 03DB } - { 03DC } { 03DD } - { 03DE } { 03DF } - { 03E0 } { 03E1 } - { 03E2 } { 03E3 } - { 03E4 } { 03E5 } - { 03E6 } { 03E7 } - { 03E8 } { 03E9 } - { 03EA } { 03EB } - { 03EC } { 03ED } - { 03EE } { 03EF } - { 03F9 } { 03F2 } - { 037F } { 03F3 } - { 03F7 } { 03F8 } - { 03FA } { 03FB } - \q_recursion_tail ? - \q_recursion_stop -% \end{macrocode} -% Odds and ends for Greek; mainly symbols that are for compatibility, -% but also things like the terminal sigma. Almost all are uppercase -% mappings, but there is one that is not! -% \begin{macrocode} - \cs_set_protected:Npn \@@_tmp:w #1#2#3 - { - \group_begin: - \cs_set_protected:Npn \@@_tmp:w ##1##2##3##4##5##6##7##8 - { - \tl_const:cx - { - c__kernel_ #3 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 } - } - } - \use:x - { - \@@_tmp:w - \char_to_utfviii_bytes:n { "#1 } - \char_to_utfviii_bytes:n { "#2 } - } - \group_end: - } - \@@_tmp:w { 0345 } { 0399 } { upper } - \@@_tmp:w { 03C2 } { 03A3 } { upper } - \@@_tmp:w { 03D0 } { 0392 } { upper } - \@@_tmp:w { 03D1 } { 0398 } { upper } - \@@_tmp:w { 03D5 } { 03A6 } { upper } - \@@_tmp:w { 03D6 } { 03A0 } { upper } - \@@_tmp:w { 03F0 } { 039A } { upper } - \@@_tmp:w { 03F1 } { 03A1 } { upper } - \@@_tmp:w { 03F4 } { 03B8 } { lower } - \@@_tmp:w { 03F5 } { 0395 } { upper } -% \end{macrocode} -% Croatian digraph letters: these have a titlecase variant. -% \begin{macrocode} - \@@_tmp:w { 01C4 } { 01C5 } { title } - \@@_tmp:w { 01C4 } { 01C6 } { lower } - \@@_tmp:w { 01C5 } { 01C4 } { upper } - \@@_tmp:w { 01C5 } { 01C6 } { lower } - \@@_tmp:w { 01C6 } { 01C4 } { upper } - \@@_tmp:w { 01C6 } { 01C5 } { title } - \@@_tmp:w { 01C7 } { 01C8 } { title } - \@@_tmp:w { 01C7 } { 01C9 } { lower } - \@@_tmp:w { 01C8 } { 01C7 } { upper } - \@@_tmp:w { 01C8 } { 01C9 } { lower } - \@@_tmp:w { 01C9 } { 01C7 } { upper } - \@@_tmp:w { 01C9 } { 01C8 } { title } - \@@_tmp:w { 01CA } { 01CB } { title } - \@@_tmp:w { 01CA } { 01CC } { lower } - \@@_tmp:w { 01CB } { 01CA } { upper } - \@@_tmp:w { 01CB } { 01CC } { lower } - \@@_tmp:w { 01CC } { 01CA } { upper } - \@@_tmp:w { 01CC } { 01CB } { title } -% \end{macrocode} -% Odds and ends that are not simple one-to-one mappings. These -% are still two-octet code points. -% \begin{macrocode} - \cs_set_protected:Npn \@@_tmp:w #1#2#3 - { - \group_begin: - \cs_set_protected:Npn \@@_tmp:w ##1##2##3##4 - { - \tl_const:cn - { - c__kernel_ #3 case_ - \char_generate:nn {##1} { 12 } - \char_generate:nn {##2} { 12 } - _tl - } - {#2} - } - \use:x - { \@@_tmp:w \char_to_utfviii_bytes:n { "#1 } } - \group_end: - } - \@@_tmp:w { 00DF } { SS } { upper } - \@@_tmp:w { 00DF } { Ss } { title } - \@@_tmp:w { 0131 } { I } { upper } -% \end{macrocode} -% Coverage for Vietnamese (\texttt{T5}) -% \begin{macrocode} - \cs_set_protected:Npn \@@_tmp:nnnnnn #1#2#3#4#5#6#7 - { - \tl_const:cx - { - c__kernel_ #1 case_ - \char_generate:nn {#2} { 12 } - \char_generate:nn {#3} { 12 } - \char_generate:nn {#4} { 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 } - \exp_after:wN \exp_after:wN \exp_after:wN - \exp_not:N \char_generate:nn {#7} { 13 } - } - } - \cs_set_protected:Npn \@@_tmp:w #1#2#3#4#5#6#7#8 - { - \tl_const:cx - { - c__kernel_lowercase_ - \char_generate:nn {#1} { 12 } - \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 {#5} { 13 } - \exp_after:wN \exp_after:wN \exp_after:wN - \exp_not:N \char_generate:nn {#6} { 13 } - \exp_after:wN \exp_after:wN \exp_after:wN - \exp_not:N \char_generate:nn {#7} { 13 } - } - \@@_tmp:nnnnnn { upper } {#5} {#6} {#7} {#1} {#2} {#3} - \@@_tmp:nnnnnn { title } {#5} {#6} {#7} {#1} {#2} {#3} - } - \@@_loop:nn - { 1EA0 } { 1EA1 } - { 1EA2 } { 1EA3 } - { 1EA4 } { 1EA5 } - { 1EA6 } { 1EA7 } - { 1EA8 } { 1EA9 } - { 1EAA } { 1EAB } - { 1EAC } { 1EAD } - { 1EAE } { 1EAF } - { 1EB0 } { 1EB1 } - { 1EB2 } { 1EB3 } - { 1EB4 } { 1EB5 } - { 1EB6 } { 1EB7 } - { 1EB8 } { 1EB9 } - { 1EBA } { 1EBB } - { 1EBC } { 1EBD } - { 1EBE } { 1EBF } - { 1EC0 } { 1EC1 } - { 1EC2 } { 1EC3 } - { 1EC4 } { 1EC5 } - { 1EC6 } { 1EC7 } - { 1EC8 } { 1EC9 } - { 1ECA } { 1ECB } - { 1ECC } { 1ECD } - { 1ECE } { 1ECF } - { 1ED0 } { 1ED1 } - { 1ED2 } { 1ED3 } - { 1ED4 } { 1ED5 } - { 1ED6 } { 1ED7 } - { 1ED8 } { 1ED9 } - { 1EDA } { 1EDB } - { 1EDC } { 1EDD } - { 1EDE } { 1EDF } - { 1EE0 } { 1EE1 } - { 1EE2 } { 1EE3 } - { 1EE4 } { 1EE5 } - { 1EE6 } { 1EE7 } - { 1EE8 } { 1EE9 } - { 1EEA } { 1EEB } - { 1EEC } { 1EED } - { 1EEE } { 1EEF } - { 1EF0 } { 1EF1 } - { 1EF2 } { 1EF3 } - { 1EF4 } { 1EF5 } - { 1EF6 } { 1EF7 } - { 1EF8 } { 1EF9 } - \q_recursion_tail ? - \q_recursion_stop -% \end{macrocode} -% Greek support: the three-octet code points. -% \begin{macrocode} - \@@_loop:nn - { 1F08 } { 1F00 } - { 1F09 } { 1F01 } - { 1F0A } { 1F02 } - { 1F0B } { 1F03 } - { 1F0C } { 1F04 } - { 1F0D } { 1F05 } - { 1F0E } { 1F06 } - { 1F0F } { 1F07 } - { 1F18 } { 1F10 } - { 1F19 } { 1F11 } - { 1F1A } { 1F12 } - { 1F1B } { 1F13 } - { 1F1C } { 1F14 } - { 1F1D } { 1F15 } - { 1F28 } { 1F20 } - { 1F29 } { 1F21 } - { 1F2A } { 1F22 } - { 1F2B } { 1F23 } - { 1F2C } { 1F24 } - { 1F2D } { 1F25 } - { 1F2E } { 1F26 } - { 1F2F } { 1F27 } - { 1F38 } { 1F30 } - { 1F39 } { 1F31 } - { 1F3A } { 1F32 } - { 1F3B } { 1F33 } - { 1F3C } { 1F34 } - { 1F3D } { 1F35 } - { 1F3E } { 1F36 } - { 1F3F } { 1F37 } - { 1F48 } { 1F40 } - { 1F49 } { 1F41 } - { 1F4A } { 1F42 } - { 1F4B } { 1F43 } - { 1F4C } { 1F44 } - { 1F4D } { 1F45 } - { 1F59 } { 1F51 } - { 1F5B } { 1F53 } - { 1F5D } { 1F55 } - { 1F5F } { 1F57 } - { 1F68 } { 1F60 } - { 1F69 } { 1F61 } - { 1F6A } { 1F62 } - { 1F6B } { 1F63 } - { 1F6C } { 1F64 } - { 1F6D } { 1F65 } - { 1F6E } { 1F66 } - { 1F6F } { 1F67 } - { 1FBA } { 1F70 } - { 1FBB } { 1F71 } - { 1FC8 } { 1F72 } - { 1FC9 } { 1F73 } - { 1FCA } { 1F74 } - { 1FCB } { 1F75 } - { 1FDA } { 1F76 } - { 1FDB } { 1F77 } - { 1FF8 } { 1F78 } - { 1FF9 } { 1F79 } - { 1FEA } { 1F7A } - { 1FEB } { 1F7B } - { 1FFA } { 1F7C } - { 1FFB } { 1F7D } - { 1F88 } { 1F80 } - { 1F89 } { 1F81 } - { 1F8A } { 1F82 } - { 1F8B } { 1F83 } - { 1F8C } { 1F84 } - { 1F8D } { 1F85 } - { 1F8E } { 1F86 } - { 1F8F } { 1F87 } - { 1F98 } { 1F90 } - { 1F99 } { 1F91 } - { 1F9A } { 1F92 } - { 1F9B } { 1F93 } - { 1F9C } { 1F94 } - { 1F9D } { 1F95 } - { 1F9E } { 1F96 } - { 1F9F } { 1F97 } - { 1FA8 } { 1FA0 } - { 1FA9 } { 1FA1 } - { 1FAA } { 1FA2 } - { 1FAB } { 1FA3 } - { 1FAC } { 1FA4 } - { 1FAD } { 1FA5 } - { 1FAE } { 1FA6 } - { 1FAF } { 1FA7 } - { 1FB8 } { 1FB0 } - { 1FB9 } { 1FB1 } - { 1FBC } { 1FB3 } - { 1FCC } { 1FC3 } - { 1FD8 } { 1FD0 } - { 1FD9 } { 1FD1 } - { 1FE8 } { 1FE0 } - { 1FE9 } { 1FE1 } - { 1FEC } { 1FE5 } - { 1FFC } { 1FF3 } - \q_recursion_tail ? - \q_recursion_stop -% \end{macrocode} -% One three-octet special case for Greek: it also moves to two-octets! -% \begin{macrocode} - \cs_set_protected:Npn \@@_tmp:w #1#2#3 - { - \group_begin: - \cs_set_protected:Npn \@@_tmp:w ##1##2##3##4##5##6##7##8 - { - \tl_const:cx - { - c__kernel_ #3 case_ - \char_generate:nn {##1} { 12 } - \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 {##5} { 13 } - \exp_after:wN \exp_after:wN \exp_after:wN - \exp_not:N \char_generate:nn {##6} { 13 } - } - } - \use:x - { - \@@_tmp:w - \char_to_utfviii_bytes:n { "#1 } - \char_to_utfviii_bytes:n { "#2 } - } - \group_end: - } - \@@_tmp:w { 1FBE } { 0399 } { upper } -% \end{macrocode} -% Greek accent suppression for uppercasing. -% \begin{macrocode} - \cs_set_protected:Npn \@@_tmp:w #1#2#3#4#5#6#7#8 - { - \tl_const:cx - { - c_@@_uppercase_el_ - \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 } - } - } - \@@_loop:nn - { 0370 } { 0370 } - { 0371 } { 0370 } - { 0372 } { 0372 } - { 0373 } { 0372 } - { 0376 } { 0376 } - { 0377 } { 0376 } - { 03FD } { 03FD } - { 037B } { 03FD } - { 03FE } { 03FE } - { 037C } { 03FE } - { 03FF } { 03FF } - { 037D } { 03FF } - { 0386 } { 0391 } - { 0388 } { 0395 } - { 0389 } { 0397 } - { 038A } { 0399 } - { 038C } { 039F } - { 038E } { 03A5 } - { 038F } { 03A9 } - { 0390 } { 03AA } - { 0391 } { 0391 } - { 0392 } { 0392 } - { 0393 } { 0393 } - { 0394 } { 0394 } - { 0395 } { 0395 } - { 0396 } { 0396 } - { 0397 } { 0397 } - { 0398 } { 0398 } - { 0399 } { 0399 } - { 039A } { 039A } - { 039B } { 039B } - { 039C } { 039C } - { 039D } { 039D } - { 039E } { 039E } - { 039F } { 039F } - { 03A0 } { 03A0 } - { 03A1 } { 03A1 } - { 03A3 } { 03A3 } - { 03A4 } { 03A4 } - { 03A5 } { 03A5 } - { 03A6 } { 03A6 } - { 03A7 } { 03A7 } - { 03A8 } { 03A8 } - { 03A9 } { 03A9 } - { 03AA } { 03AA } - { 03AB } { 03AB } - { 03AC } { 0391 } - { 03AD } { 0395 } - { 03AE } { 0397 } - { 03AF } { 0399 } - { 03B0 } { 03AB } - { 03B1 } { 0391 } - { 03B2 } { 0392 } - { 03B3 } { 0393 } - { 03B4 } { 0394 } - { 03B5 } { 0395 } - { 03B6 } { 0396 } - { 03B7 } { 0397 } - { 03B8 } { 0398 } - { 03B9 } { 0399 } - { 03BA } { 039A } - { 03BB } { 039B } - { 03BC } { 039C } - { 03BD } { 039D } - { 03BE } { 039E } - { 03BF } { 039F } - { 03C0 } { 03A0 } - { 03C1 } { 03A1 } - { 03C2 } { 03A3 } - { 03C3 } { 03A3 } - { 03C4 } { 03A4 } - { 03C5 } { 03A5 } - { 03C6 } { 03A6 } - { 03C7 } { 03A7 } - { 03C8 } { 03A8 } - { 03C9 } { 03A9 } - { 03CA } { 03AA } - { 03CB } { 03AB } - { 03CC } { 039F } - { 03CD } { 03A5 } - { 03CE } { 03A9 } - { 03D0 } { 0392 } - { 03D1 } { 0398 } - { 03D2 } { 03A5 } - { 03D3 } { 03A5 } - { 03D4 } { 03AB } - { 03D5 } { 03A6 } - { 03D6 } { 03A0 } - { 03DA } { 03DA } - { 03DB } { 03DA } - { 03DC } { 03DC } - { 03DD } { 03DC } - { 03DE } { 03DE } - { 03DF } { 03DE } - { 03E0 } { 03E0 } - { 03E1 } { 03E0 } - { 03F0 } { 039A } - { 03F1 } { 03A1 } - { 03F2 } { 03F9 } - { 03F9 } { 03F9 } - \q_recursion_tail ? - \q_recursion_stop - \cs_set_protected:Npn \@@_tmp:w #1#2#3#4#5#6#7#8 - { - \tl_const:cx - { - c_@@_uppercase_el_ - \char_generate:nn {#1} { 12 } - \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 {#5} { 13 } - \exp_after:wN \exp_after:wN \exp_after:wN - \exp_not:N \char_generate:nn {#6} { 13 } - \tl_if_blank:nF {#7} - { - \exp_after:wN \exp_after:wN \exp_after:wN - \exp_not:N \char_generate:nn {#7} { 13 } - } - } - } - \@@_loop:nn - { 1F00 } { 0391 } - { 1F01 } { 0391 } - { 1F02 } { 0391 } - { 1F03 } { 0391 } - { 1F04 } { 0391 } - { 1F05 } { 0391 } - { 1F06 } { 0391 } - { 1F07 } { 0391 } - { 1F08 } { 0391 } - { 1F09 } { 0391 } - { 1F0A } { 0391 } - { 1F0B } { 0391 } - { 1F0C } { 0391 } - { 1F0D } { 0391 } - { 1F0E } { 0391 } - { 1F0F } { 0391 } - { 1F10 } { 0395 } - { 1F11 } { 0395 } - { 1F12 } { 0395 } - { 1F13 } { 0395 } - { 1F14 } { 0395 } - { 1F15 } { 0395 } - { 1F18 } { 0395 } - { 1F19 } { 0395 } - { 1F1A } { 0395 } - { 1F1B } { 0395 } - { 1F1C } { 0395 } - { 1F1D } { 0395 } - { 1F20 } { 0397 } - { 1F21 } { 0397 } - { 1F22 } { 0397 } - { 1F23 } { 0397 } - { 1F24 } { 0397 } - { 1F25 } { 0397 } - { 1F26 } { 0397 } - { 1F27 } { 0397 } - { 1F28 } { 0397 } - { 1F29 } { 0397 } - { 1F2A } { 0397 } - { 1F2B } { 0397 } - { 1F2C } { 0397 } - { 1F2D } { 0397 } - { 1F2E } { 0397 } - { 1F2F } { 0397 } - { 1F30 } { 0399 } - { 1F31 } { 0399 } - { 1F32 } { 0399 } - { 1F33 } { 0399 } - { 1F34 } { 0399 } - { 1F35 } { 0399 } - { 1F36 } { 0399 } - { 1F37 } { 0399 } - { 1F38 } { 0399 } - { 1F39 } { 0399 } - { 1F3A } { 0399 } - { 1F3B } { 0399 } - { 1F3C } { 0399 } - { 1F3D } { 0399 } - { 1F3E } { 0399 } - { 1F3F } { 0399 } - { 1F40 } { 039F } - { 1F41 } { 039F } - { 1F42 } { 039F } - { 1F43 } { 039F } - { 1F44 } { 039F } - { 1F45 } { 039F } - { 1F48 } { 039F } - { 1F49 } { 039F } - { 1F4A } { 039F } - { 1F4B } { 039F } - { 1F4C } { 039F } - { 1F4D } { 039F } - { 1F50 } { 03A5 } - { 1F51 } { 03A5 } - { 1F52 } { 03A5 } - { 1F53 } { 03A5 } - { 1F54 } { 03A5 } - { 1F55 } { 03A5 } - { 1F56 } { 03A5 } - { 1F57 } { 03A5 } - { 1F59 } { 03A5 } - { 1F5B } { 03A5 } - { 1F5D } { 03A5 } - { 1F5F } { 03A5 } - { 1F60 } { 03A9 } - { 1F61 } { 03A9 } - { 1F62 } { 03A9 } - { 1F63 } { 03A9 } - { 1F64 } { 03A9 } - { 1F65 } { 03A9 } - { 1F66 } { 03A9 } - { 1F67 } { 03A9 } - { 1F68 } { 03A9 } - { 1F69 } { 03A9 } - { 1F6A } { 03A9 } - { 1F6B } { 03A9 } - { 1F6C } { 03A9 } - { 1F6D } { 03A9 } - { 1F6E } { 03A9 } - { 1F6F } { 03A9 } - { 1F70 } { 0391 } - { 1F71 } { 0391 } - { 1F72 } { 0395 } - { 1F73 } { 0395 } - { 1F74 } { 0397 } - { 1F75 } { 0397 } - { 1F76 } { 0399 } - { 1F77 } { 0399 } - { 1F78 } { 039F } - { 1F79 } { 039F } - { 1F7A } { 03A5 } - { 1F7B } { 03A5 } - { 1F7C } { 03A9 } - { 1F7D } { 03A9 } - { 1F80 } { 1FBC } - { 1F81 } { 1FBC } - { 1F82 } { 1FBC } - { 1F83 } { 1FBC } - { 1F84 } { 1FBC } - { 1F85 } { 1FBC } - { 1F86 } { 1FBC } - { 1F87 } { 1FBC } - { 1F88 } { 1FBC } - { 1F89 } { 1FBC } - { 1F8A } { 1FBC } - { 1F8B } { 1FBC } - { 1F8C } { 1FBC } - { 1F8D } { 1FBC } - { 1F8E } { 1FBC } - { 1F8F } { 1FBC } - { 1F90 } { 1FCC } - { 1F91 } { 1FCC } - { 1F92 } { 1FCC } - { 1F93 } { 1FCC } - { 1F94 } { 1FCC } - { 1F95 } { 1FCC } - { 1F96 } { 1FCC } - { 1F97 } { 1FCC } - { 1F98 } { 1FCC } - { 1F99 } { 1FCC } - { 1F9A } { 1FCC } - { 1F9B } { 1FCC } - { 1F9C } { 1FCC } - { 1F9D } { 1FCC } - { 1F9E } { 1FCC } - { 1F9F } { 1FCC } - { 1FA0 } { 1FFC } - { 1FA1 } { 1FFC } - { 1FA2 } { 1FFC } - { 1FA3 } { 1FFC } - { 1FA4 } { 1FFC } - { 1FA5 } { 1FFC } - { 1FA6 } { 1FFC } - { 1FA7 } { 1FFC } - { 1FA8 } { 1FFC } - { 1FA9 } { 1FFC } - { 1FAA } { 1FFC } - { 1FAB } { 1FFC } - { 1FAC } { 1FFC } - { 1FAD } { 1FFC } - { 1FAE } { 1FFC } - { 1FAF } { 1FFC } - { 1FB0 } { 1FB8 } - { 1FB1 } { 1FB9 } - { 1FB2 } { 1FBC } - { 1FB3 } { 1FBC } - { 1FB4 } { 1FBC } - { 1FB6 } { 0391 } - { 1FB7 } { 1FBC } - { 1FB8 } { 1FB8 } - { 1FB9 } { 1FB9 } - { 1FBA } { 0391 } - { 1FBB } { 0391 } - { 1FBC } { 1FBC } - { 1FBD } { 1FBD } - { 1FC2 } { 1FCC } - { 1FC3 } { 1FCC } - { 1FC4 } { 1FCC } - { 1FC6 } { 0397 } - { 1FC7 } { 1FCC } - { 1FC8 } { 0395 } - { 1FC9 } { 0395 } - { 1FCA } { 0397 } - { 1FCB } { 0397 } - { 1FCC } { 1FCC } - { 1FD0 } { 1FD8 } - { 1FD1 } { 1FD9 } - { 1FD2 } { 03AA } - { 1FD3 } { 03AA } - { 1FD6 } { 0399 } - { 1FD7 } { 03AA } - { 1FD8 } { 1FD8 } - { 1FD9 } { 1FD9 } - { 1FDA } { 0399 } - { 1FDB } { 0399 } - { 1FE0 } { 1FE8 } - { 1FE1 } { 1FE9 } - { 1FE2 } { 03AB } - { 1FE3 } { 03AB } - { 1FE4 } { 03A1 } - { 1FE5 } { 03A1 } - { 1FE6 } { 03A5 } - { 1FE7 } { 03AB } - { 1FE8 } { 1FE8 } - { 1FE9 } { 1FE9 } - { 1FEA } { 03A5 } - { 1FEB } { 03A5 } - { 1FEC } { 1FEC } - { 1FF2 } { 1FFC } - { 1FF3 } { 1FFC } - { 1FF4 } { 1FFC } - { 1FF6 } { 03A9 } - { 1FF7 } { 1FFC } - { 1FF8 } { 039F } - { 1FF9 } { 039F } - { 1FFA } { 03A9 } - { 1FFB } { 03A9 } - { 1FFC } { 1FFC } - \q_recursion_tail ? - \q_recursion_stop - } -\group_end: -% \end{macrocode} -% % The (fixed) look-up mappings for letter-like control sequences. % \begin{macrocode} \group_begin: diff --git a/macros/latex/contrib/l3kernel/l3text-map.dtx b/macros/latex/contrib/l3kernel/l3text-map.dtx index 66e8e15d8a..850ca94184 100644 --- a/macros/latex/contrib/l3kernel/l3text-map.dtx +++ b/macros/latex/contrib/l3kernel/l3text-map.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3text-purify.dtx b/macros/latex/contrib/l3kernel/l3text-purify.dtx index 8ceaa1bdc2..795e2d1524 100644 --- a/macros/latex/contrib/l3kernel/l3text-purify.dtx +++ b/macros/latex/contrib/l3kernel/l3text-purify.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % @@ -486,7 +486,7 @@ \text_declare_purify_equivalent:Nx #1 { \exp_args:Ne \@@_tmp:n - { \char_to_utfviii_bytes:n { "#2 } } + { \__kernel_codepoint_to_bytes:n { "#2 } } } \@@_loop:Nn } @@ -574,7 +574,7 @@ \cs_set:Npn \@@_tmp:n #1 { \exp_args:Ne \@@_tmp_aux:n - { \char_to_utfviii_bytes:n { "#1 } } + { \__kernel_codepoint_to_bytes:n { "#1 } } } \cs_set:Npn \@@_tmp_aux:n #1 { \@@_tmp:nnnn #1 } \cs_set:Npn \@@_tmp:nnnn #1#2#3#4 diff --git a/macros/latex/contrib/l3kernel/l3text.dtx b/macros/latex/contrib/l3kernel/l3text.dtx index 075a1d014b..0f7cad031f 100644 --- a/macros/latex/contrib/l3kernel/l3text.dtx +++ b/macros/latex/contrib/l3kernel/l3text.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % @@ -89,7 +89,7 @@ % % \section{Case changing} % -% \begin{function}[EXP, added = 2019-11-20, updated = 2020-02-24] +% \begin{function}[EXP, added = 2019-11-20, updated = 2022-10-13] % { % \text_lowercase:n, \text_uppercase:n, \text_titlecase:n, % \text_titlecase_first:n, @@ -103,8 +103,9 @@ % Takes user input \meta{text} first applies \cs{text_expand}, then % transforms the case of character tokens as specified by the % function name. The category code of letters are not changed by this -% process (at least where they can be represented by the engine as a single -% token: $8$-bit engines may require active characters). +% process when Unicode engines are used; in $8$-bit engines, case changed +% charters in the ASCII range will have the current prevailing category code, +% while those outside of it will be represented by active characters. % \end{function} % % Upper- and lowercase have the obvious meanings. Titlecasing may be regarded @@ -118,7 +119,7 @@ % Importantly, notice that these functions are intended for working with % user \emph{text for typesetting}. For case changing programmatic data see % the \pkg{l3str} module and discussion there of \cs{str_lowercase:n}, -% \cs{str_uppercase:n} and \cs{str_foldcase:n}. +% \cs{str_uppercase:n} and \cs{str_casefold:n}. % % Case changing does not take place within math mode material so for example % \begin{verbatim} @@ -129,22 +130,15 @@ % SOME TEXT $y = mx + c$ WITH {BRACES} % \end{verbatim} % -% The first maandatory argument of commands listed in +% The first mandatory argument of commands listed in % \cs{l_text_case_exclude_arg_tl} % is excluded from case changing; the latter are entirely non-textual % content (such as labels). % -% 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 +% 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|, |T2| and |LGR| font encodings. -% Thus for example \texttt{ä} can be -% case-changed using \pdfTeX{}. For \pTeX{} only the ASCII range is +% \texttt{SpecialCasing.txt}. For \pTeX{}, only the ASCII range is % covered as the engine treats input outside of this range as east Asian. % % Language-sensitive conversions are enabled using the \meta{language} @@ -173,9 +167,7 @@ % leaves accents in place. A variant \texttt{el-x-iota} is available % which retains the \textit{ypogegrammeni} (subscript muted iota) % when uppercasing: the standard version converts these to a following -% capital iota. For $8$-bit engines a simplified approach is taken -% which will remove accents when uppercasing but without full -% context analysis. +% capital iota. % \item Lithuanian (\texttt{lt}). % The lowercase letters i and j should retain a dot above when the % accents grave, acute or tilde are present. This is implemented for @@ -677,10 +669,26 @@ } \cs_new:Npn \@@_codepoint_process:nNN #1#2#3 { #1 {#2#3} } - \cs_new:Npn \@@_codepoint_process:nNNN #1#2#3#4 - { #1 {#2#3#4} } - \cs_new:Npn \@@_codepoint_process:nNNNN #1#2#3#4#5 - { #1 {#2#3#4#5} } + \sys_if_engine_ptex:TF + { + \cs_gset:Npn \@@_codepoint_process:nN #1#2 + { + \int_compare:nNnTF { `#2 } > { "80 } + { + \int_compare:nNnTF { `#2 } < { "E0 } + { \@@_codepoint_process:nNN } + { \use:n } + } + { \use:n } + {#1} #2 + } + } + { + \cs_new:Npn \@@_codepoint_process:nNNN #1#2#3#4 + { #1 {#2#3#4} } + \cs_new:Npn \@@_codepoint_process:nNNNN #1#2#3#4#5 + { #1 {#2#3#4#5} } + } } % \end{macrocode} % \end{macro} @@ -689,10 +697,11 @@ % \end{macro} % % \begin{macro}[EXP, pTF]{\@@_codepoint_compare:nNn} -% \begin{macro}[EXP]{\@@_codepoint_compare:N, \@@_codepoint_compare_aux:N} -% \begin{macro}[EXP]{\@@_codepoint_compare:NN} -% \begin{macro}[EXP]{\@@_codepoint_compare:NNN} -% \begin{macro}[EXP]{\@@_codepoint_compare:NNNN} +% \begin{macro}[EXP]{\@@_codepoint_from_chars:Nw} +% \begin{macro}[EXP]{\@@_codepoint_from_chars:N} +% \begin{macro}[EXP]{\@@_codepoint_from_chars:NN} +% \begin{macro}[EXP]{\@@_codepoint_from_chars:NNN} +% \begin{macro}[EXP]{\@@_codepoint_from_chars:NNNN} % Allows comparison for all engines using a first \enquote{character} followed % by a codepoint. % \begin{macrocode} @@ -703,51 +712,75 @@ \prg_new_conditional:Npnn \@@_codepoint_compare:nNn #1#2#3 { TF , p } { - \int_compare:nNnTF { `#1 } #2 {#3} + \int_compare:nNnTF {`#1} #2 {#3} \prg_return_true: \prg_return_false: } + \cs_new:Npn \@@_codepoint_from_chars:Nw #1 {`#1} } { \prg_new_conditional:Npnn \@@_codepoint_compare:nNn #1#2#3 { TF , p } { - \int_compare:nNnTF { \@@_codepoint_compare:N #1 } + \int_compare:nNnTF { \@@_codepoint_from_chars:Nw #1 } #2 {#3} \prg_return_true: \prg_return_false: } - \cs_new:Npn \@@_codepoint_compare:N #1 + \cs_new:Npn \@@_codepoint_from_chars:Nw #1 { \if_int_compare:w `#1 > "80 \exp_stop_f: \if_int_compare:w `#1 < "E0 \exp_stop_f: \exp_after:wN \exp_after:wN \exp_after:wN - \@@_codepoint_compare:NN + \@@_codepoint_from_chars:NN \else: \if_int_compare:w `#1 < "F0 \exp_stop_f: \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN - \exp_after:wN \@@_codepoint_compare:NNN + \exp_after:wN \@@_codepoint_from_chars:NNN \else: \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN - \exp_after:wN \@@_codepoint_compare:NNNN + \exp_after:wN \@@_codepoint_from_chars:NNNN \fi: \fi: \else: - \exp_after:wN \@@_codepoint_compare_aux:N + \exp_after:wN \@@_codepoint_from_chars:N \fi: #1 } - \cs_new:Npn \@@_codepoint_compare_aux:N #1 { `#1 } - \cs_new:Npn \@@_codepoint_compare:NN #1#2 + \cs_new:Npn \@@_codepoint_from_chars:N #1 { `#1 } + \cs_new:Npn \@@_codepoint_from_chars:NN #1#2 { (`#1 - "C0) * "40 + `#2 - "80 } - \cs_new:Npn \@@_codepoint_compare:NNN #1#2#3 - { (`#1 - "E0) * "1000 + (`#2 - "80) * "40 + `#3 - "80 } - \cs_new:Npn \@@_codepoint_compare:NNNN #1#2#3#4 + % \end{macrocode} + % Avoid high chars with p\TeX{}. + % \begin{macrocode} + \sys_if_engine_ptex:TF { - (`#1 - "F0) * "40000 - + (`#2 - "80) * "1000 - + (`#3 - "80) * "40 - + `#4 - "80 + \cs_gset:Npn \@@_codepoint_from_chars:Nw #1 + { + \if_int_compare:w `#1 > "80 \exp_stop_f: + \if_int_compare:w `#1 < "E0 \exp_stop_f: + \exp_after:wN \exp_after:wN \exp_after:wN + \@@_codepoint_from_chars:NN + \else: + \exp_after:wN \exp_after:wN \exp_after:wN + \@@_codepoint_from_chars:N + \fi: + \else: + \exp_after:wN \@@_codepoint_from_chars:N + \fi: + #1 + } + } + { + \cs_new:Npn \@@_codepoint_from_chars:NNN #1#2#3 + { (`#1 - "E0) * "1000 + (`#2 - "80) * "40 + `#3 - "80 } + \cs_new:Npn \@@_codepoint_from_chars:NNNN #1#2#3#4 + { + (`#1 - "F0) * "40000 + + (`#2 - "80) * "1000 + + (`#3 - "80) * "40 + + `#4 - "80 + } } } % \end{macrocode} @@ -756,6 +789,7 @@ % \end{macro} % \end{macro} % \end{macro} +% \end{macro} % % \subsection{Configuration variables} % @@ -793,6 +827,7 @@ { \exp_not:n { \begin \cite \end \label \ref } \exp_not:c { cite ~ } + \exp_not:n { \babelshorthand } } % \end{macrocode} % \end{variable} @@ -1144,7 +1179,8 @@ % from handling of legacy input encodings: they need to end up in a % representation we can deal with in further processing. The tests for % explicit parts of the \LaTeXe{} UTF-8 mechanism cover the case of -% bookmarks, where definitions change and are no longer protected. +% bookmarks, where definitions change and are no longer protected. The +% same is true for \pkg{babel} shorthands. % \begin{macrocode} \cs_new:Npn \@@_expand_explicit:N #1 { @@ -1161,6 +1197,7 @@ { \tl_if_head_eq_meaning_p:oN {#1} \UTFviii@two@octets } { \tl_if_head_eq_meaning_p:oN {#1} \UTFviii@three@octets } { \tl_if_head_eq_meaning_p:oN {#1} \UTFviii@four@octets } + { \tl_if_head_eq_meaning_p:oN {#1} \active@prefix } } } { \exp_after:wN \@@_expand_loop:w #1 } diff --git a/macros/latex/contrib/l3kernel/l3tl-analysis.dtx b/macros/latex/contrib/l3kernel/l3tl-analysis.dtx index 4cc0ed382c..eee5242eca 100644 --- a/macros/latex/contrib/l3kernel/l3tl-analysis.dtx +++ b/macros/latex/contrib/l3kernel/l3tl-analysis.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % diff --git a/macros/latex/contrib/l3kernel/l3tl.dtx b/macros/latex/contrib/l3kernel/l3tl.dtx index 0494e18ae5..6c129ed524 100644 --- a/macros/latex/contrib/l3kernel/l3tl.dtx +++ b/macros/latex/contrib/l3kernel/l3tl.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % @@ -450,7 +450,7 @@ % \end{syntax} % Tests if the first \meta{token} in the \meta{token list} % is an explicit space character -% (explicit token with character code~$12$ and category code~$10$). +% (explicit token with character code~$32$ and category code~$10$). % In particular, the test is \texttt{false} if the \meta{token list} % starts with an implicit token such as \cs{c_space_token}, or if it % is empty. diff --git a/macros/latex/contrib/l3kernel/l3token.dtx b/macros/latex/contrib/l3kernel/l3token.dtx index e8af4d063f..6fa3508c45 100644 --- a/macros/latex/contrib/l3kernel/l3token.dtx +++ b/macros/latex/contrib/l3kernel/l3token.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % @@ -155,26 +155,6 @@ % \end{texnote} % \end{function} % -% \begin{function}[added = 2020-01-09, EXP] -% { -% \char_lowercase:N, \char_uppercase:N, -% \char_titlecase:N, \char_foldcase:N, -% \char_str_lowercase:N, \char_str_uppercase:N, -% \char_str_titlecase:N, \char_str_foldcase:N -% } -% \begin{syntax} -% \cs{char_lowercase:N} \meta{char} -% \end{syntax} -% Converts the \meta{char} to the equivalent case-changed character -% as detailed by the function name (see \cs{str_foldcase:n} -% and \cs{text_titlecase:n} for details of these terms). The case mapping -% is carried out with no context-dependence (\emph{cf.}~\cs{text_uppercase:n}, -% \emph{etc.}) The \texttt{str} versions always generate \enquote{other} -% (category code $12$) characters, whilst the standard versions generate -% characters with the category code of the \meta{char} (i.e.~only -% the character code changes). -% \end{function} -% % \begin{variable}[added = 2011-09-05]{\c_catcode_other_space_tl} % Token list containing one character with category code $12$, % (\enquote{other}), and character code $32$ (space). @@ -1222,6 +1202,28 @@ % characters at the start of the argument are \emph{not} ignored in this % case (and they prevent brace-stripping). % +% \section{Deprecated functions} +% +% \begin{function}[added = 2020-01-09, EXP] +% { +% \char_lowercase:N, \char_uppercase:N, +% \char_titlecase:N, \char_foldcase:N, +% \char_str_lowercase:N, \char_str_uppercase:N, +% \char_str_titlecase:N, \char_str_foldcase:N +% } +% \begin{syntax} +% \cs{char_lowercase:N} \meta{char} +% \end{syntax} +% Converts the \meta{char} to the equivalent case-changed character +% as detailed by the function name (see \cs{str_foldcase:n} +% and \cs{text_titlecase:n} for details of these terms). The case mapping +% is carried out with no context-dependence (\emph{cf.}~\cs{text_uppercase:n}, +% \emph{etc.}) The \texttt{str} versions always generate \enquote{other} +% (category code $12$) characters, whilst the standard versions generate +% characters with the category code of the \meta{char} (i.e.~only +% the character code changes). +% \end{function} +% % \end{documentation} % % \begin{implementation} @@ -1690,304 +1692,78 @@ % \end{macro} % \end{macro} % -% \begin{macro}[EXP]{\char_to_utfviii_bytes:n} -% \begin{macro}[EXP]{\@@_to_utfviii_bytes_auxi:n} -% \begin{macro}[EXP]{\@@_to_utfviii_bytes_auxii:Nnn} -% \begin{macro}[EXP]{\@@_to_utfviii_bytes_auxiii:n} -% \begin{macro}[EXP] -% { -% \@@_to_utfviii_bytes_outputi:nw , -% \@@_to_utfviii_bytes_outputii:nw , -% \@@_to_utfviii_bytes_outputiii:nw , -% \@@_to_utfviii_bytes_outputiv:nw -% } -% \begin{macro}[EXP] -% {\@@_to_utfviii_bytes_output:nnn, \@@_to_utfviii_bytes_output:fnn} -% \begin{macro}[EXP]{\@@_to_utfviii_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_to_utfviii_bytes:n #1 - { - \exp_args:Nf \@@_to_utfviii_bytes_auxi:n - { \int_eval:n {#1} } - } -\cs_new:Npn \@@_to_utfviii_bytes_auxi:n #1 - { - \if_int_compare:w #1 > "80 \exp_stop_f: - \if_int_compare:w #1 < "800 \exp_stop_f: - \@@_to_utfviii_bytes_outputi:nw - { \@@_to_utfviii_bytes_auxii:Nnn C {#1} { 64 } } - \@@_to_utfviii_bytes_outputii:nw - { \@@_to_utfviii_bytes_auxiii:n {#1} } - \else: - \if_int_compare:w #1 < "10000 \exp_stop_f: - \@@_to_utfviii_bytes_outputi:nw - { \@@_to_utfviii_bytes_auxii:Nnn E {#1} { 64 * 64 } } - \@@_to_utfviii_bytes_outputii:nw - { - \@@_to_utfviii_bytes_auxiii:n - { \int_div_truncate:nn {#1} { 64 } } - } - \@@_to_utfviii_bytes_outputiii:nw - { \@@_to_utfviii_bytes_auxiii:n {#1} } - \else: - \@@_to_utfviii_bytes_outputi:nw - { - \@@_to_utfviii_bytes_auxii:Nnn F - {#1} { 64 * 64 * 64 } - } - \@@_to_utfviii_bytes_outputii:nw - { - \@@_to_utfviii_bytes_auxiii:n - { \int_div_truncate:nn {#1} { 64 * 64 } } - } - \@@_to_utfviii_bytes_outputiii:nw - { - \@@_to_utfviii_bytes_auxiii:n - { \int_div_truncate:nn {#1} { 64 } } - } - \@@_to_utfviii_bytes_outputiv:nw - { \@@_to_utfviii_bytes_auxiii:n {#1} } - \fi: - \fi: - \else: - \@@_to_utfviii_bytes_outputi:nw {#1} - \fi: - \@@_to_utfviii_bytes_end: { } { } { } { } - } -\cs_new:Npn \@@_to_utfviii_bytes_auxii:Nnn #1#2#3 - { "#10 + \int_div_truncate:nn {#2} {#3} } -\cs_new:Npn \@@_to_utfviii_bytes_auxiii:n #1 - { \int_mod:nn {#1} { 64 } + 128 } -\cs_new:Npn \@@_to_utfviii_bytes_outputi:nw - #1 #2 \@@_to_utfviii_bytes_end: #3 - { \@@_to_utfviii_bytes_output:fnn { \int_eval:n {#1} } { } {#2} } -\cs_new:Npn \@@_to_utfviii_bytes_outputii:nw - #1 #2 \@@_to_utfviii_bytes_end: #3#4 - { \@@_to_utfviii_bytes_output:fnn { \int_eval:n {#1} } { {#3} } {#2} } -\cs_new:Npn \@@_to_utfviii_bytes_outputiii:nw - #1 #2 \@@_to_utfviii_bytes_end: #3#4#5 - { - \@@_to_utfviii_bytes_output:fnn - { \int_eval:n {#1} } { {#3} {#4} } {#2} - } -\cs_new:Npn \@@_to_utfviii_bytes_outputiv:nw - #1 #2 \@@_to_utfviii_bytes_end: #3#4#5#6 - { - \@@_to_utfviii_bytes_output:fnn - { \int_eval:n {#1} } { {#3} {#4} {#5} } {#2} - } -\cs_new:Npn \@@_to_utfviii_bytes_output:nnn #1#2#3 - { - #3 - \@@_to_utfviii_bytes_end: #2 {#1} - } -\cs_generate_variant:Nn \@@_to_utfviii_bytes_output:nnn { f } -\cs_new:Npn \@@_to_utfviii_bytes_end: { } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}[rEXP]{\char_to_nfd:N} -% \begin{macro}[rEXP]{\@@_to_nfd:n, \@@_to_nfd:e} -% \begin{macro}[rEXP]{\@@_to_nfd:Nw} -% \begin{macro}[rEXP]{\char_to_nfd:n} -% \begin{macro}[rEXP]{\char_to_nfd:w} -% \begin{macro}[rEXP]{\char_nfd_generate:n} -% \begin{macro}[rEXP]{\char_nfd_generate:nnnn} -% Look up any \textsc{nfd} and recursively produce the result. Having shared -% code between Unicode and $8$-bit engines would be ideal, but this would be -% awkward as we have completely different treatment of catcodes, numbers -% of tokens, etc. The apparent saving becomes more of a headache than it's -% worth \dots -% \begin{macrocode} -\bool_lazy_or:nnTF - { \sys_if_engine_luatex_p: } - { \sys_if_engine_xetex_p: } - { - \cs_new:Npn \char_to_nfd:N #1 - { - \cs_if_exist:cTF { c_@@_nfd_ \token_to_str:N #1 _ tl } - { - \exp_after:wN \exp_after:wN \exp_after:wN \@@_to_nfd:Nw - \exp_after:wN \exp_after:wN \exp_after:wN #1 - \cs:w c_@@_nfd_ \token_to_str:N #1 _tl \cs_end: - \s_@@_stop - } - { \exp_not:n {#1} } - } - \cs_new_eq:NN \@@_to_nfd:n \char_to_nfd:N - \cs_generate_variant:Nn \@@_to_nfd:n { e } - \cs_new:Npn \@@_to_nfd:Nw #1#2#3 \s_@@_stop - { - \@@_to_nfd:e - { \char_generate:nn { `#2 } { \@@_change_case_catcode:N #1 } } - \tl_if_blank:nF {#3} - { - \@@_to_nfd:e - { \char_generate:nn { `#3 } { \char_value_catcode:n { `#3 } } } - } - } - \cs_new:Npn \char_to_nfd:n #1 - { - \@@_to_nfd:e { \char_generate:nn {#1} { \char_value_catcode:n {#1} } } - } - } - { - \cs_new:Npn \char_to_nfd:N #1 { \exp_not:n {#1} } - \cs_new:Npn \char_to_nfd:n #1 - { - \int_compare:nNnTF {#1} > { "80 } - { \exp_args:Ne \@@_to_nfd:n { \@@_nfd_generate:n {#1} } } - { \@@_nfd_generate:n {#1} } - } - \cs_new:Npn \@@_to_nfd:n #1 - { - \cs_if_exist:cTF { c_@@_nfd_ \tl_to_str:n {#1} _ tl } - { - \exp_after:wN \exp_after:wN \exp_after:wN \@@_to_nfd:w - \cs:w c_@@_nfd_ \tl_to_str:n {#1} _tl \cs_end: - \s_@@_stop - } - { \exp_not:n {#1} } - } - \cs_new:Npn \@@_to_nfd:w #1#2 \s_@@_stop - { - \@@_to_nfd:n {#1} - \tl_if_blank:nF {#2} - { \@@_to_nfd:n {#2} } - } - \cs_new:Npn \@@_nfd_generate:n #1 - { - \use:e - { - \exp_not:N \@@_nfd_generate:nnnn - \char_to_utfviii_bytes:n {#1} - } - } - \cs_new:Npn \@@_nfd_generate:nnnn #1#2#3#4 - { - \tl_if_blank:nTF {#2} - { \char_generate:nn {#1} { \char_value_catcode:n {#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_if_blank:nF {#3} - { - \exp_after:wN \exp_after:wN \exp_after:wN - \exp_not:N \char_generate:nn {#3} { 13 } - \tl_if_blank:nF {#4} - { - \exp_after:wN \exp_after:wN \exp_after:wN - \exp_not:N \char_generate:nn {#4} { 13 } - } - } - } - - } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% % \begin{macro}[EXP] % { % \char_lowercase:N, \char_uppercase:N, % \char_titlecase:N, \char_foldcase: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:nnnN} +% \begin{macro}[EXP]{\@@_change_case_auxi:nN, \@@_change_case_auxii:nN} % \begin{macro}[EXP]{\@@_change_case_catcode:N} % \begin{macro}[EXP] % { % \char_str_lowercase:N, \char_str_uppercase:N, % \char_str_titlecase:N, \char_str_foldcase:N % } -% \begin{macro}[EXP]{\@@_str_change_case:nNN} -% \begin{macro}[EXP]{\@@_str_change_case:nN} +% \begin{macro}[EXP]{\@@_str_change_case:nN, \@@_str_change_case_aux:nN} +% \begin{macro}[EXP]{\@@_str_change_case:nnnN} +% \begin{macro}[EXP]{\@@_str_change_case:n} % 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_lowercase:N #1 - { \@@_change_case:nNN { lower } \char_value_lccode:n #1 } -\cs_new:Npn \char_uppercase:N #1 - { \@@_change_case:nNN { upper } \char_value_uccode:n #1 } -\cs_new:Npn \char_titlecase:N #1 +% is re-generated even if it is otherwise unchanged. +% \begin{macrocode} +\cs_new:Npn \char_lowercase:N + { \@@_change_case:nN { lowercase } } +\cs_new:Npn \char_uppercase:N + { \@@_change_case:nN { uppercase } } +\cs_new:Npn \char_titlecase:N + { \@@_change_case:nN { titlecase } } +\cs_new:Npn \char_foldcase:N + { \@@_change_case:nN { casefold } } +\cs_new:Npn \@@_change_case:nN #1#2 { - \tl_if_exist:cTF { c_@@_titlecase_ \token_to_str:N #1 _tl } + \int_compare:nNnTF {`#2} = { `\ } + { ~ } { - \@@_change_case_multi:vN - { c_@@_titlecase_ \token_to_str:N #1 _tl } #1 + \exp_args:Ne \@@_change_case_auxi:nN + { \__kernel_codepoint_case:nn {#1} {`#2} } #2 } - { \char_uppercase:N #1 } } -\cs_new:Npn \char_foldcase:N #1 - { \@@_change_case:nNN { fold } \char_value_lccode:n #1 } -\cs_new:Npn \@@_change_case:nNN #1#2#3 +\cs_new:Npn \@@_change_case_auxi:nN #1#2 + { \use:e { \@@_change_case:nnnN #1 #2 } } +\cs_new:Npn \@@_change_case:nnnN #1#2#3#4 { - \tl_if_exist:cTF { c_@@_ #1 case_ \token_to_str:N #3 _tl } + \int_compare:nNnTF {#1} = {`#4} + { \exp_not:n {#4} } { - \@@_change_case_multi:vN - { c_@@_ #1 case_ \token_to_str:N #3 _tl } #3 + \@@_change_case_auxii:nN {#1} {#4} + \tl_if_blank:nF {#2} + { + \@@_change_case_auxii:nN {#2} {#4} + \tl_if_blank:nF {#3} + { \@@_change_case_auxii:nN {#3} {#4} } + } } - { \exp_args:Nf \@@_change_case:nN { #2 { `#3 } } #3 } } -\cs_new:Npn \@@_change_case:nN #1#2 +\cs_new:Npn \@@_change_case_auxii:nN #1#2 { - \int_compare:nNnTF {#1} = 0 - { #2 } - { \char_generate:nn {#1} { \@@_change_case_catcode:N #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 \s_@@_stop } -\cs_generate_variant:Nn \@@_change_case_multi:nN { v } -\cs_new:Npn \@@_change_case_multi:NNNNw #1#2#3#4#5 \s_@@_stop +\bool_lazy_or:nnF + { \sys_if_engine_luatex_p: } + { \sys_if_engine_xetex_p: } { - \@@_quark_if_no_value:NTF #4 + \cs_gset:Npn \@@_change_case_auxii:nN #1#2 { - \@@_quark_if_no_value:NTF #3 - { \@@_change_case:NN #1 #2 } - { \@@_change_case:NNN #1 #2#3 } + \int_compare:nNnTF {#1} < { "80 } + { + \char_generate:nn {#1} + { \@@_change_case_catcode:N #2 } + } + { \exp_not:n {#2} } } - { \@@_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 @@ -2022,47 +1798,43 @@ } % \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_lowercase:N #1 - { \@@_str_change_case:nNN { lower } \char_value_lccode:n #1 } -\cs_new:Npn \char_str_uppercase:N #1 - { \@@_str_change_case:nNN { upper } \char_value_uccode:n #1 } -\cs_new:Npn \char_str_titlecase:N #1 - { - \tl_if_exist:cTF { c_@@_titlecase_ \token_to_str:N #1 _tl } - { \tl_to_str:c { c_@@_titlecase_ \token_to_str:N #1 _tl } } - { \char_str_uppercase:N #1 } - } -\cs_new:Npn \char_str_foldcase: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 } - } +% to follow. This of course makes this version faster. +% \begin{macrocode} +\cs_new:Npn \char_str_lowercase:N + { \@@_str_change_case:nN { lowercase } } +\cs_new:Npn \char_str_uppercase:N + { \@@_str_change_case:nN { uppercase } } +\cs_new:Npn \char_str_titlecase:N + { \@@_str_change_case:nN { titlecase } } +\cs_new:Npn \char_str_foldcase:N + { \@@_str_change_case:nN { casefold } } \cs_new:Npn \@@_str_change_case:nN #1#2 { - \int_compare:nNnTF {#1} = 0 - { \tl_to_str:n {#2} } - { \char_generate:nn {#1} { 12 } } + \int_compare:nNnTF {`#2} = { `\ } + { ~ } + { + \exp_args:Ne \@@_str_change_case_aux:nN + { \__kernel_codepoint_case:nn {#1} {`#2} } #2 + } } -\bool_lazy_or:nnF - { \cs_if_exist_p:N \tex_luatexversion:D } - { \cs_if_exist_p:N \tex_XeTeXversion:D } +\cs_new:Npn \@@_str_change_case_aux:nN #1#2 + { \use:e { \@@_str_change_case:nnnN #1 #2 } } +\cs_new:Npn \@@_str_change_case:nnnN #1#2#3#4 { - \cs_set:Npn \@@_str_change_case:nN #1#2 + \int_compare:nNnTF {#1} = {`#4} + { \tl_to_str:n {#4} } { - \int_compare:nNnTF {#1} = 0 - { \tl_to_str:n {#2} } + \@@_str_change_case:n {#1} + \tl_if_blank:nF {#2} { - \int_compare:nTF { `A <= #1 <= `z } - { \char_generate:nn {#1} { 12 } } - { \tl_to_str:n {#2} } + \@@_str_change_case:n {#2} + \tl_if_blank:nF {#3} + { \@@_str_change_case:n {#3} } } } } +\cs_new:Npn \@@_str_change_case:n #1 + { \char_generate:nn {#1} { 12 } } % \end{macrocode} % \end{macro} % \end{macro} @@ -2073,9 +1845,6 @@ % \end{macro} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} % % \begin{macro}{\c_catcode_other_space_tl} % Create a space with category code $12$: an \enquote{other} space. diff --git a/macros/latex/contrib/l3kernel/l3unicode.dtx b/macros/latex/contrib/l3kernel/l3unicode.dtx index 95f410bc1e..66c1ef70ab 100644 --- a/macros/latex/contrib/l3kernel/l3unicode.dtx +++ b/macros/latex/contrib/l3kernel/l3unicode.dtx @@ -43,15 +43,72 @@ % }^^A % } % -% \date{Released 2022-11-02} +% \date{Released 2022-12-17} % % \maketitle % % \begin{documentation} % % This module provides Unicode-specific functions along with loading data -% from a range of Unicode Consortium files. At present, it provides no -% public functions. +% from a range of Unicode Consortium files. Most of the code here is +% internal, but there are a small set of public functions. These work with +% Unicode \meta{codepoints} and are designed to give useable results with +% both Unicode-aware and $8$-bit engines. +% +% \begin{function}[EXP, added = 2022-10-09, updated = 2022-11-09] +% {\codepoint_generate:nn} +% \begin{syntax} +% \cs{codepoint_generate:nn} \Arg{codepoint} \Arg{catcode} +% \end{syntax} +% Generates one or more character tokens representing the \meta{codepoint}. +% With Unicode engines, exactly one character token will be generated, and +% this will have the \meta{catcode} specified as the second argument: +% \begin{itemize} +% \item $1$ (begin group) +% \item $2$ (end group) +% \item $3$ (math toggle) +% \item $4$ (alignment) +% \item $6$ (parameter) +% \item $7$ (math superscript) +% \item $8$ (math subscript) +% \item $10$ (space) +% \item $11$ (letter) +% \item $12$ (other) +% \item $13$ (active) +% \end{itemize} +% For $8$-bit engines, between one and four character tokens will be +% produced: these will be the bytes of the UTF-8 representation of the +% \meta{codepoint}. For all codepoints outside of the classical ASCII +% range, the generated character tokens will be active (category code +% $13$); for codepoints in the ASCII range, the given \meta{catcode} +% will be used. To allow the result of this function to be used +% inside a expansion context, the result is protected by \cs{exp_not:n}. +% \end{function} +% +% \begin{function}[EXP, added = 2022-10-09] +% {\codepoint_str_generate:n} +% \begin{syntax} +% \cs{codepoint_str_generate:n} \Arg{codepoint} +% \end{syntax} +% Generates one or more character tokens representing the \meta{codepoint}. +% With Unicode engines, exactly one character token will be generated. +% For $8$-bit engines, between one and four character tokens will be +% produced: these will be the bytes of the UTF-8 representation of the +% \meta{codepoint}. All of the generated character tokens will be of +% category code $12$, except any spaces (codepoint $32$), which will be +% category code $10$. +% \end{function} +% +% \begin{function}[added = 2022-10-09, EXP]{\codepoint_to_nfd:n} +% \begin{syntax} +% \cs{codepoint_to_nfd:n} \Arg{codepoint} +% \end{syntax} +% Converts the \meta{codepoint} to the Unicode Normalization +% Form Canonical Decomposition. The generated character(s) will have +% the current category code as they would if typed in directly for Unicode +% engines; for $8$-bit engines, active characters are used for all codepoints +% outside of the ASCII range. +% \end{function} % % \end{documentation} % @@ -64,122 +121,585 @@ % \end{macrocode} % % \begin{macrocode} -%<@@=char> +%<@@=codepoint> +% \end{macrocode} +% +% \subsection{User functions} +% +% \begin{macro}[EXP]{\codepoint_str_generate:n} +% \begin{macro}[EXP]{\@@_str_generate:nnnn} +% \begin{macro}[EXP]{\codepoint_generate:nn} +% \begin{macro}[EXP]{\@@_generate:nnnn} +% \begin{macro}[EXP]{\@@_generate:n} +% Conversion of a codepoint to a character (Unicode engines) or to one +% or more bytes ($8$-bit engines) is required. For loading the data, +% all that is needed is the form which creates strings: these are outside +% the group as they will also be used when looking up data in the hash +% table storage at point-of-use. Later, we will also need functions that +% can generate character tokens for document use: those are defined below, +% in the data recovery setup. +% \begin{macrocode} +\bool_lazy_or:nnTF + { \sys_if_engine_luatex_p: } + { \sys_if_engine_xetex_p: } + { + \cs_new:Npn \codepoint_str_generate:n #1 + { + \int_compare:nNnTF {#1} = { `\ } + { ~ } + { \char_generate:nn {#1} { 12 } } + } + \cs_new:Npn \codepoint_generate:nn #1#2 + { + \int_compare:nNnTF {#1} = { `\ } + { ~ } + { + \__kernel_exp_not:w \exp_after:wN \exp_after:wN \exp_after:wN + { \char_generate:nn {#1} {#2} } + } + } + } + { + \cs_new:Npn \codepoint_str_generate:n #1 + { + \int_compare:nNnTF {#1} = { `\ } + { ~ } + { + \use:e + { + \exp_not:N \@@_str_generate:nnnn + \__kernel_codepoint_to_bytes:n {#1} + } + } + } + \cs_new:Npn \@@_str_generate:nnnn #1#2#3#4 + { + \char_generate:nn {#1} { 12 } + \tl_if_blank:nF {#2} + { + \char_generate:nn {#2} { 12 } + \tl_if_blank:nF {#3} + { + \char_generate:nn {#3} { 12 } + \tl_if_blank:nF {#4} + { \char_generate:nn {#4} { 12 } } + } + } + } + \cs_new:Npn \codepoint_generate:nn #1#2 + { + \int_compare:nNnTF {#1} = { `\ } + { ~ } + { + \int_compare:nNnTF {#1} < { "80 } + { + \__kernel_exp_not:w \exp_after:wN \exp_after:wN \exp_after:wN + { \char_generate:nn {#1} {#2} } + } + { + \use:e + { + \exp_not:N \@@_generate:nnnn + \__kernel_codepoint_to_bytes:n {#1} + } + } + } + } + \cs_new:Npn \@@_generate:nnnn #1#2#3#4 + { + \__kernel_exp_not:w \exp_after:wN + { + \tex_expanded:D + { + \@@_generate:n {#1} + \@@_generate:n {#2} + \tl_if_blank:nF {#3} + { + \@@_generate:n {#3} + \tl_if_blank:nF {#4} + { \@@_generate:n {#4} } + } + } + } + } + \cs_new:Npn \@@_generate:n #1 + { + \__kernel_exp_not:w \exp_after:wN \exp_after:wN \exp_after:wN + { \char_generate:nn {#1} { 13 } } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}[EXP]{\__kernel_codepoint_to_bytes:n} +% \begin{macro}[EXP]{\@@_to_bytes_auxi:n} +% \begin{macro}[EXP]{\@@_to_bytes_auxii:Nnn} +% \begin{macro}[EXP]{\@@_to_bytes_auxiii:n} +% \begin{macro}[EXP] +% { +% \@@_to_bytes_outputi:nw , +% \@@_to_bytes_outputii:nw , +% \@@_to_bytes_outputiii:nw , +% \@@_to_bytes_outputiv:nw +% } +% \begin{macro}[EXP] +% {\@@_to_bytes_output:nnn, \@@_to_bytes_output:fnn} +% \begin{macro}[EXP]{\@@_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 \__kernel_codepoint_to_bytes:n #1 + { + \exp_args:Nf \@@_to_bytes_auxi:n + { \int_eval:n {#1} } + } +\cs_new:Npn \@@_to_bytes_auxi:n #1 + { + \if_int_compare:w #1 > "80 \exp_stop_f: + \if_int_compare:w #1 < "800 \exp_stop_f: + \@@_to_bytes_outputi:nw + { \@@_to_bytes_auxii:Nnn C {#1} { 64 } } + \@@_to_bytes_outputii:nw + { \@@_to_bytes_auxiii:n {#1} } + \else: + \if_int_compare:w #1 < "10000 \exp_stop_f: + \@@_to_bytes_outputi:nw + { \@@_to_bytes_auxii:Nnn E {#1} { 64 * 64 } } + \@@_to_bytes_outputii:nw + { + \@@_to_bytes_auxiii:n + { \int_div_truncate:nn {#1} { 64 } } + } + \@@_to_bytes_outputiii:nw + { \@@_to_bytes_auxiii:n {#1} } + \else: + \@@_to_bytes_outputi:nw + { + \@@_to_bytes_auxii:Nnn F + {#1} { 64 * 64 * 64 } + } + \@@_to_bytes_outputii:nw + { + \@@_to_bytes_auxiii:n + { \int_div_truncate:nn {#1} { 64 * 64 } } + } + \@@_to_bytes_outputiii:nw + { + \@@_to_bytes_auxiii:n + { \int_div_truncate:nn {#1} { 64 } } + } + \@@_to_bytes_outputiv:nw + { \@@_to_bytes_auxiii:n {#1} } + \fi: + \fi: + \else: + \@@_to_bytes_outputi:nw {#1} + \fi: + \@@_to_bytes_end: { } { } { } { } + } +\cs_new:Npn \@@_to_bytes_auxii:Nnn #1#2#3 + { "#10 + \int_div_truncate:nn {#2} {#3} } +\cs_new:Npn \@@_to_bytes_auxiii:n #1 + { \int_mod:nn {#1} { 64 } + 128 } +\cs_new:Npn \@@_to_bytes_outputi:nw + #1 #2 \@@_to_bytes_end: #3 + { \@@_to_bytes_output:fnn { \int_eval:n {#1} } { } {#2} } +\cs_new:Npn \@@_to_bytes_outputii:nw + #1 #2 \@@_to_bytes_end: #3#4 + { \@@_to_bytes_output:fnn { \int_eval:n {#1} } { {#3} } {#2} } +\cs_new:Npn \@@_to_bytes_outputiii:nw + #1 #2 \@@_to_bytes_end: #3#4#5 + { + \@@_to_bytes_output:fnn + { \int_eval:n {#1} } { {#3} {#4} } {#2} + } +\cs_new:Npn \@@_to_bytes_outputiv:nw + #1 #2 \@@_to_bytes_end: #3#4#5#6 + { + \@@_to_bytes_output:fnn + { \int_eval:n {#1} } { {#3} {#4} {#5} } {#2} + } +\cs_new:Npn \@@_to_bytes_output:nnn #1#2#3 + { + #3 + \@@_to_bytes_end: #2 {#1} + } +\cs_generate_variant:Nn \@@_to_bytes_output:nnn { f } +\cs_new:Npn \@@_to_bytes_end: { } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}[EXP]{\codepoint_to_nfd:n} +% \begin{macro}[EXP]{\@@_to_nfd:nn} +% \begin{macro}[EXP]{\@@_to_nfd:nnn} +% \begin{macro}[EXP]{\@@_to_nfd:nnnn} +% \begin{macro}[EXP]{\@@_to_nfd_generate:nn} +% \begin{macro}[EXP]{\@@_to_nfd_generate:n} +% \begin{macro}[EXP]{\@@_to_nfd_generate:nnnn} +% Converted to NFD is a potentially-recursive process: the key is to +% check if we get the input codepoint back again. As far as possible, +% we use the same path for all engines. +% \begin{macrocode} +\cs_new:Npn \codepoint_to_nfd:n #1 + { \@@_to_nfd:nn {#1} { \char_value_catcode:n {#1} } } +\cs_new:Npn \@@_to_nfd:nn #1#2 + { + \exp_args:Ne \@@_to_nfd:nnn + { \@@_nfd:n {#1} } {#1} {#2} + } +\cs_new:Npn \@@_to_nfd:nnn #1#2#3 { \@@_to_nfd:nnnn #1 {#2} {#3} } +\cs_new:Npn \@@_to_nfd:nnnn #1#2#3#4 + { + \int_compare:nNnTF {#1} = {#3} + { \codepoint_generate:nn {#1} {#4} } + { + \@@_to_nfd:nn {#1} {#4} + \tl_if_blank:nF {#2} + { \@@_to_nfd:nn {#2} {#4} } + } + } % \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Data loader} % % Text operations requires data from the Unicode Consortium. Data read into % Unicode engine formats is at best a small part of what we need, so there % is a loader here to set up the appropriate data structures. % +% Where we need data for most or all of the Unicode range, we use the two-stage +% table approach recommended by the Unicode Consortium and demonstrated in a +% model implementation in Python in +% \url{https://www.strchr.com/multi-stage_tables}. This approach uses the +% \texttt{intarray} (\texttt{fontdimen}-based) data type as it is fast for +% random access and avoids significant hash table usage. In contrast, where +% only a small subset of codepoints are required, storage as macros is +% preferable. There is also some consideration of the effort needed to load +% data: see for example the grapheme breaking information, which would be +% problematic to convert into a two-stage table but which can be used with +% reasonable performance in a small number of comma lists (at the cost that +% breaking at higher codepoint Hangul characters will be slightly slow). +% +% \begin{variable}{\c_@@_block_size_int} +% Choosing the block size for the blocks in the two-stage approach is +% non-trivial: depending on the data stored, the optimal size for +% memory usage will vary. At the same time, for us there is also the +% question of load-time: larger blocks require longer comma lists +% as intermediates, so are slower. As this is going to be needed +% to use the data, we set it up outside of the group for clarity. +% \begin{macrocode} +\int_const:Nn \c_@@_block_size_int { 64 } +% \end{macrocode} +% \end{variable} +% +% Parsing the data files can be the same way for all engines, but where they +% are stored as character tokens, the construction method depends on whether +% they are Unicode or $8$-bit internally. Parsing is therefore done by common +% functions, with some data storage using engine-specific auxiliaries. +% % As only the data needs to remain at the end of this process, everything % is set up inside a group. The only thing that is outside is creating a % stream: they are global anyway and it is best to force a stream for -% all engines. For performance reasons, some of the code here is very -% low-level: the material is read during loading \pkg{expl3} in package -% mode. -% -% Parsing the data files can be the same way for all engines, but the detail -% of data storage varies depending on whether they are Unicode or $8$-bit -% internally.Parsing is therefore done by common functions, with the data -% storage usign engine-specific auxiliaries. -% -% Conversion of a codepoint to a character (Unicode engines) or to one -% or more bytes ($8$-bit engines) is required. We might need those to be -% detokenized: if not, for Unicode engines they have the current category -% code. +% all engines. +% +% \begin{variable}{\g_@@_data_ior} % \begin{macrocode} \ior_new:N \g_@@_data_ior +% \end{macrocode} +% \end{variable} +% +% We need some setup for the two-part table approach. The number of blocks we +% need will be variable, but the resulting size of the stage one table +% is predictable. For performance reasons, we therefore create the stage one +% tables now so they can be used immediately, and will later rename them as a +% constant tables. For each two-stage table construction, we need a comma +% list to hold the partial block and a couple of integers to track where +% we are up to. To avoid burning registers, the latter are stored in macros +% and are \enquote{fake} integers. We also avoid any \texttt{new} functions, +% keeping as much as possible local. +% +% As we need both positive and negative values, case data requires one +% two-stage table for each transformation. In contrasts, general Unicode +% properties could be stored in one table with appropriate combination rules: +% that is not done at present but is likely to be added over time. Here, all +% that is needed is additional entries into the comma-list to create the +% structures. +% +% Notice that in the standard \pkg{expl3} way we are indexes position not +% offset: that does mean a little work later. +% \begin{macrocode} \group_begin: - \bool_lazy_or:nnTF - { \sys_if_engine_luatex_p: } - { \sys_if_engine_xetex_p: } + \clist_map_inline:nn + { uppercase , lowercase } { - \cs_set:Npn \@@_generate_other:n #1 - { \tex_detokenize:D \tex_expandafter:D { \tex_Uchar:D #1 } } - \cs_set:Npn \@@_generate:n #1 + \cs_set_nopar:cpn { l_@@_ #1 _block_clist } { } + \cs_set_nopar:cpn { l_@@_ #1 _block_tl } { 1 } + \cs_set_nopar:cpn { l_@@_ #1 _pos_tl } { 0 } + \intarray_new:cn { g_@@_ #1 _index_intarray } + { \int_div_truncate:nn { "110000 } \c_@@_block_size_int } + } +% \end{macrocode} +% We need an integer value when matching the current block to those we have +% already seen, and a way to track codepoints for handling ranges. Again, +% we avoid using up registers or creating global names. +% \begin{macrocode} + \cs_set_nopar:Npn \l_@@_next_codepoint_fint_tl { 0 } + \cs_set_nopar:Npn \l_@@_matched_block_tl { 0 } +% \end{macrocode} +% Parse the main Unicode data file and pull out the NFD and case changing +% data. The NFD data is stored on using the hash table approach and can yield +% a predictable number of code points: one or two. We also need the case data, +% which will be modified further below. To allow for finding rangs, the +% description of the codepoint needs to be carried forward. +% \begin{macrocode} + \cs_set_protected:Npn \@@_data_auxi:w + #1 ; #2 ; #3 ; #4 ; #5 ; #6 ; #7 ; #8 ; #9 ; + { + \tl_if_blank:nF {#6} { - \tex_unexpanded:D \exp_after:wN - { \tex_Ucharcat:D #1 ~ \tex_catcode:D #1 ~ } - } + \tl_if_head_eq_charcode:nNF {#6} < % > + { \@@_data_auxii:w #1 ; #6 ~ \q_stop } + } + \@@_data_auxiii:w #1 ; #2 ; } + \cs_set_protected:Npn \@@_data_auxii:w #1 ; #2 ~ #3 \q_stop { - \cs_set:Npn \@@_generate_other:n #1 + \tl_const:cx + { c_@@_nfd_ \codepoint_str_generate:n {"#1} _tl } { - \tex_detokenize:D \tex_expandafter:D - { \tex_expanded:D { \@@_generate:n {#1} } } + {"#2} + { \tl_if_blank:nF {#3} {"#3} } } - \cs_set:Npn \@@_generate:n #1 + } +% \end{macrocode} +% The case data is going to be stored as an offset from the parent character, +% rather than an absolute value. We therefore deal with that plus the situation +% where a codepoint has no mapping data in oen shot. +% \begin{macrocode} + \cs_set_protected:Npn \@@_data_auxiii:w + #1 ; #2 ; #3 ; #4 ; #5 ; #6 ; #7 ; #8 ~ \q_stop + { + \use:e { - \use:e - { - \exp_not:N \@@_generate:nnnn - \char_to_utfviii_bytes:n {#1} - } + \@@_data_auxiv:w + #1 ; #2 ; + \@@_data_offset:nn {#1} {#6} ; + \@@_data_offset:nn {#1} {#7} ; + #8; + } + } + \cs_set:Npn \@@_data_offset:nn #1#2 + { + \tl_if_blank:nTF {#2} + { 0 } + { \int_eval:n { "#2 - "#1 } } + } +% \end{macrocode} +% To deal with ranges, we track the position of the next codepoint expected. +% If there is a gap, we deal with that separately: it could be a range or +% an unused part of the Unicode space. As such, we deal with the current +% codepoint here whether or not there is range to fill in. Upper- and +% lowercase data go into the two-stage table, any titlecase exception is +% just stored in a macro. The data for the codepoint is added to the current +% block, and if that is now complete we move on to save the block. The +% case exceptions are all stored as codepoints, with a fixed number of +% balanced text as we know that there are never more than three. +% \begin{macrocode} + \cs_set_protected:Npn \@@_data_auxiv:w #1 ; #2 ; #3 ; #4 ; #5 ; + { + \int_compare:nNnT {"#1} > \l_@@_next_codepoint_fint_tl + { + \@@_data_auxvi:nnnw {#1} {#3} {#4} + #2 Last> \q_stop } - \cs_set:Npn \@@_generate:nnnn #1#2#3#4 + \@@_add:nn { uppercase } {#3} + \@@_add:nn { lowercase } {#4} + \int_compare:nNnF {#3} = { \@@_data_offset:nn {#1} {#5} } + { + \tl_const:cx + { c_@@_titlecase_ \codepoint_str_generate:n {"#1} _tl } + { {"#5} { } { } } + } + \tl_set:Nx \l_@@_next_codepoint_fint_tl + { \int_eval:n { "#1 + 1 } } + } + \cs_set_protected:Npn \@@_add:nn #1#2 + { + \clist_put_right:cn { l_@@_ #1 _block_clist } {#2} + \int_compare:nNnT { \clist_count:c { l_@@_ #1 _block_clist } } + = \c_@@_block_size_int + { \@@_save_blocks:nn {#1} { 1 } } + } +% \end{macrocode} +% Distinguish between a range and a gap, and pass on the appropriate value(s). +% \begin{macrocode} + \cs_set_protected:Npn \@@_data_auxvi:nnnw #1#2#3#4 Last> #5 \q_stop + { + \tl_if_blank:nTF {#5} + { + \@@_range:nnn {#1} { uppercase } { 0 } + \@@_range:nnn {#1} { lowercase } { 0 } + } + { + \@@_range:nnn {#1} { uppercase } {#2} + \@@_range:nnn {#1} { lowercase } {#3} + } + } +% \end{macrocode} +% Calculated the length of the range and the space remaining in the current +% block. +% \begin{macrocode} + \cs_set_protected:Npn \@@_range:nnn #1 + { + \exp_args:Nf \@@_range_aux:nnn + { \int_eval:n { "#1 - \l_@@_next_codepoint_fint_tl } } + } + \cs_set_protected:Npn \@@_range_aux:nnn #1#2 + { + \exp_args:Nf \@@_range:nnnn { - \tex_unexpanded:D \exp_after:wN \exp_after:wN \exp_after:wN - { \char_generate:nn {#1} { 13 } } - \tl_if_blank:nF {#2} + \int_min:nn + {#1} { - \tex_unexpanded:D \exp_after:wN \exp_after:wN \exp_after:wN - { \char_generate:nn {#2} { 13 } } - \tl_if_blank:nF {#3} - { - \tex_unexpanded:D \exp_after:wN \exp_after:wN \exp_after:wN - { \char_generate:nn {#3} { 13 } } - \tl_if_blank:nF {#4} - { - \tex_unexpanded:D - \exp_after:wN \exp_after:wN \exp_after:wN - { \char_generate:nn {#4} { 13 } } - } - } + \c_@@_block_size_int + - \clist_count:c { l_@@_ #2 _block_clist } } } + {#1} {#2} } % \end{macrocode} -% Parse the main Unicode data file for two things. First, we want the titlecase -% exceptions: the one-to-one lower- and uppercase mappings it contains are all -% be covered by the \TeX{} data. Second, we need normalization data: at present, -% just the canonical \textsc{nfd} mappings. Those all yield either one or two -% codepoints, so the split is relatively easy. +% Here we want to do three things: add to and possibly complete the current +% block, add complete blocks quickly, then finish up the range in a final +% open block. We need to avoid as far as possible avoid dealing with ever +% single codepoint, so the middle step is optimised. % \begin{macrocode} - \cs_set_protected:Npn \@@_data_auxi:w - #1 ; #2 ; #3 ; #4 ; #5 ; #6 ; #7 ; #8 ; #9 ; + \cs_set_protected:Npn \@@_range:nnnn #1#2#3#4 { - \tl_if_blank:nF {#6} - { - \tl_if_head_eq_charcode:nNF {#6} < % > - { \@@_data_auxii:w #1 ; #6 ~ \q_stop } + \prg_replicate:nn {#1} + { \clist_put_right:cn { l_@@_ #3 _block_clist } {#4} } + \int_compare:nNnT { \clist_count:c { l_@@_ #3 _block_clist } } + = \c_@@_block_size_int + { \@@_save_blocks:nn {#3} { 1 } } + \int_compare:nNnF + { \int_div_truncate:nn { #2 - #1 } \c_@@_block_size_int } = 0 + { + \tl_set:cx { l_@@_ #3 _block_clist } + { + \exp_args:NNe \use:nn \use_none:n + { \prg_replicate:nn { \c_@@_block_size_int } { , #4 } } + } + \@@_save_blocks:nn {#3} + { \int_div_truncate:nn { (#2 - #1) } \c_@@_block_size_int } } - \@@_data_auxiii:w #1 ; + \prg_replicate:nn + { \int_mod:nn { #2 - #1 } \c_@@_block_size_int } + { \clist_put_right:cx { l_@@_ #3 _block_clist } {#4} } } - \cs_set_protected:Npn \@@_data_auxii:w #1 ; #2 ~ #3 \q_stop +% \end{macrocode} +% To allow rapid comparison, each completed block is stored locally as a +% comma list: once all of the blocks have been created, they are converted +% into an \texttt{intarray} in one step. The aim here is to check the current +% block against those we've already used, and either match to an existing +% block or save a new block. +% \begin{macrocode} + \cs_set_protected:Npn \@@_save_blocks:nn #1#2 { - \tl_const:cx - { c_@@_nfd_ \@@_generate_other:n { "#1 } _tl } + \tl_set_eq:Nc \l_@@_matched_block_tl { l_@@_ #1 _block_tl } + \int_step_inline:nn { \tl_use:c { l_@@_ #1 _block_tl } - 1 } { - { \@@_generate:n { "#2 } } + \tl_if_eq:ccT { l_@@_ #1 _block_clist } + { l_@@_ #1 _block_ ##1 _clist } + { \tl_set:Nn \l_@@_matched_block_tl {##1} } + } + \int_compare:nNnT + { \tl_use:c { l_@@_ #1 _block_tl } } = \l_@@_matched_block_tl { - \tl_if_blank:nF {#3} - { \@@_generate:n { "#3 } } - } + \clist_set_eq:cc + { + l_@@_ #1 _block_ + \tl_use:c { l_@@_ #1 _block_tl } _clist + } + { l_@@_ #1 _block_clist } + \tl_set:cx { l_@@_ #1 _block_tl } + { \int_eval:n { \tl_use:c { l_@@_ #1 _block_tl } + 1 } } + } + \prg_replicate:nn {#2} + { + \tl_set:cx { l_@@_ #1 _pos_tl } + { \int_eval:n { \tl_use:c { l_@@_ #1 _pos_tl } + 1 } } + \exp_args:Nc \__kernel_intarray_gset:Nnn + { g_@@_ #1 _index_intarray } + { \tl_use:c { l_@@_ #1 _pos_tl } } + \l_@@_matched_block_tl + } + \clist_clear:c { l_@@_ #1 _block_clist } + } +% \end{macrocode} +% Close out the final block, rename the first stage table, then combine all +% of the block comma-lists into one large second-stage table with offsets. +% As we use an index not an offet, there is a little back-and-forward to do. +% \begin{macrocode} + \cs_set_protected:Npn \@@_finalise_blocks: + { + \clist_map_inline:nn { uppercase , lowercase } + { + \@@_range:nnn { 110000 } {##1} { 0 } + \@@_finalise_blocks:n {##1} } + } + \cs_set_protected:Npn \@@_finalise_blocks:n #1 + { + \cs_gset_eq:cc { c_@@_ #1 _index_intarray } { g_@@_ #1 _index_intarray } + \cs_undefine:c { g_@@_ #1 _index_intarray } + \intarray_new:cn { g_@@_ #1 _blocks_intarray } + { ( \tl_use:c { l_@@_ #1 _block_tl } - 1 ) * \c_@@_block_size_int } + \int_step_inline:nn { \tl_use:c { l_@@_ #1 _block_tl } - 1 } + { + \exp_args:Nv \@@_finalise_blocks:nnn + { l_@@_ #1 _block_ ##1 _clist } + {##1} {#1} + } + \cs_gset_eq:cc { c_@@_ #1 _blocks_intarray } + { g_@@_ #1 _blocks_intarray } + \cs_undefine:c { g_@@_ #1 _blocks_intarray } } - \cs_set_protected:Npn \@@_data_auxiii:w - #1 ; #2 ; #3 ; #4 ; #5 ; #6 ; #7 ~ \q_stop + \cs_set_protected:Npn \@@_finalise_blocks:nnn #1#2#3 { - \cs_set_nopar:Npn \l_@@_tmpa_tl {#7} - \reverse_if:N \if_meaning:w \l_@@_tmpa_tl \c_empty_tl - \cs_set_nopar:Npn \l_@@_tmpb_tl {#5} - \reverse_if:N \if_meaning:w \l_@@_tmpa_tl \l_@@_tmpb_tl - \tl_const:cx - { c_@@_titlecase_ \@@_generate_other:n { "#1 } _tl } - { \@@_generate:n { "#7 } } - \fi: - \fi: + \exp_args:Nnf \@@_finalise_blocks:nnnw { 1 } + { \int_eval:n { ( #2 - 1 ) * \c_@@_block_size_int } } + {#3} + #1 , \q_recursion_tail , \q_recursion_stop + } + \cs_set_protected:Npn \@@_finalise_blocks:nnnw #1#2#3#4 , + { + \quark_if_recursion_tail_stop:n {#4} + \intarray_gset:cnn { g_@@_ #3 _blocks_intarray } + { #1 + #2 } + {#4} + \exp_args:Nf \@@_finalise_blocks:nnnw + { \int_eval:n { #1 + 1 } } {#2} {#3} } +% \end{macrocode} +% With the setup done, read the main data file: it's easiest to do that as +% a token list with spaces retained. +% \begin{macrocode} \ior_open:Nn \g_@@_data_ior { UnicodeData.txt } \group_begin: \char_set_catcode_space:n { `\ }% @@ -190,8 +710,48 @@ \fi: \exp_after:wN \@@_data_auxi:w \l_@@_tmpa_tl \q_stop }% + \@@_finalise_blocks: \group_end: +\group_end: +% \end{macrocode} +% +% \begin{macro}[EXP]{\__kernel_codepoint_data:nn} +% \begin{macro}[EXP]{\@@_data:nnn} +% Recover data from a two-stage table: entirely generic as this applies to +% all tables (as we use the same block size for all of them). Notice that +% as we use indices not offsets we have to shuffle out-by-one issues. This +% function is needed \emph{before} loading the special casing data, as there +% we need to be able to check the standard case mappings. +% \begin{macrocode} +\cs_new:Npn \__kernel_codepoint_data:nn #1#2 + { + \exp_args:Nf \@@_data:nnn + { + \int_eval:n + { + \c_@@_block_size_int * + ( + \intarray_item:cn { c_@@_ #1 _index_intarray } + { + \int_div_truncate:nn {#2} + \c_@@_block_size_int + + 1 + } + - 1 + ) + } + } + {#2} {#1} + } +\cs_new:Npn \@@_data:nnn #1#2#3 + { + \intarray_item:cn { c_@@_ #3 _blocks_intarray } + { #1 + \int_mod:nn {#2} \c_@@_block_size_int + 1 } + } % \end{macrocode} +% \end{macro} +% \end{macro} +% % The other data files all use C-style comments so we have to worry about % |#| tokens (and reading as strings). The set up for case folding is in two % parts. For the basic (core) mappings, folding is the same as lower casing in @@ -199,15 +759,17 @@ % always store the result, splitting up the two or three code points in the input % as required. % \begin{macrocode} +\group_begin: \ior_open:Nn \g_@@_data_ior { CaseFolding.txt } \cs_set_protected:Npn \@@_data_auxi:w #1 ;~ #2 ;~ #3 ; #4 \q_stop { \if:w \tl_head:n { #2 ? } C \reverse_if:N \if_int_compare:w - \char_value_lccode:n {"#1} = "#3 ~ + \int_eval:n { \__kernel_codepoint_data:nn { lowercase } {"#1} + "#1 } + = "#3 ~ \tl_const:cx - { c_@@_foldcase_ \@@_generate_other:n { "#1 } _tl } - { \@@_generate:n { "#3 } } + { c_@@_casefold_ \codepoint_str_generate:n {"#1} _tl } + { {"#3} { } { } } \fi: \else: \if:w \tl_head:n { #2 ? } F @@ -215,25 +777,17 @@ \fi: \fi: } - \bool_lazy_or:nnF - { \sys_if_engine_luatex_p: } - { \sys_if_engine_xetex_p: } - { - \cs_set_protected:Npn \@@_data_auxi:w #1 ;~ #2 ;~ #3 ; #4 \q_stop - { - \if:w \tl_head:n { #2 ? } F - \@@_data_auxii:w #1 ~ #3 ~ \q_stop - \fi: - } - } +% \end{macrocode} +% Here, |#4| can have have a trailing space, so we tidy up a bit at the cost of +% speed for these small number of cases it applies to. +% \begin{macrocode} \cs_set_protected:Npn \@@_data_auxii:w #1 ~ #2 ~ #3 ~ #4 \q_stop { - \tl_const:cx { c_@@_foldcase_ \@@_generate_other:n { "#1 } _tl } + \tl_const:cx { c_@@_casefold_ \codepoint_str_generate:n {"#1} _tl } { - \@@_generate:n { "#2 } - \@@_generate:n { "#3 } - \tl_if_blank:nF {#4} - { \@@_generate:n { \int_value:w "#4 } } + {"#2} + {"#3} + { \tl_if_blank:nF {#4} { " \int_to_Hex:n {"#4} } } } } \ior_str_map_inline:Nn \g_@@_data_ior @@ -245,7 +799,7 @@ \ior_close:N \g_@@_data_ior % \end{macrocode} % For upper- and lowercasing special situations, there is a bit more to -% do as we also have title casing to consider, plus we need to stop part-way +% do as we also have titlecasing to consider, plus we need to stop part-way % through the file. % \begin{macrocode} \ior_open:Nn \g_@@_data_ior { SpecialCasing.txt } @@ -262,12 +816,11 @@ { \tl_if_empty:nF {#4} { - \tl_const:cx { c_@@_ #2 case_ \@@_generate_other:n { "#1 } _tl } + \tl_const:cx { c_@@_ #2 case_ \codepoint_str_generate:n {"#1} _tl } { - \@@_generate:n { "#3 } - \@@_generate:n { "#4 } - \tl_if_blank:nF {#5} - { \@@_generate:n { "#5 } } + {"#3} + {"#4} + { \tl_if_blank:nF {#5} {"#5} } } } } @@ -284,9 +837,64 @@ } \ior_close:N \g_@@_data_ior \group_end: - % \end{macrocode} % +% \begin{macro}[EXP]{\__kernel_codepoint_case:nn} +% \begin{macro}[EXP]{\@@_case:nnn} +% \begin{macro}[EXP] +% {\@@_uppercase:n, \@@_lowercase:n, \@@_titlecase:n, \@@_casefold:n} +% \begin{macro}[EXP]{\@_case:nn} +% With the core data files loaded, there is now a need to provide access to +% this information for other modules. That is done here such that case +% folding can also be covered. At this level, all that needs to be returned +% is the +% \begin{macrocode} +\cs_new:Npn \__kernel_codepoint_case:nn #1#2 + { + \exp_args:Ne \@@_case:nnn + { \codepoint_str_generate:n {#2} } {#1} {#2} + } +\cs_new:Npn \@@_case:nnn #1#2#3 + { + \cs_if_exist:cTF { c_@@_ #2 _ #1 _tl } + { + \tl_use:c + { c_@@_ #2 _ #1 _tl } + } + { \use:c { @@_ #2 :n } {#3} } + } +\cs_new:Npn \@@_uppercase:n { \@@_case:nn { uppercase } } +\cs_new:Npn \@@_lowercase:n { \@@_case:nn { lowercase } } +\cs_new:Npn \@@_titlecase:n { \@@_case:nn { uppercase } } +\cs_new:Npn \@@_casefold:n { \@@_case:nn { lowercase } } +\cs_new:Npn \@@_case:nn #1#2 + { + { \int_eval:n { \__kernel_codepoint_data:nn {#1} {#2} + #2 } } + { } + { } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_nfd:n} +% \begin{macro}[EXP]{\@@_nfd:nn} +% A simple interface. +% \begin{macrocode} +\cs_new:Npn \@@_nfd:n #1 + { \exp_args:Ne \@@_nfd:nn { \codepoint_str_generate:n {#1} } {#1} } +\cs_new:Npn \@@_nfd:nn #1#2 + { + \tl_if_exist:cTF { c_@@_nfd_ #1 _tl } + { \tl_use:c { c_@@_nfd_ #1 _tl } } + { {#2} { } } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% % \begin{macrocode} %<@@=text> % \end{macrocode} diff --git a/macros/latex/contrib/l3kernel/source3.pdf b/macros/latex/contrib/l3kernel/source3.pdf Binary files differindex 14ca0f529d..1e3645636b 100644 --- a/macros/latex/contrib/l3kernel/source3.pdf +++ b/macros/latex/contrib/l3kernel/source3.pdf diff --git a/macros/latex/contrib/l3kernel/source3.tex b/macros/latex/contrib/l3kernel/source3.tex index 5a393bc8cd..55bfaf3a35 100644 --- a/macros/latex/contrib/l3kernel/source3.tex +++ b/macros/latex/contrib/l3kernel/source3.tex @@ -53,7 +53,7 @@ for those people who are interested. {latex-team@latex-project.org}% }% } -\date{Released 2022-11-02} +\date{Released 2022-12-17} \pagenumbering{roman} \maketitle diff --git a/macros/latex/contrib/l3packages/CHANGELOG.md b/macros/latex/contrib/l3packages/CHANGELOG.md index c94596cd96..06ebdc8c0c 100644 --- a/macros/latex/contrib/l3packages/CHANGELOG.md +++ b/macros/latex/contrib/l3packages/CHANGELOG.md @@ -7,6 +7,12 @@ this project uses date-based 'snapshot' version identifiers. ## [Unreleased] +## [2022-12-17] + +### Fixed +- Template editing following restricted template setting + (issue [\#1155](https://github.com/latex3/latex3/issues/1155)) + ## [2022-06-22] ### Changed @@ -24,7 +30,7 @@ this project uses date-based 'snapshot' version identifiers. ### Fixed - Space stripping from `xtemplate` key types -- Fix `log-declarations=true` (gh/1095) +- Fix `log-declarations=true` (issue [\#1095](https://github.com/latex3/latex3/issues/1095)) ## [2022-05-30] @@ -200,7 +206,8 @@ this project uses date-based 'snapshot' version identifiers. - Switch to ISO date format - Improve cross-module use of internal functions -[Unreleased]: https://github.com/latex3/latex3/compare/2022-06-22...HEAD +[Unreleased]: https://github.com/latex3/latex3/compare/2022-12-17...HEAD +[2022-12-17]: https://github.com/latex3/latex3/compare/2022-06-22...2022-12-17 [2022-06-22]: https://github.com/latex3/latex3/compare/2022-06-16...2022-06-22 [2022-06-16]: https://github.com/latex3/latex3/compare/2022-06-07...2022-06-16 [2022-06-07]: https://github.com/latex3/latex3/compare/2022-05-30...2022-06-07 diff --git a/macros/latex/contrib/l3packages/README.md b/macros/latex/contrib/l3packages/README.md index d1d8a46ad2..e85056ab5b 100644 --- a/macros/latex/contrib/l3packages/README.md +++ b/macros/latex/contrib/l3packages/README.md @@ -1,7 +1,7 @@ LaTeX3 High-Level Concepts ========================== -Release 2022-06-22 +Release 2022-12-17 Overview -------- diff --git a/macros/latex/contrib/l3packages/l3keys2e.dtx b/macros/latex/contrib/l3packages/l3keys2e.dtx index 17ce052261..880bc42c92 100644 --- a/macros/latex/contrib/l3packages/l3keys2e.dtx +++ b/macros/latex/contrib/l3packages/l3keys2e.dtx @@ -62,7 +62,7 @@ % }^^A % } % -% \date{Released 2022-06-22} +% \date{Released 2022-12-17} % % \maketitle % @@ -154,7 +154,7 @@ % \end{macrocode} % % \begin{macrocode} -\ProvidesExplPackage{l3keys2e}{2022-06-22}{} +\ProvidesExplPackage{l3keys2e}{2022-12-17}{} {LaTeX2e option processing using LaTeX3 keys} % \end{macrocode} % diff --git a/macros/latex/contrib/l3packages/l3keys2e.pdf b/macros/latex/contrib/l3packages/l3keys2e.pdf Binary files differindex 5ce8f8ae43..735bcf8231 100644 --- a/macros/latex/contrib/l3packages/l3keys2e.pdf +++ b/macros/latex/contrib/l3packages/l3keys2e.pdf diff --git a/macros/latex/contrib/l3packages/xfp.dtx b/macros/latex/contrib/l3packages/xfp.dtx index 8020d390fc..e25de010aa 100644 --- a/macros/latex/contrib/l3packages/xfp.dtx +++ b/macros/latex/contrib/l3packages/xfp.dtx @@ -63,7 +63,7 @@ % }^^A % } % -% \date{Released 2022-06-22} +% \date{Released 2022-12-17} % % \maketitle % @@ -171,7 +171,7 @@ % \end{macrocode} % % \begin{macrocode} -\ProvidesExplPackage{xfp}{2022-06-22}{} +\ProvidesExplPackage{xfp}{2022-12-17}{} {L3 Floating point unit} % \end{macrocode} % diff --git a/macros/latex/contrib/l3packages/xfp.pdf b/macros/latex/contrib/l3packages/xfp.pdf Binary files differindex 541e32926b..e8523ffd3a 100644 --- a/macros/latex/contrib/l3packages/xfp.pdf +++ b/macros/latex/contrib/l3packages/xfp.pdf diff --git a/macros/latex/contrib/l3packages/xfrac.dtx b/macros/latex/contrib/l3packages/xfrac.dtx index 5376dd4085..99b45ad337 100644 --- a/macros/latex/contrib/l3packages/xfrac.dtx +++ b/macros/latex/contrib/l3packages/xfrac.dtx @@ -65,7 +65,7 @@ % }^^A % } % -% \date{Released 2022-06-22} +% \date{Released 2022-12-17} % % \maketitle % @@ -535,7 +535,7 @@ % \end{macrocode} % % \begin{macrocode} -\ProvidesExplPackage{xfrac}{2022-06-22}{} +\ProvidesExplPackage{xfrac}{2022-12-17}{} {L3 Experimental split-level fractions} % \end{macrocode} % diff --git a/macros/latex/contrib/l3packages/xfrac.pdf b/macros/latex/contrib/l3packages/xfrac.pdf Binary files differindex a576f51ba2..97f5e08f86 100644 --- a/macros/latex/contrib/l3packages/xfrac.pdf +++ b/macros/latex/contrib/l3packages/xfrac.pdf diff --git a/macros/latex/contrib/l3packages/xparse.dtx b/macros/latex/contrib/l3packages/xparse.dtx index c70bf08cf5..d0d70d2740 100644 --- a/macros/latex/contrib/l3packages/xparse.dtx +++ b/macros/latex/contrib/l3packages/xparse.dtx @@ -67,7 +67,7 @@ % }^^A % } % -% \date{Released 2022-06-22} +% \date{Released 2022-12-17} % % \maketitle % @@ -1064,7 +1064,7 @@ % \end{macrocode} % % \begin{macrocode} -\ProvidesExplPackage{xparse}{2022-06-22}{} +\ProvidesExplPackage{xparse}{2022-12-17}{} {L3 Experimental document command parser} % \end{macrocode} % diff --git a/macros/latex/contrib/l3packages/xparse.pdf b/macros/latex/contrib/l3packages/xparse.pdf Binary files differindex c94d4cbaea..e597824008 100644 --- a/macros/latex/contrib/l3packages/xparse.pdf +++ b/macros/latex/contrib/l3packages/xparse.pdf diff --git a/macros/latex/contrib/l3packages/xtemplate.dtx b/macros/latex/contrib/l3packages/xtemplate.dtx index afd33bf380..75f8e78ee4 100644 --- a/macros/latex/contrib/l3packages/xtemplate.dtx +++ b/macros/latex/contrib/l3packages/xtemplate.dtx @@ -5,7 +5,7 @@ % Copyright (C) 1999 Frank Mittelbach, Chris Rowley, David Carlisle % (C) 2004-2010 Frank Mittelbach, The LaTeX Project % (C) 2011-2022 The LaTeX Project -% +%\ % It may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this % license or (at your option) any later version. The latest version @@ -63,7 +63,7 @@ % }^^A % } % -% \date{Released 2022-06-22} +% \date{Released 2022-12-17} % % \maketitle % @@ -706,7 +706,7 @@ % \end{macrocode} % % \begin{macrocode} -\ProvidesExplPackage{xtemplate}{2022-06-22}{} +\ProvidesExplPackage{xtemplate}{2022-12-17}{} {L3 Experimental prototype document functions} % \end{macrocode} % @@ -1830,6 +1830,7 @@ \@@_set_template_eq:nn { #1 / #3 } { #1 / #2 } \bool_set_true:N \l_@@_restrict_bool \@@_edit_defaults_aux:nnn {#1} {#3} {#4} + \bool_set_false:N \l_@@_restrict_bool } } % \end{macrocode} diff --git a/macros/latex/contrib/l3packages/xtemplate.pdf b/macros/latex/contrib/l3packages/xtemplate.pdf Binary files differindex 2c4fff1dd3..f15040a73a 100644 --- a/macros/latex/contrib/l3packages/xtemplate.pdf +++ b/macros/latex/contrib/l3packages/xtemplate.pdf |