%%%%% \iffalse meta-comment
%
%% File: unicodefonttable.dtx (C) Copyright 2019-2024 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   {2024/06/06}
\def\unicodefonttableversion{1.0i}


%<*driver>
\documentclass{l3doc-TUB2024}

% some fixes local to this documentation

\ExplSyntaxOn
  \cs_new:Npn\IfImplementationShownTF
    {\bool_if:NTF \g__codedoc_typeset_implementation_bool}
\ExplSyntaxOff

\makeatletter
\def\meta@font@select{\normalfont\itshape}

\IndexPrologue{%
   \IfImplementationShownTF{\section*{Index}%
     Numbers written in italic refer to the page
     where the corresponding entry is described
     or mentioned. Numbers underlined refer to the
     code line of the
     definition; numbers in Roman refer to the
     code lines where the entry is used.}%
   {\section{Index}%
     Numbers written in italic refer to the page
     where the corresponding entry is described
     or mentioned.}}

\makeatother


\usepackage{graphicx,unicodefonttable}

\EnableCrossrefs
\CodelineIndex
\begin{document}
  \DocInput{unicodefonttable.dtx}
\advance\signaturewidth by 40pt
\makesignature
\end{document}
%</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}
%
% \vspace*{\medskipamount}
%
% \tableofcontents
%
% \vspace*{\bigskipamount}
%
% \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
% \IfImplementationShownTF{}{\pagebreak}\ignorespaces
%    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, hex-digits-font,hex-digits-row-format,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{hex-digits-row-format}]
%    This key defines the format for the hex digits shown on the left
%    of each row. It accepts one argument hold the hex values for the
%    row except for the last digit, e.g, \texttt{0A3} for the values
%    from \texttt{0A30} to \texttt{0A3F}. The default formatting is
%    \underline{\ttfamily U+\#10\cs{,}-\cs{,}\#1F} and without further
%    adjustments it is automaticaly set
%    in  \cs{ttfamily}\cs{footnotesize} and in the color
%    specified by the \key{color} key.
%    A suitable value that takes up less space would be \texttt{U+\#1x}.
%
%
%
% \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}.
%
%    However, please note that the \LuaTeX{} fontloader uses the
%    \enquote{Supplementary Private Use Area-A}, which starts at
%    \texttt{F0000}, as its own playground and places remapping into
%    it, so by default you see random data instead of font data there. You
%    either have to use the \XeTeX{} engine or load the font with
%    \texttt{Renderer=HarfBuzz} in \LuaTeX{}.
%
%    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 \LaTeX{} using \LuaTeX{} (or \XeTeX{})
%    as the engine. 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~6 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.
%
%    Please note that this documentation was produced with
%    \LuaTeX{}. If you reuse the examples with \XeTeX{}, you may have
%    to specify the font names differently (i.e., following to the
%    \pkg{fontspec} documentation for this engine).
%
%
%
% \subsection{Computer Modern Sans --- 7-bit font}
%
% Our first example is the original Computer Modern Sans, with 
% character codes $\le 127$.
% 
% Command used: \begin{verbatim}
%   \displayfonttable*[color=none, range-end=7F]{cmss10}
% \end{verbatim}
% 
%  \displayfonttable*[color=none, range-end=7F]{cmss10}
%
%
% \iftrue
%
%\subsection{\TeX\ Gyre Heros --- 8-bit font}
%
%    This example shows the \TeX\ Gyre Heros 8-bit font,
%    in the T1 encoding, with character codes $\le 255$.
%    We used \key{hex-digits-row-format} to shorten the row titles on
%    the left:
%\begin{verbatim}
%  \displayfonttable*[color=none,hex-digits-row-format=U+#1]{ec-qhvr}
%\end{verbatim}
%
%\displayfonttable*[color=none,hex-digits-row-format=U+#1]{ec-qhvr}
%
% \fi
%
%
% \iftrue
%\subsection{Latin Modern Math --- 8-bit fonts}
%
% The traditional Latin Modern Math Italic, Symbol and Extension fonts.
% The symbol font (\texttt{lmsy10}) has two characters added to the
% Computer Modern symbol repertoire, seen in the last row of the table.
% Commands used:
% 
%\begin{verbatim}
%  \displayfonttable*[color=none]{lmmi10}
%  \displayfonttable*[color=none]{lmsy10}
%  \displayfonttable*[color=none]{lmex10}
%\end{verbatim}
% 
%\displayfonttable*[color=none]{lmmi10}
%\displayfonttable*[color=none]{lmsy10}
%\displayfonttable*[color=none]{lmex10}
%
% \fi
%
%
% \iffalse % 5pp
%
%\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
%
%
% ^^A \IfImplementationShownTF{}{\newpage}
%
% \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,
%                    title-format=\caption{Latin Modern Math compared to
%                                          New Computer Modern Math},
%                    title-format-cont=\caption{LM Math vs.\ NewCM Math,
%                                          \emph{cont.}},
%                    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,
%                    title-format=\caption{Latin Modern Math compared to
%                                          New Computer Modern Math},
%                    title-format-cont=\caption{LM Math vs.\ NewCM Math,
%                                          \emph{cont.}},
%                    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}
%    
%    This is a tmp fix for code in \texttt{lttabbing.dtx} until that
%    is corrected there (probably 2024/11).
%    \begin{macrocode}
\cs_set:Npn \tbl_crcr:n #1 {
     \int_compare:nNnT \g__tbl_col_int > 0
         {
           \tbl_count_missing_cells:n {#1}
         }
     \crcr
   }
%    \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 \LuaTeX{} engine is used without HarfBuzz and the display
%    range includes code points above \texttt{U+EFFFF} the output shows
%    remappings and not what is in the font, so we issue a warning.
% \changes{v1.0g}{2022/11/12}{Test for luatex without harfbuzz and
%    private area A and warn (gh/8)}
%    \begin{macrocode}
    \bool_lazy_and:nnT
        { \sys_if_engine_luatex_p: }
        { \int_compare_p:nNn { "EFFFF } < { "\l_@@_range_end_tl } }
        {
          \directlua{token.put_next(token.create(font.getfont(font.current()).hb~
                     and~ 'use_none:n'~  or~ 'use:n'))}
            { \msg_warning:nn {unicodefonttable}{noharfbuzz} }
        }
%    \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}
%    Typesetting the font tables in twocolumn mode makes little sense
%    due to their width, and if \env{longtable} is used it will
%    complain. However there is one case where it should work: in a
%    page-wide float. To make this happen we claim that we are not in
%    twocolumn mode if the display is inside a vertical box.
% \changes{v1.0g}{2022/11/12}{Support use in twocolumn mode if inside
%    a table* float (gh/7)}
%    \begin{macrocode}
    \if_mode_vertical: \if_mode_inner: \@twocolumnfalse \fi: \fi:
%    \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{macrocode}
\msg_new:nnn {unicodefonttable}{noharfbuzz}
    { You~ asked~ for~ displaying~ glyphs~ with~ code \iow_newline:
      points~ above~ U+EFFFF~ \msg_line_context: ,~ i.e.,~ from~ the~
      'Supplementary~ Private~ Use~ Area-A'\iow_newline:
      without~ specifying~ '[Renderer=Harfbuzz]'~ when~
      loading~ the~ font.
      \iow_newline:\iow_newline:
      With~ LuaLaTeX,~ this~ Unicode~ region~ is~ used~
      for~ remappings~ (if~ the~ HarfBuzz~ engine~ is~ not~ used).~
      Thus,~ the~ results~ shown~ do~ not~ reflect~ what~
      is~ in~ the~ font!
    }
%    \end{macrocode}
%
%
%
%  \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.
% \changes{v1.0f}{2021/10/29}{Make documentation and code match:
%                             it should be \texttt{title-format-cont}}
%    \begin{macrocode}
       ,title-format-cont .cs_set:Np = \@@_format_table_cont:nn #1#2
       ,title-format-cont .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}
