summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/l3kernel/l3text-case.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/l3kernel/l3text-case.dtx')
-rw-r--r--macros/latex/contrib/l3kernel/l3text-case.dtx693
1 files changed, 604 insertions, 89 deletions
diff --git a/macros/latex/contrib/l3kernel/l3text-case.dtx b/macros/latex/contrib/l3kernel/l3text-case.dtx
index 3f8f381063..fd41c6bdd3 100644
--- a/macros/latex/contrib/l3kernel/l3text-case.dtx
+++ b/macros/latex/contrib/l3kernel/l3text-case.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2020-10-05}
+% \date{Released 2020-10-27}
%
% \maketitle
%
@@ -155,6 +155,9 @@
% \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}
% \begin{macro}[EXP]
@@ -206,6 +209,7 @@
\cs_new:Npn \@@_change_case_aux:nnn #1#2#3
{
\group_align_safe_begin:
+ \cs_if_exist_use:c { @@_change_case_boundary_ #2 _ #3 :Nnnw }
\@@_change_case_loop:nnw {#2} {#3} #1
\q_@@_recursion_tail \q_@@_recursion_stop
\@@_change_case_result:n { }
@@ -296,6 +300,7 @@
}
{
\@@_change_case_store:n { ~ }
+ \cs_if_exist_use:c { @@_change_case_boundary_ #1 _ #2 :Nnnw }
\@@_change_case_loop:nnw {#1} {#2}
}
% \end{macrocode}
@@ -461,16 +466,10 @@
% is there the special case of a terminal sigma. If not, then we pass to
% a simple character mapping.
% \begin{macrocode}
-\cs_new:Npx \@@_change_case_char_lower:nnN #1#2#3
+\cs_new:Npn \@@_change_case_char_lower:nnN #1#2#3
{
- \exp_not:N \cs_if_exist_use:cF { @@_change_case_lower_ #2 :nnnN }
- {
- \bool_lazy_or:nnTF
- { \sys_if_engine_luatex_p: }
- { \sys_if_engine_xetex_p: }
- { \exp_not:N \@@_change_case_lower_sigma:nnnN }
- { \exp_not:N \@@_change_case_char:nnnN }
- }
+ \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
@@ -485,7 +484,7 @@
% then there is a look-ahead phase: the logic here is simply based on letters.
% The one exception is Dutch: see below.
% \begin{macrocode}
-\bool_lazy_or:nnT
+\bool_lazy_or:nnTF
{ \sys_if_engine_luatex_p: }
{ \sys_if_engine_xetex_p: }
{
@@ -518,6 +517,48 @@
}
}
% \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
+ {
+ \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
+ {
+ \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 } }
+ }
+ { \@@_change_case_store:V \c_@@_sigma_tl }
+ { \@@_change_case_store:V \c_@@_final_sigma_tl }
+ \@@_change_case_loop:nnw {#1} {#2} #3
+ }
+ }
+% \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
@@ -664,6 +705,9 @@
% \end{macro}
% \end{macro}
% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
%
% \begin{macro}[EXP]{\@@_change_case_upper_de-alt:nnnN}
% \begin{macro}[EXP]{\@@_change_case_upper_de-alt:nnnNN}
@@ -710,16 +754,28 @@
% \end{macro}
%
% \begin{macro}[EXP]{\@@_change_case_upper_el:nnnN}
-% \begin{macro}[EXP]{\@@_change_case_upper_el:nnnn}
-% \begin{macro}[EXP]{\@@_change_case_upper_el_aux:nnnN}
-% \begin{macro}[EXP]{\@@_change_case_upper_el_loop:nnw}
-% \begin{macro}[EXP]{\@@_change_case_upper_el:nnN}
-% \begin{macro}[EXP]{\@@_change_case_if_greek:nTF}
+% \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_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_gobble:nnw}
+% \begin{macro}[EXP]{\@@_change_case_upper_el_gobble:nnN}
+% \begin{macro}[EXP,TF]{\@@_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,pTF]{\@@_change_case_if_greek_diacritic:n}
+% \begin{macro}[EXP,TF]{\@@_change_case_if_takes_dialytika: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
% need to be found \emph{after} any U+0308 (diaeresis) and are done in two
-% groups to allow for the canonical ordering.
+% groups to allow for the canonical ordering. The implementation here follows
+% the data and examples from ICU
+% (\url{https://sites.google.com/site/icusite/design/case/greek-upper}),
+% although necessarily the implementation is somewhat different.
% \begin{macrocode}
\bool_lazy_or:nnT
{ \sys_if_engine_luatex_p: }
@@ -729,97 +785,233 @@
{
\@@_change_case_if_greek:nTF { `#4 }
{
- \exp_args:Ne \@@_change_case_upper_el:nnnn
- { \char_to_nfd:N #4 } {#1} {#2} {#3}
+ \exp_args:Ne \@@_change_case_upper_el:nnn
+ { \char_to_nfd:N #4 } {#2} {#3}
}
{ \@@_change_case_char:nnnN {#1} {#2} {#3} #4 }
}
- \cs_new:Npn \@@_change_case_upper_el:nnnn #1#2#3#4
- { \@@_change_case_upper_el_aux:nnnN {#2} {#3} {#4} #1 }
- \cs_new:Npn \@@_change_case_upper_el_aux:nnnN #1#2#3#4
- {
- \@@_change_case_store:e { \use:c { char_ #1 case:N } #4 }
- \@@_change_case_upper_el_loop:nnw {#2} {#3}
- }
- \cs_new:Npn \@@_change_case_upper_el_loop:nnw
- #1#2#3 \q_@@_recursion_stop
+ \cs_new:Npn \@@_change_case_upper_el:nnn #1#2#3
+ { \@@_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
+% 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
{
- \tl_if_head_is_N_type:nTF {#3}
- { \@@_change_case_upper_el:nnN }
- { \@@_change_case_loop:nnw }
- {#1} {#2} #3 \q_@@_recursion_stop
+ \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
}
% \end{macrocode}
-% In addition to the Greek accents, we list three cases here where an
-% accent outside the Greek range has a \text{nfd} that would make it
-% equivalent. That includes U+0344, which has to insert U+0308.
+% 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.
+% (The latter do not have the same hiatus behavior as accents.)
% \begin{macrocode}
- \cs_new:Npn \@@_change_case_upper_el:nnN #1#2#3
+ \cs_new:Npn \@@_change_case_upper_el:NnnN #1#2#3#4
{
- \token_if_cs:NTF #3
- { \@@_change_case_loop:nnw {#1} {#2} #3 }
+ \token_if_cs:NTF #4
{
- \int_compare:nNnTF { `#3 } = { "0308 }
- {
- \@@_change_case_store:n {#3}
- \@@_change_case_upper_el_loop:nnw {#1} {#2}
- }
+ \@@_change_case_store:e { \char_uppercase:N #1 }
+ \@@_change_case_loop:nnw {#2} {#3} #4
+ }
+ {
+ \int_compare:nNnTF { `#4 } = { "0308 }
+ { \@@_change_case_upper_el_dialytika:nnN {#2} {#3} #1 }
{
- \bool_lazy_any:nTF
+ \@@_change_case_if_greek_accent:nTF { `#4 }
+ { \@@_change_case_upper_el_hiatus:nnNw {#2} {#3} #1 }
{
- { \int_compare_p:nNn { `#3 } = { "0300 } }
- { \int_compare_p:nNn { `#3 } = { "0301 } }
- { \int_compare_p:nNn { `#3 } = { "0304 } }
- { \int_compare_p:nNn { `#3 } = { "0306 } }
- { \int_compare_p:nNn { `#3 } = { "0308 } }
- { \int_compare_p:nNn { `#3 } = { "0313 } }
- { \int_compare_p:nNn { `#3 } = { "0314 } }
- { \int_compare_p:nNn { `#3 } = { "0342 } }
- { \int_compare_p:nNn { `#3 } = { "0340 } }
- { \int_compare_p:nNn { `#3 } = { "0341 } }
- { \int_compare_p:nNn { `#3 } = { "0343 } }
- }
- { \@@_change_case_upper_el_loop:nnw {#1} {#2} }
- {
- \int_compare:nNnTF { `#3 } = { "0344 }
+ \@@_change_case_if_greek_diacritic:nTF { `#4 }
{
- \@@_change_case_store:e
- {
- \char_generate:nn { "0308 }
- { \@@_char_catcode:N #3 }
- }
- \@@_change_case_upper_el_loop:nnw {#1} {#2}
+ \@@_change_case_store:e { \char_uppercase:N #1 }
+ \@@_change_case_loop:nnw {#2} {#3}
}
{
- \int_compare:nNnTF { `#3 } = { "0345 }
- { \@@_change_case_loop:nnw {#1} {#2} }
- { \@@_change_case_loop:nnw {#1} {#2} #3 }
+ \@@_change_case_store:e { \char_uppercase:N #1 }
+ \@@_change_case_loop:nnw {#2} {#3} #4
}
}
}
}
}
- \prg_new_conditional:Npnn \@@_change_case_if_greek:n #1 { TF }
+% \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
+ {
+ \@@_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}
+ }
+ \cs_new:Npn \@@_change_case_upper_el_dialytika:N #1
+ {
+ \@@_change_case_store:e
+ {
+ \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 } }
+ }
+ }
+% \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
+ {
+ \@@_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
+ }
+ \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_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 }
+ }
+ }
+% \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
{
- \if_int_compare:w #1 < "0370 \exp_stop_f:
+ \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} }
+ }
+ }
+% \end{macrocode}
+% Luckily the Greek range is limited and clear.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \@@_change_case_if_greek:n #1 { TF }
+ {
+ \if_int_compare:w #1 < "0370 \exp_stop_f:
+ \prg_return_false:
+ \else:
+ \if_int_compare:w #1 > "03FF \exp_stop_f:
+ \if_int_compare:w #1 < "1F00 \exp_stop_f:
\prg_return_false:
\else:
- \if_int_compare:w #1 > "03FF \exp_stop_f:
- \if_int_compare:w #1 < "1F00 \exp_stop_f:
- \prg_return_false:
+ \if_int_compare:w #1 > "1FFF \exp_stop_f:
+ \prg_return_false:
+ \else:
+ \prg_return_true:
+ \fi:
+ \fi:
+ \else:
+ \prg_return_true:
+ \fi:
+ \fi:
+ }
+% \end{macrocode}
+% We follow ICU in adding a few extras to the accent list here.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \@@_change_case_if_greek_accent:n #1 { TF , p }
+ {
+ \if_int_compare:w #1 = "0300 \exp_stop_f:
+ \prg_return_true:
+ \else:
+ \if_int_compare:w #1 = "0301 \exp_stop_f:
+ \prg_return_true:
+ \else:
+ \if_int_compare:w #1 = "0342 \exp_stop_f:
+ \prg_return_true:
+ \else:
+ \if_int_compare:w #1 = "0302 \exp_stop_f:
+ \prg_return_true:
+ \else:
+ \if_int_compare:w #1 = "0303 \exp_stop_f:
+ \prg_return_true:
\else:
- \if_int_compare:w #1 > "1FFF \exp_stop_f:
- \prg_return_false:
- \else:
+ \if_int_compare:w #1 = "0311 \exp_stop_f:
\prg_return_true:
+ \else:
+ \prg_return_false:
\fi:
\fi:
- \else:
+ \fi:
+ \fi:
+ \fi:
+ \fi:
+ }
+\prg_new_conditional:Npnn \@@_change_case_if_greek_diacritic:n
+ #1 { TF , p }
+ {
+ \if_int_compare:w #1 = "0304 \exp_stop_f:
+ \prg_return_true:
+ \else:
+ \if_int_compare:w #1 = "0306 \exp_stop_f:
+ \prg_return_true:
+ \else:
+ \if_int_compare:w #1 = "0313 \exp_stop_f:
+ \prg_return_true:
+ \else:
+ \if_int_compare:w #1 = "0314 \exp_stop_f:
\prg_return_true:
+ \else:
+ \if_int_compare:w #1 = "0343 \exp_stop_f:
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
\fi:
\fi:
- }
+ \fi:
+ \fi:
}
+\prg_new_conditional:Npnn \@@_change_case_if_takes_dialytika:n #1 { TF }
+ {
+ \if_int_compare:w #1 = "0399 \exp_stop_f:
+ \prg_return_true:
+ \else:
+ \if_int_compare:w #1 = "03B9 \exp_stop_f:
+ \prg_return_true:
+ \else:
+ \if_int_compare:w #1 = "03A5 \exp_stop_f:
+ \prg_return_true:
+ \else:
+ \if_int_compare:w #1 = "03C5 \exp_stop_f:
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ \fi:
+ \fi:
+ \fi:
+ }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -827,6 +1019,76 @@
% \end{macro}
% \end{macro}
% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \begin{macro}[EXP]{\@@_change_case_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}
+% 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
+ {
+ \bool_lazy_or:nnTF
+ { \token_if_cs_p:N #3 }
+ {
+ ! \bool_lazy_or_p:nn
+ { \int_compare_p:nNn { `#3 } = { "03AE } }
+ { \int_compare_p:nNn { `#3 } = { "1F22 } }
+ }
+ { \@@_change_case_loop:nnw }
+ { \@@_change_case_boundary_upper_el:nnNw }
+ {#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 }
+ {
+ \@@_change_case_store:e
+ { \char_generate:nn { "0389 } { \@@_char_catcode:N #3 } }
+ \@@_change_case_loop:nnw
+ }
+ {#1} {#2} #4 \q_@@_recursion_stop
+ }
+ \cs_new:Npn \@@_change_case_boundary_upper_el:NnnN #1#2#3#4
+ {
+ \token_if_letter:NTF #4
+ { \@@_change_case_loop:nnw {#2} {#3} #1#4 }
+ {
+ \@@_change_case_store:e
+ { \char_generate:nn { "0389 } { \@@_char_catcode:N #1 } }
+ \@@_change_case_loop:nnw {#2} {#3} #4
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \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.
@@ -1198,14 +1460,17 @@
%
% \begin{variable}
% {
-% \c_@@_dotless_i_tl ,
-% \c_@@_dotted_I_tl ,
-% \c_@@_i_ogonek_tl ,
-% \c_@@_I_ogonek_tl ,
+% \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.
+% a variant is provided in both cases. There are also a few extras for
+% |LGR|.
% \begin{macrocode}
\group_begin:
\bool_lazy_or:nnF
@@ -1238,6 +1503,8 @@
\@@_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:
@@ -1245,7 +1512,9 @@
% \end{variable}
%
% For $8$-bit engines we now need to define the case-change data for
-% the multi-octet mappings. These need a list of what code points are
+% 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.
+% These need a list of what code points are
% doable in |T1| so the list is hard coded (there's no saving in loading
% the mappings dynamically). All of the straight-forward ones have two
% octets, so that is taken as read.
@@ -1454,9 +1723,18 @@
{ 042E } { 044E }
{ 042F } { 044F }
% \end{macrocode}
-% Core Greek support: there may need to be a little more work here to
-% deal completely with accents.
+% 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 }
@@ -1481,17 +1759,39 @@
{ 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
+ \cs_set_protected:Npn \@@_tmp:w ##1##2##3##4##5##6##7##8
{
\tl_const:cx
{
@@ -1500,6 +1800,47 @@
\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}
+% 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_@@_ #3 case_
+ \char_generate:nn {##1} { 12 }
+ \char_generate:nn {##2} { 12 }
+ _tl
+ }
{#2}
}
\use:x
@@ -1509,8 +1850,182 @@
\@@_tmp:w { 00DF } { SS } { upper }
\@@_tmp:w { 00DF } { Ss } { title }
\@@_tmp:w { 0131 } { I } { upper }
- }
- \group_end:
+% \end{macrocode}
+% Greek support: the three-octet code points.
+% \begin{macrocode}
+ \cs_set_protected:Npn \@@_tmp:nnnnnn #1#2#3#4#5#6#7
+ {
+ \tl_const:cx
+ {
+ c_@@_ #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_@@_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
+ { 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_@@_ #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 }
+ }
+\group_end:
% \end{macrocode}
%
% The (fixed) look-up mappings for letter-like control sequences.