texlive[60826] Master: unicodefonttable (21oct21)

commits+karl at tug.org commits+karl at tug.org
Thu Oct 21 22:31:49 CEST 2021


Revision: 60826
          http://tug.org/svn/texlive?view=revision&revision=60826
Author:   karl
Date:     2021-10-21 22:31:49 +0200 (Thu, 21 Oct 2021)
Log Message:
-----------
unicodefonttable (21oct21)

Modified Paths:
--------------
    trunk/Master/tlpkg/bin/tlpkg-ctan-check
    trunk/Master/tlpkg/libexec/ctan2tds
    trunk/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc

Added Paths:
-----------
    trunk/Master/texmf-dist/doc/latex/unicodefonttable/
    trunk/Master/texmf-dist/doc/latex/unicodefonttable/README.md
    trunk/Master/texmf-dist/doc/latex/unicodefonttable/TODO.md
    trunk/Master/texmf-dist/doc/latex/unicodefonttable/changes.txt
    trunk/Master/texmf-dist/doc/latex/unicodefonttable/l3doc-TUB.cls
    trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-code.pdf
    trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-code.tex
    trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-doc.pdf
    trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-doc.tex
    trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-samples.pdf
    trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-samples.tex
    trunk/Master/texmf-dist/source/latex/unicodefonttable/
    trunk/Master/texmf-dist/source/latex/unicodefonttable/unicodefonttable.dtx
    trunk/Master/texmf-dist/source/latex/unicodefonttable/unicodefonttable.ins
    trunk/Master/texmf-dist/tex/latex/unicodefonttable/
    trunk/Master/texmf-dist/tex/latex/unicodefonttable/unicodefont.tex
    trunk/Master/texmf-dist/tex/latex/unicodefonttable/unicodefonttable.sty
    trunk/Master/tlpkg/tlpsrc/unicodefonttable.tlpsrc

Added: trunk/Master/texmf-dist/doc/latex/unicodefonttable/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/unicodefonttable/README.md	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/unicodefonttable/README.md	2021-10-21 20:31:49 UTC (rev 60826)
@@ -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)<br />
+<https://latex-project.org/> <br />
+All rights reserved.
+
+


Property changes on: trunk/Master/texmf-dist/doc/latex/unicodefonttable/README.md
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/unicodefonttable/TODO.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/unicodefonttable/TODO.md	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/unicodefonttable/TODO.md	2021-10-21 20:31:49 UTC (rev 60826)
@@ -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).
+
+


Property changes on: trunk/Master/texmf-dist/doc/latex/unicodefonttable/TODO.md
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/unicodefonttable/changes.txt
===================================================================
--- trunk/Master/texmf-dist/doc/latex/unicodefonttable/changes.txt	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/unicodefonttable/changes.txt	2021-10-21 20:31:49 UTC (rev 60826)
@@ -0,0 +1,20 @@
+2021-10-19  Frank Mittelbach  <Frank.Mittelbach at latex-project.org>
+
+	* 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  <Frank.Mittelbach at latex-project.org>
+
+	* 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  <Frank.Mittelbach at latex-project.org>
+
+	* 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.
+


