diff options
author | Karl Berry <karl@freefriends.org> | 2020-06-03 21:26:23 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2020-06-03 21:26:23 +0000 |
commit | 810785e2302cd260eb73f01e897c5e5978963cb8 (patch) | |
tree | a832daf8f6a5bc8c0d1dc54758abb5561e93cdb9 /Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx | |
parent | 27b8d6a6263cb4e808d7f6ad452462f9f455e97c (diff) |
l3 (3jun20)
git-svn-id: svn://tug.org/texlive/trunk@55406 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx | 134 |
1 files changed, 103 insertions, 31 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx b/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx index 5836bea27ba..4000a2d1f70 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx @@ -44,7 +44,7 @@ % }^^A % } % -% \date{Released 2020-05-15} +% \date{Released 2020-06-03} % % \maketitle % @@ -186,6 +186,19 @@ % encoding. Instead, the \meta{false code} is performed. % \end{function} % +% \section{Conversion by expansion (for PDF contexts)} +% +% A small number of expandable functions are provided for use in PDF string/name +% contexts. These \emph{assume UTF-8} and \emph{no escaping} in the input. +% +% \begin{function}[EXP]{\str_convert_pdfname:n} +% \begin{syntax} +% \cs{str_convert_pdfname:n} \meta{string} +% \end{syntax} +% As \cs{str_set_convert:Nnnn}, converts the \meta{string} on a byte-by-byte +% basis with non-ASCII codepoints escaped using hashes. +% \end{function} +% % \section[Creating 8-bit mappings]{Creating $8$-bit mappings} % % \begin{function}{\str_declare_eight_bit_encoding:nnn} @@ -345,39 +358,41 @@ % % \subsection{String conditionals} % -% \begin{macro}[EXP]{\@@_if_contains_char:NNT, \@@_if_contains_char:NNTF} -% \begin{macro}[EXP]{\@@_if_contains_char:nNTF} -% \begin{macro}[EXP]{\@@_if_contains_char_aux:NN} +% \begin{macro}[EXP]{\@@_if_contains_char:NnT, \@@_if_contains_char:NnTF} +% \begin{macro}[EXP]{\@@_if_contains_char:nnTF} +% \begin{macro}[EXP]{\@@_if_contains_char_aux:nn,\@@_if_contains_char_auxi:nN} % \begin{macro}[EXP]{\@@_if_contains_char_true:} % \begin{syntax} -% \cs{@@_if_contains_char:nNTF} \Arg{token list} \meta{char} +% \cs{@@_if_contains_char:nnTF} \Arg{token list} \meta{char} % \end{syntax} % Expects the \meta{token list} to be an \meta{other string}: the % caller is responsible for ensuring that no (too-)special catcodes -% remain. Spaces with catcode $10$ are ignored. +% remain. % Loop over the characters of the string, comparing character codes. % The loop is broken if character codes match. Otherwise we return % \enquote{false}. % \begin{macrocode} -\prg_new_conditional:Npnn \@@_if_contains_char:NN #1#2 { T , TF } +\prg_new_conditional:Npnn \@@_if_contains_char:Nn #1#2 { T , TF } { - \exp_after:wN \@@_if_contains_char_aux:NN \exp_after:wN #2 - #1 { \prg_break:n { ? \fi: } } + \exp_after:wN \@@_if_contains_char_aux:nn \exp_after:wN {#1} {#2} + { \prg_break:n { ? \fi: } } \prg_break_point: \prg_return_false: } -\prg_new_conditional:Npnn \@@_if_contains_char:nN #1#2 { TF } +\cs_new:Npn \@@_if_contains_char_aux:nn #1#2 + { \@@_if_contains_char_auxi:nN {#2} #1 } +\prg_new_conditional:Npnn \@@_if_contains_char:nn #1#2 { TF } { - \@@_if_contains_char_aux:NN #2 #1 { \prg_break:n { ? \fi: } } + \@@_if_contains_char_auxi:nN {#2} #1 { \prg_break:n { ? \fi: } } \prg_break_point: \prg_return_false: } -\cs_new:Npn \@@_if_contains_char_aux:NN #1#2 +\cs_new:Npn \@@_if_contains_char_auxi:nN #1#2 { \if_charcode:w #1 #2 \exp_after:wN \@@_if_contains_char_true: \fi: - \@@_if_contains_char_aux:NN #1 + \@@_if_contains_char_auxi:nN {#1} } \cs_new:Npn \@@_if_contains_char_true: { \prg_break:n { \prg_return_true: \use_none:n } } @@ -1595,8 +1610,8 @@ % \end{macro} % % \begin{macro}{\@@_convert_escape_name:} -% \begin{macro}[rEXP]{\@@_escape_name_char:N} -% \begin{macro}[rEXP]{\@@_if_escape_name:NTF} +% \begin{macro}[rEXP]{\@@_escape_name_char:n} +% \begin{macro}[rEXP]{\@@_if_escape_name:nTF} % \begin{variable}{\c_@@_escape_name_str} % \begin{variable}{\c_@@_escape_name_not_str} % For each byte, test whether it should be output as is, or be @@ -1609,22 +1624,22 @@ \str_const:Nn \c_@@_escape_name_not_str { ! " $ & ' } %$ \str_const:Nn \c_@@_escape_name_str { {}/<>[] } \cs_new_protected:Npn \@@_convert_escape_name: - { \@@_convert_gmap:N \@@_escape_name_char:N } -\cs_new:Npn \@@_escape_name_char:N #1 + { \@@_convert_gmap:N \@@_escape_name_char:n } +\cs_new:Npn \@@_escape_name_char:n #1 { - \@@_if_escape_name:NTF #1 {#1} + \@@_if_escape_name:nTF {#1} {#1} { \c_hash_str \@@_output_hexadecimal:n {`#1} } } -\prg_new_conditional:Npnn \@@_if_escape_name:N #1 { TF } +\prg_new_conditional:Npnn \@@_if_escape_name:n #1 { TF } { \if_int_compare:w `#1 < "2A \exp_stop_f: - \@@_if_contains_char:NNTF \c_@@_escape_name_not_str #1 + \@@_if_contains_char:NnTF \c_@@_escape_name_not_str {#1} \prg_return_true: \prg_return_false: \else: \if_int_compare:w `#1 > "7E \exp_stop_f: \prg_return_false: \else: - \@@_if_contains_char:NNTF \c_@@_escape_name_str #1 + \@@_if_contains_char:NnTF \c_@@_escape_name_str {#1} \prg_return_false: \prg_return_true: \fi: \fi: @@ -1652,8 +1667,8 @@ { \@@_if_escape_string:NTF #1 { - \@@_if_contains_char:NNT - \c_@@_escape_string_str #1 + \@@_if_contains_char:NnT + \c_@@_escape_string_str {#1} { \c_backslash_str } #1 } @@ -1683,28 +1698,28 @@ % \end{macro} % % \begin{macro}{\@@_convert_escape_url:} -% \begin{macro}[rEXP]{\@@_escape_url_char:N} -% \begin{macro}[rEXP]{\@@_if_escape_url:NTF} +% \begin{macro}[rEXP]{\@@_escape_url_char:n} +% \begin{macro}[rEXP]{\@@_if_escape_url:nTF} % This function is similar to \cs{@@_convert_escape_name:}, escaping % different characters. % \begin{macrocode} \cs_new_protected:Npn \@@_convert_escape_url: - { \@@_convert_gmap:N \@@_escape_url_char:N } -\cs_new:Npn \@@_escape_url_char:N #1 + { \@@_convert_gmap:N \@@_escape_url_char:n } +\cs_new:Npn \@@_escape_url_char:n #1 { - \@@_if_escape_url:NTF #1 {#1} + \@@_if_escape_url:nTF {#1} {#1} { \c_percent_str \@@_output_hexadecimal:n { `#1 } } } -\prg_new_conditional:Npnn \@@_if_escape_url:N #1 { TF } +\prg_new_conditional:Npnn \@@_if_escape_url:n #1 { TF } { \if_int_compare:w `#1 < "41 \exp_stop_f: - \@@_if_contains_char:nNTF { "-.<> } #1 + \@@_if_contains_char:nnTF { "-.<> } {#1} \prg_return_true: \prg_return_false: \else: \if_int_compare:w `#1 > "7E \exp_stop_f: \prg_return_false: \else: - \@@_if_contains_char:nNTF { [ ] } #1 + \@@_if_contains_char:nnTF { [ ] } {#1} \prg_return_false: \prg_return_true: \fi: \fi: @@ -2581,6 +2596,63 @@ \group_end: % \end{macrocode} % +% \subsection{PDF names and strings by expansion} +% +% \begin{macro}[EXP]{\str_convert_pdfname:n} +% \begin{macro}[EXP]{\@@_convert_pdfname:n} +% \begin{macro}[EXP] +% {\@@_convert_pdfname_bytes:n, \@@_convert_pdfname_bytes_aux:n} +% \begin{macro}[EXP]{\@@_convert_pdfname_bytes_aux:nnn} +% To convert to PDF names by expansion, we work purely on UTF-8 input. The +% first step is to make a string with \enquote{other} spaces, +% after which we use a simple token-by-token approach. In Unicode +% engines, we break down everything before one-byte codepoints, but for +% $8$-bit engines there is no need to worry. Actual escaping is covered +% by the same code as used in the non-expandable route. +% \begin{macrocode} +\cs_new:Npn \str_convert_pdfname:n #1 + { + \exp_args:Ne \tl_to_str:n + { \str_map_function:nN {#1} \@@_convert_pdfname:n } + } +\bool_lazy_or:nnTF + { \sys_if_engine_luatex_p: } + { \sys_if_engine_xetex_p: } + { + \cs_new:Npn \@@_convert_pdfname:n #1 + { + \int_compare:nNnTF { `#1 } > { "7F } + { \@@_convert_pdfname_bytes:n {#1} } + { \@@_escape_name_char:n {#1} } + } + \cs_new:Npn \@@_convert_pdfname_bytes:n #1 + { + \exp_args:Ne \@@_convert_pdfname_bytes_aux:n + { \char_to_utfviii_bytes:n {`#1} } + } + \cs_new:Npn \@@_convert_pdfname_bytes_aux:n #1 + { \@@_convert_pdfname_bytes_aux:nnnn #1 } + \cs_new:Npx \@@_convert_pdfname_bytes_aux:nnnn #1#2#3#4 + { + \c_hash_str \exp_not:N \@@_output_hexadecimal:n {#1} + \c_hash_str \exp_not:N \@@_output_hexadecimal:n {#2} + \exp_not:N \tl_if_blank:nF {#3} + { + \c_hash_str \exp_not:N \@@_output_hexadecimal:n {#3} + \exp_not:N \tl_if_blank:nF {#4} + { + \c_hash_str \exp_not:N \@@_output_hexadecimal:n {#4} + } + } + } + } + { \cs_new_eq:NN \@@_convert_pdfname:n \@@_escape_name_char:n } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% % \begin{macrocode} %</initex|package> % \end{macrocode} |