diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx | 105 |
1 files changed, 85 insertions, 20 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx b/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx index b44b307bbf1..e4dba1753ff 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx @@ -43,7 +43,7 @@ % }^^A % } % -% \date{Released 2023-06-16} +% \date{Released 2023-06-30} % % \maketitle % @@ -106,6 +106,22 @@ % category code $10$. % \end{function} % +% \begin{function}[added = 2023-06-19, EXP]{\codepoint_to_category:n} +% \begin{syntax} +% \cs{codepoint_to_category:n} \Arg{codepoint} +% \end{syntax} +% Expands to the Unicode general category identifier of the \meta{codepoint}. +% The general category identifier is a string made up of two letter +% characters, the first uppercase and the second lowercase. The uppercase +% letters divide codepoints into broader groups, which are then refined +% by the lowercase letter. For example, codepoints representing letters +% all have identifiers starting \texttt{L}, for example \texttt{Lu} +% (uppercase letter), \texttt{Lt} (titlecase letter), \emph{etc.} +% Full details are available in the documentation provided by the Unicode +% Consortium: see +% \url{https://www.unicode.org/reports/tr44/#General_Category_Values} +% \end{function} +% % \begin{function}[added = 2022-10-09, EXP]{\codepoint_to_nfd:n} % \begin{syntax} % \cs{codepoint_to_nfd:n} \Arg{codepoint} @@ -347,6 +363,21 @@ % \end{macro} % \end{macro} % +% \begin{macro}[EXP]{\codepoint_to_category:n} +% Get the value and convert back to the string. +% \begin{macrocode} +\cs_new:Npn \codepoint_to_category:n #1 + { + \cs:w + c_@@_category_ + \tex_romannumeral:D + \__kernel_codepoint_data:nn { category } {#1} + _str + \cs_end: + } +% \end{macrocode} +% \end{macro} +% % \begin{macro}[EXP]{\codepoint_to_nfd:n, \@@_to_nfd:n} % \begin{macro}[EXP]{\@@_to_nfd:nn} % \begin{macro}[EXP]{\@@_to_nfd:nnn} @@ -461,7 +492,7 @@ % \begin{macrocode} \group_begin: \clist_map_inline:nn - { uppercase , lowercase } + { category , uppercase , lowercase } { \cs_set_nopar:cpn { l_@@_ #1 _block_clist } { } \cs_set_nopar:cpn { l_@@_ #1 _block_tl } { 1 } @@ -477,6 +508,29 @@ \cs_set_nopar:Npn \l_@@_next_codepoint_fint_tl { 0 } \cs_set_nopar:Npn \l_@@_matched_block_tl { 0 } % \end{macrocode} +% For Unicode general category, there needs to be numerical representation of +% each possible value. As we need to go from string to number here, but the +% other way elsewhere, we set up fast mappings both ways, but one set local +% and the other as constants. +% \begin{macrocode} + \cs_set_protected:Npn \@@_data_auxi:w #1#2 + { + \quark_if_recursion_tail_stop:n {#2} + \cs_set_nopar:cpn { l_@@_category_ #2 _tl } {#1} + \str_const:cn { c_@@_category_ \tex_romannumeral:D #1 _str } {#2} + \exp_args:Ne \@@_data_auxi:w { \int_eval:n { #1 + 1 } } + } + \@@_data_auxi:w { 1 } + { Lu } { Ll } { Lt } { Lm } { Lo } + { Mn } { Me } { Mc } + { Nd } { Nl } { No } + { Zs } { Zl } { Zp } + { Cc } { Cf } { Co } { Cs } { Cn } + { Pd } { Ps } { Pe } { Pc } { Po } { Pi } { Pf } + { Sm } { Sc } { Sk } { So } + \q_recursion_tail + \q_recursion_stop +% \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 codepoints: one or two. We also need the case data, @@ -491,7 +545,7 @@ \tl_if_head_eq_charcode:nNF {#6} < % > { \@@_data_auxii:w #1 ; #6 ~ \q_stop } } - \@@_data_auxiii:w #1 ; #2 ; + \@@_data_auxiii:w #1 ; #2 ; #3 ; } \cs_set_protected:Npn \@@_data_auxii:w #1 ; #2 ~ #3 \q_stop { @@ -503,22 +557,27 @@ } } % \end{macrocode} +% The category data needs to be converted from a string to the numerical +% equivalent: a simple operation. % 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. +% where a codepoint has no mapping data in one shot. % \begin{macrocode} \cs_set_protected:Npn \@@_data_auxiii:w - #1 ; #2 ; #3 ; #4 ; #5 ; #6 ; #7 ; #8 ~ \q_stop + #1 ; #2 ; #3 ; #4 ; #5 ; #6 ; #7 ; #8 ; #9 ~ \q_stop { \use:e { \@@_data_auxiv:w #1 ; #2 ; - \@@_data_offset:nn {#1} {#6} ; + \@@_data_category:n {#3} ; \@@_data_offset:nn {#1} {#7} ; - #8; + \@@_data_offset:nn {#1} {#8} ; + #9; } } + \cs_set:Npn \@@_data_category:n #1 + { \use:c { l_@@_category_ #1 _tl } } \cs_set:Npn \@@_data_offset:nn #1#2 { \tl_if_blank:nTF {#2} @@ -536,20 +595,21 @@ % 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 ; + \cs_set_protected:Npn \@@_data_auxiv:w #1 ; #2 ; #3 ; #4 ; #5 ; #6 ; { \int_compare:nNnT {"#1} > \l_@@_next_codepoint_fint_tl { - \@@_data_auxvi:nnnw {#1} {#3} {#4} + \@@_data_auxv:nnnnw {#1} {#3} {#4} {#5} #2 Last> \q_stop } - \@@_add:nn { uppercase } {#3} - \@@_add:nn { lowercase } {#4} - \int_compare:nNnF {#3} = { \@@_data_offset:nn {#1} {#5} } + \@@_add:nn { category } {#3} + \@@_add:nn { uppercase } {#4} + \@@_add:nn { lowercase } {#5} + \int_compare:nNnF {#4} = { \@@_data_offset:nn {#1} {#6} } { \tl_const:cx { c_@@_titlecase_ \codepoint_str_generate:n {"#1} _tl } - { {"#5} { } { } } + { {"#6} { } { } } } \tl_set:Nx \l_@@_next_codepoint_fint_tl { \int_eval:n { "#1 + 1 } } @@ -563,17 +623,22 @@ } % \end{macrocode} % Distinguish between a range and a gap, and pass on the appropriate value(s). +% The general category for unassigned characters is \texttt{Cn}, so we +% find the correct value once and then use that. % \begin{macrocode} - \cs_set_protected:Npn \@@_data_auxvi:nnnw #1#2#3#4 Last> #5 \q_stop + \cs_set_protected:Npx \@@_data_auxv:nnnnw #1#2#3#4#5 Last> #6 \q_stop { - \tl_if_blank:nTF {#5} + \exp_not:N \tl_if_blank:nTF {#6} { - \@@_range:nnn {#1} { uppercase } { 0 } - \@@_range:nnn {#1} { lowercase } { 0 } + \exp_not:N \@@_range:nnn {#1} { category } + { \exp_not:V \l_@@_category_Cn_tl } + \exp_not:N \@@_range:nnn {#1} { uppercase } { 0 } + \exp_not:N \@@_range:nnn {#1} { lowercase } { 0 } } { - \@@_range:nnn {#1} { uppercase } {#2} - \@@_range:nnn {#1} { lowercase } {#3} + \exp_not:N \@@_range:nnn {#1} { category } {#2} + \exp_not:N \@@_range:nnn {#1} { uppercase } {#3} + \exp_not:N \@@_range:nnn {#1} { lowercase } {#4} } } % \end{macrocode} @@ -672,7 +737,7 @@ % \begin{macrocode} \cs_set_protected:Npn \@@_finalise_blocks: { - \clist_map_inline:nn { uppercase , lowercase } + \clist_map_inline:nn { category , uppercase , lowercase } { \@@_range:nnn { 110000 } {##1} { 0 } \@@_finalise_blocks:n {##1} |