From a4756b9a2c587fe3fe092cc9cfd8e3b1fb267445 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Thu, 21 Oct 2021 20:31:49 +0000 Subject: unicodefonttable (21oct21) git-svn-id: svn://tug.org/texlive/trunk@60826 c570f23f-e606-0410-a88d-b1316a301751 --- .../doc/latex/unicodefonttable/README.md | 29 + .../texmf-dist/doc/latex/unicodefonttable/TODO.md | 20 + .../doc/latex/unicodefonttable/changes.txt | 20 + .../doc/latex/unicodefonttable/l3doc-TUB.cls | 2306 ++++++++++++++++++++ .../unicodefonttable/unicodefonttable-code.pdf | Bin 0 -> 890196 bytes .../unicodefonttable/unicodefonttable-code.tex | 4 + .../unicodefonttable/unicodefonttable-doc.pdf | Bin 0 -> 707853 bytes .../unicodefonttable/unicodefonttable-doc.tex | 6 + .../unicodefonttable/unicodefonttable-samples.pdf | Bin 0 -> 742559 bytes .../unicodefonttable/unicodefonttable-samples.tex | 104 + .../latex/unicodefonttable/unicodefonttable.dtx | 2295 +++++++++++++++++++ .../latex/unicodefonttable/unicodefonttable.ins | 72 + .../tex/latex/unicodefonttable/unicodefont.tex | 125 ++ .../latex/unicodefonttable/unicodefonttable.sty | 725 ++++++ Master/tlpkg/bin/tlpkg-ctan-check | 2 +- Master/tlpkg/libexec/ctan2tds | 1 + Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc | 1 + Master/tlpkg/tlpsrc/unicodefonttable.tlpsrc | 0 18 files changed, 5709 insertions(+), 1 deletion(-) create mode 100644 Master/texmf-dist/doc/latex/unicodefonttable/README.md create mode 100644 Master/texmf-dist/doc/latex/unicodefonttable/TODO.md create mode 100644 Master/texmf-dist/doc/latex/unicodefonttable/changes.txt create mode 100644 Master/texmf-dist/doc/latex/unicodefonttable/l3doc-TUB.cls create mode 100644 Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-code.pdf create mode 100644 Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-code.tex create mode 100644 Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-doc.pdf create mode 100644 Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-doc.tex create mode 100644 Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-samples.pdf create mode 100644 Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-samples.tex create mode 100644 Master/texmf-dist/source/latex/unicodefonttable/unicodefonttable.dtx create mode 100644 Master/texmf-dist/source/latex/unicodefonttable/unicodefonttable.ins create mode 100644 Master/texmf-dist/tex/latex/unicodefonttable/unicodefont.tex create mode 100644 Master/texmf-dist/tex/latex/unicodefonttable/unicodefonttable.sty create mode 100644 Master/tlpkg/tlpsrc/unicodefonttable.tlpsrc diff --git a/Master/texmf-dist/doc/latex/unicodefonttable/README.md b/Master/texmf-dist/doc/latex/unicodefonttable/README.md new file mode 100644 index 00000000000..b1f92c1fd0c --- /dev/null +++ b/Master/texmf-dist/doc/latex/unicodefonttable/README.md @@ -0,0 +1,29 @@ +# The unicodefonttable package + +----- + +This package produces font tables for unicode fonts as well as for +8bit fonts. The table layout can be adjusted in various ways +including restricting the range of output to show only a portion of a +specific font. + +To quickly produce a one-off table there is a stand-alone version +`unicodefont.tex` that asks you a few questions and then generates the +table --- somewhat similar to `nfssfont.tex` for 8-bit fonts. + + +The official package source can be found at: + + https://github.com/FrankMittelbach/fmitex-unicodefonttable/ + +The license is LPPL. + +For version information see the .dtx file. + +----- + +Copyright (C) Frank Mittelbach (for copyright date see the .dtx file)
+
+All rights reserved. + + diff --git a/Master/texmf-dist/doc/latex/unicodefonttable/TODO.md b/Master/texmf-dist/doc/latex/unicodefonttable/TODO.md new file mode 100644 index 00000000000..6cee8ebf495 --- /dev/null +++ b/Master/texmf-dist/doc/latex/unicodefonttable/TODO.md @@ -0,0 +1,20 @@ +# Collection of possible todos + +These are an unsorted collection of thoughts by others or myself and may or may not get done depending ... + + +## Comparing + +- When comparing, I suggest writing the log file with the + the list of glyphs found only in the comparison font. That way, people + developing a font who want to have equal coverage can easily see what + glyphs they are missing. Since you are already discovering the + information, why not log it ... + + +- Also, if there are first-font-only symbols (maybe not in + this case -- is there a way to get a textual list of the differing code + points?), I'd suggest trying an open box (cf. the shaded box for + second-font-only). + + diff --git a/Master/texmf-dist/doc/latex/unicodefonttable/changes.txt b/Master/texmf-dist/doc/latex/unicodefonttable/changes.txt new file mode 100644 index 00000000000..a632e273f8a --- /dev/null +++ b/Master/texmf-dist/doc/latex/unicodefonttable/changes.txt @@ -0,0 +1,20 @@ +2021-10-19 Frank Mittelbach + + * unicodefonttable.dtx + Extended support up to U+FFFFF after all, but not plane 16. + A bit more explanation in different places. + Some speed improvements (could be improved further) + +2021-10-17 Frank Mittelbach + + * unicodefonttable.dtx: + Extend support to the higher planes of Unicode by allowing a + range from U+0000 to U+EFFFF + +2021-10-08 Frank Mittelbach + + * unicodefonttable.dtx (subsection{Keys and their values}): + Added statistics-compare-format key. + Use longtable* from the caption package when not showing a + header with a \caption. + diff --git a/Master/texmf-dist/doc/latex/unicodefonttable/l3doc-TUB.cls b/Master/texmf-dist/doc/latex/unicodefonttable/l3doc-TUB.cls new file mode 100644 index 00000000000..50a8a9a9d90 --- /dev/null +++ b/Master/texmf-dist/doc/latex/unicodefonttable/l3doc-TUB.cls @@ -0,0 +1,2306 @@ +%% +%% This is file `l3doc-TUB.cls' +%% +%% The original source files were: +%% +%% l3doc.dtx (with options: `class') + several manual changes! +%% +%% Copyright (C) 1990-2018 The LaTeX3 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 of this license is in the file: +%% +%% https://www.latex-project.org/lppl.txt +%% +%% File: l3doc.dtx Copyright (C) 1990-2018 The LaTeX3 project +%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% This is really a temporary file intended for a single article +%% written for TugBoat It is a copy of l3doc.cls with a couple of +%% changes, nothing more. Eventually this will get replaced by a real +%% class once l3doc.cls gets properly split into a class part and a +%% support part. +%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% If you use this for anything other than processing the documents it +%% was meant for (which so far is 2) you are on your own :-) +%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\RequirePackage{expl3,xparse,calc} +\ProvidesExplClass{l3doc-TUB}{2021/03/02}{} + {L3 Experimental documentation class (special version for TUGboat with fixes)} +\clist_new:N \g_docinput_clist +\seq_new:N \g_doc_functions_seq +\seq_new:N \g_doc_macros_seq +\bool_new:N \l__codedoc_detect_internals_bool +\bool_set_true:N \l__codedoc_detect_internals_bool +\tl_new:N \l__codedoc_detect_internals_tl +\tl_new:N \l__codedoc_detect_internals_cs_tl +\coffin_new:N \l__codedoc_output_coffin +\coffin_new:N \l__codedoc_functions_coffin +\coffin_new:N \l__codedoc_descr_coffin +\coffin_new:N \l__codedoc_syntax_coffin +\box_new:N \g__codedoc_syntax_box +\bool_new:N \l__codedoc_in_function_bool +\bool_new:N \l__codedoc_long_name_bool +\dim_new:N \l__codedoc_trial_width_dim +\int_new:N \l__codedoc_nested_macro_int +\bool_new:N \l__codedoc_macro_tested_bool +\prop_new:N \g__codedoc_missing_tests_prop +\seq_new:N \g__codedoc_not_tested_seq +\seq_new:N \g__codedoc_testfiles_seq +\bool_new:N \l__codedoc_macro_internal_set_bool +\bool_new:N \l__codedoc_macro_internal_bool +\bool_new:N \l__codedoc_macro_TF_bool +\bool_new:N \l__codedoc_macro_pTF_bool +\bool_new:N \l__codedoc_macro_noTF_bool +\bool_new:N \l__codedoc_macro_EXP_bool +\bool_new:N \l__codedoc_macro_rEXP_bool +\bool_new:N \l__codedoc_macro_var_bool +\tl_new:N \l__codedoc_override_module_tl +\tl_set:Nn \l__codedoc_override_module_tl { \q_no_value } +\tl_new:N \l__codedoc_macro_documented_tl +\bool_new:N \g__codedoc_lmodern_bool +\bool_new:N \g__codedoc_checkfunc_bool +\bool_new:N \g__codedoc_checktest_bool +\bool_new:N \g__codedoc_kernel_bool +\tl_new:N \l__codedoc_tmpa_tl +\tl_new:N \l__codedoc_tmpb_tl +\int_new:N \l__codedoc_tmpa_int +\int_new:N \l__codedoc_tmpa_seq +\tl_new:N \l__codedoc_names_block_tl +\seq_new:N \g__codedoc_variants_seq +\bool_new:N \l__codedoc_names_verb_bool +\seq_new:N \l__codedoc_names_seq +\seq_new:N \g__codedoc_nested_names_seq +\tl_const:Nx \c__codedoc_backslash_tl { \iow_char:N \\ } +\exp_last_unbraced:NNo + \cs_new_eq:NN \c__codedoc_backslash_token { \c__codedoc_backslash_tl } +\tl_new:N \l__codedoc_index_macro_tl +\tl_new:N \l__codedoc_index_key_tl +\tl_new:N \l__codedoc_index_module_tl +\bool_new:N \l__codedoc_index_internal_bool +\tl_new:N \g__codedoc_module_name_tl +\tl_const:Nn \c__codedoc_iow_rule_tl + { ======================================== } +\tl_const:Nn \c__codedoc_iow_mid_rule_tl + { -------------------------------------- } +\box_new:N \l__codedoc_macro_box +\box_new:N \l__codedoc_macro_index_box +\int_new:N \l__codedoc_macro_int +\tl_new:N \l__codedoc_cmd_tl +\tl_new:N \l__codedoc_cmd_index_tl +\tl_new:N \l__codedoc_cmd_module_tl +\bool_new:N \l__codedoc_cmd_noindex_bool +\bool_new:N \l__codedoc_cmd_replace_bool +\bool_new:N \l__codedoc_in_implementation_bool +\bool_new:N \g__codedoc_typeset_documentation_bool +\bool_new:N \g__codedoc_typeset_implementation_bool +\bool_set_true:N \g__codedoc_typeset_documentation_bool +\bool_set_true:N \g__codedoc_typeset_implementation_bool +\tl_new:N \g__codedoc_base_name_tl +\prop_new:N \l__codedoc_variants_prop +\clist_new:N \l__codedoc_function_label_clist +\bool_new:N \l__codedoc_no_label_bool +\tl_new:N \l__codedoc_date_added_tl +\tl_new:N \l__codedoc_date_updated_tl +\tl_new:N \l__codedoc_macro_argument_tl +\cs_new_eq:NN \__codedoc_tmpa:w ? +\cs_new_eq:NN \__codedoc_tmpb:w ? +\cs_generate_variant:Nn \seq_set_split:Nnn { NoV } +\cs_generate_variant:Nn \seq_gput_right:Nn { Nf } +\cs_generate_variant:Nn \str_case:nn { fn } +\cs_generate_variant:Nn \tl_count:n { f } +\cs_generate_variant:Nn \tl_greplace_all:Nnn { Nx , Nno } +\cs_generate_variant:Nn \tl_if_empty:nTF { f } +\cs_generate_variant:Nn \tl_if_head_eq_charcode:nNTF { o } +\cs_generate_variant:Nn \tl_if_head_eq_charcode:nNT { o } +\cs_generate_variant:Nn \tl_if_head_eq_charcode:nNF { o } +\cs_generate_variant:Nn \tl_if_head_eq_meaning:nNF { V } +\cs_generate_variant:Nn \tl_if_in:nnTF { no , oo } +\cs_generate_variant:Nn \tl_if_in:NnTF { No } +\cs_generate_variant:Nn \tl_if_in:NnT { No } +\cs_generate_variant:Nn \tl_if_in:NnF { No } +\cs_generate_variant:Nn \tl_remove_all:Nn { Nx } +\cs_generate_variant:Nn \tl_replace_all:Nnn { Nx , Nnx, No , Nno } +\cs_generate_variant:Nn \tl_replace_once:Nnn { Noo } +\cs_generate_variant:Nn \tl_to_str:n { f , o } +\cs_generate_variant:Nn \prop_get:NnNTF { Nx } +\cs_generate_variant:Nn \prop_put:Nnn { Nx } +\cs_generate_variant:Nn \prop_gput:Nnn { NVx } +\prg_new_protected_conditional:Npnn \__codedoc_if_almost_str:n #1 { TF , T , F } + { + \int_compare:nNnTF + { \tl_count:n {#1} } + < { \tl_count:f { \tl_to_str:f {#1} } } + { \prg_return_false: } + { \prg_return_true: } + } +\cs_generate_variant:Nn \__codedoc_if_almost_str:nT { V } +\cs_new_protected:Npn \__codedoc_trim_right:Nn #1#2 + { + \cs_set:Npn \__codedoc_tmp:w ##1 #2 ##2 \q_stop { \exp_not:n {##1} } + \tl_set:Nx #1 { \exp_after:wN \__codedoc_tmp:w #1 #2 \q_stop } + } +\cs_generate_variant:Nn \__codedoc_trim_right:Nn { No } +\prg_new_protected_conditional:Npnn \__codedoc_str_if_begin:nn #1#2 { TF , T , F } + { + \tl_if_in:ooTF + { \exp_after:wN \scan_stop: \tl_to_str:n {#1} } + { \exp_after:wN \scan_stop: \tl_to_str:n {#2} } + { \prg_return_true: } + { \prg_return_false: } + } +\prg_generate_conditional_variant:Nnn \__codedoc_str_if_begin:nn + { oo } { TF , T , F } +\cs_new_protected:Npn \__codedoc_replace_at_at:N #1 + { + \bool_if:NT \l__codedoc_in_implementation_bool + { + \bool_if:NT \l__codedoc_detect_internals_bool + { \__codedoc_detect_internals:N #1 } + } + \tl_if_empty:NF \g__codedoc_module_name_tl + { + \exp_args:NNo \__codedoc_replace_at_at_aux:Nn + #1 \g__codedoc_module_name_tl + } + } +\cs_new_protected:Npx \__codedoc_replace_at_at_aux:Nn #1#2 + { + \tl_replace_all:Nnn #1 { \token_to_str:N @ } { @ } + \tl_replace_all:Nnn #1 { \token_to_str:N _ } { _ } + \tl_replace_all:Nnn #1 { @ @ @ @ } { \token_to_str:N a a } + \tl_replace_all:Nnn #1 { _ _ @ @ } { _ _ #2 } + \tl_replace_all:Nnn #1 { _ @ @ } { _ _ #2 } + \tl_replace_all:Nnn #1 { @ @ } { _ _ #2 } + \tl_replace_all:Nnn #1 { \token_to_str:N a a } { @ @ } + } +\group_begin: + \char_set_catcode_active:N \^^M + \cs_new_protected:Npn \__codedoc_detect_internals:N #1 + { + \tl_set_eq:NN \l__codedoc_detect_internals_tl #1 + \tl_replace_all:Non \l__codedoc_detect_internals_tl { \token_to_str:N _ } { _ } + \seq_set_split:NnV \l__codedoc_tmpa_seq { _ _ } \l__codedoc_detect_internals_tl + \seq_pop_left:NN \l__codedoc_tmpa_seq \l__codedoc_detect_internals_tl + \seq_map_variable:NNn \l__codedoc_tmpa_seq \l__codedoc_detect_internals_tl + { + \__codedoc_trim_right:No \l__codedoc_detect_internals_tl + \c_catcode_active_space_tl + \__codedoc_trim_right:Nn \l__codedoc_detect_internals_tl ^^M + \__codedoc_if_detect_internals_ok:NF \l__codedoc_detect_internals_tl + { + \tl_set_eq:NN \l__codedoc_detect_internals_cs_tl \l__codedoc_detect_internals_tl + \__codedoc_trim_right:Nn \l__codedoc_detect_internals_tl _ + \__codedoc_trim_right:Nn \l__codedoc_detect_internals_tl : + \__codedoc_trim_right:No \l__codedoc_detect_internals_tl { \token_to_str:N : } + \msg_warning:nnxxx { l3doc-TUB } { foreign-internal } + { \tl_to_str:N \l__codedoc_detect_internals_cs_tl } + { \tl_to_str:N \l__codedoc_detect_internals_tl } + { \tl_to_str:N \g__codedoc_module_name_tl } + } + } + } +\group_end: +\prg_new_protected_conditional:Npnn \__codedoc_if_detect_internals_ok:N #1 { F } + { + \__codedoc_str_if_begin:ooTF {#1} { \g__codedoc_module_name_tl _ } + { \prg_return_true: } + { + \__codedoc_str_if_begin:ooTF {#1} { \g__codedoc_module_name_tl : } + { \prg_return_true: } + { + \bool_if:NTF \g__codedoc_kernel_bool + { + \__codedoc_str_if_begin:ooTF {#1} { kernel _ } + { \prg_return_true: } + { \prg_return_false: } + } + { \prg_return_false: } + } + } + } +\cs_new:Npn \__codedoc_signature_base_form:n #1 + { \__codedoc_signature_base_form_aux:n #1 \q_stop } +\cs_new:Npn \__codedoc_signature_base_form_aux:n #1 + { + \str_case:nnTF {#1} + { + { N } { N } + { c } { N } + { n } { n } + { o } { n } + { f } { n } + { x } { n } + { V } { n } + { v } { n } + } + { \__codedoc_signature_base_form_aux:n } + { \__codedoc_signature_base_form_aux:w #1 } + } +\cs_new:Npn \__codedoc_signature_base_form_aux:w #1 \q_stop + { \exp_not:n {#1} } +\cs_new:Npn \__codedoc_predicate_from_base:n #1 + { + \__codedoc_get_function_name:n {#1} + \tl_to_str:n { _p: } + \__codedoc_get_function_signature:n {#1} + } +\cs_new:Npn \__codedoc_get_function_name:n #1 + { \__codedoc_split_function_do:nn {#1} { \use_i:nnn } } +\cs_new:Npn \__codedoc_get_function_signature:n #1 + { \__codedoc_split_function_do:nn {#1} { \use_ii:nnn } } +\cs_set_protected:Npn \__codedoc_tmpa:w #1 + { + \cs_new:Npn \__codedoc_split_function_do:nn ##1 + { + \exp_after:wN \__codedoc_split_function_auxi:w + \tl_to_str:n {##1} \q_mark \c_true_bool + #1 \q_mark \c_false_bool + \q_stop + } + \cs_new:Npn \__codedoc_split_function_auxi:w + ##1 #1 ##2 \q_mark ##3##4 \q_stop ##5 + { \__codedoc_split_function_auxii:w {##5} ##1 \q_mark \q_stop {##2} ##3 } + \cs_new:Npn \__codedoc_split_function_auxii:w + ##1##2 \q_mark ##3 \q_stop + { ##1 {##2} } + } +\exp_args:No \__codedoc_tmpa:w { \token_to_str:N : } +\cs_generate_variant:Nn \__codedoc_split_function_do:nn { o } +\cs_new_protected:Npn \__codedoc_key_get_base:nN #1#2 + { + \__codedoc_if_almost_str:nTF {#1} + { + \__codedoc_key_get_base_TF:nN {#1} \l__codedoc_tmpa_tl + \tl_set:Nx #2 + { \__codedoc_split_function_do:on \l__codedoc_tmpa_tl { \__codedoc_base_form_aux:nnN } } + } + { \tl_set:Nn #2 {#1} } + } +\cs_new:Npx \__codedoc_key_get_base_TF:nN #1#2 + { + \tl_set:Nx #2 { \exp_not:N \tl_to_str:n {#1} \scan_stop: } + \tl_if_in:NnTF #2 { \tl_to_str:n { F } \scan_stop: } + { + \tl_if_in:NnF #2 { \tl_to_str:n { TF } \scan_stop: } + { + \tl_replace_once:Nnn #2 + { \tl_to_str:n { F } \scan_stop: } + { \tl_to_str:n { TF } \scan_stop: } + } + } + { + \tl_replace_once:Nnn #2 + { \tl_to_str:n { T } \scan_stop: } + { \tl_to_str:n { TF } \scan_stop: } + } + \tl_remove_once:Nn #2 { \scan_stop: } + } +\cs_new:Npn \__codedoc_base_form_aux:nnN #1#2#3 + { + \exp_not:n {#1} + \bool_if:NT #3 + { + \token_to_str:N : + \str_if_eq:nnTF { #1 ~ } { \exp_args } + { \exp_not:n {#2} } + { \__codedoc_signature_base_form:n {#2} } + } + } +\cs_new_protected:Npn \__codedoc_base_form_signature_do:nnn #1#2#3 + { + \__codedoc_split_function_do:nn {#1} + { \__codedoc_base_form_aux:nnnnnN {#1} {#2} {#3} } + } +\cs_new_protected:Npn \__codedoc_base_form_aux:nnnnnN #1#2#3#4#5#6 + { + \bool_if:NTF #6 + { + \tl_if_head_eq_charcode:nNTF {#4} : + { #2 {#1} } + { + \use:x + { + \exp_not:n {#3} + { \__codedoc_base_form_aux:nnN {#4} {#5} #6 } + } + {#4} {#5} + } + } + { #2 {#1} } + } +\prg_new_conditional:Npnn \__codedoc_date_compare:nNn #1#2#3 { TF , T , F , p } + { \__codedoc_date_compare_aux:w #1--- \q_mark #2 #3--- \q_stop } +\cs_new:Npn \__codedoc_date_compare_aux:w + #1 - #2 - #3 - #4 \q_mark #5 #6 - #7 - #8 - #9 \q_stop + { + \__codedoc_date_compare_aux:nnnNnnn + { \tl_if_empty:nTF {#1} { 0 } {#1} } + { \tl_if_empty:nTF {#2} { 0 } {#2} } + { \tl_if_empty:nTF {#3} { 0 } {#3} } + #5 + { \tl_if_empty:nTF {#6} { 0 } {#6} } + { \tl_if_empty:nTF {#7} { 0 } {#7} } + { \tl_if_empty:nTF {#8} { 0 } {#8} } + } +\cs_new:Npn \__codedoc_date_compare_aux:nnnNnnn #1#2#3#4#5#6#7 + { + \int_compare:nNnTF {#1} = {#5} + { + \int_compare:nNnTF {#2} = {#6} + { + \int_compare:nNnTF {#3} #4 {#7} + { \prg_return_true: } { \prg_return_false: } + } + { + \int_compare:nNnTF {#2} #4 {#6} + { \prg_return_true: } { \prg_return_false: } + } + } + { + \int_compare:nNnTF {#1} #4 {#5} + { \prg_return_true: } { \prg_return_false: } + } + \use_none:n + \q_stop + } +\cs_new:Npn \__codedoc_gprop_name:n #1 { g__codedoc ~ \tl_to_str:n {#1} } +\cs_new:Npn \__codedoc_lseq_name:n #1 { l__codedoc ~ \tl_to_str:n {#1} } +\msg_new:nnnn { l3doc-TUB } { no-signature-TF } + { Function/macro~'#1'~cannot~be~turned~into~a~conditional. } + { + A~function~or~macro~environment~with~option~pTF,~TF~or~noTF~ + received~the~argument~'#1'.~This~function's~name~has~no~ + ':'~hence~it~is~not~clear~where~to~add~'_p'~or~'TF'.~ + Please~follow~expl3~naming~conventions. + } +\msg_new:nnn { l3doc-TUB } { deprecated-function } + { The~deprecated~function(s)~'#1'~should~have~been~removed~on~#2. } +\msg_new:nnn { l3doc-TUB } { date-format } + { The~date~'#1'~should~be~given~in~YYYY-MM-DD~format. } +\msg_new:nnn { l3doc-TUB } { syntax-nested-function } + { + The~'syntax'~environment~should~be~used~in~the~ + innermost~'function'~environment. + } +\msg_new:nnn { l3doc-TUB } { multiple-syntax } + { + The~'syntax'~environment~should~only~be~used~once~in~ + a~'function'~environment. + } +\msg_new:nnn { l3doc-TUB } { deprecated-option } + { The~option~'#1'~has~been~deprecated~for~'#2'. } +\msg_new:nnn { l3doc-TUB } { foreign-internal } + { + A~control~sequence~of~the~form~'...__#1'~was~used.~ + It~should~only~be~used~in~the~module~'#2' + \tl_if_empty:nF {#3} { ,~not~in~'#3' } . + } +\DeclareOption { a5paper } { \@latexerr { Option~not~supported } { } } +\DeclareOption { full } + { + \bool_gset_true:N \g__codedoc_typeset_documentation_bool + \bool_gset_true:N \g__codedoc_typeset_implementation_bool + } +\DeclareOption { onlydoc } + { + \bool_gset_true:N \g__codedoc_typeset_documentation_bool + \bool_gset_false:N \g__codedoc_typeset_implementation_bool + } +\DeclareOption { check } + { \bool_gset_true:N \g__codedoc_checkfunc_bool } +\DeclareOption { nocheck } + { \bool_gset_false:N \g__codedoc_checkfunc_bool } +\DeclareOption { checktest } + { \bool_gset_true:N \g__codedoc_checktest_bool } +\DeclareOption { nochecktest } + { \bool_gset_false:N \g__codedoc_checktest_bool } +\DeclareOption { kernel } + { \bool_gset_true:N \g__codedoc_kernel_bool } +\DeclareOption { stdmodule } + { \bool_gset_false:N \g__codedoc_kernel_bool } +\DeclareOption { cm-default } + { \bool_gset_false:N \g__codedoc_lmodern_bool } +\DeclareOption { lm-default } + { \bool_gset_true:N \g__codedoc_lmodern_bool } +\DeclareOption* { \PassOptionsToClass { \CurrentOption } { ltugboat } } +\ExecuteOptions { full, kernel, nocheck, nochecktest, lm-default } +%%FMi \PassOptionsToClass { a4paper } { article } +\msg_new:nnn { l3doc-TUB } { input-cfg } + { Local~config~file~l3doc-TUB.cfg~loaded. } +\file_if_exist:nT { l3doc-TUB.cfg } + { + \file_input:nT { l3doc-TUB.cfg } + { + \cs_if_exist:cF { ExplMakeTitle } + { \msg_info:nn { l3doc-TUB } { input-cfg } } + } + } +\ProcessOptions +\LoadClass[final]{ltugboat} +\RequirePackage{doc} + +\newcommand\bibname{References} % otherwise \bibname is undefined at \Finale +\TBtocsectionspace=0pt plus 1pt + +\IndexPrologue + {\section*{Index} + \markboth{Index}{Index} + \addcontentsline{toc}{section}{Index} + \noindent + Underlined numbers point to the definition, + italicized numbers denote the pages where the + corresponding entry is described, + all others indicate the places where it is used.} +%\EnableCrossrefs +%\CodelineIndex + +\RequirePackage + { + microtype, + array, + alphalph, + amsmath, + amssymb, + booktabs, + color, + colortbl, + hologo, + enumitem, + pifont, + textcomp, + trace, + underscore, + csquotes, + fancyvrb, + verbatim + } +\raggedbottom +\bool_if:NT \g__codedoc_lmodern_bool + { + \RequirePackage[T1]{fontenc} + \RequirePackage{lmodern} + \group_begin: + \ttfamily + \DeclareFontShape{T1}{lmtt}{m}{it}{<->ec-lmtto10}{} + \group_end: + } + +\RequirePackage{hypdoc} + +%%FMi: +\hypersetup{allcolors=black} + +\cs_gset:Npn \MakePrivateLetters + { + \char_set_catcode_letter:N \@ + \char_set_catcode_letter:N \_ + \char_set_catcode_letter:N \: + } +\setcounter{StandardModuleDepth}{1} +\@addtoreset{CodelineNo}{part} +\tl_replace_once:Nnn \theCodelineNo + { \HDorg@theCodelineNo } + { \textcolor[gray]{0.5} { \sffamily\tiny\arabic{CodelineNo} } } +\fvset{gobble=2} +\cs_gset_eq:NN \verbatim \Verbatim +\cs_gset_eq:NN \endverbatim \endVerbatim +\cs_set_protected:Npn \ifnot@excluded + { + \exp_args:Nxx \expanded@notin + { \c__codedoc_backslash_tl \tl_to_str:N \macro@namepart , } + { \exp_args:NV \tl_to_str:n \index@excludelist } + } +\cs_new:Npn \pdfstringnewline { : ~ } +\DeclareExpandableDocumentCommand + { \__codedoc_pdfstring_newline:w } { s o m } { \pdfstringnewline #3 } +\pdfstringdefDisableCommands + { \cs_set_eq:NN \\ \__codedoc_pdfstring_newline:w } +\setlength \textwidth { 385pt } +\addtolength \marginparwidth { 30pt } +\addtolength \oddsidemargin { 20pt } +\addtolength \evensidemargin { 20pt } +\cs_new_eq:NN \__codedoc_oldlist:nn \list +\cs_gset:Npn \list #1 #2 + { \__codedoc_oldlist:nn {#1} { #2 \dim_zero:N \listparindent } } +\setlength \parindent { 2em } +\setlength \itemindent { 0pt } +\setlength \parskip { 1pt plus 3pt minus 0pt } +\tl_gset:Nn \partname {File} +\@addtoreset{section}{part} +\cs_gset:Npn \l@section #1#2 + { + \ifnum \c@tocdepth >\z@ + \addpenalty\@secpenalty + \addvspace{\TBtocsectionspace}% + \setlength\@tempdima{2.5em} % was 1.5em + \begingroup + \parindent \z@ \rightskip \@pnumwidth + \parfillskip -\@pnumwidth + \leavevmode \TBtocsectionfont + \advance\leftskip\@tempdima + \hskip -\leftskip + #1\nobreak\hfil \nobreak\hb@xt@\@pnumwidth{\hss #2}\par + \endgroup + \fi + } +\cs_gset:Npn \l@subsection + { \@dottedtocline{2}{2.5em}{2.3em} } % #2 = 1.5em +\AtBeginDocument + { + \MakeShortVerb \" + \MakeShortVerb \| + \onecolumn + \SelfDocumenting + } +\AtEndDocument + { + \DeleteShortVerb \" + \DeleteShortVerb \| + } +\providecommand*\eTeX{\hologo{eTeX}} +\providecommand*\IniTeX{\hologo{iniTeX}} +\providecommand*\Lua{Lua} +\providecommand*\LuaTeX{\hologo{LuaTeX}} +\providecommand*\pdfTeX{\hologo{pdfTeX}} +\providecommand*\XeTeX{\hologo{XeTeX}} +\providecommand*\pTeX{p\kern-.2em\hologo{TeX}} +\providecommand*\upTeX{up\kern-.2em\hologo{TeX}} +\providecommand*\epTeX{$\varepsilon$-\pTeX} +\providecommand*\eupTeX{$\varepsilon$-\upTeX} +\DeclareDocumentCommand \cmd { O{} m } + { \__codedoc_cmd:no {#1} { \token_to_str:N #2 } } +\DeclareDocumentCommand \cs { O{} m } + { \__codedoc_cmd:no {#1} { \c__codedoc_backslash_tl #2 } } +\DeclareDocumentCommand \tn { O{} m } + { + \__codedoc_cmd:no + { module = TeX , replace = false , #1 } + { \c__codedoc_backslash_tl #2 } + } +\DeclareDocumentCommand \meta { m } + { \__codedoc_meta:n {#1} } +\DeclareExpandableDocumentCommand + { \__codedoc_pdfstring_cmd:w } { o m } { \token_to_str:N #2 } +\DeclareExpandableDocumentCommand + { \__codedoc_pdfstring_cs:w } { o m } { \textbackslash \tl_to_str:n {#2} } +\cs_new:Npn \__codedoc_pdfstring_meta:w #1 + { < \tl_to_str:n {#1} > } +\pdfstringdefDisableCommands + { + \cs_set_eq:NN \cmd \__codedoc_pdfstring_cmd:w + \cs_set_eq:NN \cs \__codedoc_pdfstring_cs:w + \cs_set_eq:NN \tn \__codedoc_pdfstring_cs:w + \cs_set_eq:NN \meta \__codedoc_pdfstring_meta:w + } +\newcommand\Arg[1] + { \texttt{\char`\{} \meta{#1} \texttt{\char`\}} } +\providecommand\marg[1]{ \Arg{#1} } +\providecommand\oarg[1]{ \texttt[ \meta{#1} \texttt] } +\providecommand\parg[1]{ \texttt( \meta{#1} \texttt) } +\DeclareRobustCommand \file {\nolinkurl} +\DeclareRobustCommand \env {\texttt} +\DeclareRobustCommand \pkg {\textsf} +\DeclareRobustCommand \cls {\textsf} +\NewDocumentCommand \EnableDocumentation { } + { \bool_gset_true:N \g__codedoc_typeset_documentation_bool } +\NewDocumentCommand \EnableImplementation { } + { \bool_gset_true:N \g__codedoc_typeset_implementation_bool } +\NewDocumentCommand \DisableDocumentation { } + { \bool_gset_false:N \g__codedoc_typeset_documentation_bool } +\NewDocumentCommand \DisableImplementation { } + { \bool_gset_false:N \g__codedoc_typeset_implementation_bool } +\NewDocumentEnvironment { documentation } { } + { + \bool_if:NTF \g__codedoc_typeset_documentation_bool + { \bool_set_false:N \l__codedoc_in_implementation_bool } + { \comment } + } + { \bool_if:NF \g__codedoc_typeset_documentation_bool { \endcomment } } +\NewDocumentEnvironment { implementation } { } + { + \bool_if:NTF \g__codedoc_typeset_implementation_bool + { \bool_set_true:N \l__codedoc_in_implementation_bool } + { \comment } + } + { \bool_if:NF \g__codedoc_typeset_implementation_bool { \endcomment } } +\DeclareDocumentEnvironment { variable } { O{} +v } + { + \bool_if:NTF \l__codedoc_in_implementation_bool + { \__codedoc_macro:nnw { var , #1 } {#2} } + { \__codedoc_function:nnw {#1} {#2} } + } + { + \bool_if:NTF \l__codedoc_in_implementation_bool + { \__codedoc_macro_end: } + { \__codedoc_function_end: } + } +\DeclareDocumentEnvironment { function } { O{} +v } + { \__codedoc_function:nnw {#1} {#2} } + { \__codedoc_function_end: } +\DeclareDocumentEnvironment { macro } { O{} +v } + { \__codedoc_macro:nnw {#1} {#2} } + { \__codedoc_macro_end: } +\NewDocumentEnvironment { syntax } { } + { \__codedoc_syntax:w } + { + \__codedoc_syntax_end: + \ignorespacesafterend + } +\NewDocumentEnvironment { texnote } { } + { + \endgraf + \vspace{3mm} + \small\textbf{\TeX~hackers~note:} + } + { + \vspace{3mm} + } +\NewDocumentEnvironment { arguments } { } + { + \enumerate [ + nolistsep , + label = \texttt{\#\arabic*} ~ : , + labelsep = * , + ] + } + { + \endenumerate + } +\NewDocumentCommand { \CodedocExplain } { } + { \CodedocExplainEXP \ \CodedocExplainREXP \ \CodedocExplainTF } +\NewDocumentCommand { \CodedocExplainEXP } { } + { + \raisebox{\baselineskip}[0pt][0pt]{\hypertarget{expstar}{}}% + \__codedoc_typeset_exp:\ indicates~fully~expandable~functions,~which~ + can~be~used~within~an~\texttt{x}-type~argument~(in~plain~ + \TeX{}~terms,~inside~an~\cs{edef}),~as~well~as~within~an~ + \texttt{f}-type~argument. + } +\NewDocumentCommand { \CodedocExplainREXP } { } + { + \raisebox{\baselineskip}[0pt][0pt]{\hypertarget{rexpstar}{}}% + \__codedoc_typeset_rexp:\ indicates~ + restricted~expandable~functions,~which~can~be~used~within~an~ + \texttt{x}-type~argument~but~cannot~be~fully~expanded~within~an~ + \texttt{f}-type~argument. + } +\NewDocumentCommand { \CodedocExplainTF } { } + { + \raisebox{\baselineskip}[0pt][0pt]{\hypertarget{explTF}{}}% + \__codedoc_typeset_TF:\ indicates~conditional~(\texttt{if})~functions~ + whose~variants~with~\texttt{T},~\texttt{F}~and~\texttt{TF}~ + argument~specifiers~expect~different~ + \enquote{true}/\enquote{false}~branches. + } +\keys_define:nn { l3doc-TUB/cmd } + { + index .tl_set:N = \l__codedoc_cmd_index_tl , + module .tl_set:N = \l__codedoc_cmd_module_tl , + no-index .bool_set:N = \l__codedoc_cmd_noindex_bool , + replace .bool_set:N = \l__codedoc_cmd_replace_bool , + } +\cs_new_protected:Npn \__codedoc_cmd:nn #1#2 + { + \bool_set_false:N \l__codedoc_cmd_noindex_bool + \bool_set_true:N \l__codedoc_cmd_replace_bool + \tl_set:Nn \l__codedoc_cmd_index_tl { \q_no_value } + \tl_set:Nn \l__codedoc_cmd_module_tl { \q_no_value } + \keys_set:nn { l3doc-TUB/cmd } {#1} + \tl_set:Nn \l__codedoc_cmd_tl {#2} + \bool_if:NT \l__codedoc_cmd_replace_bool + { + \tl_set_rescan:Nnn \l__codedoc_tmpb_tl { } { _ } + \tl_replace_all:Non \l__codedoc_cmd_tl \l__codedoc_tmpb_tl { _ } + \__codedoc_replace_at_at:N \l__codedoc_cmd_tl + \tl_replace_all:Nno \l__codedoc_cmd_tl { _ } \l__codedoc_tmpb_tl + } + \mode_if_math:T { \mbox } + { + \verbatim@font + \__codedoc_if_almost_str:VT \l__codedoc_cmd_tl + { + \tl_set:Nx \l__codedoc_cmd_tl { \tl_to_str:N \l__codedoc_cmd_tl } + \tl_replace_all:Non \l__codedoc_cmd_tl + { \token_to_str:N _ } { \_ } + } + \tl_replace_all:Nnn \l__codedoc_cmd_tl { ~ } { \@xobeysp } + \l__codedoc_cmd_tl + \@ + } + \bool_if:NF \l__codedoc_cmd_noindex_bool + { + \quark_if_no_value:NF \l__codedoc_cmd_index_tl + { + \tl_set:Nx \l__codedoc_cmd_tl + { \c_backslash_str \exp_not:o { \l__codedoc_cmd_index_tl } } + } + + \exp_args:No \__codedoc_key_get:n { \l__codedoc_cmd_tl } + \quark_if_no_value:NF \l__codedoc_cmd_module_tl + { + \tl_set:Nx \l__codedoc_index_module_tl + { \tl_to_str:N \l__codedoc_cmd_module_tl } + } + \__codedoc_special_index_module:ooonN + { \l__codedoc_index_key_tl } + { \l__codedoc_index_macro_tl } + { \l__codedoc_index_module_tl } + { usage } + \l__codedoc_index_internal_bool + } + } +\cs_generate_variant:Nn \__codedoc_cmd:nn { no } +\cs_new_protected:Npn \__codedoc_meta:n #1 + { + \tl_set:Nn \l__codedoc_tmpa_tl {#1} + \tl_map_inline:nn + { { 3 } { 4 } { 7 } { 8 } { 11 } { 12 } { 13 } } + { + \tl_set_rescan:Nnn \l__codedoc_tmpb_tl + { \char_set_catcode:nn { `_ } {##1} } { _ } + \tl_replace_all:Non \l__codedoc_tmpa_tl \l__codedoc_tmpb_tl + { \__codedoc_ensuremath_sb:n } + } + \exp_args:NV \__codedoc_meta_original:n \l__codedoc_tmpa_tl + } +\cs_new_protected:Npn \__codedoc_ensuremath_sb:n #1 + { \ensuremath { \sb {#1} } } +\cs_new_protected:Npn \__codedoc_meta_original:n #1 + { + \ensuremath \langle + \mode_if_math:T { \nfss@text } + { + \meta@font@select + \edef \meta@hyphen@restore + { \hyphenchar \the \font \the \hyphenchar \font } + \hyphenchar \font \m@ne + \language \l@nohyphenation + #1 \/ + \meta@hyphen@restore + } + \ensuremath \rangle + } +\cs_new_protected:Npn \__codedoc_typeset_exp: + { \hyperlink{expstar} {$\star$} } +\cs_new_protected:Npn \__codedoc_typeset_rexp: + { \hyperlink{rexpstar} {\ding{73}} } % hollow star +\cs_new_protected:Npn \__codedoc_typeset_TF: + { + \hyperlink{explTF} + { + \color{black} + \itshape TF + \makebox[0pt][r] + { + \color{red} + \underline { \phantom{\itshape TF} \kern-0.1em } + } + } + } +\cs_new_protected:Npn \__codedoc_typeset_aux:n #1 + { + { \color[gray]{0.5} #1 } + } +\cs_new_protected:Npn \__codedoc_get_hyper_target:nN #1#2 + { + \tl_set:Nx #2 { \tl_to_str:n {#1} } + \tl_replace_all:Nxn #2 { \iow_char:N \_ } { / } + \tl_remove_all:Nx #2 { \iow_char:N \\ } + \tl_put_left:Nn #2 { doc/function// } + } +\cs_generate_variant:Nn \__codedoc_get_hyper_target:nN { o , x } +\cs_new_protected:Npn \__codedoc_names_get_seq:nN #1#2 + { + \tl_set:Nx \l__codedoc_tmpa_tl { \tl_to_str:n {#1} } + \bool_if:NTF \l__codedoc_names_verb_bool + { + \seq_clear:N #2 + \seq_put_right:NV #2 \l__codedoc_tmpa_tl + } + { + \tl_remove_all:Nx \l__codedoc_tmpa_tl + { \iow_char:N \^^M \iow_char:N \% } + \tl_remove_all:Nx \l__codedoc_tmpa_tl { \tl_to_str:n { ^ ^ A } } + \tl_remove_all:Nx \l__codedoc_tmpa_tl { \iow_char:N \^^I } + \tl_remove_all:Nx \l__codedoc_tmpa_tl { \iow_char:N \^^M } + \__codedoc_replace_at_at:N \l__codedoc_tmpa_tl + \exp_args:NNx \seq_set_from_clist:Nn #2 + { \tl_to_str:N \l__codedoc_tmpa_tl } + } + } +\cs_new_protected:Npn \__codedoc_names_parse: + { + \tl_clear:N \l__codedoc_names_block_tl + \seq_map_function:NN + \l__codedoc_names_seq + \__codedoc_names_parse_one:n + } +\cs_new_protected:Npn \__codedoc_names_parse_one:n #1 + { + \__codedoc_split_function_do:nn {#1} + { \__codedoc_names_parse_one_aux:nnNn } + {#1} + } +\cs_new_protected:Npn \__codedoc_names_parse_one_aux:nnNn #1#2#3#4 + { + \bool_if:NTF #3 + { + \tl_if_head_eq_charcode:nNTF {#2} : + { \__codedoc_names_parse_aux:nnn {#4} {#4} { \scan_stop: } } + { + \exp_args:Nx \__codedoc_names_parse_aux:nnn + { \__codedoc_base_form_aux:nnN {#1} {#2} #3 } + {#1} {#2} + } + } + { + \bool_if:NT \l__codedoc_macro_TF_bool + { \msg_error:nnx { l3doc-TUB } { no-signature-TF } {#4} } + \__codedoc_names_parse_aux:nnn {#4} {#4} { \scan_stop: } + } + } +\cs_new_protected:Npn \__codedoc_names_parse_aux:nnn #1 + { \exp_args:Nc \__codedoc_names_parse_aux:Nnn { \__codedoc_lseq_name:n {#1} } } +\cs_new_protected:Npn \__codedoc_names_parse_aux:Nnn #1#2#3 + { + \tl_if_in:NnF \l__codedoc_names_block_tl {#1} + { + \tl_put_right:Nn \l__codedoc_names_block_tl {#1} + \seq_clear_new:N #1 + \seq_put_right:Nn #1 {#2} + } + \seq_put_right:Nn #1 {#3} + } +\cs_new_protected:Npn \__codedoc_names_typeset: + { + \tl_map_function:NN \l__codedoc_names_block_tl + \__codedoc_names_typeset_auxi:n + } +\cs_new_protected:Npn \__codedoc_names_typeset_auxi:n #1 + { + \seq_pop:NN #1 \l__codedoc_tmpa_tl + \tl_gset_eq:NN \g__codedoc_base_name_tl \l__codedoc_tmpa_tl + \tl_greplace_all:Nno \g__codedoc_base_name_tl + { ~ } { \c_catcode_other_space_tl } + \seq_get:NN #1 \l__codedoc_tmpa_tl + \str_if_eq:eeTF { \l__codedoc_tmpa_tl } { \scan_stop: } + { + \seq_gclear:N \g__codedoc_variants_seq + \__codedoc_names_typeset_auxii:x { \g__codedoc_base_name_tl } + } + { + \seq_gset_eq:NN \g__codedoc_variants_seq #1 + \seq_gpop:NN \g__codedoc_variants_seq \l__codedoc_tmpb_tl + \__codedoc_names_typeset_auxii:x + { \g__codedoc_base_name_tl : \l__codedoc_tmpb_tl } + } + } +\cs_new_protected:Npn \__codedoc_names_typeset_auxii:n #1 + { + \bool_if:NT \l__codedoc_macro_pTF_bool + { + \__codedoc_names_typeset_block:xN + { \__codedoc_predicate_from_base:n {#1} } + \c_false_bool + } + \bool_if:NT \l__codedoc_macro_noTF_bool + { \__codedoc_names_typeset_block:nN {#1} \c_false_bool } + \__codedoc_names_typeset_block:nN {#1} \l__codedoc_macro_TF_bool + } +\cs_generate_variant:Nn \__codedoc_names_typeset_auxii:n { x } +\cs_new_protected:Npn \__codedoc_names_typeset_block:nN + { + \int_compare:nNnTF \l__codedoc_nested_macro_int = 0 + { \__codedoc_typeset_function_block:nN } + { \__codedoc_macro_typeset_block:nN } + } +\cs_generate_variant:Nn \__codedoc_names_typeset_block:nN { x } +\prg_new_conditional:Npnn \__codedoc_if_macro_internal:n #1 { p , T , F , TF } + { + \bool_if:NTF \l__codedoc_macro_internal_set_bool + { + \bool_if:NTF \l__codedoc_macro_internal_bool + { \prg_return_true: } { \prg_return_false: } + } + { + \tl_if_empty:fTF + { + \exp_after:wN \__codedoc_if_macro_internal_aux:w + \tl_to_str:n { #1 ~ __ } + } + { \prg_return_false: } { \prg_return_true: } + } + } +\exp_last_unbraced:NNNNo + \cs_new:Npn \__codedoc_if_macro_internal_aux:w #1 { \tl_to_str:n { __ } } { } +\cs_new_protected:Npn \__codedoc_names_block_base_map:N #1 + { + \tl_map_inline:Nn \l__codedoc_names_block_tl + { + \group_begin: + \seq_set_eq:NN \l__codedoc_tmpa_seq ##1 + \seq_pop:NN \l__codedoc_tmpa_seq \l__codedoc_tmpa_tl + \seq_get:NN \l__codedoc_tmpa_seq \l__codedoc_tmpb_tl + \exp_args:NNx + \group_end: + #1 + { + \l__codedoc_tmpa_tl + \str_if_eq:eeF { \l__codedoc_tmpb_tl } { \scan_stop: } + { : \l__codedoc_tmpb_tl } + \bool_if:NT \l__codedoc_macro_TF_bool { TF } + } + } + } +\keys_define:nn { l3doc-TUB/function } + { + TF .value_forbidden:n = true , + TF .code:n = + { + \bool_set_true:N \l__codedoc_macro_TF_bool + } , + EXP .value_forbidden:n = true , + EXP .code:n = + { + \bool_set_true:N \l__codedoc_macro_EXP_bool + \bool_set_false:N \l__codedoc_macro_rEXP_bool + } , + rEXP .value_forbidden:n = true , + rEXP .code:n = + { + \bool_set_false:N \l__codedoc_macro_EXP_bool + \bool_set_true:N \l__codedoc_macro_rEXP_bool + } , + pTF .value_forbidden:n = true , + pTF .code:n = + { + \bool_set_true:N \l__codedoc_macro_pTF_bool + \bool_set_true:N \l__codedoc_macro_TF_bool + \bool_set_true:N \l__codedoc_macro_EXP_bool + \bool_set_false:N \l__codedoc_macro_rEXP_bool + } , + noTF .value_forbidden:n = true , + noTF .code:n = + { + \bool_set_true:N \l__codedoc_macro_noTF_bool + \bool_set_true:N \l__codedoc_macro_TF_bool + } , + added .code:n = { \__codedoc_date_set:Nn \l__codedoc_date_added_tl {#1} }, + updated .code:n = { \__codedoc_date_set:Nn \l__codedoc_date_updated_tl {#1} } , + deprecated .code:n = { \__codedoc_deprecated_on:n {#1} } , + tested .code:n = { } , + label .code:n = + { + \clist_set:Nn \l__codedoc_function_label_clist {#1} + \bool_set_true:N \l__codedoc_no_label_bool + } , + verb .value_forbidden:n = true , + verb .bool_set:N = \l__codedoc_names_verb_bool , + module .tl_set:N = \l__codedoc_override_module_tl , + } +\cs_new_protected:Npn \__codedoc_date_set:Nn #1#2 + { + \tl_set:Nn #1 {#2} + \regex_replace_once:nnNF + { \A(\d\d\d\d)[-/](\d\d?)[-/](\d\d?)\Z } { \1-\2-\3 } #1 + { + \msg_error:nnn { l3doc-TUB } { date-format } {#2} + \tl_set:Nn #1 { 1970-01-01 } + } + } +\cs_new_protected:Npn \__codedoc_deprecated_on:n #1 + { + \__codedoc_date_set:Nn \l__codedoc_tmpa_tl {#1} + \exp_args:No \__codedoc_date_compare:nNnT + { \l__codedoc_tmpa_tl } < { \tex_year:D - \tex_month:D - \tex_day:D } + { + \msg_error:nnxx { l3doc-TUB } { deprecated-function } + { \tl_to_str:N \l__codedoc_macro_argument_tl } + { \l__codedoc_tmpa_tl } + } + \bool_set_true:N \l__codedoc_macro_internal_bool + \bool_set_true:N \l__codedoc_macro_internal_set_bool + } +\cs_new_protected:Npn \__codedoc_function:nnw #1#2 + { + \__codedoc_function_typeset_start: + \__codedoc_function_init: + \tl_set:Nn \l__codedoc_macro_argument_tl {#2} + \keys_set:nn { l3doc-TUB/function } {#1} + \__codedoc_names_get_seq:nN {#2} \l__codedoc_names_seq + \__codedoc_names_parse: + \__codedoc_function_typeset: + \__codedoc_function_reset: + \__codedoc_function_descr_start:w + } +\cs_new_protected:Npn \__codedoc_function_end: + { + \__codedoc_function_descr_stop: + \__codedoc_function_assemble: + \__codedoc_function_typeset_stop: + } +\cs_new_protected:Npn \__codedoc_function_typeset_start: + { + \par \bigskip \noindent + } +\cs_new_protected:Npn \__codedoc_function_typeset_stop: + { + \par + \allowbreak + } +\cs_new_protected:Npn \__codedoc_function_init: + { + \box_if_empty:NF \g__codedoc_syntax_box + { \msg_error:nn { l3doc-TUB } { syntax-nested-function } } + \coffin_clear:N \l__codedoc_descr_coffin + \box_gclear:N \g__codedoc_syntax_box + \coffin_clear:N \l__codedoc_syntax_coffin + \coffin_clear:N \l__codedoc_functions_coffin + \bool_set_false:N \l__codedoc_macro_TF_bool + \bool_set_false:N \l__codedoc_macro_pTF_bool + \bool_set_false:N \l__codedoc_macro_noTF_bool + \bool_set_false:N \l__codedoc_macro_EXP_bool + \bool_set_false:N \l__codedoc_macro_rEXP_bool + \bool_set_false:N \l__codedoc_no_label_bool + \bool_set_false:N \l__codedoc_names_verb_bool + \bool_set_true:N \l__codedoc_in_function_bool + \clist_clear:N \l__codedoc_function_label_clist + \tl_set:Nn \l__codedoc_override_module_tl { \q_no_value } + \char_set_active_eq:NN \< \__codedoc_shorthand_meta: + \char_set_catcode_active:N \< + } +\cs_new_protected:Npn \__codedoc_shorthand_meta: + { \mode_if_math:TF { < } { \__codedoc_shorthand_meta:w } } +\cs_new_protected_nopar:Npn \__codedoc_shorthand_meta:w #1 > { \meta {#1} } +\cs_new_protected:Npn \__codedoc_function_reset: + { + \tl_set:Nn \l__codedoc_override_module_tl { \q_no_value } + } +\cs_new_protected:Npn \__codedoc_function_typeset: + { + \dim_zero:N \l__codedoc_trial_width_dim + \hcoffin_set:Nn \l__codedoc_functions_coffin { \__codedoc_typeset_functions: } + \dim_set:Nn \l__codedoc_trial_width_dim + { \box_wd:N \l__codedoc_functions_coffin } + \bool_set:Nn \l__codedoc_long_name_bool + { \dim_compare_p:nNn \l__codedoc_trial_width_dim > {\marginparwidth + 1cm} } % FMi crude fix + } +\cs_new_protected:Npn \__codedoc_function_descr_start:w + { + \vcoffin_set:Nnw \l__codedoc_descr_coffin { \textwidth } + \noindent \ignorespaces + } +\cs_new_protected:Npn \__codedoc_function_descr_stop: + { \vcoffin_set_end: } +\cs_new_protected:Npn \__codedoc_function_assemble: + { + \hcoffin_set:Nn \l__codedoc_syntax_coffin + { \box_use_drop:N \g__codedoc_syntax_box } + \bool_if:NTF \l__codedoc_long_name_bool + { + \coffin_join:NnnNnnnn + \l__codedoc_output_coffin {hc} {vc} + \l__codedoc_syntax_coffin {l} {T} + {0pt} {0pt} + \coffin_join:NnnNnnnn + \l__codedoc_output_coffin {l} {t} + \l__codedoc_functions_coffin {r} {t} + {-\marginparsep} {0pt} + \coffin_join:NnnNnnnn + \l__codedoc_output_coffin {l} {b} + \l__codedoc_descr_coffin {l} {t} + {0.75\marginparwidth + \marginparsep} {-\medskipamount} + \coffin_typeset:Nnnnn \l__codedoc_output_coffin + {\l__codedoc_descr_coffin-l} {\l__codedoc_descr_coffin-t} + {0pt} {0pt} + } + { + \coffin_join:NnnNnnnn + \l__codedoc_output_coffin {hc} {vc} + \l__codedoc_syntax_coffin {l} {t} + {0pt} {0pt} + \coffin_join:NnnNnnnn + \l__codedoc_output_coffin {l} {b} + \l__codedoc_descr_coffin {l} {t} + {0pt} {-\medskipamount} + \coffin_join:NnnNnnnn + \l__codedoc_output_coffin {l} {t} + \l__codedoc_functions_coffin {r} {t} + {-\marginparsep} {0pt} + \coffin_typeset:Nnnnn \l__codedoc_output_coffin + {\l__codedoc_syntax_coffin-l} {\l__codedoc_syntax_coffin-T} + {0pt} {0pt} + } + } +\cs_new_protected:Npn \__codedoc_typeset_functions: + { + \small\ttfamily + \HD@savedestfalse + \HD@target + \Hy@MakeCurrentHref { HD. \int_use:N \c@HD@hypercount } + \begin{tabular} [t] { @{} l @{} >{\hspace{\tabcolsep}} r @{} } + \toprule + \__codedoc_function_extra_labels: + \__codedoc_names_typeset: + \__codedoc_typeset_dates: + \bottomrule + \end{tabular} + \normalfont\normalsize + } +\cs_new_protected:Npn \__codedoc_typeset_function_block:nN #1#2 + { + \__codedoc_function_index:x + { #1 \bool_if:NT #2 { \tl_to_str:n {TF} } } + \__codedoc_function_label:xN {#1} #2 + #1 + \bool_if:NT #2 { \__codedoc_typeset_TF: } + \__codedoc_typeset_expandability: + \seq_if_empty:NF \g__codedoc_variants_seq + { \__codedoc_typeset_variant_list:nN {#1} #2 } + \\ + } +\cs_generate_variant:Nn \__codedoc_typeset_function_block:nN { x } +\cs_new_protected:Npn \__codedoc_function_index:n #1 + { + \seq_gput_right:Nn \g_doc_functions_seq {#1} + \__codedoc_special_index:nn {#1} { usage } + } +\cs_generate_variant:Nn \__codedoc_function_index:n { x } +\cs_new_protected:Npn \__codedoc_typeset_expandability: + { + & + \bool_if:NT \l__codedoc_macro_EXP_bool { \__codedoc_typeset_exp: } + \bool_if:NT \l__codedoc_macro_rEXP_bool { \__codedoc_typeset_rexp: } + } +\cs_new_protected:Npn \__codedoc_typeset_variant_list:nN #1#2 + { + \\ + \__codedoc_typeset_aux:n { \__codedoc_get_function_name:n {#1} } + : + \int_compare:nTF { \seq_count:N \g__codedoc_variants_seq == 1 } + { \seq_use:Nn \g__codedoc_variants_seq { } } + { + \textrm( + \seq_use:Nn \g__codedoc_variants_seq { \textrm| } + \textrm) + } + \bool_if:NT #2 { \__codedoc_typeset_TF: } + \__codedoc_typeset_expandability: + } +\cs_new_protected:Npn \__codedoc_function_extra_labels: + { + \bool_if:NT \l__codedoc_no_label_bool + { + \clist_map_inline:Nn \l__codedoc_function_label_clist + { + \__codedoc_get_hyper_target:oN { \token_to_str:N ##1 } + \l__codedoc_tmpa_tl + \exp_args:No \label { \l__codedoc_tmpa_tl } + } + } + } +\cs_new_protected:Npn \__codedoc_function_label:nN #1#2 + { + \bool_if:NF \l__codedoc_no_label_bool + { + \__codedoc_get_hyper_target:xN + { + \exp_not:n {#1} + \bool_if:NT #2 { \tl_to_str:n {TF} } + } + \l__codedoc_tmpa_tl + \exp_args:No \label { \l__codedoc_tmpa_tl } + } + } +\cs_generate_variant:Nn \__codedoc_function_label:nN { x } +\cs_new:Npn \__codedoc_typeset_dates: + { + \bool_lazy_and:nnF + { \tl_if_empty_p:N \l__codedoc_date_added_tl } + { \tl_if_empty_p:N \l__codedoc_date_updated_tl } + { \midrule } + \tl_if_empty:NF \l__codedoc_date_added_tl + { + \multicolumn { 2 } { @{} r @{} } + { \scriptsize New: \, \l__codedoc_date_added_tl } \\ + } + + \tl_if_empty:NF \l__codedoc_date_updated_tl + { + \multicolumn { 2 } { @{} r @{} } + { \scriptsize Updated: \, \l__codedoc_date_updated_tl } \\ + } + } +\dim_new:N \l__codedoc_syntax_dim +\cs_new_protected:Npn \__codedoc_syntax:w + { + \box_if_empty:NF \g__codedoc_syntax_box + { \msg_error:nn { l3doc-TUB } { multiple-syntax } } + \dim_set:Nn \l__codedoc_syntax_dim + { + \textwidth + \bool_if:NT \l__codedoc_long_name_bool + { + 0.75 \marginparwidth - \l__codedoc_trial_width_dim } + } + \hbox_gset:Nw \g__codedoc_syntax_box + \small \ttfamily + \arrayrulecolor{white} + \begin{tabular} { @{} l @{} } + \toprule + \begin{minipage}[t]{\l__codedoc_syntax_dim} + \raggedright + \obeyspaces + \obeylines + } +\cs_new_protected:Npn \__codedoc_syntax_end: + { + \end{minipage} + \end{tabular} + \arrayrulecolor{black} + \hbox_gset_end: + \bool_if:NF \l__codedoc_in_function_bool + { + \begin{quote} + \mode_leave_vertical: + \box_use_drop:N \g__codedoc_syntax_box + \end{quote} + } + } +\keys_define:nn { l3doc-TUB/macro } + { + aux .value_forbidden:n = true , + aux .code:n = + { + \msg_warning:nnnn { l3doc-TUB } { deprecated-option } + { aux } { function/macro } + } , + internal .value_forbidden:n = true , + internal .code:n = + { + \bool_set_true:N \l__codedoc_macro_internal_bool + \bool_set_true:N \l__codedoc_macro_internal_set_bool + } , + int .value_forbidden:n = true , + int .code:n = + { + \bool_set_true:N \l__codedoc_macro_internal_bool + \bool_set_true:N \l__codedoc_macro_internal_set_bool + } , + var .value_forbidden:n = true , + var .code:n = + { \bool_set_true:N \l__codedoc_macro_var_bool } , + TF .value_forbidden:n = true , + TF .code:n = + { \bool_set_true:N \l__codedoc_macro_TF_bool } , + pTF .value_forbidden:n = true , + pTF .code:n = + { + \bool_set_true:N \l__codedoc_macro_TF_bool + \bool_set_true:N \l__codedoc_macro_pTF_bool + \bool_set_true:N \l__codedoc_macro_EXP_bool + \bool_set_false:N \l__codedoc_macro_rEXP_bool + } , + noTF .value_forbidden:n = true , + noTF .code:n = + { + \bool_set_true:N \l__codedoc_macro_TF_bool + \bool_set_true:N \l__codedoc_macro_noTF_bool + } , + EXP .value_forbidden:n = true , + EXP .code:n = + { + \bool_set_true:N \l__codedoc_macro_EXP_bool + \bool_set_false:N \l__codedoc_macro_rEXP_bool + } , + rEXP .value_forbidden:n = true , + rEXP .code:n = + { + \bool_set_false:N \l__codedoc_macro_EXP_bool + \bool_set_true:N \l__codedoc_macro_rEXP_bool + } , + tested .code:n = + { + \bool_set_true:N \l__codedoc_macro_tested_bool + } , + added .code:n = {} , % TODO + updated .code:n = {} , % TODO + deprecated .code:n = { \__codedoc_deprecated_on:n {#1} } , + verb .bool_set:N = \l__codedoc_names_verb_bool , + module .tl_set:N = \l__codedoc_override_module_tl , + documented-as .tl_set:N = \l__codedoc_macro_documented_tl , + } +\cs_new_protected:Npn \__codedoc_macro:nnw #1#2 + { + \__codedoc_macro_init: + \tl_set:Nn \l__codedoc_macro_argument_tl {#2} + \keys_set:nn { l3doc-TUB/macro } {#1} + \__codedoc_names_get_seq:nN {#2} \l__codedoc_names_seq + \__codedoc_names_parse: + \__codedoc_macro_save_names: + \__codedoc_names_typeset: + \__codedoc_macro_dump: + \__codedoc_macro_reset: + } +\cs_new_protected:Npn \__codedoc_macro_init: + { + \int_incr:N \l__codedoc_nested_macro_int + \bool_set_false:N \l__codedoc_macro_internal_bool + \bool_set_false:N \l__codedoc_macro_internal_set_bool + \bool_set_false:N \l__codedoc_macro_TF_bool + \bool_set_false:N \l__codedoc_macro_pTF_bool + \bool_set_false:N \l__codedoc_macro_noTF_bool + \bool_set_false:N \l__codedoc_macro_EXP_bool + \bool_set_false:N \l__codedoc_macro_rEXP_bool + \bool_set_false:N \l__codedoc_macro_var_bool + \bool_set_false:N \l__codedoc_macro_tested_bool + \bool_set_false:N \l__codedoc_names_verb_bool + \tl_set:Nn \l__codedoc_override_module_tl { \q_no_value } + \tl_clear:N \l__codedoc_macro_documented_tl + \cs_set_eq:NN \testfile \__codedoc_print_testfile:n + \box_clear:N \l__codedoc_macro_index_box + \vbox_set:Nn \l__codedoc_macro_box + { + \hbox:n + { + \strut + \int_compare:nNnT \l__codedoc_macro_int = 0 + { \HD@target } + } + \vskip \int_eval:n { \l__codedoc_macro_int - 1 } \baselineskip + } + } +\cs_new_protected:Npn \__codedoc_macro_reset: + { + \tl_set:Nn \l__codedoc_override_module_tl { \q_no_value } + } +\cs_new_protected:Npn \__codedoc_macro_save_names: + { + \tl_if_empty:NTF \l__codedoc_macro_documented_tl + { \__codedoc_names_block_base_map:N \__codedoc_macro_save_names_aux:n } + { + \seq_gput_right:Nf \g__codedoc_nested_names_seq + { \exp_after:wN \token_to_str:N \l__codedoc_macro_documented_tl } + } + } +\cs_new_protected:Npn \__codedoc_macro_save_names_aux:n #1 + { \seq_gput_right:Nn \g__codedoc_nested_names_seq {#1} } +\cs_new_protected:Npn \__codedoc_macro_dump: + { + \topsep\MacroTopsep + \trivlist + \cs_set:Npn \makelabel ##1 + { + \llap + { + \hbox_unpack_drop:N \l__codedoc_macro_index_box + \vtop to \baselineskip + { + \vbox_unpack_drop:N \l__codedoc_macro_box + \vss + } + } + } + \item [ ] + } +\cs_new_protected:Npn \__codedoc_macro_typeset_block:nN #1#2 + { + \__codedoc_macro_single:nNN {#1} \c_true_bool #2 + \seq_if_empty:NF \g__codedoc_variants_seq + { + \__codedoc_macro_typeset_variant_list:xN + { \__codedoc_get_function_name:n {#1} } #2 + } + } +\cs_generate_variant:Nn \__codedoc_macro_typeset_block:nN { x } +\cs_new_protected:Npn \__codedoc_macro_typeset_variant_list:nN #1#2 + { + \seq_map_inline:Nn \g__codedoc_variants_seq + { \__codedoc_macro_single:nNN { #1 : ##1 } \c_false_bool #2 } + } +\cs_generate_variant:Nn \__codedoc_macro_typeset_variant_list:nN { x } +\cs_new_protected:Npn \__codedoc_macro_single:nNN #1#2#3 + { + \tl_set:Nn \saved@macroname {#1} + \__codedoc_macro_typeset_one:nN {#1} #3 + \bool_if:NT #3 { \DoNotIndex {#1} } + \exp_args:Nx \__codedoc_macro_index:nN + { #1 \bool_if:NT #3 { \tl_to_str:n { TF } } } + #2 + } +\cs_new_protected:Npn \__codedoc_macro_index:nN #1#2 + { + \DoNotIndex {#1} + \bool_if:NT #2 + { + \__codedoc_if_macro_internal:nF {#1} + { \seq_gput_right:Nn \g_doc_macros_seq {#1} } + \hbox_set:Nw \l__codedoc_macro_index_box + \hbox_unpack_drop:N \l__codedoc_macro_index_box + \int_gincr:N \c@CodelineNo + \__codedoc_special_index:nn {#1} { main } + \int_gdecr:N \c@CodelineNo + \exp_args:NNNo \hbox_set_end: + \tl_set:Nn \saved@indexname { \l__codedoc_index_key_tl } + } + } +\cs_new_protected:Npn \__codedoc_macro_typeset_one:nN #1#2 + { + \vbox_set:Nn \l__codedoc_macro_box + { + \vbox_unpack_drop:N \l__codedoc_macro_box + \hbox { \llap { \__codedoc_print_macroname:nN {#1} #2 \ } } + } + \int_incr:N \l__codedoc_macro_int + } +\cs_new_protected:Npn \__codedoc_print_macroname:nN #1#2 + { + \strut + \__codedoc_get_hyper_target:xN + { + \exp_not:n {#1} + \bool_if:NT #2 { \tl_to_str:n {TF} } + } + \l__codedoc_tmpa_tl + \cs_if_exist:cTF { r@ \l__codedoc_tmpa_tl } + { \exp_last_unbraced:NNo \hyperref [ \l__codedoc_tmpa_tl ] } + { \use:n } + { + \int_compare:nTF { \str_count:n {#1} <= 28 } + { \MacroFont } { \MacroLongFont } + \tl_set:Nn \l__codedoc_tmpa_tl {#1} + \tl_replace_all:Nno \l__codedoc_tmpa_tl + { ~ } { \c_catcode_other_space_tl } + \__codedoc_macroname_prefix:o \l__codedoc_tmpa_tl + \__codedoc_macroname_suffix:N #2 + } + } +\cs_new_protected:Npn \__codedoc_macroname_prefix:n #1 + { + \__codedoc_if_macro_internal:nTF {#1} + { \__codedoc_typeset_aux:n {#1} } {#1} + } +\cs_generate_variant:Nn \__codedoc_macroname_prefix:n { o } +\cs_new_protected:Npn \__codedoc_macroname_suffix:N #1 + { \bool_if:NTF #1 { \__codedoc_typeset_TF: } { } } +\providecommand \MacroLongFont + { + \fontfamily{lmtt}\fontseries{lc}\small + } +\cs_new_protected:Npn \__codedoc_print_testfile:n #1 + { + \bool_set_true:N \l__codedoc_macro_tested_bool + \tl_if_eq:nnF {#1} {*} + { + \seq_if_in:NnF \g__codedoc_testfiles_seq {#1} + { + \seq_gput_right:Nn \g__codedoc_testfiles_seq {#1} + \par + \__codedoc_print_testfile_aux:n {#1} + } + } + } +\cs_new_protected:Npn \__codedoc_print_testfile_aux:n #1 + { + \footnotesize + ( + \textit + { + The~ test~ suite~ for~ this~ command,~ + and~ others~ in~ this~ file,~ is~ \textsf{#1} + }. + )\par + } +\DeclareDocumentCommand \TestFiles {m} + { + \par + \textit + { + The~ following~ test~ files~ are~ + used~ for~ this~ code:~ \textsf{#1}. + } + \par \ignorespaces + } +\DeclareDocumentCommand \UnitTested { } { \testfile* } +\DeclareDocumentCommand \TestMissing { m } + { \__codedoc_test_missing:n {#1} } +\cs_new_protected:Npn \__codedoc_test_missing:n #1 + { + \__codedoc_test_missing_aux:Nxn + \g__codedoc_missing_tests_prop + { \seq_use:Nn \l__codedoc_names_seq { , } } + { { \g_file_curr_name_str \iow_char:N \ (#1) } } + } +\cs_new_protected:Npn \__codedoc_test_missing_aux:Nnn #1#2#3 + { + \prop_get:NnNTF #1 {#2} \l__codedoc_tmpa_tl + { \tl_put_right:Nn \l__codedoc_tmpa_tl { , #3 } } + { \tl_set:Nn \l__codedoc_tmpa_tl {#3} } + \prop_put:Nno #1 {#2} \l__codedoc_tmpa_tl + } +\cs_generate_variant:Nn \__codedoc_test_missing_aux:Nnn { Nx } +\cs_new_protected:Npn \__codedoc_macro_end: + { + \endtrivlist + \__codedoc_macro_end_check_tested: + \int_compare:nNnT \l__codedoc_nested_macro_int = 1 + { \__codedoc_macro_end_style:n { \__codedoc_print_end_definition: } } + } +\cs_new_protected:Npn \__codedoc_macro_end_check_tested: + { + \bool_lazy_all:nT + { + { \g__codedoc_checktest_bool } + { ! \l__codedoc_macro_var_bool } + { ! \l__codedoc_macro_tested_bool } + } + { + \seq_set_filter:NNn \l__codedoc_tmpa_seq \l__codedoc_names_seq + { ! \__codedoc_if_macro_internal_p:n {##1} } + \seq_gput_right:Nx \g__codedoc_not_tested_seq + { + \seq_use:Nn \l__codedoc_tmpa_seq { , } + \bool_if:NTF \l__codedoc_macro_pTF_bool {~(pTF)} + { \bool_if:NT \l__codedoc_macro_TF_bool {~(TF)} } + } + } + } +\cs_new_protected:Npn \__codedoc_macro_end_style:n #1 + { + \nobreak \noindent + { \footnotesize ( \emph{#1} ) \par } + } +\cs_new_protected:Npn \__codedoc_macro_end_wrap_item:n #1 + { + \tl_set:Nn \l__codedoc_tmpa_tl {#1} + \tl_replace_all:Non \l__codedoc_tmpa_tl + { \token_to_str:N _ } { \_ } + \texttt { \l__codedoc_tmpa_tl } + } +\cs_new_protected:Npn \__codedoc_print_end_definition: + { + \seq_set_map:NNn \l__codedoc_tmpa_seq + \g__codedoc_nested_names_seq + { \exp_not:n { \__codedoc_macro_end_wrap_item:n {##1} } } + End~ definition~ for~ + \int_compare:nTF { \seq_count:N \l__codedoc_tmpa_seq <= 3 } + { + \seq_use:Nnnn \l__codedoc_tmpa_seq + { \,~and~ } { \,,~ } { \,,~and~ } + } + { \seq_item:Nn \l__codedoc_tmpa_seq {1}\,~and~others } + \@. + \__codedoc_print_documented: + } +\cs_new_protected:Npn \__codedoc_print_documented: + { + \seq_gset_filter:NNn \g__codedoc_nested_names_seq + \g__codedoc_nested_names_seq + { ! \__codedoc_if_macro_internal_p:n {##1} } + \seq_if_empty:NF \g__codedoc_nested_names_seq + { + \int_set:Nn \l__codedoc_tmpa_int + { \seq_count:N \g__codedoc_nested_names_seq } + \int_compare:nNnTF \l__codedoc_tmpa_int = 1 {~This~} {~These~} + \bool_if:NTF \l__codedoc_macro_var_bool {variable} {function} + \int_compare:nNnTF \l__codedoc_tmpa_int = 1 {~is~} {s~are~} + documented~on~page~ + \__codedoc_get_hyper_target:xN + { \seq_item:Nn \g__codedoc_nested_names_seq { 1 } } + \l__codedoc_tmpa_tl + \exp_args:Nx \pageref { \l__codedoc_tmpa_tl } . + } + \seq_gclear:N \g__codedoc_nested_names_seq + } +\newcommand*{\DescribeOption} + { + \leavevmode + \@bsphack + \begingroup + \MakePrivateLetters + \Describe@Option + } +\newcommand*{\Describe@Option}[1] + { + \endgroup + \marginpar{ + \raggedleft + \PrintDescribeEnv{#1} + } + \SpecialOptionIndex{#1} + \@esphack + \ignorespaces + } +\newcommand*{\SpecialOptionIndex}[1] + { + \@bsphack + \begingroup + \HD@target + \let\HDorg@encapchar\encapchar + \edef\encapchar usage + { + \HDorg@encapchar hdclindex{\the\c@HD@hypercount}{usage} + } + \index + { + #1\actualchar{\protect\ttfamily#1}~(option) + \encapchar usage + } + \index + { + options:\levelchar#1\actualchar{\protect\ttfamily#1} + \encapchar usage + } + \endgroup + \@esphack + } +\font \manual = manfnt \scan_stop: +\cs_gset:Npn \dbend { {\manual\char127} } +\newenvironment {danger} + { + \begin{trivlist}\item[]\noindent + \begingroup\hangindent=2pc\hangafter=-2 + \cs_set:Npn \par{\endgraf\endgroup} + \hbox to0pt{\hskip-\hangindent\dbend\hfill}\ignorespaces + } + { + \par\end{trivlist} + } +\newenvironment {ddanger} + { + \begin{trivlist}\item[]\noindent + \begingroup\hangindent=3.5pc\hangafter=-2 + \cs_set:Npn \par{\endgraf\endgroup} + \hbox to0pt{\hskip-\hangindent\dbend\kern2pt\dbend\hfill}\ignorespaces + }{ + \par\end{trivlist} + } +\newenvironment{TemplateInterfaceDescription}[1] + { + \subsection{The~object~type~`#1'} + \begingroup + \@beginparpenalty\@M + \description + \def\TemplateArgument##1##2{\item[Arg:~##1]##2\par} + \def\TemplateSemantics + { + \enddescription\endgroup + \subsubsection*{Semantics:} + } + } + { + \par\bigskip + } +\newenvironment{TemplateDescription}[2] + { + \subsection{The~template~`#2'~(object~type~#1)} + \subsubsection*{Attributes:} + \begingroup + \@beginparpenalty\@M + \description + \def\TemplateKey##1##2##3##4 + { + \item[##1~(##2)]##3% + \ifx\TemplateKey##4\TemplateKey\else + \hfill\penalty500\hbox{}\hfill Default:~##4% + \nobreak\hskip-\parfillskip\hskip0pt\relax + \fi + \par + } + \def\TemplateSemantics + { + \enddescription\endgroup + \subsubsection*{Semantics~\&~Comments:} + } + } + { \par \bigskip } +\newenvironment{InstanceDescription}[4][xxxxxxxxxxxxxxx] + { + \subsubsection{The~instance~`#3'~(template~#2/#4)} + \subsubsection*{Attribute~values:} + \begingroup + \@beginparpenalty\@M + \def\InstanceKey##1##2{\>\textbf{##1}\>##2\\} + \def\InstanceSemantics{\endtabbing\endgroup + \vskip-30pt\vskip0pt + \subsubsection*{Layout~description~\&~Comments:}} + \tabbing + xxxx\=#1\=\kill + } + { \par \bigskip } +\DeclareDocumentCommand \OnlyDescription { } + { \bool_gset_false:N \g__codedoc_typeset_implementation_bool } +\DeclareDocumentCommand \AlsoImplementation { } + { \bool_gset_true:N \g__codedoc_typeset_implementation_bool } +\DeclareDocumentCommand \StopEventually { m } + { + \bool_if:NTF \g__codedoc_typeset_implementation_bool + { + \@bsphack + \tl_gset:Nn \g__codedoc_finale_tl { #1 \check@checksum } + \init@checksum + \@esphack + } + { #1 \endinput } + } +\DeclareDocumentCommand \Finale { } + { \tl_use:N \g__codedoc_finale_tl } +\tl_new:N \g__codedoc_finale_tl +\cs_new_protected:Npn \__codedoc_input:n #1 + { + \tl_gclear:N \g__codedoc_module_name_tl + \MakePercentIgnore + \input{#1} + \MakePercentComment + } +\DeclareDocumentCommand \DocInput { m } + { + \clist_map_inline:nn {#1} + { + \clist_put_right:Nn \g_docinput_clist {##1} + \__codedoc_input:n {##1} + } + } +\DeclareDocumentCommand \DocInputAgain { } + { \clist_map_function:NN \g_docinput_clist \__codedoc_input:n } +\NewDocumentCommand \DocInclude { m } + { + \relax\clearpage + \docincludeaux + \IfFileExists{#1.fdd} + { \cs_set:Npn \currentfile{#1.fdd} } + { \cs_set:Npn \currentfile{#1.dtx} } + \int_compare:nNnTF \@auxout = \@partaux + { \@latexerr{\string\include\space cannot~be~nested}\@eha } + { \@docinclude #1 } + } +\cs_gset:Npn \@docinclude #1 + { + \clearpage + \immediate\write\@mainaux{\string\@input{#1.aux}} + \@tempswatrue + \if@partsw + \@tempswafalse + \cs_set:Npx \@tempb{#1} + \@for\@tempa:=\@partlist\do + { + \ifx\@tempa\@tempb\@tempswatrue\fi + } + \fi + \if@tempswa + \cs_set_eq:NN \@auxout \@partaux + \immediate\openout\@partaux #1.aux + \immediate\write\@partaux{\relax} + \cs_set_eq:NN \@ltxdoc@PrintIndex \PrintIndex + \cs_set_eq:NN \PrintIndex \relax + \cs_set_eq:NN \@ltxdoc@PrintChanges \PrintChanges + \cs_set_eq:NN \PrintChanges \relax + \cs_set_eq:NN \@ltxdoc@theglossary \theglossary + \cs_set_eq:NN \@ltxdoc@endtheglossary \endtheglossary + \part{\currentfile} + { + \cs_set_eq:NN \ttfamily\relax + \cs_gset:Npx \filekey + { \filekey, \thepart = { \ttfamily \currentfile } } + } + \DocInput{\currentfile} + \cs_set_eq:NN \PrintIndex \@ltxdoc@PrintIndex + \cs_set_eq:NN \PrintChanges \@ltxdoc@PrintChanges + \cs_set_eq:NN \theglossary \@ltxdoc@theglossary + \cs_set_eq:NN \endtheglossary \@ltxdoc@endtheglossary + \clearpage + \@writeckpt{#1} + \immediate \closeout \@partaux + \else + \@nameuse{cp@#1} + \fi + \cs_set_eq:NN \@auxout \@mainaux + } +\cs_gset:Npn \codeline@wrindex #1 + { + \immediate\write\@indexfile + { + \string\indexentry{#1} + { \filesep \int_use:N \c@CodelineNo } + } + } +\tl_gclear:N \filesep +\cs_gset:Npn \docincludeaux + { + \tl_set:Nn \thepart { \alphalph { part } } + \tl_set:Nn \filesep { \thepart - } + \cs_set_eq:NN \filekey \use_none:n + \tl_gput_right:Nn \index@prologue + { + \cs_gset:Npn \@oddfoot + { + \parbox { \textwidth } + { + \strut \footnotesize + \raggedright { \bfseries File~Key: } ~ \filekey + } + } + \cs_set_eq:NN \@evenfoot \@oddfoot + } + \cs_gset_eq:NN \docincludeaux \relax + \cs_gset:Npn \@oddfoot + { + \cs_if_exist:cTF { ver @ \currentfile } + { File~\thepart :~{\ttfamily\currentfile}~ } + { + \GetFileInfo{\currentfile} + File~\thepart :~{\ttfamily\filename}~ + Date:~\ExplFileDate\ % space + Version~\ExplFileVersion + } + \hfill \thepage + } + \cs_set_eq:NN \@evenfoot \@oddfoot + } +\group_begin: + \char_set_catcode_other:N \^^A + \char_set_catcode_active:N \^^S + \char_set_catcode_active:N \^^B + \char_set_catcode_other:N \^^L + \char_set_catcode_other:N \^^R + \char_set_lccode:nn { `\^^A } { `\% } + \char_set_lccode:nn { `\^^S } { `\ } + \char_set_lccode:nn { `\^^B } { `\\ } + \char_set_lccode:nn { `\^^L } { `\{ } + \char_set_lccode:nn { `\^^R } { `\} } + \tex_lowercase:D + { + \group_end: + \cs_set_protected:Npn \xmacro@code + #1 ^^A ^^S^^S^^S^^S ^^Bend ^^Lmacrocode^^R + { \__codedoc_xmacro_code:n {#1} \end{macrocode} } + } +\group_begin: + \char_set_catcode_active:N \< + \char_set_catcode_active:N \> + \cs_new_protected:Npn \__codedoc_xmacro_code:n #1 + { + \tl_if_in:nnTF {#1} { < @ @ = } + { \__codedoc_xmacro_code:w #1 \q_stop } + { + \tl_set:Nn \l__codedoc_tmpa_tl {#1} + \__codedoc_replace_at_at:N \l__codedoc_tmpa_tl + \tl_use:N \l__codedoc_tmpa_tl + } + } + \cs_new_protected:Npn \__codedoc_xmacro_code:w #1 < @ @ = #2 > #3 \q_stop + { + \tl_set:Nn \l__codedoc_tmpa_tl {#1} + \__codedoc_replace_at_at:N \l__codedoc_tmpa_tl + + \tl_gset:Nn \g__codedoc_module_name_tl {#2} + \tl_put_right:Nn \l__codedoc_tmpa_tl { < @ @ = #2 > } + + \tl_set:Nn \l__codedoc_tmpb_tl {#3} + \__codedoc_replace_at_at:N \l__codedoc_tmpb_tl + \tl_put_right:No \l__codedoc_tmpa_tl { \l__codedoc_tmpb_tl } + + \tl_use:N \l__codedoc_tmpa_tl + } +\group_end: +\iow_new:N \g__codedoc_func_iow +\tl_new:N \l__codedoc_doc_def_tl +\tl_new:N \l__codedoc_doc_undef_tl +\tl_new:N \l__codedoc_undoc_def_tl +\cs_new_protected:Npn \__codedoc_show_functions_defined: + { + \bool_lazy_and:nnT + { \g__codedoc_typeset_implementation_bool } { \g__codedoc_checkfunc_bool } + { + \iow_term:x { \c__codedoc_iow_separator_tl \iow_newline: } + \iow_open:Nn \g__codedoc_func_iow { \c_sys_jobname_str .cmds } + + \tl_clear:N \l__codedoc_doc_def_tl + \tl_clear:N \l__codedoc_doc_undef_tl + \tl_clear:N \l__codedoc_undoc_def_tl + \seq_map_inline:Nn \g_doc_functions_seq + { + \seq_if_in:NnTF \g_doc_macros_seq {##1} + { + \tl_put_right:Nx \l__codedoc_doc_def_tl + { ##1 \iow_newline: } + \iow_now:Nn \g__codedoc_func_iow { > ~ ##1 } + } + { + \tl_put_right:Nx \l__codedoc_doc_undef_tl + { ##1 \iow_newline: } + \iow_now:Nn \g__codedoc_func_iow { ! ~ ##1 } + } + } + \seq_map_inline:Nn \g_doc_macros_seq + { + \seq_if_in:NnF \g_doc_functions_seq {##1} + { + \tl_put_right:Nx \l__codedoc_undoc_def_tl + { ##1 \iow_newline: } + \iow_now:Nn \g__codedoc_func_iow { ? ~ ##1 } + } + } + \__codedoc_functions_typeout:nN + { + Functions~both~documented~and~defined: \iow_newline: + (In~order~of~being~documented) + } + \l__codedoc_doc_def_tl + \__codedoc_functions_typeout:nN + { Functions~documented~but~not~defined: } + \l__codedoc_doc_undef_tl + \__codedoc_functions_typeout:nN + { Functions~defined~but~not~documented: } + \l__codedoc_undoc_def_tl + + \iow_close:N \g__codedoc_func_iow + \iow_term:x { \c__codedoc_iow_separator_tl } + } + } +\AtEndDocument { \__codedoc_show_functions_defined: } +\cs_new_protected:Npn \__codedoc_functions_typeout:nN #1#2 + { + \tl_if_empty:NF #2 + { + \typeout + { + \c__codedoc_iow_midrule_tl \iow_newline: + #1 \iow_newline: + \c__codedoc_iow_midrule_tl \iow_newline: + #2 + } + \tl_clear:N #2 + } + } +\cs_new_protected:Npn \__codedoc_show_not_tested: + { + \bool_if:NT \g__codedoc_checktest_bool + { + \tl_clear:N \l__codedoc_tmpa_tl + \prop_if_empty:NF \g__codedoc_missing_tests_prop + { + \cs_set:Npn \__codedoc_tmpa:w ##1##2 + { + \iow_newline: + \space\space\space\space \exp_not:n {##1} + \clist_map_function:nN {##2} \__codedoc_tmpb:w + } + \cs_set:Npn \__codedoc_tmpb:w ##1 + { + \iow_newline: + \space\space\space\space\space\space * ~ ##1 + } + \tl_put_right:Nx \l__codedoc_tmpa_tl + { + \iow_newline: \iow_newline: + The~ following~ macro(s)~ have~ incomplete~ tests: + \iow_newline: + \prop_map_function:NN + \g__codedoc_missing_tests_prop \__codedoc_tmpa:w + } + } + \seq_if_empty:NF \g__codedoc_not_tested_seq + { + \cs_set:Npn \__codedoc_tmpa:w ##1 + { \clist_map_function:nN {##1} \__codedoc_tmpb:w } + \cs_set:Npn \__codedoc_tmpb:w ##1 + { + \iow_newline: + \space\space\space\space ##1 + } + \tl_put_right:Nx \l__codedoc_tmpa_tl + { + \iow_newline: + \iow_newline: + The~ following~ macro(s)~ do~ not~ have~ any~ tests: + \iow_newline: + \seq_map_function:NN + \g__codedoc_not_tested_seq \__codedoc_tmpa:w + } + } + \tl_if_empty:NF \l__codedoc_tmpa_tl + { + \int_set:Nn \l__codedoc_tmpa_int { \etex_interactionmode:D } + \errorstopmode + \ClassError { l3doc-TUB } { \l__codedoc_tmpa_tl } { } + \int_set:Nn \etex_interactionmode:D { \l__codedoc_tmpa_int } + } + } + } +\AtEndDocument { \__codedoc_show_not_tested: } +\g@addto@macro \theindex { \MakePrivateLetters } +\cs_gset:Npn \verbatimchar {&} +\setcounter { IndexColumns } { 2 } +\IndexPrologue + { + \section*{Index} + \markboth{Index}{Index} + \addcontentsline{toc}{section}{Index} + The~italic~numbers~denote~the~pages~where~the~ + corresponding~entry~is~described,~ + numbers~underlined~point~to~the~definition,~ + all~others~indicate~the~places~where~it~is~used. + } +\cs_gset_protected:Npn \SpecialIndex #1 + { + \@bsphack + \__codedoc_special_index:nn {#1} { } + \@esphack + } +\msg_new:nnn { l3doc-TUB } { print-index-howto } + { + Generate~the~index~by~executing\\ + \iow_indent:n + { makeindex~-s~gind.ist~-o~\c_sys_jobname_str.ind~\c_sys_jobname_str.idx } + } +\tl_gput_right:Nn \PrintIndex + { \AtEndDocument { \msg_info:nn { l3doc-TUB } { print-index-howto } } } +\cs_gset_protected:Npn \it@is@a #1 + { + \use:x + { + \__codedoc_special_index_module:nnnnN + {#1} + { \bslash #1 } + { } + { } + \c_false_bool + } + } +\cs_new_protected:Npn \__codedoc_special_index:nn #1#2 + { + \__codedoc_key_get:n {#1} + \quark_if_no_value:NF \l__codedoc_override_module_tl + { \tl_set_eq:NN \l__codedoc_index_module_tl \l__codedoc_override_module_tl } + \__codedoc_special_index_module:ooonN + { \l__codedoc_index_key_tl } + { \l__codedoc_index_macro_tl } + { \l__codedoc_index_module_tl } + {#2} + \l__codedoc_index_internal_bool + } +\cs_generate_variant:Nn \__codedoc_special_index:nn { o } +\tl_new:N \l__codedoc_index_escaped_macro_tl +\tl_new:N \l__codedoc_index_escaped_key_tl +\cs_new_protected:Npn \__codedoc_special_index_module:nnnnN #1#2#3#4#5 + { + \use:x + { + \exp_not:n { \__codedoc_special_index_aux:nnnnnn {#1} {#2} } + \tl_if_empty:nTF {#3} + { { } { } { } } + { + \str_if_eq:eeTF {#3} { TeX } + { + { TeX~and~LaTeX2e } + { \string\TeX{}~and~\string\LaTeXe{} } + } + { + {#3} + { \string\pkg{#3} } + } + { \bool_if:NT #5 { ~internal } ~commands: } + } + } + {#4} + } +\cs_generate_variant:Nn \__codedoc_special_index_module:nnnnN { ooo } +\cs_new_protected:Npn \__codedoc_special_index_aux:nnnnnn #1#2#3#4#5#6 + { + \tl_set:Nn \l__codedoc_index_escaped_key_tl {#1} + \__codedoc_quote_special_char:N \l__codedoc_index_escaped_key_tl + \__codedoc_special_index_set:Nn \l__codedoc_index_escaped_macro_tl {#2} + \str_if_eq:onTF { \@currenvir } { macrocode } + { \codeline@wrindex } + { + \str_case:nnF {#6} + { + { main } { \codeline@wrindex } + { usage } { \index } + } + { \HD@target \index } + } + { + \tl_if_empty:nF { #3 #4 #5 } + { #3 #5 \actualchar #4 #5 \levelchar } + \l__codedoc_index_escaped_key_tl + \actualchar + { + \token_to_str:N \verbatim@font \c_space_tl + \l__codedoc_index_escaped_macro_tl + } + \encapchar + hdclindex{\the\c@HD@hypercount}{#6} + } + } +\cs_new_protected:Npn \__codedoc_special_index_set:Nn #1#2 + { + \tl_set:Nx #1 { \tl_to_str:n {#2} } + \__codedoc_if_almost_str:nTF {#2} + { + \tl_replace_all:Non #1 { \tl_to_str:n { __ } } + { + \verbatimchar + \token_to_str:N \_ \token_to_str:N \_ + \token_to_str:N \verb * \verbatimchar + } + \exp_args:Nx \tl_map_inline:nn + { \tl_to_str:N \verbatimchar \token_to_str:N _ } + { + \tl_replace_all:Nnn #1 {##1} + { + \verbatimchar \c__codedoc_backslash_tl ##1 + \token_to_str:N \verb * \verbatimchar + } + } + \tl_set:Nx #1 + { + \token_to_str:N \verb * \verbatimchar + #1 \verbatimchar + } + } + { + \tl_set:Nn #1 {#2} + \tl_replace_all:Non #1 + { \c__codedoc_backslash_tl } + { \token_to_str:N \bslash \c_space_tl } + } + \__codedoc_quote_special_char:N #1 + } +\cs_new_protected:Npn \__codedoc_quote_special_char:N #1 + { + \tl_map_inline:nn { \quotechar \actualchar \encapchar \levelchar } + { + \tl_replace_all:Nxn #1 + { \tl_to_str:N ##1 } { \quotechar \tl_to_str:N ##1 } + } + } +\cs_new_protected:Npn \__codedoc_key_get:n #1 + { + \__codedoc_key_get_base:nN {#1} \l__codedoc_index_macro_tl + \tl_set:Nx \l__codedoc_index_key_tl + { \tl_to_str:N \l__codedoc_index_macro_tl } + \tl_clear:N \l__codedoc_index_module_tl + \tl_if_in:NoTF \l__codedoc_index_key_tl { \tl_to_str:n { __ } } + { \bool_set_true:N \l__codedoc_index_internal_bool } + { \bool_set_false:N \l__codedoc_index_internal_bool } + \tl_if_head_eq_charcode:oNT + { \l__codedoc_index_key_tl } \c__codedoc_backslash_token + { \__codedoc_key_pop: } + \tl_if_in:NoTF \l__codedoc_index_key_tl { \token_to_str:N : } + { \__codedoc_key_func: } + { + \tl_if_in:NoTF \l__codedoc_index_key_tl { \token_to_str:N _ } + { \__codedoc_key_var: } + { + \tl_if_in:NoT \l__codedoc_index_key_tl { \token_to_str:N @ } + { \tl_set:Nn \l__codedoc_index_module_tl { TeX } } + } + } + } +\cs_new_protected:Npn \__codedoc_key_pop: + { + \tl_set:Nx \l__codedoc_index_key_tl + { \tl_tail:N \l__codedoc_index_key_tl } + } +\cs_new_protected:Npn \__codedoc_key_trim_module:n #1 + { + \cs_set:Npn \__codedoc_tmpa:w ##1 #1 ##2 \q_stop + { \exp_not:n {##1} } + \tl_set:Nx \l__codedoc_index_module_tl + { \exp_after:wN \__codedoc_tmpa:w \l__codedoc_index_module_tl #1 \q_stop } + } +\cs_new_protected:Npn \__codedoc_key_drop_underscores: + { + \tl_if_head_eq_charcode:oNT { \l__codedoc_index_key_tl } _ + { \__codedoc_key_pop: \__codedoc_key_drop_underscores: } + } +\cs_new_protected:Npn \__codedoc_key_func: + { + \tl_if_head_eq_charcode:oNT { \l__codedoc_index_key_tl } . + { \__codedoc_key_pop: } + \__codedoc_key_drop_underscores: + \tl_set_eq:NN \l__codedoc_index_module_tl \l__codedoc_index_key_tl + \exp_args:No \__codedoc_key_trim_module:n { \token_to_str:N : } + \exp_args:No \__codedoc_key_trim_module:n { \token_to_str:N _ } + } +\cs_new_protected:Npn \__codedoc_key_var: + { + \exp_args:Nx \tl_if_head_eq_charcode:nNTF + { \exp_args:No \str_tail:n \l__codedoc_index_key_tl } _ + { + \str_case:fn { \str_head:N \l__codedoc_index_key_tl } + { + { q } { \tl_set:Nn \l__codedoc_index_module_tl { quark } } + { s } { \tl_set:Nn \l__codedoc_index_module_tl { quark } } + } + \__codedoc_key_pop: + \__codedoc_key_pop: + \__codedoc_key_drop_underscores: + \tl_if_empty:NT \l__codedoc_index_module_tl + { + \seq_set_split:NoV \l__codedoc_tmpa_seq + { \token_to_str:N _ } \l__codedoc_index_key_tl + \tl_set:Nx \l__codedoc_index_module_tl + { + \int_case:nnF { \seq_count:N \l__codedoc_tmpa_seq } + { + { 0 } { } + { 1 } { int } + { 2 } { \seq_item:Nn \l__codedoc_tmpa_seq { 2 } } + } + { \seq_item:Nn \l__codedoc_tmpa_seq { 1 } } + } + } + } + { + \tl_set_eq:NN \l__codedoc_index_module_tl \l__codedoc_index_key_tl + \exp_args:No \__codedoc_key_trim_module:n { \token_to_str:N _ } + } + } +\GlossaryPrologue + { + \part*{Change~History} + {\GlossaryParms\ttfamily\hyphenchar\font=`\-} + \markboth{Change~History}{Change~History} + \addcontentsline{toc}{part}{Change~History} + } +\msg_new:nnn { l3doc-TUB } { print-changes-howto } + { + Generate~the~change~list~by~executing\\ + \iow_indent:n + { makeindex~-s~gglo.ist~-o~\c_sys_jobname_str.gls~\c_sys_jobname_str.glo } + } +\tl_gput_right:Nn \PrintChanges + { \AtEndDocument { \msg_info:nn { l3doc-TUB } { print-changes-howto } } } +\bool_if:NTF \g__codedoc_typeset_implementation_bool + { + \RecordChanges + \CodelineIndex + \EnableCrossrefs + \AlsoImplementation + } + { + \CodelineNumbered + \DisableCrossrefs + \OnlyDescription + } + +%%FMi + +\def\maketitle{\@ifstar + {\@articletitlefalse\@r@maketitle}% + {\@articletitletrue\@r@maketitle}% +} + +%% +%% +%% End of file `l3doc-TUB.cls'. diff --git a/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-code.pdf b/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-code.pdf new file mode 100644 index 00000000000..17a9c6bc61c Binary files /dev/null and b/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-code.pdf differ diff --git a/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-code.tex b/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-code.tex new file mode 100644 index 00000000000..7f9a4882199 --- /dev/null +++ b/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-code.tex @@ -0,0 +1,4 @@ +% this will typeset documentation + code + +\AtBeginDocument{\AlsoImplementation} +\input{unicodefonttable.dtx} diff --git a/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-doc.pdf b/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-doc.pdf new file mode 100644 index 00000000000..87914ad4965 Binary files /dev/null and b/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-doc.pdf differ diff --git a/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-doc.tex b/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-doc.tex new file mode 100644 index 00000000000..4b98461ade3 --- /dev/null +++ b/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-doc.tex @@ -0,0 +1,6 @@ +% this will typeset only documentation but not the code + +\AtBeginDocument{\OnlyDescription +% \let\tableofcontents\relax + } +\input{unicodefonttable.dtx} diff --git a/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-samples.pdf b/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-samples.pdf new file mode 100644 index 00000000000..b5a4d6399a7 Binary files /dev/null and b/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-samples.pdf differ diff --git a/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-samples.tex b/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-samples.tex new file mode 100644 index 00000000000..3a14c32014a --- /dev/null +++ b/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-samples.tex @@ -0,0 +1,104 @@ +%% +%% This is file `unicodefonttable-samples.tex', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% unicodefonttable.dtx (with options: `samples') +%% +%% This is a generated file. +%% +%% Copyright 2019-2021 Frank Mittelbach +%% +%% This file was generated from file(s) of the LaTeX `unicodefonttable Bundle'. +%% -------------------------------------------------------------------------- +%% +%% It may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3c +%% of this license or (at your option) any later version. +%% The latest version of this license is in +%% https://www.latex-project.org/lppl.txt +%% and version 1.3c or later is part of all distributions of LaTeX +%% version 2008 or later. +%% +%% This file may only be distributed together with a copy of the LaTeX +%% `unicodefonttable Bundle'. You may however distribute the `unicodefonttable Bundle' +%% without such generated files. +%% +%% The newest sources can be found below +%% +%% https://github.com/FrankMittelbach/fmitex-unicodetable +%% +%% where one can also log issues in case there are any. +%% +%% +%%%%% \iffalse meta-comment +%% File: unicodefonttable.dtx (C) Copyright 2019-2021 Frank Mittelbach + +\def\unicodefonttabledate {2021/10/19} +\def\unicodefonttableversion{v1.0e} + + +%!TEX program = lualatex + +\documentclass{article} + +\usepackage{xparse,color} + +\usepackage{fontspec} + +\setmainfont{Linux Biolinum O} +\setmonofont{SourceCodePro} + +\usepackage{unicodefonttable} + +\addtolength\textwidth{30pt} + +\begin{document} + +\listoftables + +\section{Computer Modern --- 8bit font} + +\displayfonttable*[color=none, + range-end = 7F, +]{cmr10} + + +\newpage + +\section{TeX Gyre Heros (Helvetica) --- 8bit font} + +\displayfonttable*[color=red,nostatistics=false, + hex-digits = head+foot, + range-end = FF, +]{ec-qhvr} + +\newpage + +\section{Latin Modern Sans --- OTF font} + +\displayfonttable[ + % missing-glyph = \tiny\setlength\fboxsep{0pt}\fbox{$\times$}, + hex-digits = block, + title-cont-format = \caption[]{\emph{continued}}, +]{Latin Modern Sans} + +\newpage + +\section{\TeX{} Gyre Pagella (Palatino) oldstyle figures --- OTF font} + +\displayfonttable{TeX Gyre Pagella}[Numbers=OldStyle] + +\newpage + +\section{Comparing Latin Modern Math with New Computer Modern Math} + +\displayfonttable[compare-with=NewCMMath-Regular.otf, range-end=1FFFF] + {latinmodern-math.otf} + +\end{document} + +\endinput +%% +%% End of file `unicodefonttable-samples.tex'. diff --git a/Master/texmf-dist/source/latex/unicodefonttable/unicodefonttable.dtx b/Master/texmf-dist/source/latex/unicodefonttable/unicodefonttable.dtx new file mode 100644 index 00000000000..67cb3a8d643 --- /dev/null +++ b/Master/texmf-dist/source/latex/unicodefonttable/unicodefonttable.dtx @@ -0,0 +1,2295 @@ +%%%%% \iffalse meta-comment +% +%% File: unicodefonttable.dtx (C) Copyright 2019-2021 Frank Mittelbach +% +% 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 +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% +% The development version of the bundle can be found below +% +% https://github.com/FrankMittelbach/fmitex/ +% +% for those people who are interested or want to report an issue. +% + +\def\unicodefonttabledate {2021/10/19} +\def\unicodefonttableversion{v1.0e} + + +%<*driver> +\documentclass{l3doc-TUB} + +% some fixes local to this documentation + +\ExplSyntaxOn + \cs_new:Npn\IfImplementationShownTF + {\bool_if:NTF \g__codedoc_typeset_implementation_bool} +\ExplSyntaxOff + +\makeatletter +\def\meta@font@select{\normalfont\itshape} + +\IndexPrologue{% + \IfImplementationShownTF{\section*{Index}% + Numbers written in italic refer to the page + where the corresponding entry is described + or mentioned. Numbers underlined refer to the + code line of the + definition; numbers in Roman refer to the + code lines where the entry is used.}% + {\section{Index}% + Numbers written in italic refer to the page + where the corresponding entry is described + or mentioned.}} + +\makeatother + + +\usepackage{graphicx,unicodefonttable} + +\EnableCrossrefs +\CodelineIndex +\begin{document} + \DocInput{unicodefonttable.dtx} +\advance\signaturewidth by 40pt +\makesignature +\end{document} +% +% +% \fi +% +% \tracinglostchars=3 +% +% \newcommand\key [1]{\texttt{#1}} +% \newcommand\kval[1]{\texttt{#1}} +% +% \newcommand\keysetup[1]{\noindent\marginpar{\raggedleft Key setup: #1}\ignorespaces} +% \renewcommand\keysetup[1]{\paragraph*{\hspace*{-8pc}Key setup (#1)}} +% +% +% \title{The \texttt{unicodefonttable} package\thanks{This is +% version \unicodefonttableversion\ of the package, dated +% \unicodefonttabledate; the license is LPPL.}} +% \author{Frank Mittelbach} +% \address{Mainz, Germany} +% \netaddress{https://www.latex-project.org} +% \personalURL{https://ctan.org/pkg/unicodefonttable} +% \raggedbottom +% +% \maketitle +% +% +% \begin{abstract} +% A package for typesetting font tables for larger fonts, e.g., +% TrueType or OpenType Unicode fonts. +% To produce a one-off table, a standalone version is available as well. +% \end{abstract} +% +% +% \tableofcontents +% +% +% +% \section{Introduction} +% +% When I started to write a new chapter for the third edition of +% \emph{The \LaTeX{} Companion} on modern fonts available for +% different \LaTeX{} engines, I was a bit surprised that I couldn't +% find a way to easily typeset tables showing the glyphs available in +% TrueType or OpenType fonts. The \pkg{nfssfont} package available +% with \LaTeX{} only supports fonts from the 8-bit world, but +% modern fonts that can be used with \XeTeX{} or \LuaTeX{} can +% contain thousands of glyphs and having a method to display what +% is available in them was important for me. +% +% I therefore set out to write my own little package and what +% started as an afternoon exercise ended up being this package, +% offering plenty of bells and whistles for typesetting such +% font tables. +% +% As there can be many glyphs in such fonts a tabular +% representation of them might run for several pages, so the +% package internally uses the \pkg{longtable} package to handle +% that. +% +% In most cases the glyphs inside the fonts are indexed by their +% Unicode numbers so it is natural to display them sorted by their +% position in the Unicode character set. +% +% Unicode is organized in named blocks such as ``Basic Latin'', +% ``Latin-1~Supplement'', etc., typically consisting of 265 +% characters each.\footnote{Some blocks are smaller, while those +% containing the Asian ideographs are much larger.} It is therefore +% helpful to use these block names as subtitles within the table, +% to more easily find the information one is looking for. +% +% A common way to represent the number of a single Unicode +% character is \texttt{U+} followed by four (or more) +% hexadecimal digits. For example, \texttt{U+0041} represents the letter +% ``A'' and \texttt{U+20AC} the Euro currency symbol ``\texteuro''. +% We use this convention by showing a Unicode range of sixteen +% characters at the left of each table row, e.g., \texttt{U+0040 - +% 004F}, followed by the sixteen glyphs in the range. Thus that +% particular table row from the ``Basic Latin'' block would show +% something like +% +% \displayfonttable*[noheader,range-start=0040, range-end=004F, +% color=black!50]{Latin Modern Sans} +% +% If a Unicode character has no glyph representation in a given +% font then this is indicated by a special symbol (by default a +% colored hyphen). By default some color is used, but we've grayscaled +% the output for \TUB. +% +% In order to easily locate any Unicode character the table shows by +% default sixteen hex digits as a column heading. For example, to find +% Euro currency symbol (\texttt{U+20AC}) one first finds the +% right row, which is the range \texttt{U+20A0 - 20AF}, and then +% the \texttt{C} column in that row, and the glyph is there (or an +% indication that the font is missing that glyph; +% the line shows that for some of the other slots). +% +% \displayfonttable*[noheader,range-start=20A0, range-end=20AF, +% color=black!50]{Latin Modern Sans} +% +% It can be useful to compare two fonts with each other by +% filling the table with glyphs from a secondary font if the +% primary font is missing them. For example, the next display shows +% two rows of Latin Modern Math (black glyphs) and instead of showing +% a missing glyph symbol in most slots, we use the glyphs from New +% Computer Modern Math, which has a much larger glyph set +% (normally red glyphs with gray background but again, grayscaled for +% \TUB). +% +% +% \displayfonttable[noheader,nostatistics,display-block=none, +% compare-with=NewCMMath-Regular.otf,range-start=2A00,range-end=2A1F, +% color=black!50,compare-color=none] +% {latinmodern-math.otf} +% +% +% \section{The user interface} +% +% The package offers one command to typeset a font table. The +% appearance of the table can be customized by specifying key/value +% pairs. +% +% \begin{function}{\displayfonttable} +% \begin{syntax} +% \cs{displayfonttable} \texttt{*} \oarg{key/value-list} \Arg{font-name} \oarg{font-features} +% \end{syntax} +% The \meta{font-name} is the font to be displayed. This and the +% \meta{font-features} argument are passed to \pkg{fontspec}, thus they +% should follow the conventions of that package for specifying a +% font. The \meta{key/value-list} offers customization +% possibilities discussed below. +% +% The \cs{displayfonttable*} is a variant of the command, intended +% for use with 8-bit legacy fonts. It presets some keys, but +% otherwise behaves identically. The preset values are: +%\begin{verbatim} +% nostatistics, display-block=none, hex-digits=head, range-end=FF +%\end{verbatim} +% For details see the next section. +% \end{function} +% +% +% +% \begin{function}{\fonttablesetup} +% \begin{syntax} +% \cs{fonttablesetup} \Arg{key/value-list} +% \end{syntax} +% Instead of or in addition to specifying key/values to +% \cs{displayfonttable} it is possible to set them up as +% defaults. Inside \cs{displayfonttable} the defaults are applied first, +% so one can still overwrite their values for an individual table. +% \end{function} +% +% +% \begin{function}{\fonttableglyphcount} +% \begin{syntax} +% \cs{fonttableglyphcount} +% \end{syntax} +% While typesetting a font table the package keeps track of the +% number of glyphs it finds in the font. After the table has finished, +% this value is available in \cs{fonttableglyphcount} and it is, for +% example, used when statistics are produced. At the start of the +% next table it is reset to zero. +% \end{function} +% +% +% +% +% \subsection{Keys and their values} +% +% Several of the available keys are booleans accepting \texttt{true} +% or \texttt{false}. They usually exist in pairs so that one can +% specify the desired behavior without needing to provide a value, +% e.g., specifying \key{header} is equivalent to specifying +% \key{header}\texttt{=true} or \key{noheader}\texttt{=false}, etc. +% In the lists below the default settings are indicated by an +% underline. +% +% \begin{variable}{ +% header, noheader, +% title-format, title-format-cont, +% } +% The first set of keys is concerned with the overall look and +% feel of the generated table. +% \begin{description} +% \item[\underline{\key{header}}, \key{noheader}] +% These keys determine whether a header to the table is +% produced. +% +% \item[\key{title-format}, \key{title-format-cont}] +% These keys define what is provided as a header title or +% continuation title if the table consists of several pages. +% They expect code as their value. This code can contain \verb=#1= +% and \verb=#2= to denote the \meta{font-name} and +% \meta{font-features} arguments, respectively. +% +% By default a title using the \cs{caption} command is produced; on +% continuation titles, the \meta{font-features} are not shown. +% This is typeset as a \env{longtable} header row, so you either need to use +% \cs{multicolumn} or a \cs{caption} command\Dash otherwise everything +% ends up in the first column. +% +% \end{description} +% +% \end{variable} +% +% +% \begin{variable}{ +% display-block, +% hex-digits, color, +% } +% These keys handle the inner parts of the table. +% +% \begin{description} +% \item[\key{display-block}] +% The Unicode dataset is organized in named blocks that are typically 128 or +% 256 characters, though some are noticeably larger and a few are +% smaller. With the \key{display-block} key it is +% possible to specify if and how such blocks should be made visible. +% The following values are supported: +% \begin{description} +% \item[\underline{\kval{titles}}] +% Above each display block that contains glyphs the Unicode title +% of the block is displayed. +% +% \item[\kval{rules}] +% Display blocks are indicated only by a \cs{midrule}. +% +% \item[\kval{none}] +% Display blocks are not indicated at all. +% \end{description} +% +% \item[\key{hex-digits}] +% To ease reading the table, rows of hex digits are added to +% it. Where or if this happens is controlled by this key. Allowed +% values for it are the following: +% \begin{description} +% \item[\kval{block}] +% A row of hex digits is placed at the beginning of each Unicode +% block containing glyphs in the displayed font. +% +% \item[\kval{foot}] +% A row is added to the foot of each table page. +% +% \item[\underline{\kval{head}}] +% A row is added to the top of each table page. +% +% \item[\kval{head+foot}] +% A row is added to the top and the foot of each table page. +% +% \item[\kval{none}] +% All hex digit rows are suppressed. +% \end{description}% +% +% \item[\key{hex-digits-font}] +% The font to use for the hex digits, by default +% \underline{\cs{ttfamily}\cs{scriptsize}}.{\hfuzz=2.7pt\par} +% +% \item[\key{color}] +% This key determines the color for parts of the table (hex digits +% and Unicode ranges). It can be either \kval{none} or a color +% specification as understood by the \cs{color} command. +% The default is \underline{\texttt{blue}}. +% +% \end{description} +% +% \end{variable} +% +% +% \begin{variable}{ +% statistics, nostatistics, +% statistics-font,statistics-format, +% } +% The next set of keys allows altering the statistics that are produced. +% \begin{description} +% +% \item[\underline{\key{statistics}}, \key{nostatistics}] +% These keys determine whether some statistics are listed at +% the end of the table. +% +% \item[\key{statistics-font}] +% The font used to typeset the statistics; the default is\\ +% \underline{\cs{normalfont}\cs{small}}. +% +% +% \item[\key{statistics-format}] +% Code (text) to specify what should be typeset in the +% statistics. One can use \verb=#1= for the \meta{font-name} and +% \verb=#2= for the glyph count. +% The material is typeset on a single line at the end of the +% table. If several lines are needed you need to use \cs{parbox} +% or a similar construct. +% \end{description} +% \end{variable} +% +% +% +% \begin{variable}{ +% glyph-width, +% missing-glyph, missing-glyph-font, missing-glyph-color, +% } +% Another set of keys deals with customization on the glyph level. +% \begin{description} +% \item[\key{glyph-width}] +% All glyphs are typeset in a box with the same width, the default +% value is \underline{\texttt{6pt}} which is suitable for most 10pt +% fonts +% and make the table fit comfortably into the text width of +% a typical document. +% +% \item[\key{missing-glyph}] +% If a slot in a row doesn't have a glyph in the font you may still +% want display something to indicate this state. By giving the key +% a value any arbitrary glyph or material can be typeset. The +% default is to typeset a \kval{-} (hyphen) in a special color. +% +% Rows that contain no glyph whatsoever are not displayed at +% all. Instead a small vertical space is added to indicate the one +% or more rows are omitted. +% +% \item[\key{missing-glyph-font}] +% +% The font used for the missing glyphs (the default value is +% \underline{\cs{ttfamily}\cs{scriptsize}}). +% +% \item[\key{missing-glyph-color}] +% If not specified it uses the value specified with the \key{color} +% key. If you want a different color, e.g., \texttt{red}, you can +% use a color value or you can specify \kval{none} to use no coloring. +% +% \end{description} +% +% \end{variable} +% +% +% \begin{variable}{ +% compare-with,compare-color, compare-bgcolor,statistics-compare-format +% } +% +% You can make comparisons between two fonts, which is useful, for +% example when dealing with incomplete math fonts and you need to +% see how well the symbols from one font blend with the supplementary +% symbols from another font. +% +% \begin{description} +% \item[\key{compare-with}] +% +% If given, the value is a \meta{comparison-font-name} that is used +% to supply missing glyphs. This means that if the \meta{font-name} +% to be displayed is missing a glyph in a slot, then the +% \meta{comparison-font-name} is checked, and if that font has the +% glyph in question, it will be displayed instead of showing a +% missing glyph indicator. +% +% \item[\key{compare-color}, \key{compare-bgcolor}] +% +% To distinguish real glyphs from missing but substituted glyphs, +% they can be colored specially (default \underline{\texttt{red}}) +% and/or you can have their background colored (default is +% \underline{\texttt{black!10}}, i.e., a light gray). +% +% \item[\key{statistics-compare-format}] +% +% Code (text) to specify what should be typeset in the statistics +% when comparing two fonts. One can use \verb=#1= for the +% \meta{font-name} and \verb=#2= for its glyph count, \verb=#3= is +% the name of the comparison font, \verb=#4= its glyph count, +% \verb=#5= for the number of glyphs missing in this font and +% \verb=#6= the number of extra glyphs in it. This code is used +% instead of \key{statistics-format} when comparisons are made. +% +% The material is typeset on a single line at the end of the +% table. If several lines are needed you need to use \cs{parbox} +% or a similar construct. +% +% \end{description} +% \end{variable} +% +% +% \begin{variable}{ +% range-start, range-end, +% } +% Finally there are two keys for restricting the display range. +% \begin{description} +% \item[\key{range-start}, \key{range-end}] +% The full Unicode set of characters is huge and checking every +% slot to see if the current font contains a glyph in the slot +% takes a long time. If you know that font contains only a +% certain subset then you can speed up the table generation +% considerably by limiting the search (and consequently the output +% generation). +% The \key{range-start} specifies where to start with the search +% (default \underline{\texttt{0000}}) and \key{range-end} gives +% the last slot that is tested (default +% \underline{\texttt{FFFF}}). +% +% Thus, by default we restrict the display to slots below +% \texttt{10000}, because text fonts seldom contain glyphs in the +% higher planes. But if you want to see everything of the font (as +% far as supported by this package) and are prepared to wait for +% the higher +% planes to be scanned, you can go up to a value of \texttt{FFFFF}. +% +% These keys are also quite useful in combination with the previous +% \key{compare-with} key, to display only, for example, the Greek +% letters and see how glyphs from two fonts blend with each other. + +% \end{description} +% \end{variable} +% +% +% +% \subsection{A standalone interactive version} +% +% If you want to quickly display a single font, you can run +% \texttt{unicodefont.tex} through \LuaTeX{} (or \XeTeX{}). Similar to +% \texttt{nfssfont.tex} (which is for 8-bit fonts with \pdfTeX) it +% asks you a few questions and then generates the font table for +% you. There are fewer configuration options available, +% but this workflow saves you writing a document to get a +% one-off table. +% +% Most font tables need several runs due to the use of +% \pkg{longtable}, which has to find the right width for the columns +% across several pages. The \texttt{unicodefont} file therefore +% remembers your selection from the previous run and asks you if +% you want to reapply it to speed up the process. +% +% +% +% \section{Notes on the table data} +% +% If you look at some parts of a Unicode font table you see a number of slots that +% do not show a \enquote{missing glyph} sign, but nonetheless appear +% to be empty. For example: +% +% \displayfonttable[noheader,nostatistics,display-block=none, +% range-start=0020,range-end=00BF, +% color=black!50] +% {TeX Gyre Pagella} +% +% +% The reason is that Unicode contains a lot of special +% spaces or otherwise invisible characters, e.g., \texttt{U+0020} +% is the normal space, \texttt{U+00A0} is a non-breaking space, +% \texttt{U+00AD} is a soft-hyphen (what \LaTeX{} users would +% indicate with \cs{-}), and so forth. Especially the row +% \texttt{U+2000-200F} in Table~1 looks strange as it appears to be totally +% empty, but in fact most of its slots contain spaces of different +% width. +% +%\displayfonttable[noheader,nostatistics,hex-digits=foot, +% range-start=2000,range-end=202F, +% color=black!50] +% {latinmodern-math.otf} +% +% +% Another somewhat surprising area is the \enquote{Mathematical +% Alphanumeric Symbols} block in math fonts, starting at \texttt{U+1D400}. +% There you see a number of missing characters, the first two being +% \texttt{U+1D455} (math italic small h) and \texttt{U+1D49D} (math +% script B). +% +% \displayfonttable[noheader,nostatistics,hex-digits=foot, +% range-start=1D400,range-end=1D4AF, +% color=black!50] +% {latinmodern-math.otf} +% +% In this case the reason is \emph{not} that the font +% fails to implement the characters, but that these characters have +% already been defined in earlier revisions of the Unicode standard in the +% lower Unicode plane. For example, the \enquote{h} is the +% Planck constant \texttt{U+210E} and \texttt{U+212C} is +% the script capital B, etc. The Unicode Consortium decided not +% to encode the \emph{same} character twice, hence the apparent +% holes. +% +% +% \IfImplementationShownTF{} +% {\appendix +% \def\theHsection{Appendix.\thesection} +% \addtocontents{toc}{\smallskip} +% \setlength\IndexMin{200pt} +% \PrintIndex +% } +% +% +% \section{Examples} +% +% In this section we show the results of a few calls to +% \cs{displayfonttable}. +% The tables are a bit easier to navigate if they use color in some +% places, but for \TUB{} this is not practical, so we +% use black and gray. +% +% \subsection{Computer Modern Sans --- 8-bit font} +% +% Our first example is an 8-bit font which gives a concise table. +% Command used: \begin{verbatim} +% \displayfonttable*[color=none, range-end=7F]{cmss10} +% \end{verbatim} +% +% \displayfonttable*[color=none, range-end=7F]{cmss10} +% +% +% \iffalse +% +%\subsection{\TeX{} Gyre Pagella (Palatino) oldstyle figures --- OTF font} +% +% This example shows Pagella with oldstyle numerals. +% Command used: +%\begin{verbatim} +%\displayfonttable{TeX Gyre Pagella}[Numbers=OldStyle] +%\end{verbatim} +% +%\displayfonttable{TeX Gyre Pagella}[Numbers=OldStyle] +% +% \fi +% +% +% +% \subsection{Latin Modern Math compared to New Computer Modern Math} +% +% This example shows the extra symbols available in New Computer +% Modern Math in comparison to Latin Modern Math as the base font. +% We use the following setup (including settings for the +% grayscaled \TUB\ output, as an example of color overrides): +%\begin{verbatim} +% \displayfonttable[hex-digits=head+foot, range-end=1FFFF, +% compare-with=New Computer Modern Math, +% compare-color=black, compare-bgcolor=black!5, +% missing-glyph-color=black!50, color=black!75] +% {Latin Modern Math} +%\end{verbatim} +% That is, glyphs only in \texttt{NewCM} are shown with a light gray +% background. +% +% We also extended the range to cover \texttt{U+10000} to +% \texttt{U+1FFFF} in order to include the Unicode Math alphabets. +% +% \displayfonttable[hex-digits=head+foot, range-end=1FFFF, +% compare-with=New Computer Modern Math, +% compare-color=black, compare-bgcolor=black!5, +% missing-glyph-color=black!50, color=black!75] +% {Latin Modern Math} +% +% +%\subsection{Garamond Libre's Byzantine Musical Symbols} +% +% As a final example we exhibit the Byzantine Musical Symbols as provided by +% Garamond Libre. +% Command used: +%\begin{verbatim} +% \displayfonttable[range-start=1D000, range-end=1D0FF, +% hex-digits=block, +% missing-glyph-color=black!50, color=black!75, +% statistics-format=Total number of glyphs in +% this block of #1 is #2] +% {Garamond Libre} +%\end{verbatim} +% +% Note that we have altered the text produced by the statistics, +% because the default is somewhat misleading if only a portion of +% the font is displayed. This produces the following table: +% +% \displayfonttable[range-start=1D000, range-end=1D0FF, +% hex-digits=foot, +% missing-glyph-color=black!50, color=black!75, +% statistics-format=Total number of glyphs in +% this block of #1 is #2] +% {Garamond Libre} +% +% +% +% \IfImplementationShownTF +% {\StopEventually{\setlength\IndexMin{200pt} \PrintIndex }} +% {\StopEventually{}} +% +% +% +% \section{The package implementation} +% +% \hfuzz=10pt ^^A lots of slightly overfull tt lines +% +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% By default the package uses coloring to improve the table +% appearance and therefore requires a color package. +% \begin{macrocode} +\RequirePackage{xcolor} +% \end{macrocode} +% + +% \begin{macrocode} +%<@@=fmuft> +% \end{macrocode} +% +% We need the package \pkg{xparse} for specifying the document-level +% interface commands and \pkg{l3keys2e} to use the \pkg{expl3} key +% value methods within \LaTeXe{}. These packages automatically +% require \pkg{expl3} so there is no need to load that explicitly. +% Actually, \pkg{expl3}, \pkg{l3keys2e} and the \pkg{xparse} +% functionality is now all part of the \LaTeX{} kernel so the next +% line is actually not needed at all with a current \LaTeX{} kernel, but +% in order to support older installations we keep it for now. +% +% \begin{macrocode} +\RequirePackage{xparse,l3keys2e} +% \end{macrocode} +% +% Here we introduce the package and specify its version number: +% \begin{macrocode} +\ProvidesExplPackage{unicodefonttable} + {\unicodefonttabledate} + {\unicodefonttableversion} + {Producing font tables for Unicode and other fonts} +% \end{macrocode} +% +% \newcommand\hex[1]{$\langle\textit{hex}_{#1}\rangle$} +% +% +% +% +% +% \subsection{User interface commands} +% +% +% Throughout the implementation we will define a number of keys (and +% their allowed values). We introduce them at the point where they are +% used, so they are sprinkled throughout the code.\footnote{This fits +% with the way this package was developed. I first implemented a +% single rigid table layout without configuration possibilities and +% then thought about which parts I wanted to have flexible. I then +% replaced the rigid code with code that is affected by setting +% key/value pairs.} + +% \begin{macro}{\fonttablesetup} +% To set up user defaults for the keys we provide a standard +% interface. The command \cs{unicodefonttabletablesetup} expects a +% key/value list and can be called as often as necessary. +% \begin{macrocode} +\NewDocumentCommand \fonttablesetup { m } + { \keys_set:nn {@@} {#1} \ignorespaces } +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\displayfonttable} +% The document-level command for generating a font table. +% \begin{macrocode} +\NewDocumentCommand\displayfonttable {s O{} m o}{% + \IfBooleanTF #1 + { +% \end{macrocode} +% For the starred form we preset a number of keys with values +% suitable when displaying 8-bit legacy fonts. +% With such fonts Unicode block headers make little +% sense (as the fonts do not conform to the Unicode layout and +% since they have at most 265 glyphs). It is therefore also unnecessary to +% loop over the whole Unicode range of the first plane. +% If necessary all of them can still be overwritten in the optional argument. +% \begin{macrocode} + \@@_display_fonttable:nnn + {nostatistics,display-block=none,hex-digits=head,range-end=FF,#2} + {#3}{#4} + } + { + \@@_display_fonttable:nnn {#2}{#3}{#4} + } +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_display_fonttable:nnn} +% This command is the main workhorse of the +% package. It produces a \texttt{longtable} containing all font +% glyphs with 16 glyphs per row. The first optional argument is +% used to configure the table through key/value pairs, the +% mandatory argument is the font name to display (in +% \texttt{fontspec} conventions) and the final optional argument is +% the font feature list if any. If the latter is not provided it +% will get a special value (\texttt{--NoValue--}) assigned by +% \texttt{xparse}, which is something that can be tested for. +% \begin{macrocode} +\cs_new:Npn \@@_display_fonttable:nnn #1#2#3 { + \group_begin: +% \end{macrocode} +% First initialize the font that should be displayed (perhaps with a +% feature list) and then update the key/value list using \verb=#1=. +% \begin{macrocode} + \fontspec{#2}[#3] + \keys_set:nn{@@}{#1} +% \end{macrocode} +% If the user has asked for a comparsion to some other font we need to set this up: +% \begin{macrocode} + \tl_if_empty:NTF \l_@@_compare_with_tl + { \tl_clear:N \l_@@_compare_font_tl } + { + \setfontface \l_@@_compare_font_tl {\l_@@_compare_with_tl}[] + \cs_set_eq:NN \@@_handle_missing_glyph:n + \@@_handle_missing_glyph_compare:n + } +% \end{macrocode} +% Then we start the table with 17 columns. We use \texttt{longtable} +% if we produce a caption and \texttt{longtable*} if not (so that +% the table number is not increased, which would look odd if you +% have other tables in your document). +% \begin{macrocode} + \begin{longtable\bool_if:NF\l_@@_display_header_bool{*}} + {@{}r@{\quad}*{16}{c}@{}} +% \end{macrocode} +% Special headers and footers are set up first: +% \begin{macrocode} + \@@_setup_header_footer:nn{#2}{#3} +% \end{macrocode} +% Then we produce all table rows with the glyphs. +% \begin{macrocode} + \@@_produce_table_rows: +% \end{macrocode} +% At the very end we may typeset some statistics. This can't be +% done in the table footer, because the data is dynamic (e.g., +% number of glyphs processed) and the table footers are static and +% do not change based on the table content. +% \begin{macrocode} + \@@_handle_table_ending:n {#2} + \end{longtable\bool_if:NF\l_@@_display_header_bool{*}} + \group_end: +} +% \end{macrocode} +% \end{macro} + + +% +% \begin{macro}{\fonttableglyphcount} +% \begin{macro}{\g_@@_glyph_int,\g_@@_glyph_only_B_int,\g_@@_glyph_also_B_int} +% While generating the font table we count the number of glyphs we +% see (and typeset). The total is available in the command +% \cs{fonttableglyphcount} after the table got finished and will be reset to +% zero when the next table starts. +% \begin{macrocode} +\DeclareDocumentCommand \fonttableglyphcount {} + { \int_use:N \g_@@_glyph_int } +% \end{macrocode} +% +% \begin{macrocode} +\int_new:N \g_@@_glyph_int +% \end{macrocode} +% When comparing fonts we also record data for the second font: the +% number of glyphs in both and the number of glyphs only in the +% second one. +% \begin{macrocode} +\int_new:N \g_@@_glyph_only_B_int +\int_new:N \g_@@_glyph_also_B_int +% \end{macrocode} +% \end{macro} +% \end{macro} + + + + +% \subsection{The overall table layout} +% +% +% \begin{macro}{\@@_setup_header_footer:nn} +% Setting up header and footer lines of the table. +% This macro receives the \textit{font name} and the \textit{font +% features} specified by the user as its arguments. +% \begin{macrocode} +\cs_new:Npn \@@_setup_header_footer:nn #1#2{ +% \end{macrocode} +% On the first page of the table the header may show a caption or +% some other sort of title based on the value of +% \cs{l_@@_display_header_bool}. The formatting is handled by +% \cs{@@_format_table_title:nn} which can be customized through the +% key \key{title-format}. +% \begin{macrocode} + \bool_if:NT \l_@@_display_header_bool + { \@@_format_table_title:nn{#1}{#2} \@@_debug_nl:n{T}\\*[6pt] } +% \end{macrocode} +% We may also want to display a line of hex digits. This is +% controlled through the key \key{hex-digits} that accepts different +% values: \kval{head}, \kval{foot}, \kval{head+foo}, \kval{block} +% (after a block title) or \kval{none}. +% \begin{macrocode} + \bool_if:NT \l_@@_header_hex_digits_bool + { \@@_display_row_of_hex_digits: \@@_debug_nl:n{H}\\* } + \endfirsthead +% \end{macrocode} +% Headers for later table pages have a continuation title and +% maybe a row of hex digits. +% \begin{macrocode} + \bool_if:NT \l_@@_display_header_bool + { \@@_format_table_cont:nn{#1}{#2} \@@_debug_nl:n{T}\\*[6pt] } + \bool_if:NT \l_@@_header_hex_digits_bool + { \@@_display_row_of_hex_digits: \@@_debug_nl:n{H}\\* } + \endhead +% \end{macrocode} +% Footers of the table are either empty or show a row of hex digits. +% \begin{macrocode} + \bool_if:NT \l_@@_footer_hex_digits_bool + { \@@_display_row_of_hex_digits: \@@_debug_nl:n{H}\\* } + \endfoot +% \end{macrocode} +% The footer of the last page of the table will always be +% empty. Any special row, such as a row of hex digits, will be +% provided in the table body. The reason is that we may want to +% display statistics at the very end of the table and those can't be +% placed into a static footer. +% \begin{macrocode} + \endlastfoot +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\l_@@_header_hex_digits_bool} +% \begin{macro}{\l_@@_footer_hex_digits_bool} +% \begin{macro}{\l_@@_blockwise_hex_digits_bool} +% Here are the booleans we use in the code. +% \begin{macrocode} +\bool_new:N \l_@@_header_hex_digits_bool +\bool_new:N \l_@@_footer_hex_digits_bool +\bool_new:N \l_@@_blockwise_hex_digits_bool +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% \begin{macro}{\@@_display_row_of_hex_digits:} +% \begin{macro}{\@@_format_hex_digit:n} +% Producing a row of hex digits is simple. +% \begin{macrocode} +\cs_new:Npn \@@_display_row_of_hex_digits: { + & \@@_format_hex_digit:n{0} & \@@_format_hex_digit:n{1} + & \@@_format_hex_digit:n{2} & \@@_format_hex_digit:n{3} + & \@@_format_hex_digit:n{4} & \@@_format_hex_digit:n{5} + & \@@_format_hex_digit:n{6} & \@@_format_hex_digit:n{7} + & \@@_format_hex_digit:n{8} & \@@_format_hex_digit:n{9} + & \@@_format_hex_digit:n{A} & \@@_format_hex_digit:n{B} + & \@@_format_hex_digit:n{C} & \@@_format_hex_digit:n{D} + & \@@_format_hex_digit:n{E} & \@@_format_hex_digit:n{F} } +% \end{macrocode} +% Each digit is typeset in typewriter and in script size. We offer +% font and color +% customizations. Note that it is important to set an explicit +% family. Otherwise the hex digits are formatted using the current +% table font (which may or may not work at all). +% \begin{macrocode} +\cs_new:Npn \@@_format_hex_digit:n #1 { + \l_@@_hex_digits_font_tl \l_@@_color_tl #1 } +% \end{macrocode} +% \end{macro} +% \end{macro} +% + +% \begin{macro}{\l_@@_color_tl} +% The token list to hold definition if set up. +% \begin{macrocode} +\tl_new:N \l_@@_color_tl +% \end{macrocode} +% \end{macro} +% +% +% \keysetup{overall table} +% Here are the definitions for the keys used in the code above: +% \begin{macrocode} +\keys_define:nn {@@} { +% \end{macrocode} +% The \key{header} key is a boolean that determines if a header +% title should be produced (default) +% \begin{macrocode} + ,header .bool_set:N = \l_@@_display_header_bool + ,header .default:n = true + ,header .initial:n = true +% \end{macrocode} +% To ease the setup we also support the key \key{noheader} which is +% a short form for \texttt{header=false}. +% \begin{macrocode} + ,noheader .bool_set_inverse:N = \l_@@_display_header_bool + ,noheader .default:n = true +% \end{macrocode} +% The default for the \key{title-format} key is to produce a +% \cs{caption} listing the font name and any features (if +% given). Note the \cs{IfValueTF} command (provided by +% \texttt{xparse}) that checks if the second argument got any value +% or has the special \texttt{--NoValue--} value. +% \begin{macrocode} + ,title-format .cs_set:Np = \@@_format_table_title:nn #1#2 + ,title-format .initial:n = + \IfValueTF{#2} { \caption{ #1~ (features:~ \texttt{\small#2}) } } + { \caption{ #1 } } +% \end{macrocode} +% The default continuation title ignores the given features, so the +% formatting is somewhat simpler. It uses \verb=\caption[]{...}= to +% make a caption that doesn't alter the table number. +% \begin{macrocode} + ,title-cont-format .cs_set:Np = \@@_format_table_cont:nn #1#2 + ,title-cont-format .initial:n = \caption[]{#1~ \emph{cont.}} +% \end{macrocode} +% The key \key{hex-digits} is implemented as a choice, where each +% allowed value sets different booleans that are then used in the code. +% \begin{macrocode} + ,hex-digits .choice: + ,hex-digits / block .code:n = + \bool_set_true:N \l_@@_blockwise_hex_digits_bool + \bool_set_false:N \l_@@_header_hex_digits_bool + \bool_set_false:N \l_@@_footer_hex_digits_bool + ,hex-digits / foot .code:n = + \bool_set_true:N \l_@@_footer_hex_digits_bool + \bool_set_false:N \l_@@_header_hex_digits_bool + \bool_set_false:N \l_@@_blockwise_hex_digits_bool + ,hex-digits / head .code:n = + \bool_set_true:N \l_@@_header_hex_digits_bool + \bool_set_false:N \l_@@_footer_hex_digits_bool + \bool_set_false:N \l_@@_blockwise_hex_digits_bool + ,hex-digits / head+foot .code:n = + \bool_set_true:N \l_@@_header_hex_digits_bool + \bool_set_true:N \l_@@_footer_hex_digits_bool + \bool_set_false:N \l_@@_blockwise_hex_digits_bool + ,hex-digits / none .code:n = + \bool_set_false:N \l_@@_header_hex_digits_bool + \bool_set_false:N \l_@@_footer_hex_digits_bool + \bool_set_false:N \l_@@_blockwise_hex_digits_bool + ,hex-digits .initial:n = head +% \end{macrocode} +% The font for hex digits are set with \key{hex-digits-font}. +% \begin{macrocode} + ,hex-digits-font .tl_set:N = \l_@@_hex_digits_font_tl + ,hex-digits-font .initial:n = \ttfamily \scriptsize +% \end{macrocode} +% The \key{color} key is used in most places that get colored; some +% have their own key but default to the main color. +% \begin{macrocode} + ,color .choice: + ,color / none .code:n = \tl_clear:N \l_@@_color_tl + ,color / unknown .code:n = \tl_set:Nn \l_@@_color_tl { \color {#1} } + ,color .initial:n = blue + } +% \end{macrocode} +% +% +% +% +% \begin{macro}{\@@_handle_table_ending:n} +% At the end of the table we may want to display a final row of +% hex digits and perhaps some statistics, i.e., the number of +% typeset glyphs. +% \begin{macrocode} +\cs_new:Npn \@@_handle_table_ending:n #1 { +% \end{macrocode} +% +% \begin{macrocode} + \@@_debug_nl:n{H} \\* + \bool_if:NT \l_@@_footer_hex_digits_bool + { \@@_display_row_of_hex_digits: \@@_debug_nl:n{H} \\* } + \bool_if:NT \l_@@_display_statistics_bool + { \\*[2pt] + \multicolumn{17}{l}{ \l_@@_stats_font_tl +% \end{macrocode} +% If we do font comparison, we use a different command for +% displaying statistics and pass more data to it. +% \begin{macrocode} + \tl_if_empty:NTF \l_@@_compare_with_tl + { + \@@_format_stats:nn{#1}{\fonttableglyphcount} + } + { + \@@_format_compare_stats:nnnnnn{#1}{\fonttableglyphcount} + { \l_@@_compare_with_tl } +% \end{macrocode} +% The extra arguments are total glyph number in second font, glyphs +% missing in second font and glyphs only in second font. +% \begin{macrocode} + { \int_eval:n { \int_use:N\g_@@_glyph_also_B_int + + \int_use:N\g_@@_glyph_only_B_int } + } + { \int_eval:n { \fonttableglyphcount - + \int_use:N\g_@@_glyph_also_B_int } + } + { \int_use:N\g_@@_glyph_only_B_int } + } +% \end{macrocode} +% We don't know exactly how wide the table is (and nor does the +% user) but one may need to use \cs{parbox} when formatting +% the statistic line(s). So we back up a bit (rather random) which +% allows us to use \verb=\parbox{\linewidth}{...= in the key +% without thinking too much about it. +% \begin{macrocode} + \hspace*{-3cm} + } + } +} +% \end{macrocode} +% +% \keysetup{for statistics} +% Here are the keys used above. By default we produce statistics. +% \begin{macrocode} +\keys_define:nn {@@} { + ,statistics .bool_set:N = \l_@@_display_statistics_bool + ,statistics .default:n = true + ,statistics .initial:n = true +% \end{macrocode} +% the key \key{nostatistics} is just short for \texttt{statistics=false}: +% \begin{macrocode} + ,nostatistics .bool_set_inverse:N = \l_@@_display_statistics_bool + ,nostatistics .default:n = true +% \end{macrocode} +% The default font we use is \cs{normalfont}. Again we need to +% supply a family to avoid getting the font used in the table body. +% \begin{macrocode} + ,statistics-font .tl_set:N = \l_@@_stats_font_tl + ,statistics-font .initial:n = \normalfont\small +% \end{macrocode} +% And here we have the default text. There is only space for a +% single line. If more text is needed one needs to provide some +% explicit \cs{parbox}. +% \begin{macrocode} + ,statistics-format .cs_set:Np = \@@_format_stats:nn #1#2 + ,statistics-format .initial:n = Total~ number~ of~ glyphs~ in~ #1:~#2 + } +% \end{macrocode} +% \end{macro} +% +% +% +% +% +% \begin{macro}{\@@_debug_nl:n} +% While developing the code I had a bit of trouble getting the line +% endings correct, so I added a little macro that made them visible +% (displaying its argument in the table margin when the key +% \key{debug} is used. By default it does nothing. +% \begin{macrocode} +\cs_new:Npn \@@_debug_nl:n #1 {} +% \end{macrocode} +% +% \keysetup{debugging} +% This key is really internal and is therefore not documented above +% (and its behavior may changes over time). +% \begin{macrocode} +\keys_define:nn {@@} { + debug .code:n = \cs_set:Npn \@@_debug_nl:n ##1 + {\rlap{\normalfont\scriptsize \qquad ##1}} } +% \end{macrocode} +% \end{macro} +% +% +% +% +% +% +% +% \subsection{The producing the table content} +% +% +% The body of the table consists of rows with sixteen glyphs each +% and to produce it we loop through all possible Unicode points +% starting at \texttt{U+0000} and ending with \texttt{U+FFFF}. +% +% This is implemented with a four-level nested loop that runs through the +% values \texttt{0}, \texttt{1}, \ldots, \texttt{F} with the +% current hex value in each of the four positions stored in some variable. + + +% \begin{macro}{\g_@@_hex_H_tl,\g_@@_hex_A_tl, +% \g_@@_hex_B_tl,\g_@@_hex_C_tl} +% \cs{g_@@_hex_H_tl} is a bit special because, it is initially not +% zero, but empty, so that slots in the lower plane are denoted by 4 +% hex digits. +% We really only need three further variables, as the value in the +% innermost loop can used directly. +% \begin{macrocode} +\tl_new:N \g_@@_hex_H_tl % higher plane +\tl_new:N \g_@@_hex_A_tl +\tl_new:N \g_@@_hex_B_tl +\tl_new:N \g_@@_hex_C_tl +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\c_@@_hex_digits_clist} +% Here is the sequence we loop through on each level, except the +% one for the outer level. +% \begin{macrocode} +\clist_const:Nn\c_@@_hex_digits_clist{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\@@_produce_table_rows:,\@@_handle_hex_H:n, +% \@@_handle_hex_A:n,\@@_handle_hex_B:n, +% \@@_handle_hex_C:n,\@@_handle_hex_D:n} +% The overall code layout is then fairly simply: +% \begin{macrocode} +\cs_new:Npn \@@_produce_table_rows: { +% \end{macrocode} +% First to some general initialization +% \begin{macrocode} + \@@_initialize_table_rows: +% \end{macrocode} +% and then loop we start the loop. The outer level is a bit special +% as currently Unicode has only slots allocated in plane 0, 1, 2 +% and E (well, and F, but that is a private area) so we loop only +% over those and instead of \texttt{0} we use an empty value. +% Not covered is the whole of plane 16 which too is now a +% private area. +% +% \begin{macrocode} + \clist_map_function:nN { { } , 1, 2, E, F } \@@_handle_hex_H:n } +% \end{macrocode} +% +% Most fonts do not have glyphs in the higher planes, which is why +% by default we don't loop using a nonempty \cs{@@_handle_hex_H:n}. +% But if the user wants to scan and display the higher slots they +% can by setting \key{range-end} appropriatly. +% +% So after setting \cs{@@_handle_hex_H:n} we loop over +% \cs{c_@@_hex_digits_clist} for the next +% hex digit (which we call \enquote{A}). +% \begin{macrocode} +\cs_new:Npn \@@_handle_hex_H:n #1 { \tl_gset:Nn\g_@@_hex_H_tl{#1} + \clist_map_function:NN \c_@@_hex_digits_clist \@@_handle_hex_A:n } +% \end{macrocode} +% +% Handling \enquote{A} means storing its value for later use and +% then start a loop for setting the second (or third on higher planes) hex digits: +% \begin{macrocode} +\cs_new:Npn \@@_handle_hex_A:n #1 { \tl_gset:Nn\g_@@_hex_A_tl{#1} + \clist_map_function:NN \c_@@_hex_digits_clist \@@_handle_hex_B:n } +% \end{macrocode} +% +% Same game for \enquote{B} and \enquote{C}\footnote{Actually this +% is a white lie. In reality we do a lot of extra stuff when +% handling \enquote{C} so later one we give a second definition for +% \cs{@@_handle_hex_C:n} but for understanding the overall picture +% the simpler one shown here is better.}: +% \begin{macrocode} +\cs_new:Npn \@@_handle_hex_B:n #1 { \tl_gset:Nn\g_@@_hex_B_tl{#1} + \clist_map_function:NN \c_@@_hex_digits_clist \@@_handle_hex_C:n } +% \end{macrocode} +% +% \begin{macrocode} +\cs_new:Npn \@@_handle_hex_C:n #1 { \tl_gset:Nn\g_@@_hex_C_tl{#1} + \clist_map_function:NN \c_@@_hex_digits_clist \@@_handle_hex_D:n } +% \end{macrocode} +% In the innermost loop we now have the full Unicode number +% available, so there we have to decide what to do with it. This is +% done by \cs{@@_handle_hex_D:n} that receives the full number, +% e.g., \texttt{1A7C} or \texttt{1AD00}, as its argument. +% \begin{macrocode} +\cs_new:Npn \@@_handle_hex_D:n #1 { + \@@_handle_slot:x + { " \g_@@_hex_H_tl \g_@@_hex_A_tl + \g_@@_hex_B_tl \g_@@_hex_C_tl #1 } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\g_@@_row_tl} +% We first collect the glyphs for a whole row before deciding to +% typeset it, because if the row is entirely empty we want to omit +% it. The data for the row is collected slot by slot and the typesetting +% information (the glyph or the indication for a missing glyph is +% appended to \cs{g_@@_row_tl}. +% \begin{macrocode} +\tl_new:N \g_@@_row_tl +% \end{macrocode} +% \end{macro} + + +% \begin{macro}{\@@_handle_slot:n,\@@_handle_slot:x} +% If the current slot number under inspection contains a glyph in +% our font we want to typeset it. But we don't do this immediately, +% instead we build up the whole row and typeset it later. We +% therefore append a \verb=&= and the glyph (including the necessary +% formatting) to the token list \cs{g_@@_row_tl}. +% \begin{macrocode} +\cs_new:Npn \@@_handle_slot:n #1 { + \@@_if_uchar_exists:nTF { #1 } + { \tl_gput_right:Nn \g_@@_row_tl + { & \@@_format_glyph:n { \symbol{#1} } } +% \end{macrocode} +% We then increment the overall glyph count and record that we have +% seen at least one glyph in the current row. There is not much +% point in displaying rows that are completely empty; indeed, +% we'd end up with extremely large tables which are +% mostly empty. +% \begin{macrocode} + \int_gincr:N\g_@@_glyph_int + \bool_gset_true:N \g_@@_glyph_seen_bool +% \end{macrocode} +% If we do font comparison we also check if the glyph is in the +% second font and if so record that fact. +% \begin{macrocode} + \tl_if_empty:NF \l_@@_compare_font_tl + { + \group_begin: + \l_@@_compare_font_tl + \@@_if_uchar_exists:nT { #1 } + { \int_gincr:N \g_@@_glyph_also_B_int } + \group_end: + } + } +% \end{macrocode} +% If the current slot has no glyph in the font we also add a +% \verb=&= followed by something that indicates the glyph is +% missing. If we do font comparison, it may show the glyph from +% the other font (if it exists there) in some special way to indicate which glyph +% should be in this slot. +% \begin{macrocode} + { \@@_handle_missing_glyph:n {#1} } +} +% \end{macrocode} +% +% \begin{macrocode} +\cs_generate_variant:Nn \@@_handle_slot:n {x} +% \end{macrocode} +% \end{macro} +% + +% \begin{macro}{\@@_handle_missing_glyph:n, +% \@@_handle_missing_glyph_std:n, +% \@@_handle_missing_glyph_compare:n} +% +% In the standard case we typeset a special symbol to indicate that the glyph is missing. +% For this case we provide some customization through keys: +% \cs{l_@@_missing_glyph_tl} holds the symbol for a missing glyph +% (default: a hyphen). It is typeset in a specific color and we allow for +% setting it in a special font. The actual symbol number in +% \verb=#1= is not needed in this scenario. +% \begin{macrocode} +\cs_new:Npn \@@_handle_missing_glyph_std:n #1 { + \tl_gput_right:Nn \g_@@_row_tl + { & + \@@_format_glyph:n { +% \colorbox{black!30} % <--- povide interface + {\l_@@_missing_glyph_color_tl + \l_@@_missing_glyph_font_tl + \l_@@_missing_glyph_tl } + } + } +} +% \end{macrocode} +% +% \keysetup{missing glyphs} +% Here are the keys for customizing the missing glyph representation. +% \begin{macrocode} +\keys_define:nn {@@} { + missing-glyph-color .choice: + ,missing-glyph-color / none .code:n = + \tl_clear:N \l_@@_missing_glyph_color_tl + ,missing-glyph-color / unknown .code:n = + \tl_set:Nn \l_@@_missing_glyph_color_tl { \color {#1} } +% + ,missing-glyph-font .tl_set:N = \l_@@_missing_glyph_font_tl + ,missing-glyph-font .initial:n = \ttfamily \scriptsize + ,missing-glyph .tl_set:N = \l_@@_missing_glyph_tl + ,missing-glyph .initial:n = - } +% \end{macrocode} +% +% +% The default definition for the color is to use the same as the +% one specified by the \key{color} key. We therefore define the +% default outside of the \pkg{l3keys} method. +% \begin{macrocode} +\tl_new:N \l_@@_missing_glyph_color_tl +\tl_set:Nn \l_@@_missing_glyph_color_tl {\l_@@_color_tl} +% \end{macrocode} +% +% This is the version that handles a missing glyph by checking +% the \key{compare-with} font to see if that font contains the +% glyph. +% If yes, the substitute glyph will be typeset, otherwise the missing +% glyph symbol is shown by calling \cs{@@_handle_missing_glyph_std:n}. +% \begin{macrocode} +\cs_new:Npn \@@_handle_missing_glyph_compare:n #1 { + \group_begin: +% \end{macrocode} +% Locally switch to the other font, then check for the glyph: +% \begin{macrocode} + \l_@@_compare_font_tl + \@@_if_uchar_exists:nTF { #1 } + { +% \end{macrocode} +% If available, format it (together with the \texttt{\&}) but use a +% special color and perhaps a background color. +% \begin{macrocode} + \tl_gput_right:Nn \g_@@_row_tl + { & + \@@_format_glyph:n + { \l_@@_compare_bgcolor_tl { \l_@@_compare_color_tl + \l_@@_compare_font_tl + \symbol {#1} } + } + } +% \end{macrocode} +% Having seen a glyph only in the second font we record this fact. +% \begin{macrocode} + \int_gincr:N \g_@@_glyph_only_B_int +% \end{macrocode} +% Also tell the algorithm that we have seen a glyph to typeset. If +% we don't do this then a row consisting of only substitute glyphs is not +% typeset. However, we don't update the glyph count, because this +% is not a glyph from the main font we display. +% \begin{macrocode} + \bool_gset_true:N \g_@@_glyph_seen_bool + } +% \end{macrocode} +% If the alternate font doesn't have the glyph either we +% typeset the missing glyph symbol. +% \begin{macrocode} + { \@@_handle_missing_glyph_std:n {} } + \group_end: +} +% \end{macrocode} +% +% \keysetup{comparison} +% +% In order to display glyphs from a secondary font we need a +% secondary color for the glyph itself and possibly some background color. +% \begin{macrocode} +\tl_new:N \l_@@_compare_with_tl +\tl_new:N \l_@@_compare_color_tl +\tl_new:N \l_@@_compare_bgcolor_tl +% \end{macrocode} +% +% \begin{macrocode} +\keys_define:nn {@@} + { + ,compare-with .tl_set:N = \l_@@_compare_with_tl + ,compare-with .initial:n = + ,compare-color .choice: + ,compare-color / none .code:n + = \tl_clear:N \l_@@_compare_color_tl + ,compare-color / unknown .code:n + = \tl_set:Nn \l_@@_compare_color_tl { \color {#1} } + ,compare-color .initial:n = red + ,compare-bgcolor .choice: + ,compare-bgcolor / none .code:n + = \tl_clear:N \l_@@_compare_bgcolor_tl + ,compare-bgcolor / unknown .code:n + = \tl_set:Nn \l_@@_compare_bgcolor_tl { \colorbox {#1} } + ,compare-bgcolor .initial:n = black!10 +% \end{macrocode} +% If we run a comparison we show different statistics that have +% their own key. +% \begin{macrocode} + ,statistics-compare-format .cs_set:Np + = \@@_format_compare_stats:nnnnnn #1#2#3#4#5#6 + ,statistics-compare-format .initial:n + = \parbox{\linewidth}{ + Total~ number~ of~ glyphs~ in~ \texttt{#1}:~#2\\ + Comparison~ font~ \texttt{#3}~ has~ #5~ missing~ and~ #6~ + extra~ glyphs} + } +% \end{macrocode} +% +% +% By default, i.e., if no font for comparison has been specified, we +% handle missing glyphs by displaying a missing glyph symbol. +% \begin{macrocode} +\cs_new_eq:NN \@@_handle_missing_glyph:n + \@@_handle_missing_glyph_std:n +% \end{macrocode} +% \end{macro} +% + + +% \begin{macro}{\@@_format_glyph:n} +% Every glyph is typeset in a box of equal width with the glyph +% centered and if necessary protruding on both sides. +% \begin{macrocode} +\cs_new:Npn \@@_format_glyph:n #1 { + \hbox_to_wd:nn {\l_@@_glyph_box_dim} { \hss #1 \hss } } +% \end{macrocode} +% +% \keysetup{glyph typesetting} +% The key to customize the width. The 6pt are fine for most cases. +% \begin{macrocode} +\dim_new:N\l_@@_glyph_box_dim +% \end{macrocode} +% +% \begin{macrocode} +\keys_define:nn {@@} { + glyph-width .dim_set:N = \l_@@_glyph_box_dim + ,glyph-width .initial:n = 6pt +} +% \end{macrocode} +% \end{macro} + + +% \begin{macro}{\@@_if_uchar_exists:n} +% For testing whether or not a slot position contains a glyph we +% need to resort to low-level methods, because so far +% \texttt{expl3} doesn't offer an interface. +% \begin{macrocode} +\prg_set_conditional:Npnn \@@_if_uchar_exists:n #1 { TF , T } + { \tex_iffontchar:D \tex_font:D #1 \scan_stop: + \prg_return_true: + \else: + \prg_return_false: + \fi: + } +% \end{macrocode} +% \end{macro} +% +% +% +% +% \subsection{Handling a single row} +% +% +% \begin{macro}{\@@_handle_hex_C:n} +% As promised here is the read definition for +% \cs{@@_handle_hex_C:n} in all its glory. +% \begin{macrocode} +\cs_set:Npn \@@_handle_hex_C:n #1 { +% \end{macrocode} +% We are now at the start of a new row (but with the last row not +% yet typeset) and this last row may need a Unicode block heading +% before it. This is the reason why we have to delay the +% typesetting, because in case the line doesn't contain any glyphs +% we want to typeset neither and that is only known after all +% slots in the row have been processed. +% \begin{macrocode} + \@@_maybe_typeset_a_row_and_display_a_block_title: +% \end{macrocode} +% We then store away the value for the third hex digit (denoted as +% C) in order to start with the next row. +% \begin{macrocode} + \tl_gset:Nn\g_@@_hex_C_tl{#1} +% \end{macrocode} +% Being at the start of a new row we might be at the start of a new +% Unicode block. If so we have to update the block title to add in +% front of the row when we typeset it (or in front of one of the +% next rows if the first rows in the is block have no glyphs). If +% we are still in the same block no update happens. +% \begin{macrocode} + \@@_update_block_title:n { \g_@@_hex_H_tl + \g_@@_hex_A_tl + \g_@@_hex_B_tl + \g_@@_hex_C_tl } +% \end{macrocode} +% We now check if this row is within the requested range, i.e., +% greater than or equal to \cs{l_@@_range_start_tl} and not greater than +% \cs{l_@@_range_end_tl}. +% \begin{macrocode} + \int_compare:nNnF + { " \g_@@_hex_H_tl \g_@@_hex_A_tl + \g_@@_hex_B_tl \g_@@_hex_C_tl 0 } + < { "\l_@@_range_start_tl } + { + \int_compare:nNnTF + { " \g_@@_hex_H_tl \g_@@_hex_A_tl + \g_@@_hex_B_tl \g_@@_hex_C_tl 0 } + > { "\l_@@_range_end_tl } +% \end{macrocode} +% If we are past the \texttt{end-range} we break out the clist +% mapping, to avoind unnecessary repetition. This should be +% propagated back to the outer clists as well (not done). +% \begin{macrocode} + { \clist_map_break: } +% \end{macrocode} +% If we are within range we process the slots in the row by first +% initializing \cs{g_@@_row_tl} with the row title (the info on the +% left) and then loop through all slots the row to append glyphs +% (or missing glyphs) to \cs{g_@@_row_tl} to build up everything we +% need to finally typeset it. +% \begin{macrocode} + { + \tl_gset:Nx \g_@@_row_tl + { + \exp_not:N \@@_format_row_title:n + { \g_@@_hex_H_tl \g_@@_hex_A_tl + \g_@@_hex_B_tl \g_@@_hex_C_tl } + } + \clist_map_function:NN \c_@@_hex_digits_clist + \@@_handle_hex_D:n + } + } +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_format_row_title:n} +% The function to format the row title on the left, as used above. +% \begin{macrocode} +\cs_new:Npn \@@_format_row_title:n #1 { + \texttt { \footnotesize \l_@@_color_tl U+#1 0 \, - \, #1 F } +} +% \end{macrocode} +% \end{macro} +% +% +% +% \keysetup{ranges} +% +% For the range we have two keys, its start and the end. By default the +% whole range from 0 to FFFF is processed. +% +% \begin{macrocode} +\tl_new:N \l_@@_range_start_tl +\tl_new:N \l_@@_range_end_tl +% \end{macrocode} +% +% \begin{macrocode} +\keys_define:nn {@@} + { + ,range-start .tl_set:N = \l_@@_range_start_tl + ,range-start .initial:n = 0000 + ,range-end .tl_set:N = \l_@@_range_end_tl + ,range-end .initial:n = FFFF + } +% \end{macrocode} +% +% +% +% +% +% \begin{macro}{\@@_maybe_typeset_a_row_and_display_a_block_title:} +% The function handles the just-finished row and, if the row does not +% consist only of missing glyphs, typesets it. If necessary it also typesets +% a Unicode block name first. +% \begin{macrocode} +\cs_new:Npn \@@_maybe_typeset_a_row_and_display_a_block_title: { +% \end{macrocode} +% We first check if the row had any real glyphs. +% \begin{macrocode} + \bool_if:NTF \g_@@_glyph_seen_bool + { +% \end{macrocode} +% If the row needs typesetting the fun part starts. We first look +% at the content of \cs{g_@@_block_title_tl}. +% \begin{macrocode} + \tl_if_empty:NTF \g_@@_block_title_tl + { +% \end{macrocode} +% It is empty we are in the middle of a block and we can ignore +% the Unicode title. However, we have to see if the previous row +% (or several) was missing (i.e., contained no glyphs). In that +% case we leave a little extra space, otherwise we just finish the +% previous row +% \begin{macrocode} + \bool_if:NTF \g_@@_row_missing_bool + { \@@_debug_nl:n{A}\\[6pt] } + { \@@_debug_nl:n{B}\\ } + } + { +% \end{macrocode} +% Otherwise we first have to typeset the Unicode block title (or +% whatever should happen instead). +% \begin{macrocode} + \typeout{ Processing~ \tl_use:N \g_@@_block_title_tl } + \bool_if:NTF \l_@@_display_block_bool + { +% \end{macrocode} +% If we are to typeset the title the action depends a bit on +% whether we are at the very first row or typesetting a later block. +% \begin{macrocode} + \bool_if:NTF \g_@@_first_row_bool + { + \bool_gset_false:N \g_@@_first_row_bool + \@@_debug_nl:n{C}\\[-4pt] + } + { + \@@_debug_nl:n{D}\\[8pt] + \noalign{\vskip 1pt plus 1pt} % space above block: customizable? + } +% \noalign{\smallskip} % space above block: customizable? + \multicolumn{17}{c}{\normalfont \bfseries + \tl_use:N \g_@@_block_title_tl} +% \end{macrocode} +% After the block title is typeset we may want to add a row of hex +% digits as well if that was requested, otherwise we only leave a +% bit of extra space. +% \begin{macrocode} + \bool_if:NTF \l_@@_blockwise_hex_digits_bool + { \@@_debug_nl:n{E}\\* + \@@_display_row_of_hex_digits: + \@@_debug_nl:n{H}\\*[2pt] + } + { \@@_debug_nl:n{F}\\*[2pt] } + } + { +% \end{macrocode} +% If the Unicode block title is not typeset we may still have to do +% someting special and again it differs if we at the very beginning +% of the table (because there we do nothing except changing the +% state of \cs{g_@@_first_row_bool}). +% \begin{macrocode} + \bool_if:NTF \g_@@_first_row_bool + { \bool_gset_false:N \g_@@_first_row_bool } + { + \@@_debug_nl:n{G~ (new~ block)} + \l_@@_display_block_action_tl + } + } +% \end{macrocode} +% Once we are past the block title we clear it, so that it is not +% retypeset before the next row. +% \begin{macrocode} + \tl_gclear:N \g_@@_block_title_tl + } +% \end{macrocode} +% The final action is to typeset the row and reset the booleans (in +% case they were true; if they are false already then we do this +% unnecessarily, but that is probably faster than testing first). +% \begin{macrocode} + \bool_gset_false:N \g_@@_glyph_seen_bool + \bool_gset_false:N \g_@@_row_missing_bool + \tl_use:N \g_@@_row_tl + } +% \end{macrocode} +% Current row had no glyphs; remember that fact, and that is all we +% have to do in that case. +% \begin{macrocode} + { + \bool_gset_true:N \g_@@_row_missing_bool + } +} +% \end{macrocode} +% \end{macro} + +% +% +% \subsection{Initialisation at the start of the table} +% +% +% \begin{macro}{\g_@@_first_row_bool,\g_@@_glyph_seen_bool,\g_@@_row_missing_bool} +% Declare the three booleans used in the code below. They will tell +% us answers to the following questions: +% \begin{itemize} +% \item Are we processing the first row? +% \item Have we seen any glyph so far (in the current row)? +% \item Did we have one or more missing rows recently? +% \end{itemize} +% \begin{macrocode} +\bool_new:N \g_@@_first_row_bool +\bool_new:N \g_@@_glyph_seen_bool +\bool_new:N \g_@@_row_missing_bool +% \end{macrocode} +% \end{macro} + + + + + + +% \begin{macro}{\@@_initialize_table_rows:} +% At the start of a table we are processing the first row +% and so we (obviously) haven't seen a glyph yet and there wasn't a +% missing row recently. +% \begin{macrocode} +\cs_new:Npn \@@_initialize_table_rows: { + \bool_gset_true:N \g_@@_first_row_bool + \bool_gset_false:N \g_@@_glyph_seen_bool + \bool_gset_false:N \g_@@_row_missing_bool +% \end{macrocode} +% And clearly the glyph count for the font(s) is zero. +% \begin{macrocode} + \int_gzero:N \g_@@_glyph_int + \int_gzero:N \g_@@_glyph_only_B_int + \int_gzero:N \g_@@_glyph_also_B_int +} +% \end{macrocode} +% \end{macro} + + +% +% +% \subsection{Handling block titles} +% +% \begin{macro}{g_@@_block_title_tl} +% We keep the current block title in this token list. +% \begin{macrocode} +\tl_new:N \g_@@_block_title_tl +% \end{macrocode} +% \end{macro} + + +% \begin{macro}{\@@_update_block_title:n} +% A block title is updated when the hex digits A,B,C have a certain +% value, so this is nothing more than a huge case switch. +% \begin{macrocode} +\cs_new:Npn \@@_update_block_title:n #1 { + \tl_gset:Nx \g_@@_block_title_tl { + \int_case:nnF{ "#1 } + { + { "000 }{ Basic~ Latin } + { "008 }{ Latin-1~ Supplement } + { "010 }{ Latin~ Extended-A } + { "018 }{ Latin~ Extended-B } + { "025 }{ IPA~ Extensions } + { "02B }{ Spacing~ Modifier~ Letters } + { "030 }{ Combining~ Diacritical~ Marks } + { "037 }{ Greek~ and~ Coptic } + { "040 }{ Cyrillic } + { "053 }{ Armenian } + { "059 }{ Hebrew } + { "060 }{ Arabic } + { "070 }{ Syriac } + { "075 }{ Arabic~ Supplement } + { "078 }{ Thaana } + { "07C }{ NKo } + { "090 }{ Devanagari } + { "098 }{ Bengali } + { "0A0 }{ Gurmukhi } + { "0A8 }{ Gujarati } + { "0B0 }{ Oriya } + { "0B8 }{ Tamil } + { "0C0 }{ Telugu } + { "0C8 }{ Kannada } + { "0D0 }{ Malayalm } + { "0D8 }{ Sinhala } + { "0E0 }{ Thai } + { "0E8 }{ Lao } + { "0F0 }{ Tibetan } + { "100 }{ Myanmar } + { "10A }{ Georgian } + { "110 }{ Hangul~ Jamo } + { "120 }{ Ethiopic } + { "138 }{ Ethiopic~ Supplement } + { "13A }{ Cherokee } + { "140 }{ Unified~ Canadian~ Aboriginal~ Syllabics } + { "168 }{ Ogham } + { "16A }{ Runic } + { "170 }{ Tagalog } + { "172 }{ Hanunoo } + { "174 }{ Buhid } + { "176 }{ Tagbanwa } + { "178 }{ Khmer } + { "180 }{ Mongolian } + { "190 }{ Limbu } + { "195 }{ Tai~ Le } + { "198 }{ New~ Tai~ Le } + { "19E }{ Khmer~ Symbols } + { "1A0 }{ Buginese } + { "1B0 }{ Balinese } + { "1D0 }{ Phonetic~ Extensions } + { "1D8 }{ Phonetic~ Extensions~ Supplement } + { "1DC }{ Combining~ Diacritical~ Marks~ Supplement } + { "1E0 }{ Latin~ Extended~ Additional } + { "1F0 }{ Greek~ Extended } + { "200 }{ General~ Punctuation } + { "207 }{ Superscripts~ and~ Subscripts } + { "20A }{ Currency~ Symbols } + { "20D }{ Combining~ Diacritical~ Marks~ for~ Symbols } + { "210 }{ Letterlike~ Symbols } + { "215 }{ Number~ Forms } + { "219 }{ Arrows } + { "220 }{ Mathematical~ Operators } + { "230 }{ Miscellaneous~ Technical } + { "240 }{ Control~ Pictures } + { "244 }{ Optical~ Character~ Recognition } + { "246 }{ Enclosed~ Alphanumerics } + { "250 }{ Box~ Drawing } + { "258 }{ Block~ Elements } + { "25A }{ Geometric~ Shapes } + { "260 }{ Miscellaneous~ Shapes } + { "270 }{ Dingbats } + { "27C }{ Miscellaneous~ Mathematical~ Symbols-A } + { "27F }{ Supplemental~ Arrows-A } + { "280 }{ Braille~ Patterns } + { "290 }{ Supplemental~ Arrows-B } + { "298 }{ Miscellaneous~ Mathematical~ Symbols-B } + { "2A0 }{ Supplemental~ Mathematical~ Operators } + { "2B0 }{ Miscellaneous~ Symbols~ and~ Arrows } + { "2C0 }{ Glagolitic } + { "2C6 }{ Latin~ Extended-C } + { "2C8 }{ Coptic } + { "2D0 }{ Georgian~ Supplement } + { "2D3 }{ Tifinagh } + { "2D8 }{ Ethiopic~ Extended } + { "2E0 }{ Supplemental~ Punctuation } + { "2E8 }{ CJK~ Radicals~ Supplement } + { "2F0 }{ Kangxi~ Radicals } + { "2FF }{ Ideographic~ Description~ Characters } + { "300 }{ CJK~ Symbols~ and~ Punctuation } + { "304 }{ Hiragana } + { "30A }{ Katakana } + { "310 }{ Bopomofo } + { "313 }{ Hangul~ Compatibility~ Jamo } + { "319 }{ Kanbun } + { "31A }{ Bopomofo~ Extended } + { "31C }{ CJK~ Strokes } + { "31F }{ Katakana~ Phonetic~ Extensions } + { "320 }{ Enclosed~ CJK~ Letters~ and~ Months } + { "330 }{ CJK~ Compatibility } + { "4DC }{ Yijing~ Hexagram~ Symbols } + { "A00 }{ Yi~ Syllables } + { "A49 }{ Yi~ Radicals } + { "A70 }{ Modifier~ Tone~ Letters } + { "A72 }{ Latin~ Extended-D } + { "A80 }{ Syloti~ Nagri } + { "A84 }{ Phags-pa } + { "A88 }{ Saurashtra } + { "A8E }{ Devanagari Extended } + { "A90 }{ Kayah Li } + { "A93 }{ Rejang } + { "A96 }{ Hangul Jamo Extended-A } + { "A98 }{ Javanese } + { "A9E }{ Myanmar Extended-B } + { "AA0 }{ Cham } + { "AA6 }{ Myanmar Extended-A } + { "AA8 }{ Tai Viet } + { "AAE }{ Meetei Mayek Extensions } + { "AB0 }{ Ethiopic Extended-A } + { "AB3 }{ Latin Extended-E } + { "AB7 }{ Cherokee Supplement } + { "ABC }{ Meetei Mayek } + { "AC0 }{ Hangul Syllables } + { "D7B }{ Hangul Jamo Extended-B } + { "D80 }{ High Surrogates } + { "DB8 }{ High Private Use Surrogates } + { "DC0 }{ Low Surrogates } + { "E00 }{ Private~ Use~ Area } + { "F90 }{ CJK~ Compatibility~ Ideographs } + { "FB0 }{ Alphabetic~ Presentation~ Forms } + { "FB5 }{ Arabic~ Presentation~ Forms-A } + { "FE0 }{ Variation~ Selectors } + { "FE1 }{ Vertical~ Forms } + { "FE2 }{ Combining~ Half~ Marks } + { "FE3 }{ CJK~ Compatibility~ Forms } + { "FE5 }{ Small~ Form~ Variants } + { "FE7 }{ Arabic~ Presentation~ Forms-B } + { "FF0 }{ Halfwidth~ and Fullwidth~ Forms } + { "FFF }{ Specials~ ... } +%% ... Plane 1 ... + { "1000 }{ Linear~ B~ Syllabary } + { "1008 }{ Linear~ B~ Ideograms } + { "1010 }{ Aegean~ Numbers } + { "1014 }{ Ancient~ Greek~ Numbers } + { "1019 }{ Ancient~ Symbols } + { "101D }{ Phaistos~ Disc } + { "1028 }{ Lycian } + { "102A }{ Carian } + { "102E }{ Coptic~ Epact~ Numbers } + { "1030 }{ Old~ Italic } + { "1033 }{ Gothic } + { "1035 }{ Old~ Permic } + { "1038 }{ Ugaritic } + { "103A }{ Old~ Persian } + { "1040 }{ Deseret } + { "1045 }{ Shavian } + { "1048 }{ Osmanya } + { "104B }{ Osage } + { "1050 }{ Elbasan } + { "1053 }{ Caucasian~ Albanian } + { "1060 }{ Linear~ A } + { "1080 }{ Cypriot~ Syllabary } + { "1084 }{ Imperial~ Aramaic } + { "1086 }{ Palmyrene } + { "1088 }{ Nabataean } + { "108E }{ Hatran } + { "1090 }{ Phoenician } + { "1092 }{ Lydian } + { "1098 }{ Meroitic~ Hieroglyphs } + { "109A }{ Meroitic~ Cursive } + { "10A0 }{ Kharoshthi } + { "10A6 }{ Old~ South~ Arabian } + { "10A8 }{ Old~ North~ Arabian } + { "10AC }{ Manichaean } + { "10B0 }{ Avestan } + { "10B4 }{ Inscriptional~ Parthian } + { "10B6 }{ Inscriptional~ Pahlavi } + { "10B8 }{ Psalter~ Pahlavi } + { "10C0 }{ Old~ Turkic } + { "10C8 }{ Old~ Hungarian } + { "10E6 }{ Rumi~ Numeral~ Symbols } + { "1100 }{ Brahmi } + { "1108 }{ Kaithi } + { "110D }{ Sora~ Sompeng } + { "1110 }{ Chakma } + { "1115 }{ Mahajani } + { "1118 }{ Sharada } + { "111E }{ Sinhala~ Archaic~ Numbers } + { "1120 }{ Khojki } + { "1128 }{ Multani } + { "112B }{ Khudawadi } + { "1130 }{ Grantha } + { "1140 }{ Newa } + { "1148 }{ Tirhuta } + { "1158 }{ Siddham } + { "1160 }{ Modi } + { "1166 }{ Mongolian~ Supplement } + { "1168 }{ Takri } + { "1170 }{ Ahom } + { "118A }{ Warang~ Citi } + { "11A0 }{ Zanabazar~ Square } + { "11A5 }{ Soyombo } + { "11AC }{ Pau~ Cin~ Hau } + { "11C0 }{ Bhaiksuki } + { "11C7 }{ Marchen } + { "11D0 }{ Masaram~ Gondi } + { "1200 }{ Cuneiform } + { "1240 }{ Cuneiform~ Numbers~ and~ Punctuation } + { "1248 }{ Early~ Dynastic~ Cuneiform } + { "1300 }{ Egyptian~ Hieroglyphs } + { "1440 }{ Anatolian~ Hieroglyphs } + { "1680 }{ Bamum~ Supplement } + { "16A4 }{ Mro } + { "16AD }{ Bassa~ Vah } + { "16B0 }{ Pahawh~ Hmong } + { "16F0 }{ Miao } + { "16FE }{ Ideographic~ Symbols~ and~ Punctuation } + { "1700 }{ Tangut } + { "1880 }{ Tangut~ Components } + { "1B00 }{ Kana~ Supplement } + { "1B10 }{ Kana~ Extended-A } + { "1B17 }{ Nushu } + { "1BC0 }{ Duployan } + { "1BCA }{ Shorthand~ Format~ Controls } + { "1D00 }{ Byzantine~ Musical~ Symbols } + { "1D10 }{ Musical~ Symbols } + { "1D20 }{ Ancient~ Greek~ Musical~ Notation } + { "1D30 }{ Tai~ Xuan~ Jing~ Symbols } + { "1D36 }{ Counting~ Rod~ Numerals } + { "1D40 }{ Mathematical~ Alphanumeric~ Symbols } + { "1D80 }{ Sutton~ SignWriting } + { "1E00 }{ Glagolitic~ Supplement } + { "1E80 }{ Mende~ Kikakui } + { "1E90 }{ Adlam } + { "1EE0 }{ Arabic~ Mathematical~ Alphabetic~ Symbols } + { "1F00 }{ Mahjong~ Tiles } + { "1F03 }{ Domino~ Tiles } + { "1F0A }{ Playing~ Cards } + { "1F10 }{ Enclosed~ Alphanumeric~ Supplement } + { "1F20 }{ Enclosed~ Ideographic~ Supplement } + { "1F30 }{ Miscellaneous~ Symbols~ and~ Pictographs } + { "1F60 }{ Emoticons } + { "1F65 }{ Ornamental~ Dingbats } + { "1F68 }{ Transport~ and~ Map~ Symbols } + { "1F70 }{ Alchemical~ Symbols } + { "1F78 }{ Geometric~ Shapes~ Extended } + { "1F80 }{ Supplemental~ Arrows-C } + { "1F90 }{ Supplemental~ Symbols~ and~ Pictographs } + { "2000 }{ CJK~ Unified~ Ideographs~ Extension~ B } + { "2A70 }{ CJK~ Unified~ Ideographs~ Extension~ C } + { "2B74 }{ CJK~ Unified~ Ideographs~ Extension~ D } + { "2B82 }{ CJK~ Unified~ Ideographs~ Extension~ E } + { "2CEB }{ CJK~ Unified~ Ideographs~ Extension~ F } + { "2F80 }{ CJK~ Compatibility~ Ideographs~ Supplement } + { "E010 }{ Tags } + { "E000 }{ Variation~ Selectors~ Supplement } + { "F000 }{ Supplementary~ Private~ Use~ Area-A } +% higher up not covered! + } +% \end{macrocode} +% If none of the above has matched we are somewhere within a block +% so we want keep the current name. However, since the case +% statement was executed within a |\tl_gset:Nx| we have to do this +% by passing the current block name back. +% \begin{macrocode} + { \tl_use:N \g_@@_block_title_tl } + } +} +% \end{macrocode} +% \end{macro} +% +% +% \keysetup{display blocks} +% +% The Unicode blocks may get indicated in different ways: with titles, +% only through rules, or not at all. Here is the necessary setup. +% +% \begin{macrocode} +\bool_new:N \l_@@_display_block_bool +\tl_new:N \l_@@_display_block_action_tl +% \end{macrocode} +% +% \begin{macrocode} +\keys_define:nn {@@} + { + ,display-block .choice: + ,display-block / titles .code:n = + \bool_set_true:N \l_@@_display_block_bool + \tl_set:Nn \l_@@_display_block_action_tl {\\} + ,display-block / rules .code:n = + \bool_set_false:N \l_@@_display_block_bool + \tl_set:Nn \l_@@_display_block_action_tl {\\ \midrule} + ,display-block / none .code:n = + \bool_set_false:N \l_@@_display_block_bool + \tl_set:Nn \l_@@_display_block_action_tl {\\} + ,display-block .initial:n = titles + } +% \end{macrocode} +% +% +% That's all of the programming using the L3 layer. +% \begin{macrocode} +\ExplSyntaxOff +% \end{macrocode} +% What remains is to require all packages needed \ldots +% \begin{macrocode} +\RequirePackage{longtable,booktabs,caption,fontspec} +% \end{macrocode} +% \ldots and executing all options passed to the +% package via \cs{usepackage}. +% \begin{macrocode} +\ProcessKeysPackageOptions{@@} +% +% \end{macrocode} +% +% +% +% +% +% \section{The standalone \texttt{unicodefont.tex} file} +% +% \begin{macrocode} +%<*standalone> +\documentclass{article} +% \end{macrocode} +% +% \begin{macrocode} +\setlength\textwidth{470pt} +\setlength\oddsidemargin{0pt} +\addtolength\textheight{7\baselineskip} +\addtolength\topmargin{-3\baselineskip} +% \end{macrocode} +% +% \begin{macrocode} +\usepackage{unicodefonttable} +% \end{macrocode} +% +% \begin{macrocode} +\def\DEFAULTfontname{Latin Modern Roman} +\def\DEFAULTfontfeatures{} +\def\DEFAULTtableconfig{} +\def\DEFAULTunicodefont{} +\begin{document} +% \end{macrocode} +% +% \begin{macrocode} +\typeout{^^J} +% \end{macrocode} +% +% \begin{macrocode} +\ifx\generatetable\undefined +\else + \typein[\answer]{^^JReuse settings from last time (default yes)?^^J^^J% + [ font name = \DEFAULTfontname^^J + \space unicode? = \ifx\DEFAULTunicodefont\empty yes^^J + \space font features = \DEFAULTfontfeatures + \else no\fi^^J + \space table config = \DEFAULTtableconfig \space]} +\fi +% \end{macrocode} +% +% \begin{macrocode} +\ifx\answer\empty + \let\FontNameToTable\DEFAULTfontname + \let\IsUnicodeFont\DEFAULTunicodefont + \let\FontFeaturesToApply\DEFAULTfontfeatures + \let\TableConfigurationToApply\DEFAULTtableconfig +\else +% \end{macrocode} +% +% \begin{macrocode} +\typein[\FontNameToTable]% + {^^JInput external font name as understood by fontspec, e.g.,^^J% + 'TeX Gyre Pagella' or 'lmroman10-regular.otf'% + \ifx\DEFAULTfontname\empty\else + ^^J^^J[default \DEFAULTfontname]\fi:} +\ifx\FontNameToTable\empty \let\FontNameToTable\DEFAULTfontname \fi +% \end{macrocode} +% +% \begin{macrocode} +\typein[\IsUnicodeFont]% + {^^JIs this a Unicode font?^^J^^J% + \ifx\DEFAULTunicodefont\empty [default yes]\else [default no]\fi:} +% \end{macrocode} +% +% \begin{macrocode} +\ifx\IsUnicodeFont\empty +% \ifx\DEFAULTunicodefont\empty +% \else + \let\IsUnicodeFont\DEFAULTunicodefont +% \fi +\else + \ifx\DEFAULTunicodefont\empty + \else + \let\IsUnicodeFont\empty + \fi +\fi +% \end{macrocode} +% +% \begin{macrocode} +\ifx\IsUnicodeFont\empty + \typein[\FontFeaturesToApply]% + {^^JInput font feature key/value list to apply% + \ifx\DEFAULTfontfeatures\empty\else + ^^J^^J[default \DEFAULTfontfeatures]\fi:} + \ifx\FontFeaturesToApply\empty \let\FontFeaturesToApply\DEFAULTfontfeatures \fi +\else + \let\FontFeaturesToApply\DEFAULTfontfeatures +\fi +% \end{macrocode} +% +% \begin{macrocode} +\typein[\TableConfigurationToApply]% + {^^JInput table configuration key/value list to apply% + \ifx\DEFAULTtableconfig\empty\else + ^^J^^J[default + \expandafter\detokenize\expandafter{\DEFAULTtableconfig}]\fi:} +\ifx\TableConfigurationToApply\empty + \let\TableConfigurationToApply\DEFAULTtableconfig +\fi +% \end{macrocode} +% +% \begin{macrocode} +\edef\generatetable{\noexpand\displayfonttable + \ifx\IsUnicodeFont\empty\else *\fi + \ifx\TableConfigurationToApply\empty\else + [\expandafter\unexpanded\expandafter{\TableConfigurationToApply}]\fi + {\FontNameToTable}% + \ifx\FontFeaturesToApply\empty\else[\FontFeaturesToApply]\fi +} +% \end{macrocode} +% +% \begin{macrocode} +\fi +% \end{macrocode} +% +% \begin{macrocode} +\makeatletter +\protected@write\@auxout{}{\gdef\string\generatetable + {\expandafter\detokenize\expandafter{\generatetable}}} +\protected@write\@auxout{}{\gdef\string\DEFAULTfontname{\FontNameToTable}} +\protected@write\@auxout{}{\gdef\string\DEFAULTunicodefont{\IsUnicodeFont}} +\protected@write\@auxout{}{\gdef\string\DEFAULTfontfeatures{\FontFeaturesToApply}} +\protected@write\@auxout{}{\gdef\string\DEFAULTtableconfig + {\expandafter\detokenize\expandafter{\TableConfigurationToApply}}} +\makeatother +% \end{macrocode} +% +% \begin{macrocode} +\generatetable +\end{document} +% +% \end{macrocode} +% +% +% +% \section{A samples file} +% +% \begin{macrocode} +%<*samples> +% \end{macrocode} +% +% \begin{macrocode} +%< +% \end{macrocode} +% +% \Finale +% + + +\endinput + +%%%%%%%%%%%%%%%%%%% diff --git a/Master/texmf-dist/source/latex/unicodefonttable/unicodefonttable.ins b/Master/texmf-dist/source/latex/unicodefonttable/unicodefonttable.ins new file mode 100644 index 00000000000..b87cb4e13f4 --- /dev/null +++ b/Master/texmf-dist/source/latex/unicodefonttable/unicodefonttable.ins @@ -0,0 +1,72 @@ +%% +%% This file will generate fast loadable files and documentation +%% driver files from the dtx file(s) in this package when run through +%% LaTeX or TeX. +%% +%% Copyright 2019-2021 Frank Mittelbach +%% +%% +%% This file is part of the unicodefonttable Bundle for LaTeX. +%% ------------------------------------------------------- +%% +%% It may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3c +%% of this license or (at your option) any later version. +%% The latest version of this license is in +%% https://www.latex-project.org/lppl.txt +%% and version 1.3c or later is part of all distributions of LaTeX +%% version 2008 or later. +%% +%% As this file contains legal notices, it is NOT PERMITTED to modify +%% this file in any way that the legal information placed into +%% generated files is changed (i.e., the files generated when the +%% original file is executed). This restriction does not apply if +%% (parts of) the content is reused in a different WORK producing its +%% own generated files. +%% +%% +%% --------------- start of docstrip commands ------------------ +%% +\input docstrip + +\keepsilent +\askforoverwritefalse + +\usedir{tex/latex/unicodefonttable} + +\preamble + +This is a generated file. + +Copyright 2019-2021 Frank Mittelbach + +This file was generated from file(s) of the LaTeX `unicodefonttable Bundle'. +-------------------------------------------------------------------------- + +It may be distributed and/or modified under the +conditions of the LaTeX Project Public License, either version 1.3c +of this license or (at your option) any later version. +The latest version of this license is in + https://www.latex-project.org/lppl.txt +and version 1.3c or later is part of all distributions of LaTeX +version 2008 or later. + +This file may only be distributed together with a copy of the LaTeX +`unicodefonttable Bundle'. You may however distribute the `unicodefonttable Bundle' +without such generated files. + +The newest sources can be found below + + https://github.com/FrankMittelbach/fmitex-unicodetable + +where one can also log issues in case there are any. + + +\endpreamble + +\generate{\file{unicodefonttable.sty}{\from{unicodefonttable.dtx}{package}}} +\generate{\file{unicodefonttable-samples.tex}{\from{unicodefonttable.dtx}{samples}}} + +\generate{\file{unicodefont.tex}{\from{unicodefonttable.dtx}{standalone}}} + +\endbatchfile diff --git a/Master/texmf-dist/tex/latex/unicodefonttable/unicodefont.tex b/Master/texmf-dist/tex/latex/unicodefonttable/unicodefont.tex new file mode 100644 index 00000000000..309f1eb1b9b --- /dev/null +++ b/Master/texmf-dist/tex/latex/unicodefonttable/unicodefont.tex @@ -0,0 +1,125 @@ +%% +%% This is file `unicodefont.tex', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% unicodefonttable.dtx (with options: `standalone') +%% +%% This is a generated file. +%% +%% Copyright 2019-2021 Frank Mittelbach +%% +%% This file was generated from file(s) of the LaTeX `unicodefonttable Bundle'. +%% -------------------------------------------------------------------------- +%% +%% It may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3c +%% of this license or (at your option) any later version. +%% The latest version of this license is in +%% https://www.latex-project.org/lppl.txt +%% and version 1.3c or later is part of all distributions of LaTeX +%% version 2008 or later. +%% +%% This file may only be distributed together with a copy of the LaTeX +%% `unicodefonttable Bundle'. You may however distribute the `unicodefonttable Bundle' +%% without such generated files. +%% +%% The newest sources can be found below +%% +%% https://github.com/FrankMittelbach/fmitex-unicodetable +%% +%% where one can also log issues in case there are any. +%% +%% +%%%%% \iffalse meta-comment +%% File: unicodefonttable.dtx (C) Copyright 2019-2021 Frank Mittelbach + +\def\unicodefonttabledate {2021/10/19} +\def\unicodefonttableversion{v1.0e} + + +\documentclass{article} +\setlength\textwidth{470pt} +\setlength\oddsidemargin{0pt} +\addtolength\textheight{7\baselineskip} +\addtolength\topmargin{-3\baselineskip} +\usepackage{unicodefonttable} +\def\DEFAULTfontname{Latin Modern Roman} +\def\DEFAULTfontfeatures{} +\def\DEFAULTtableconfig{} +\def\DEFAULTunicodefont{} +\begin{document} +\typeout{^^J} +\ifx\generatetable\undefined +\else + \typein[\answer]{^^JReuse settings from last time (default yes)?^^J^^J% + [ font name = \DEFAULTfontname^^J + \space unicode? = \ifx\DEFAULTunicodefont\empty yes^^J + \space font features = \DEFAULTfontfeatures + \else no\fi^^J + \space table config = \DEFAULTtableconfig \space]} +\fi +\ifx\answer\empty + \let\FontNameToTable\DEFAULTfontname + \let\IsUnicodeFont\DEFAULTunicodefont + \let\FontFeaturesToApply\DEFAULTfontfeatures + \let\TableConfigurationToApply\DEFAULTtableconfig +\else +\typein[\FontNameToTable]% + {^^JInput external font name as understood by fontspec, e.g.,^^J% + 'TeX Gyre Pagella' or 'lmroman10-regular.otf'% + \ifx\DEFAULTfontname\empty\else + ^^J^^J[default \DEFAULTfontname]\fi:} +\ifx\FontNameToTable\empty \let\FontNameToTable\DEFAULTfontname \fi +\typein[\IsUnicodeFont]% + {^^JIs this a Unicode font?^^J^^J% + \ifx\DEFAULTunicodefont\empty [default yes]\else [default no]\fi:} +\ifx\IsUnicodeFont\empty + \let\IsUnicodeFont\DEFAULTunicodefont +\else + \ifx\DEFAULTunicodefont\empty + \else + \let\IsUnicodeFont\empty + \fi +\fi +\ifx\IsUnicodeFont\empty + \typein[\FontFeaturesToApply]% + {^^JInput font feature key/value list to apply% + \ifx\DEFAULTfontfeatures\empty\else + ^^J^^J[default \DEFAULTfontfeatures]\fi:} + \ifx\FontFeaturesToApply\empty \let\FontFeaturesToApply\DEFAULTfontfeatures \fi +\else + \let\FontFeaturesToApply\DEFAULTfontfeatures +\fi +\typein[\TableConfigurationToApply]% + {^^JInput table configuration key/value list to apply% + \ifx\DEFAULTtableconfig\empty\else + ^^J^^J[default + \expandafter\detokenize\expandafter{\DEFAULTtableconfig}]\fi:} +\ifx\TableConfigurationToApply\empty + \let\TableConfigurationToApply\DEFAULTtableconfig +\fi +\edef\generatetable{\noexpand\displayfonttable + \ifx\IsUnicodeFont\empty\else *\fi + \ifx\TableConfigurationToApply\empty\else + [\expandafter\unexpanded\expandafter{\TableConfigurationToApply}]\fi + {\FontNameToTable}% + \ifx\FontFeaturesToApply\empty\else[\FontFeaturesToApply]\fi +} +\fi +\makeatletter +\protected@write\@auxout{}{\gdef\string\generatetable + {\expandafter\detokenize\expandafter{\generatetable}}} +\protected@write\@auxout{}{\gdef\string\DEFAULTfontname{\FontNameToTable}} +\protected@write\@auxout{}{\gdef\string\DEFAULTunicodefont{\IsUnicodeFont}} +\protected@write\@auxout{}{\gdef\string\DEFAULTfontfeatures{\FontFeaturesToApply}} +\protected@write\@auxout{}{\gdef\string\DEFAULTtableconfig + {\expandafter\detokenize\expandafter{\TableConfigurationToApply}}} +\makeatother +\generatetable +\end{document} + +\endinput +%% +%% End of file `unicodefont.tex'. diff --git a/Master/texmf-dist/tex/latex/unicodefonttable/unicodefonttable.sty b/Master/texmf-dist/tex/latex/unicodefonttable/unicodefonttable.sty new file mode 100644 index 00000000000..fb4df406402 --- /dev/null +++ b/Master/texmf-dist/tex/latex/unicodefonttable/unicodefonttable.sty @@ -0,0 +1,725 @@ +%% +%% This is file `unicodefonttable.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% unicodefonttable.dtx (with options: `package') +%% +%% This is a generated file. +%% +%% Copyright 2019-2021 Frank Mittelbach +%% +%% This file was generated from file(s) of the LaTeX `unicodefonttable Bundle'. +%% -------------------------------------------------------------------------- +%% +%% It may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3c +%% of this license or (at your option) any later version. +%% The latest version of this license is in +%% https://www.latex-project.org/lppl.txt +%% and version 1.3c or later is part of all distributions of LaTeX +%% version 2008 or later. +%% +%% This file may only be distributed together with a copy of the LaTeX +%% `unicodefonttable Bundle'. You may however distribute the `unicodefonttable Bundle' +%% without such generated files. +%% +%% The newest sources can be found below +%% +%% https://github.com/FrankMittelbach/fmitex-unicodetable +%% +%% where one can also log issues in case there are any. +%% +%% +%%%%% \iffalse meta-comment +%% File: unicodefonttable.dtx (C) Copyright 2019-2021 Frank Mittelbach + +\def\unicodefonttabledate {2021/10/19} +\def\unicodefonttableversion{v1.0e} + + +\RequirePackage{xcolor} + +\RequirePackage{xparse,l3keys2e} +\ProvidesExplPackage{unicodefonttable} + {\unicodefonttabledate} + {\unicodefonttableversion} + {Producing font tables for Unicode and other fonts} + +\NewDocumentCommand \fonttablesetup { m } + { \keys_set:nn {__fmuft} {#1} \ignorespaces } +\NewDocumentCommand\displayfonttable {s O{} m o}{% + \IfBooleanTF #1 + { + \__fmuft_display_fonttable:nnn + {nostatistics,display-block=none,hex-digits=head,range-end=FF,#2} + {#3}{#4} + } + { + \__fmuft_display_fonttable:nnn {#2}{#3}{#4} + } +} +\cs_new:Npn \__fmuft_display_fonttable:nnn #1#2#3 { + \group_begin: + \fontspec{#2}[#3] + \keys_set:nn{__fmuft}{#1} + \tl_if_empty:NTF \l__fmuft_compare_with_tl + { \tl_clear:N \l__fmuft_compare_font_tl } + { + \setfontface \l__fmuft_compare_font_tl {\l__fmuft_compare_with_tl}[] + \cs_set_eq:NN \__fmuft_handle_missing_glyph:n + \__fmuft_handle_missing_glyph_compare:n + } + \begin{longtable\bool_if:NF\l__fmuft_display_header_bool{*}} + {@{}r@{\quad}*{16}{c}@{}} + \__fmuft_setup_header_footer:nn{#2}{#3} + \__fmuft_produce_table_rows: + \__fmuft_handle_table_ending:n {#2} + \end{longtable\bool_if:NF\l__fmuft_display_header_bool{*}} + \group_end: +} + +\DeclareDocumentCommand \fonttableglyphcount {} + { \int_use:N \g__fmuft_glyph_int } +\int_new:N \g__fmuft_glyph_int +\int_new:N \g__fmuft_glyph_only_B_int +\int_new:N \g__fmuft_glyph_also_B_int + +\cs_new:Npn \__fmuft_setup_header_footer:nn #1#2{ + \bool_if:NT \l__fmuft_display_header_bool + { \__fmuft_format_table_title:nn{#1}{#2} \__fmuft_debug_nl:n{T}\\*[6pt] } + \bool_if:NT \l__fmuft_header_hex_digits_bool + { \__fmuft_display_row_of_hex_digits: \__fmuft_debug_nl:n{H}\\* } + \endfirsthead + \bool_if:NT \l__fmuft_display_header_bool + { \__fmuft_format_table_cont:nn{#1}{#2} \__fmuft_debug_nl:n{T}\\*[6pt] } + \bool_if:NT \l__fmuft_header_hex_digits_bool + { \__fmuft_display_row_of_hex_digits: \__fmuft_debug_nl:n{H}\\* } + \endhead + \bool_if:NT \l__fmuft_footer_hex_digits_bool + { \__fmuft_display_row_of_hex_digits: \__fmuft_debug_nl:n{H}\\* } + \endfoot + \endlastfoot +} +\bool_new:N \l__fmuft_header_hex_digits_bool +\bool_new:N \l__fmuft_footer_hex_digits_bool +\bool_new:N \l__fmuft_blockwise_hex_digits_bool +\cs_new:Npn \__fmuft_display_row_of_hex_digits: { + & \__fmuft_format_hex_digit:n{0} & \__fmuft_format_hex_digit:n{1} + & \__fmuft_format_hex_digit:n{2} & \__fmuft_format_hex_digit:n{3} + & \__fmuft_format_hex_digit:n{4} & \__fmuft_format_hex_digit:n{5} + & \__fmuft_format_hex_digit:n{6} & \__fmuft_format_hex_digit:n{7} + & \__fmuft_format_hex_digit:n{8} & \__fmuft_format_hex_digit:n{9} + & \__fmuft_format_hex_digit:n{A} & \__fmuft_format_hex_digit:n{B} + & \__fmuft_format_hex_digit:n{C} & \__fmuft_format_hex_digit:n{D} + & \__fmuft_format_hex_digit:n{E} & \__fmuft_format_hex_digit:n{F} } +\cs_new:Npn \__fmuft_format_hex_digit:n #1 { + \l__fmuft_hex_digits_font_tl \l__fmuft_color_tl #1 } + +\tl_new:N \l__fmuft_color_tl +\keys_define:nn {__fmuft} { + ,header .bool_set:N = \l__fmuft_display_header_bool + ,header .default:n = true + ,header .initial:n = true + ,noheader .bool_set_inverse:N = \l__fmuft_display_header_bool + ,noheader .default:n = true + ,title-format .cs_set:Np = \__fmuft_format_table_title:nn #1#2 + ,title-format .initial:n = + \IfValueTF{#2} { \caption{ #1~ (features:~ \texttt{\small#2}) } } + { \caption{ #1 } } + ,title-cont-format .cs_set:Np = \__fmuft_format_table_cont:nn #1#2 + ,title-cont-format .initial:n = \caption[]{#1~ \emph{cont.}} + ,hex-digits .choice: + ,hex-digits / block .code:n = + \bool_set_true:N \l__fmuft_blockwise_hex_digits_bool + \bool_set_false:N \l__fmuft_header_hex_digits_bool + \bool_set_false:N \l__fmuft_footer_hex_digits_bool + ,hex-digits / foot .code:n = + \bool_set_true:N \l__fmuft_footer_hex_digits_bool + \bool_set_false:N \l__fmuft_header_hex_digits_bool + \bool_set_false:N \l__fmuft_blockwise_hex_digits_bool + ,hex-digits / head .code:n = + \bool_set_true:N \l__fmuft_header_hex_digits_bool + \bool_set_false:N \l__fmuft_footer_hex_digits_bool + \bool_set_false:N \l__fmuft_blockwise_hex_digits_bool + ,hex-digits / head+foot .code:n = + \bool_set_true:N \l__fmuft_header_hex_digits_bool + \bool_set_true:N \l__fmuft_footer_hex_digits_bool + \bool_set_false:N \l__fmuft_blockwise_hex_digits_bool + ,hex-digits / none .code:n = + \bool_set_false:N \l__fmuft_header_hex_digits_bool + \bool_set_false:N \l__fmuft_footer_hex_digits_bool + \bool_set_false:N \l__fmuft_blockwise_hex_digits_bool + ,hex-digits .initial:n = head + ,hex-digits-font .tl_set:N = \l__fmuft_hex_digits_font_tl + ,hex-digits-font .initial:n = \ttfamily \scriptsize + ,color .choice: + ,color / none .code:n = \tl_clear:N \l__fmuft_color_tl + ,color / unknown .code:n = \tl_set:Nn \l__fmuft_color_tl { \color {#1} } + ,color .initial:n = blue + } +\cs_new:Npn \__fmuft_handle_table_ending:n #1 { + \__fmuft_debug_nl:n{H} \\* + \bool_if:NT \l__fmuft_footer_hex_digits_bool + { \__fmuft_display_row_of_hex_digits: \__fmuft_debug_nl:n{H} \\* } + \bool_if:NT \l__fmuft_display_statistics_bool + { \\*[2pt] + \multicolumn{17}{l}{ \l__fmuft_stats_font_tl + \tl_if_empty:NTF \l__fmuft_compare_with_tl + { + \__fmuft_format_stats:nn{#1}{\fonttableglyphcount} + } + { + \__fmuft_format_compare_stats:nnnnnn{#1}{\fonttableglyphcount} + { \l__fmuft_compare_with_tl } + { \int_eval:n { \int_use:N\g__fmuft_glyph_also_B_int + + \int_use:N\g__fmuft_glyph_only_B_int } + } + { \int_eval:n { \fonttableglyphcount - + \int_use:N\g__fmuft_glyph_also_B_int } + } + { \int_use:N\g__fmuft_glyph_only_B_int } + } + \hspace*{-3cm} + } + } +} +\keys_define:nn {__fmuft} { + ,statistics .bool_set:N = \l__fmuft_display_statistics_bool + ,statistics .default:n = true + ,statistics .initial:n = true + ,nostatistics .bool_set_inverse:N = \l__fmuft_display_statistics_bool + ,nostatistics .default:n = true + ,statistics-font .tl_set:N = \l__fmuft_stats_font_tl + ,statistics-font .initial:n = \normalfont\small + ,statistics-format .cs_set:Np = \__fmuft_format_stats:nn #1#2 + ,statistics-format .initial:n = Total~ number~ of~ glyphs~ in~ #1:~#2 + } +\cs_new:Npn \__fmuft_debug_nl:n #1 {} +\keys_define:nn {__fmuft} { + debug .code:n = \cs_set:Npn \__fmuft_debug_nl:n ##1 + {\rlap{\normalfont\scriptsize \qquad ##1}} } + +\tl_new:N \g__fmuft_hex_H_tl % higher plane +\tl_new:N \g__fmuft_hex_A_tl +\tl_new:N \g__fmuft_hex_B_tl +\tl_new:N \g__fmuft_hex_C_tl +\clist_const:Nn\c__fmuft_hex_digits_clist{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F} +\cs_new:Npn \__fmuft_produce_table_rows: { + \__fmuft_initialize_table_rows: + \clist_map_function:nN { { } , 1, 2, E, F } \__fmuft_handle_hex_H:n } +\cs_new:Npn \__fmuft_handle_hex_H:n #1 { \tl_gset:Nn\g__fmuft_hex_H_tl{#1} + \clist_map_function:NN \c__fmuft_hex_digits_clist \__fmuft_handle_hex_A:n } +\cs_new:Npn \__fmuft_handle_hex_A:n #1 { \tl_gset:Nn\g__fmuft_hex_A_tl{#1} + \clist_map_function:NN \c__fmuft_hex_digits_clist \__fmuft_handle_hex_B:n } +\cs_new:Npn \__fmuft_handle_hex_B:n #1 { \tl_gset:Nn\g__fmuft_hex_B_tl{#1} + \clist_map_function:NN \c__fmuft_hex_digits_clist \__fmuft_handle_hex_C:n } +\cs_new:Npn \__fmuft_handle_hex_C:n #1 { \tl_gset:Nn\g__fmuft_hex_C_tl{#1} + \clist_map_function:NN \c__fmuft_hex_digits_clist \__fmuft_handle_hex_D:n } +\cs_new:Npn \__fmuft_handle_hex_D:n #1 { + \__fmuft_handle_slot:x + { " \g__fmuft_hex_H_tl \g__fmuft_hex_A_tl + \g__fmuft_hex_B_tl \g__fmuft_hex_C_tl #1 } +} +\tl_new:N \g__fmuft_row_tl + +\cs_new:Npn \__fmuft_handle_slot:n #1 { + \__fmuft_if_uchar_exists:nTF { #1 } + { \tl_gput_right:Nn \g__fmuft_row_tl + { & \__fmuft_format_glyph:n { \symbol{#1} } } + \int_gincr:N\g__fmuft_glyph_int + \bool_gset_true:N \g__fmuft_glyph_seen_bool + \tl_if_empty:NF \l__fmuft_compare_font_tl + { + \group_begin: + \l__fmuft_compare_font_tl + \__fmuft_if_uchar_exists:nT { #1 } + { \int_gincr:N \g__fmuft_glyph_also_B_int } + \group_end: + } + } + { \__fmuft_handle_missing_glyph:n {#1} } +} +\cs_generate_variant:Nn \__fmuft_handle_slot:n {x} + +\cs_new:Npn \__fmuft_handle_missing_glyph_std:n #1 { + \tl_gput_right:Nn \g__fmuft_row_tl + { & + \__fmuft_format_glyph:n { + {\l__fmuft_missing_glyph_color_tl + \l__fmuft_missing_glyph_font_tl + \l__fmuft_missing_glyph_tl } + } + } +} +\keys_define:nn {__fmuft} { + missing-glyph-color .choice: + ,missing-glyph-color / none .code:n = + \tl_clear:N \l__fmuft_missing_glyph_color_tl + ,missing-glyph-color / unknown .code:n = + \tl_set:Nn \l__fmuft_missing_glyph_color_tl { \color {#1} } + ,missing-glyph-font .tl_set:N = \l__fmuft_missing_glyph_font_tl + ,missing-glyph-font .initial:n = \ttfamily \scriptsize + ,missing-glyph .tl_set:N = \l__fmuft_missing_glyph_tl + ,missing-glyph .initial:n = - } +\tl_new:N \l__fmuft_missing_glyph_color_tl +\tl_set:Nn \l__fmuft_missing_glyph_color_tl {\l__fmuft_color_tl} +\cs_new:Npn \__fmuft_handle_missing_glyph_compare:n #1 { + \group_begin: + \l__fmuft_compare_font_tl + \__fmuft_if_uchar_exists:nTF { #1 } + { + \tl_gput_right:Nn \g__fmuft_row_tl + { & + \__fmuft_format_glyph:n + { \l__fmuft_compare_bgcolor_tl { \l__fmuft_compare_color_tl + \l__fmuft_compare_font_tl + \symbol {#1} } + } + } + \int_gincr:N \g__fmuft_glyph_only_B_int + \bool_gset_true:N \g__fmuft_glyph_seen_bool + } + { \__fmuft_handle_missing_glyph_std:n {} } + \group_end: +} +\tl_new:N \l__fmuft_compare_with_tl +\tl_new:N \l__fmuft_compare_color_tl +\tl_new:N \l__fmuft_compare_bgcolor_tl +\keys_define:nn {__fmuft} + { + ,compare-with .tl_set:N = \l__fmuft_compare_with_tl + ,compare-with .initial:n = + ,compare-color .choice: + ,compare-color / none .code:n + = \tl_clear:N \l__fmuft_compare_color_tl + ,compare-color / unknown .code:n + = \tl_set:Nn \l__fmuft_compare_color_tl { \color {#1} } + ,compare-color .initial:n = red + ,compare-bgcolor .choice: + ,compare-bgcolor / none .code:n + = \tl_clear:N \l__fmuft_compare_bgcolor_tl + ,compare-bgcolor / unknown .code:n + = \tl_set:Nn \l__fmuft_compare_bgcolor_tl { \colorbox {#1} } + ,compare-bgcolor .initial:n = black!10 + ,statistics-compare-format .cs_set:Np + = \__fmuft_format_compare_stats:nnnnnn #1#2#3#4#5#6 + ,statistics-compare-format .initial:n + = \parbox{\linewidth}{ + Total~ number~ of~ glyphs~ in~ \texttt{#1}:~#2\\ + Comparison~ font~ \texttt{#3}~ has~ #5~ missing~ and~ #6~ + extra~ glyphs} + } +\cs_new_eq:NN \__fmuft_handle_missing_glyph:n + \__fmuft_handle_missing_glyph_std:n + +\cs_new:Npn \__fmuft_format_glyph:n #1 { + \hbox_to_wd:nn {\l__fmuft_glyph_box_dim} { \hss #1 \hss } } +\dim_new:N\l__fmuft_glyph_box_dim +\keys_define:nn {__fmuft} { + glyph-width .dim_set:N = \l__fmuft_glyph_box_dim + ,glyph-width .initial:n = 6pt +} + +\prg_set_conditional:Npnn \__fmuft_if_uchar_exists:n #1 { TF , T } + { \tex_iffontchar:D \tex_font:D #1 \scan_stop: + \prg_return_true: + \else: + \prg_return_false: + \fi: + } +\cs_set:Npn \__fmuft_handle_hex_C:n #1 { + \__fmuft_maybe_typeset_a_row_and_display_a_block_title: + \tl_gset:Nn\g__fmuft_hex_C_tl{#1} + \__fmuft_update_block_title:n { \g__fmuft_hex_H_tl + \g__fmuft_hex_A_tl + \g__fmuft_hex_B_tl + \g__fmuft_hex_C_tl } + \int_compare:nNnF + { " \g__fmuft_hex_H_tl \g__fmuft_hex_A_tl + \g__fmuft_hex_B_tl \g__fmuft_hex_C_tl 0 } + < { "\l__fmuft_range_start_tl } + { + \int_compare:nNnTF + { " \g__fmuft_hex_H_tl \g__fmuft_hex_A_tl + \g__fmuft_hex_B_tl \g__fmuft_hex_C_tl 0 } + > { "\l__fmuft_range_end_tl } + { \clist_map_break: } + { + \tl_gset:Nx \g__fmuft_row_tl + { + \exp_not:N \__fmuft_format_row_title:n + { \g__fmuft_hex_H_tl \g__fmuft_hex_A_tl + \g__fmuft_hex_B_tl \g__fmuft_hex_C_tl } + } + \clist_map_function:NN \c__fmuft_hex_digits_clist + \__fmuft_handle_hex_D:n + } + } +} +\cs_new:Npn \__fmuft_format_row_title:n #1 { + \texttt { \footnotesize \l__fmuft_color_tl U+#1 0 \, - \, #1 F } +} +\tl_new:N \l__fmuft_range_start_tl +\tl_new:N \l__fmuft_range_end_tl +\keys_define:nn {__fmuft} + { + ,range-start .tl_set:N = \l__fmuft_range_start_tl + ,range-start .initial:n = 0000 + ,range-end .tl_set:N = \l__fmuft_range_end_tl + ,range-end .initial:n = FFFF + } +\cs_new:Npn \__fmuft_maybe_typeset_a_row_and_display_a_block_title: { + \bool_if:NTF \g__fmuft_glyph_seen_bool + { + \tl_if_empty:NTF \g__fmuft_block_title_tl + { + \bool_if:NTF \g__fmuft_row_missing_bool + { \__fmuft_debug_nl:n{A}\\[6pt] } + { \__fmuft_debug_nl:n{B}\\ } + } + { + \typeout{ Processing~ \tl_use:N \g__fmuft_block_title_tl } + \bool_if:NTF \l__fmuft_display_block_bool + { + \bool_if:NTF \g__fmuft_first_row_bool + { + \bool_gset_false:N \g__fmuft_first_row_bool + \__fmuft_debug_nl:n{C}\\[-4pt] + } + { + \__fmuft_debug_nl:n{D}\\[8pt] + \noalign{\vskip 1pt plus 1pt} % space above block: customizable? + } + \multicolumn{17}{c}{\normalfont \bfseries + \tl_use:N \g__fmuft_block_title_tl} + \bool_if:NTF \l__fmuft_blockwise_hex_digits_bool + { \__fmuft_debug_nl:n{E}\\* + \__fmuft_display_row_of_hex_digits: + \__fmuft_debug_nl:n{H}\\*[2pt] + } + { \__fmuft_debug_nl:n{F}\\*[2pt] } + } + { + \bool_if:NTF \g__fmuft_first_row_bool + { \bool_gset_false:N \g__fmuft_first_row_bool } + { + \__fmuft_debug_nl:n{G~ (new~ block)} + \l__fmuft_display_block_action_tl + } + } + \tl_gclear:N \g__fmuft_block_title_tl + } + \bool_gset_false:N \g__fmuft_glyph_seen_bool + \bool_gset_false:N \g__fmuft_row_missing_bool + \tl_use:N \g__fmuft_row_tl + } + { + \bool_gset_true:N \g__fmuft_row_missing_bool + } +} + +\bool_new:N \g__fmuft_first_row_bool +\bool_new:N \g__fmuft_glyph_seen_bool +\bool_new:N \g__fmuft_row_missing_bool + +\cs_new:Npn \__fmuft_initialize_table_rows: { + \bool_gset_true:N \g__fmuft_first_row_bool + \bool_gset_false:N \g__fmuft_glyph_seen_bool + \bool_gset_false:N \g__fmuft_row_missing_bool + \int_gzero:N \g__fmuft_glyph_int + \int_gzero:N \g__fmuft_glyph_only_B_int + \int_gzero:N \g__fmuft_glyph_also_B_int +} + +\tl_new:N \g__fmuft_block_title_tl + +\cs_new:Npn \__fmuft_update_block_title:n #1 { + \tl_gset:Nx \g__fmuft_block_title_tl { + \int_case:nnF{ "#1 } + { + { "000 }{ Basic~ Latin } + { "008 }{ Latin-1~ Supplement } + { "010 }{ Latin~ Extended-A } + { "018 }{ Latin~ Extended-B } + { "025 }{ IPA~ Extensions } + { "02B }{ Spacing~ Modifier~ Letters } + { "030 }{ Combining~ Diacritical~ Marks } + { "037 }{ Greek~ and~ Coptic } + { "040 }{ Cyrillic } + { "053 }{ Armenian } + { "059 }{ Hebrew } + { "060 }{ Arabic } + { "070 }{ Syriac } + { "075 }{ Arabic~ Supplement } + { "078 }{ Thaana } + { "07C }{ NKo } + { "090 }{ Devanagari } + { "098 }{ Bengali } + { "0A0 }{ Gurmukhi } + { "0A8 }{ Gujarati } + { "0B0 }{ Oriya } + { "0B8 }{ Tamil } + { "0C0 }{ Telugu } + { "0C8 }{ Kannada } + { "0D0 }{ Malayalm } + { "0D8 }{ Sinhala } + { "0E0 }{ Thai } + { "0E8 }{ Lao } + { "0F0 }{ Tibetan } + { "100 }{ Myanmar } + { "10A }{ Georgian } + { "110 }{ Hangul~ Jamo } + { "120 }{ Ethiopic } + { "138 }{ Ethiopic~ Supplement } + { "13A }{ Cherokee } + { "140 }{ Unified~ Canadian~ Aboriginal~ Syllabics } + { "168 }{ Ogham } + { "16A }{ Runic } + { "170 }{ Tagalog } + { "172 }{ Hanunoo } + { "174 }{ Buhid } + { "176 }{ Tagbanwa } + { "178 }{ Khmer } + { "180 }{ Mongolian } + { "190 }{ Limbu } + { "195 }{ Tai~ Le } + { "198 }{ New~ Tai~ Le } + { "19E }{ Khmer~ Symbols } + { "1A0 }{ Buginese } + { "1B0 }{ Balinese } + { "1D0 }{ Phonetic~ Extensions } + { "1D8 }{ Phonetic~ Extensions~ Supplement } + { "1DC }{ Combining~ Diacritical~ Marks~ Supplement } + { "1E0 }{ Latin~ Extended~ Additional } + { "1F0 }{ Greek~ Extended } + { "200 }{ General~ Punctuation } + { "207 }{ Superscripts~ and~ Subscripts } + { "20A }{ Currency~ Symbols } + { "20D }{ Combining~ Diacritical~ Marks~ for~ Symbols } + { "210 }{ Letterlike~ Symbols } + { "215 }{ Number~ Forms } + { "219 }{ Arrows } + { "220 }{ Mathematical~ Operators } + { "230 }{ Miscellaneous~ Technical } + { "240 }{ Control~ Pictures } + { "244 }{ Optical~ Character~ Recognition } + { "246 }{ Enclosed~ Alphanumerics } + { "250 }{ Box~ Drawing } + { "258 }{ Block~ Elements } + { "25A }{ Geometric~ Shapes } + { "260 }{ Miscellaneous~ Shapes } + { "270 }{ Dingbats } + { "27C }{ Miscellaneous~ Mathematical~ Symbols-A } + { "27F }{ Supplemental~ Arrows-A } + { "280 }{ Braille~ Patterns } + { "290 }{ Supplemental~ Arrows-B } + { "298 }{ Miscellaneous~ Mathematical~ Symbols-B } + { "2A0 }{ Supplemental~ Mathematical~ Operators } + { "2B0 }{ Miscellaneous~ Symbols~ and~ Arrows } + { "2C0 }{ Glagolitic } + { "2C6 }{ Latin~ Extended-C } + { "2C8 }{ Coptic } + { "2D0 }{ Georgian~ Supplement } + { "2D3 }{ Tifinagh } + { "2D8 }{ Ethiopic~ Extended } + { "2E0 }{ Supplemental~ Punctuation } + { "2E8 }{ CJK~ Radicals~ Supplement } + { "2F0 }{ Kangxi~ Radicals } + { "2FF }{ Ideographic~ Description~ Characters } + { "300 }{ CJK~ Symbols~ and~ Punctuation } + { "304 }{ Hiragana } + { "30A }{ Katakana } + { "310 }{ Bopomofo } + { "313 }{ Hangul~ Compatibility~ Jamo } + { "319 }{ Kanbun } + { "31A }{ Bopomofo~ Extended } + { "31C }{ CJK~ Strokes } + { "31F }{ Katakana~ Phonetic~ Extensions } + { "320 }{ Enclosed~ CJK~ Letters~ and~ Months } + { "330 }{ CJK~ Compatibility } + { "4DC }{ Yijing~ Hexagram~ Symbols } + { "A00 }{ Yi~ Syllables } + { "A49 }{ Yi~ Radicals } + { "A70 }{ Modifier~ Tone~ Letters } + { "A72 }{ Latin~ Extended-D } + { "A80 }{ Syloti~ Nagri } + { "A84 }{ Phags-pa } + { "A88 }{ Saurashtra } + { "A8E }{ Devanagari Extended } + { "A90 }{ Kayah Li } + { "A93 }{ Rejang } + { "A96 }{ Hangul Jamo Extended-A } + { "A98 }{ Javanese } + { "A9E }{ Myanmar Extended-B } + { "AA0 }{ Cham } + { "AA6 }{ Myanmar Extended-A } + { "AA8 }{ Tai Viet } + { "AAE }{ Meetei Mayek Extensions } + { "AB0 }{ Ethiopic Extended-A } + { "AB3 }{ Latin Extended-E } + { "AB7 }{ Cherokee Supplement } + { "ABC }{ Meetei Mayek } + { "AC0 }{ Hangul Syllables } + { "D7B }{ Hangul Jamo Extended-B } + { "D80 }{ High Surrogates } + { "DB8 }{ High Private Use Surrogates } + { "DC0 }{ Low Surrogates } + { "E00 }{ Private~ Use~ Area } + { "F90 }{ CJK~ Compatibility~ Ideographs } + { "FB0 }{ Alphabetic~ Presentation~ Forms } + { "FB5 }{ Arabic~ Presentation~ Forms-A } + { "FE0 }{ Variation~ Selectors } + { "FE1 }{ Vertical~ Forms } + { "FE2 }{ Combining~ Half~ Marks } + { "FE3 }{ CJK~ Compatibility~ Forms } + { "FE5 }{ Small~ Form~ Variants } + { "FE7 }{ Arabic~ Presentation~ Forms-B } + { "FF0 }{ Halfwidth~ and Fullwidth~ Forms } + { "FFF }{ Specials~ ... } +%% ... Plane 1 ... + { "1000 }{ Linear~ B~ Syllabary } + { "1008 }{ Linear~ B~ Ideograms } + { "1010 }{ Aegean~ Numbers } + { "1014 }{ Ancient~ Greek~ Numbers } + { "1019 }{ Ancient~ Symbols } + { "101D }{ Phaistos~ Disc } + { "1028 }{ Lycian } + { "102A }{ Carian } + { "102E }{ Coptic~ Epact~ Numbers } + { "1030 }{ Old~ Italic } + { "1033 }{ Gothic } + { "1035 }{ Old~ Permic } + { "1038 }{ Ugaritic } + { "103A }{ Old~ Persian } + { "1040 }{ Deseret } + { "1045 }{ Shavian } + { "1048 }{ Osmanya } + { "104B }{ Osage } + { "1050 }{ Elbasan } + { "1053 }{ Caucasian~ Albanian } + { "1060 }{ Linear~ A } + { "1080 }{ Cypriot~ Syllabary } + { "1084 }{ Imperial~ Aramaic } + { "1086 }{ Palmyrene } + { "1088 }{ Nabataean } + { "108E }{ Hatran } + { "1090 }{ Phoenician } + { "1092 }{ Lydian } + { "1098 }{ Meroitic~ Hieroglyphs } + { "109A }{ Meroitic~ Cursive } + { "10A0 }{ Kharoshthi } + { "10A6 }{ Old~ South~ Arabian } + { "10A8 }{ Old~ North~ Arabian } + { "10AC }{ Manichaean } + { "10B0 }{ Avestan } + { "10B4 }{ Inscriptional~ Parthian } + { "10B6 }{ Inscriptional~ Pahlavi } + { "10B8 }{ Psalter~ Pahlavi } + { "10C0 }{ Old~ Turkic } + { "10C8 }{ Old~ Hungarian } + { "10E6 }{ Rumi~ Numeral~ Symbols } + { "1100 }{ Brahmi } + { "1108 }{ Kaithi } + { "110D }{ Sora~ Sompeng } + { "1110 }{ Chakma } + { "1115 }{ Mahajani } + { "1118 }{ Sharada } + { "111E }{ Sinhala~ Archaic~ Numbers } + { "1120 }{ Khojki } + { "1128 }{ Multani } + { "112B }{ Khudawadi } + { "1130 }{ Grantha } + { "1140 }{ Newa } + { "1148 }{ Tirhuta } + { "1158 }{ Siddham } + { "1160 }{ Modi } + { "1166 }{ Mongolian~ Supplement } + { "1168 }{ Takri } + { "1170 }{ Ahom } + { "118A }{ Warang~ Citi } + { "11A0 }{ Zanabazar~ Square } + { "11A5 }{ Soyombo } + { "11AC }{ Pau~ Cin~ Hau } + { "11C0 }{ Bhaiksuki } + { "11C7 }{ Marchen } + { "11D0 }{ Masaram~ Gondi } + { "1200 }{ Cuneiform } + { "1240 }{ Cuneiform~ Numbers~ and~ Punctuation } + { "1248 }{ Early~ Dynastic~ Cuneiform } + { "1300 }{ Egyptian~ Hieroglyphs } + { "1440 }{ Anatolian~ Hieroglyphs } + { "1680 }{ Bamum~ Supplement } + { "16A4 }{ Mro } + { "16AD }{ Bassa~ Vah } + { "16B0 }{ Pahawh~ Hmong } + { "16F0 }{ Miao } + { "16FE }{ Ideographic~ Symbols~ and~ Punctuation } + { "1700 }{ Tangut } + { "1880 }{ Tangut~ Components } + { "1B00 }{ Kana~ Supplement } + { "1B10 }{ Kana~ Extended-A } + { "1B17 }{ Nushu } + { "1BC0 }{ Duployan } + { "1BCA }{ Shorthand~ Format~ Controls } + { "1D00 }{ Byzantine~ Musical~ Symbols } + { "1D10 }{ Musical~ Symbols } + { "1D20 }{ Ancient~ Greek~ Musical~ Notation } + { "1D30 }{ Tai~ Xuan~ Jing~ Symbols } + { "1D36 }{ Counting~ Rod~ Numerals } + { "1D40 }{ Mathematical~ Alphanumeric~ Symbols } + { "1D80 }{ Sutton~ SignWriting } + { "1E00 }{ Glagolitic~ Supplement } + { "1E80 }{ Mende~ Kikakui } + { "1E90 }{ Adlam } + { "1EE0 }{ Arabic~ Mathematical~ Alphabetic~ Symbols } + { "1F00 }{ Mahjong~ Tiles } + { "1F03 }{ Domino~ Tiles } + { "1F0A }{ Playing~ Cards } + { "1F10 }{ Enclosed~ Alphanumeric~ Supplement } + { "1F20 }{ Enclosed~ Ideographic~ Supplement } + { "1F30 }{ Miscellaneous~ Symbols~ and~ Pictographs } + { "1F60 }{ Emoticons } + { "1F65 }{ Ornamental~ Dingbats } + { "1F68 }{ Transport~ and~ Map~ Symbols } + { "1F70 }{ Alchemical~ Symbols } + { "1F78 }{ Geometric~ Shapes~ Extended } + { "1F80 }{ Supplemental~ Arrows-C } + { "1F90 }{ Supplemental~ Symbols~ and~ Pictographs } + { "2000 }{ CJK~ Unified~ Ideographs~ Extension~ B } + { "2A70 }{ CJK~ Unified~ Ideographs~ Extension~ C } + { "2B74 }{ CJK~ Unified~ Ideographs~ Extension~ D } + { "2B82 }{ CJK~ Unified~ Ideographs~ Extension~ E } + { "2CEB }{ CJK~ Unified~ Ideographs~ Extension~ F } + { "2F80 }{ CJK~ Compatibility~ Ideographs~ Supplement } + { "E010 }{ Tags } + { "E000 }{ Variation~ Selectors~ Supplement } + { "F000 }{ Supplementary~ Private~ Use~ Area-A } + } + { \tl_use:N \g__fmuft_block_title_tl } + } +} +\bool_new:N \l__fmuft_display_block_bool +\tl_new:N \l__fmuft_display_block_action_tl +\keys_define:nn {__fmuft} + { + ,display-block .choice: + ,display-block / titles .code:n = + \bool_set_true:N \l__fmuft_display_block_bool + \tl_set:Nn \l__fmuft_display_block_action_tl {\\} + ,display-block / rules .code:n = + \bool_set_false:N \l__fmuft_display_block_bool + \tl_set:Nn \l__fmuft_display_block_action_tl {\\ \midrule} + ,display-block / none .code:n = + \bool_set_false:N \l__fmuft_display_block_bool + \tl_set:Nn \l__fmuft_display_block_action_tl {\\} + ,display-block .initial:n = titles + } +\ExplSyntaxOff +\RequirePackage{longtable,booktabs,caption,fontspec} +\ProcessKeysPackageOptions{__fmuft} + +\endinput +%% +%% End of file `unicodefonttable.sty'. diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check index f1863c5df4b..3a93de35c47 100755 --- a/Master/tlpkg/bin/tlpkg-ctan-check +++ b/Master/tlpkg/bin/tlpkg-ctan-check @@ -820,7 +820,7 @@ my @TLP_working = qw( unfonts-core unfonts-extra uni-titlepage uni-wtal-ger uni-wtal-lin unicode-alphabets unicode-data unicode-bidi unicode-math - unifith uninormalize uniquecounter unisugar + unicodefonttable unifith uninormalize uniquecounter unisugar unitconv unitipa unitn-bimrep units unitsdef universa universalis univie-ling unizgklasa unravel unswcover diff --git a/Master/tlpkg/libexec/ctan2tds b/Master/tlpkg/libexec/ctan2tds index ae8c3e39801..a3fab12d123 100755 --- a/Master/tlpkg/libexec/ctan2tds +++ b/Master/tlpkg/libexec/ctan2tds @@ -2312,6 +2312,7 @@ $standardtex 'underscore', '^..[^s].*\.sty', # not miscdoc.sty 'undolabl', '\.sty|[^c]\.cfg', # omit ltxdoc.cfg, would be system-wide 'unicode-alphabets', '\..sv|' . $standardtex, + 'unicodefonttable', '(\.sty|unicodefont.tex)$', # not .cls 'uninormalize', '\.lua|' . $standardtex, 'unitn-bimrep','\.jpg|' . $standardtex, 'univie-ling', 'univie.*logo.*.pdf|' . $standardtex, diff --git a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc index b72bbe641e2..d129ad07609 100644 --- a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc +++ b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc @@ -1306,6 +1306,7 @@ depend underlin depend underoverlap depend undolabl depend uni-titlepage +depend unicodefonttable depend unitconv depend unitipa depend units diff --git a/Master/tlpkg/tlpsrc/unicodefonttable.tlpsrc b/Master/tlpkg/tlpsrc/unicodefonttable.tlpsrc new file mode 100644 index 00000000000..e69de29bb2d -- cgit v1.2.3