Property changes on: trunk/Master/texmf-dist/doc/latex/unicodefonttable/changes.txt
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/unicodefonttable/l3doc-TUB.cls
===================================================================
--- trunk/Master/texmf-dist/doc/latex/unicodefonttable/l3doc-TUB.cls	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/unicodefonttable/l3doc-TUB.cls	2021-10-21 20:31:49 UTC (rev 60826)
@@ -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 at 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 at excluded
+  {
+    \exp_args:Nxx \expanded at notin
+      { \c__codedoc_backslash_tl \tl_to_str:N \macro at namepart , }
+      { \exp_args:NV \tl_to_str:n \index at 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 at section #1#2
+  {
+    \ifnum \c at 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 at xt@\@pnumwidth{\hss #2}\par
+      \endgroup
+    \fi
+  }
+\cs_gset:Npn \l at 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 at 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 at text }
+    {
+      \meta at font@select
+      \edef \meta at hyphen@restore
+        { \hyphenchar \the \font \the \hyphenchar \font }
+      \hyphenchar \font \m at ne
+      \language \l at nohyphenation
+      #1 \/
+      \meta at 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 at savedestfalse
+    \HD at target
+    \Hy at MakeCurrentHref { HD. \int_use:N \c at 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 at 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 at 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 at CodelineNo
+          \__codedoc_special_index:nn {#1} { main }
+          \int_gdecr:N \c at CodelineNo
+        \exp_args:NNNo \hbox_set_end:
+          \tl_set:Nn \saved at 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 at Option
+  }
+\newcommand*{\Describe at Option}[1]
+  {
+    \endgroup
+    \marginpar{
+      \raggedleft
+      \PrintDescribeEnv{#1}
+    }
+    \SpecialOptionIndex{#1}
+    \@esphack
+    \ignorespaces
+  }
+\newcommand*{\SpecialOptionIndex}[1]
+  {
+    \@bsphack
+    \begingroup
+      \HD at target
+      \let\HDorg at encapchar\encapchar
+      \edef\encapchar usage
+        {
+          \HDorg at encapchar hdclindex{\the\c at 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 at checksum }
+        \init at 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 at partsw
+      \@tempswafalse
+      \cs_set:Npx \@tempb{#1}
+      \@for\@tempa:=\@partlist\do
+        {
+          \ifx\@tempa\@tempb\@tempswatrue\fi
+        }
+    \fi
+    \if at tempswa
+      \cs_set_eq:NN \@auxout                 \@partaux
+      \immediate\openout\@partaux #1.aux
+      \immediate\write\@partaux{\relax}
+      \cs_set_eq:NN \@ltxdoc at PrintIndex      \PrintIndex
+      \cs_set_eq:NN \PrintIndex              \relax
+      \cs_set_eq:NN \@ltxdoc at PrintChanges    \PrintChanges
+      \cs_set_eq:NN \PrintChanges            \relax
+      \cs_set_eq:NN \@ltxdoc at theglossary     \theglossary
+      \cs_set_eq:NN \@ltxdoc at 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 at PrintIndex
+      \cs_set_eq:NN \PrintChanges            \@ltxdoc at PrintChanges
+      \cs_set_eq:NN \theglossary             \@ltxdoc at theglossary
+      \cs_set_eq:NN \endtheglossary          \@ltxdoc at endtheglossary
+      \clearpage
+      \@writeckpt{#1}
+      \immediate \closeout \@partaux
+    \else
+      \@nameuse{cp@#1}
+    \fi
+    \cs_set_eq:NN \@auxout \@mainaux
+  }
+\cs_gset:Npn \codeline at wrindex #1
+  {
+    \immediate\write\@indexfile
+      {
+        \string\indexentry{#1}
+          { \filesep \int_use:N \c at 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 at 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 at 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 at 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 at 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 at wrindex }
+      {
+        \str_case:nnF {#6}
+          {
+            { main }  { \codeline at wrindex }
+            { usage } { \index }
+          }
+          { \HD at 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 at font \c_space_tl
+          \l__codedoc_index_escaped_macro_tl
+        }
+        \encapchar
+        hdclindex{\the\c at 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 at maketitle}%
+  {\@articletitletrue\@r at maketitle}%
+}
+  
+%% 
+%%
+%% End of file `l3doc-TUB.cls'.


Property changes on: trunk/Master/texmf-dist/doc/latex/unicodefonttable/l3doc-TUB.cls
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-code.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-code.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-code.pdf	2021-10-21 20:28:46 UTC (rev 60825)
+++ trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-code.pdf	2021-10-21 20:31:49 UTC (rev 60826)

Property changes on: trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-code.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-code.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-code.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-code.tex	2021-10-21 20:31:49 UTC (rev 60826)
@@ -0,0 +1,4 @@
+% this will typeset documentation + code
+
+\AtBeginDocument{\AlsoImplementation}
+\input{unicodefonttable.dtx}


Property changes on: trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-code.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-doc.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-doc.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-doc.pdf	2021-10-21 20:28:46 UTC (rev 60825)
+++ trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-doc.pdf	2021-10-21 20:31:49 UTC (rev 60826)

Property changes on: trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-doc.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-doc.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-doc.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-doc.tex	2021-10-21 20:31:49 UTC (rev 60826)
@@ -0,0 +1,6 @@
+% this will typeset only documentation but not the code
+
+\AtBeginDocument{\OnlyDescription
+%                 \let\tableofcontents\relax
+                 }
+\input{unicodefonttable.dtx}


Property changes on: trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-doc.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-samples.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-samples.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-samples.pdf	2021-10-21 20:28:46 UTC (rev 60825)
+++ trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-samples.pdf	2021-10-21 20:31:49 UTC (rev 60826)

Property changes on: trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-samples.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-samples.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-samples.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-samples.tex	2021-10-21 20:31:49 UTC (rev 60826)
@@ -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'.


Property changes on: trunk/Master/texmf-dist/doc/latex/unicodefonttable/unicodefonttable-samples.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex/unicodefonttable/unicodefonttable.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/unicodefonttable/unicodefonttable.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex/unicodefonttable/unicodefonttable.dtx	2021-10-21 20:31:49 UTC (rev 60826)
@@ -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 at 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}
+%</driver>
+%
+% \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{@@}
+%</package>
+%    \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 at write\@auxout{}{\gdef\string\generatetable
+     {\expandafter\detokenize\expandafter{\generatetable}}}
+\protected at write\@auxout{}{\gdef\string\DEFAULTfontname{\FontNameToTable}}
+\protected at write\@auxout{}{\gdef\string\DEFAULTunicodefont{\IsUnicodeFont}}
+\protected at write\@auxout{}{\gdef\string\DEFAULTfontfeatures{\FontFeaturesToApply}}
+\protected at write\@auxout{}{\gdef\string\DEFAULTtableconfig
+                  {\expandafter\detokenize\expandafter{\TableConfigurationToApply}}}
+\makeatother
+%    \end{macrocode}
+%    
+%    \begin{macrocode}
+\generatetable
+\end{document}
+%</standalone>
+%    \end{macrocode}
+%
+%
+%
+% \section{A samples file}
+%
+%    \begin{macrocode}
+%<*samples>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%<<VERBATIMLINE
+%!TEX program = lualatex
+
+%VERBATIMLINE
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\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}
+
+%\section{Computer Modern Sans --- 8bit font} \displayfonttable*[]{cmss10}
+
+\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[
+%  display-block = rules,
+  %              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}
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%</samples>
+%    \end{macrocode}
+%
+% \Finale
+%
+
+
+\endinput
+
+%%%%%%%%%%%%%%%%%%%


Property changes on: trunk/Master/texmf-dist/source/latex/unicodefonttable/unicodefonttable.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/latex/unicodefonttable/unicodefonttable.ins
===================================================================
--- trunk/Master/texmf-dist/source/latex/unicodefonttable/unicodefonttable.ins	                        (rev 0)
+++ trunk/Master/texmf-dist/source/latex/unicodefonttable/unicodefonttable.ins	2021-10-21 20:31:49 UTC (rev 60826)
@@ -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

Added: trunk/Master/texmf-dist/tex/latex/unicodefonttable/unicodefont.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/unicodefonttable/unicodefont.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/latex/unicodefonttable/unicodefont.tex	2021-10-21 20:31:49 UTC (rev 60826)
@@ -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 at write\@auxout{}{\gdef\string\generatetable
+     {\expandafter\detokenize\expandafter{\generatetable}}}
+\protected at write\@auxout{}{\gdef\string\DEFAULTfontname{\FontNameToTable}}
+\protected at write\@auxout{}{\gdef\string\DEFAULTunicodefont{\IsUnicodeFont}}
+\protected at write\@auxout{}{\gdef\string\DEFAULTfontfeatures{\FontFeaturesToApply}}
+\protected at write\@auxout{}{\gdef\string\DEFAULTtableconfig
+                  {\expandafter\detokenize\expandafter{\TableConfigurationToApply}}}
+\makeatother
+\generatetable
+\end{document}
+
+\endinput
+%%
+%% End of file `unicodefont.tex'.


Property changes on: trunk/Master/texmf-dist/tex/latex/unicodefonttable/unicodefont.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/latex/unicodefonttable/unicodefonttable.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/unicodefonttable/unicodefonttable.sty	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/latex/unicodefonttable/unicodefonttable.sty	2021-10-21 20:31:49 UTC (rev 60826)
@@ -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'.


Property changes on: trunk/Master/texmf-dist/tex/latex/unicodefonttable/unicodefonttable.sty
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/tlpkg/bin/tlpkg-ctan-check
===================================================================
--- trunk/Master/tlpkg/bin/tlpkg-ctan-check	2021-10-21 20:28:46 UTC (rev 60825)
+++ trunk/Master/tlpkg/bin/tlpkg-ctan-check	2021-10-21 20:31:49 UTC (rev 60826)
@@ -820,7 +820,7 @@
     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

Modified: trunk/Master/tlpkg/libexec/ctan2tds
===================================================================
--- trunk/Master/tlpkg/libexec/ctan2tds	2021-10-21 20:28:46 UTC (rev 60825)
+++ trunk/Master/tlpkg/libexec/ctan2tds	2021-10-21 20:31:49 UTC (rev 60826)
@@ -2312,6 +2312,7 @@
  '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,

Modified: trunk/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc
===================================================================
--- trunk/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc	2021-10-21 20:28:46 UTC (rev 60825)
+++ trunk/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc	2021-10-21 20:31:49 UTC (rev 60826)
@@ -1306,6 +1306,7 @@
 depend underoverlap
 depend undolabl
 depend uni-titlepage
+depend unicodefonttable
 depend unitconv
 depend unitipa
 depend units

Added: trunk/Master/tlpkg/tlpsrc/unicodefonttable.tlpsrc
===================================================================


More information about the tex-live-commits mailing list.