%    Customizing the row header (on the left) can be done with this
%    key. Defaults for font, fontsize, and color is set on the outside, but can, of
%    course, be overwritten inside if that is desired.
% \changes{v1.0g}{2022/11/12}{Add key hex-digits-row-format to allow
%    customizing the row title on the left (gh/3)}
%    \begin{macrocode}
       ,hex-digits-row-format  .cs_set:Np = \@@_format_row_hex_digits:n #1
       ,hex-digits-row-format  .initial:n = U+#1 0 \, - \, #1 F
%    \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}.
% \changes{v1.0g}{2022/11/12}{Change default text so that it makes
%    more sense if only a portion of the font is displayed (gh/4)}
%    \begin{macrocode}
    ,statistics-format  .cs_set:Np = \@@_format_stats:nn #1#2
    ,statistics-format  .initial:n = Total~ number~ of~ glyphs~ shown~ from~ #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.
% \changes{v1.0g}{2022/11/12}{Change default text so that it makes
%    more sense if only a portion of the font is displayed (gh/4)}
%    \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~ shown~ from~ \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.
% \changes{v1.0g}{2022/11/12}{Add key hex-digits-row-format to allow
%    customizing the row title on the left (gh/3)}
%    \begin{macrocode}
\cs_new:Npn \@@_format_row_title:n #1 {
  \texttt { \footnotesize \l_@@_color_tl \@@_format_row_hex_digits:n {#1} }
}
%    \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 }{ Malayalam }
         { "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@write\@auxout{}{\gdef\string\generatetable
     {\expandafter\detokenize\expandafter{\generatetable}}}
\protected@write\@auxout{}{\gdef\string\DEFAULTfontname{\FontNameToTable}}
\protected@write\@auxout{}{\gdef\string\DEFAULTunicodefont{\IsUnicodeFont}}
\protected@write\@auxout{}{\gdef\string\DEFAULTfontfeatures{\FontFeaturesToApply}}
\protected@write\@auxout{}{\gdef\string\DEFAULTtableconfig
                  {\expandafter\detokenize\expandafter{\TableConfigurationToApply}}}
\makeatother
%    \end{macrocode}
%    
%    \begin{macrocode}
\generatetable
\end{document}
%</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-format-cont = \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

%%%%%%%%%%%%%%%%%%%
